Skip to content

Conversation

@Dubabbi
Copy link
Collaborator

@Dubabbi Dubabbi commented Jan 8, 2026

🔗 관련 이슈

Closes #45

💡 작업 내용

로그인 페이지 UI 퍼블리싱을 추가했습니다.

그래픽은 레이아웃과 분리해서 LoginDecorations 컴포넌트로 분리했고, 페이지 위에 absolute로 얹되 클릭이나 스크롤에 영향이 없도록 pointer-events: none 처리했습니다. 각 svg는 next/imagefill + objectFit: contain으로 감싸서 컨테이너 박스 안에서 비율 깨짐 없이 렌더링되도록 했습니다.

또한 피그마 상단 기준값에서 상태바 높이(4.6rem)를 뺀 위치값으로 맞췄습니다.

그래픽 요소를 sprite가 아니라 public/login/에 둔 이유

이번 그래픽 이미지들은 “아이콘”처럼 여러 화면에서 반복 재사용되는 성격이라기보다, 로그인 화면에서만 쓰이는 큰 배경/데코 SVG에 가깝다고 생각했어요. 스프라이트에 넣으면 전체 스프라이트에 포함되어 초기 로드 비용이 늘어날 수 있고 실제로는 로그인에서만 필요한 리소스인데도 전역으로 함께 관리되는 구조가 되어 유지보수에 좋지 않습니다,,,
반대로 public/login/에 파일로 분리해두면, 로그인 전용 리소스를 한곳에서 관리할 수 있고(추후 디자인 교체 용이..!), 렌더링도 next/image로 컨테이너 기준 배치가 가능해서 화면별 그래픽 요소 관리가 명확해지는 장점이 있어서 이 방식으로 정리했습니다.

💬 원하는 리뷰 방식(선택)

그래픽 요소 처리 방식이 괜찮은지 의견 부탁드려요!

📸 Screenshots or Video(선택)

image

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 로그인 페이지 UI 구현 완료 및 Kakao/Apple 소셜 로그인 버튼 추가
    • 로그인 페이지 장식 SVG 컴포넌트 추가
  • Style

    • 로그인 레이아웃 및 장식 요소 스타일링 추가
    • 로그인 전용 배경 그라디언트 테마 추가

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 8, 2026

Walkthrough

로그인 페이지 관련 코드 추가 및 확장: 데코레이션용 React 컴포넌트, vanilla-extract 스타일 모듈(그래디언트·절대위치 장식 요소 포함), 로그인 페이지 클라이언트 컴포넌트 및 테마 색상(로그인 배경 그래디언트) 필드가 추가되었습니다.

Changes

Cohort / File(s) 변경 사항
Login UI
apps/web/src/app/login/login-decorations.tsx, apps/web/src/app/login/page.tsx
로그인 화면 구성 요소 추가: SVG 장식 렌더링용 LoginDecorations 컴포넌트 추가(기본 export), 클라이언트 페이지로 전환된 page.tsx에 로고·태그라인·소셜 로그인 버튼 및 라우팅 핸들러 추가 (+45/-2 줄 등).
Login styles
apps/web/src/app/login/login.css.ts
vanilla-extract 스타일 모듈 추가: 페이지 배경 ::before 그래디언트, content/header/tagline/actions 등 스타일 토큰 및 여러 절대 위치 데코 요소(벡터, 펜실, 연산 기호 등) 정의 (+126 줄).
Theme / Colors
apps/web/src/shared/styles/theme.css.ts, apps/web/src/shared/styles/color.css.ts
테마 확장: color.loginbgGradient 필드 추가 및 lightTheme에 그라디언트 값 삽입. color.css.ts에 해당 그라디언트를 노출하는 bgGradient 상수 추가 (+~4 줄).

Sequence Diagram(s)

(생성 조건에 부합하지 않아 생략)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • kimkimjunjun
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 로그인 페이지 퍼블리싱이라는 주요 변경사항을 명확하게 요약하고 있습니다.
Linked Issues check ✅ Passed 로그인 페이지 UI 퍼블리싱 목표가 LoginDecorations 컴포넌트, 스타일 정의, 페이지 레이아웃 및 소셜 로그인 버튼 구현으로 완벽하게 충족되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 로그인 페이지 퍼블리싱 범위 내에 있으며, 로그인 페이지에 필요한 컴포넌트, 스타일, 테마 확장만 포함되어 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

🔺 세모-STORYBOOK

세모 Storybook 배포 완료!!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @apps/web/src/app/login/login-decorations.tsx:
- Around line 4-62: The LoginDecorations component duplicates the same Image
wrapper six times; refactor it to a data-driven render: create a DECORATIONS
array of items with className and src, import Image and s, then map over
DECORATIONS inside LoginDecorations to return each <div className={className}>
with the Image using src and a stable key (e.g., src); ensure the exported
component name LoginDecorations remains and optionally export default
LoginDecorations.

In @apps/web/src/app/login/login.css.ts:
- Line 20: Replace the hardcoded hex colors in the background linear-gradient
with design tokens from vars.color: swap "#ffffff" and "#ffdbd6" for the
appropriate vars.color tokens (e.g., vars.color.white and the closest token such
as vars.color["main-100"] or add a new token if needed), updating the background
property in login.css.ts to use those tokens in the linear-gradient and confirm
with design if an exact match token must be added.
🧹 Nitpick comments (6)
apps/web/src/app/login/login.css.ts (2)

44-50: 타이포그래피 토큰의 fontWeight를 오버라이드하지 마세요.

typo.h3를 사용하면서 fontWeight를 별도로 오버라이드하면 디자인 토큰 시스템의 일관성이 깨집니다. 대신 적절한 타이포그래피 토큰을 사용하거나, 필요하다면 새로운 variant를 디자인 시스템에 추가하세요.

♻️ 개선 방안

옵션 1: 적절한 기존 토큰 사용

-export const tagline = style([
-  typo.h3,
-  color["grayscale-700"],
-  {
-    fontWeight: 500,
-  },
-]);
+export const tagline = style([
+  typo.subtitle.semibold, // 또는 적절한 다른 토큰
+  color["grayscale-700"],
+]);

옵션 2: 디자인 시스템에 새 variant 추가를 요청

Based on coding guidelines, 디자인 토큰의 일관성 유지가 중요합니다.


70-126: 선택사항: 데코레이션 스타일에 recipe 패턴 고려

현재는 각 데코레이션마다 별도 style을 export하고 있습니다. 향후 다른 페이지에서도 유사한 데코레이션 패턴을 사용할 가능성이 있다면, recipe를 사용해 variant로 관리하는 것도 고려해보세요.

♻️ Recipe 패턴 예시
import { recipe } from "@vanilla-extract/recipes";

export const decoration = recipe({
  base: {
    position: "absolute",
    pointerEvents: "none",
  },
  variants: {
    type: {
      vector14: { left: "-4.3rem", top: "27.8rem", width: "45.5rem", height: "51.3rem" },
      pencil: { right: "-5.0rem", top: "8.4rem", width: "27.0rem", height: "27.0rem" },
      // ...
    },
  },
});

사용:

<div className={decoration({ type: "vector14" })} />

Based on coding guidelines, recipe와 variant의 적절한 사용이 권장됩니다.

apps/web/src/app/login/login-decorations.tsx (2)

4-4: React.memo로 불필요한 리렌더링 방지를 고려하세요.

이 컴포넌트는 props가 없고 순수하게 장식 요소만 렌더링하므로, React.memo로 감싸면 부모가 리렌더링될 때 불필요한 재렌더링을 방지할 수 있습니다.

🚀 성능 최적화 제안
+import { memo } from "react";
 import Image from "next/image";
 import * as s from "./login.css";

-export const LoginDecorations = () => {
+export const LoginDecorations = memo(() => {
   return (
     <div className={s.decorations} aria-hidden>
       {/* ... */}
     </div>
   );
-};
+});
+
+LoginDecorations.displayName = "LoginDecorations";

 export default LoginDecorations;

Based on coding guidelines, React.memo, useMemo, useCallback의 적절한 사용이 권장됩니다.


12-12: 인라인 스타일을 CSS 모듈로 이동하세요.

style={{ objectFit: "contain" }}가 6번 반복되고 있습니다. CSS 모듈에 정의하면 더 깔끔합니다.

♻️ 제안하는 수정

login.css.ts에 추가:

export const decoImage = style({
  objectFit: "contain",
});

컴포넌트에서 사용:

 <Image
   src="/login/vector-14.svg"
   alt=""
   fill
-  style={{ objectFit: "contain" }}
+  className={s.decoImage}
 />

Based on coding guidelines, 스타일은 반드시 Vanilla Extract로 작성해야 합니다.

apps/web/src/app/login/page.tsx (2)

25-28: 헤딩 계층 구조를 개선하세요.

로고와 태그라인이 <header> 안에 있지만, 의미론적 헤딩(h1)이 없습니다. 스크린 리더 사용자를 위해 헤딩 계층을 명확히 하면 접근성이 향상됩니다.

♻️ 접근성 개선 제안
 <header className={s.header}>
-  <Icon width={13.3} height={4.2} name="logo-default" />
-  <p className={s.tagline}>나만의 수학 오답노트</p>
+  <h1>
+    <Icon width={13.3} height={4.2} name="logo-default" />
+    <span className="sr-only">Math Wiki</span>
+  </h1>
+  <p className={s.tagline} aria-label="서비스 소개">나만의 수학 오답노트</p>
 </header>

또는 태그라인을 h2로:

 <header className={s.header}>
-  <Icon width={13.3} height={4.2} name="logo-default" />
-  <p className={s.tagline}>나만의 수학 오답노트</p>
+  <h1>
+    <Icon width={13.3} height={4.2} name="logo-default" />
+  </h1>
+  <h2 className={s.tagline}>나만의 수학 오답노트</h2>
 </header>

sr-only 유틸리티 클래스가 필요하면 추가해야 합니다.


12-18: 핸들러를 useCallback으로 감싸세요.

onKakaoStartonAppleStart가 Button 컴포넌트에 props로 전달되므로, useCallback으로 감싸면 Button이 불필요하게 리렌더링되는 것을 방지할 수 있습니다.

🚀 성능 최적화 제안
+"use client";

+import { useCallback } from "react";
 import { useRouter } from "next/navigation";
 import Icon from "@/shared/components/icon/icon";
 import { Button } from "@/shared/components/button/button/button";
 import LoginDecorations from "./login-decorations";
 import * as s from "./login.css";

 const LoginPage = () => {
   const router = useRouter();

-  const onKakaoStart = () => {
+  const onKakaoStart = useCallback(() => {
     router.push("/");
-  };
+  }, [router]);

-  const onAppleStart = () => {
+  const onAppleStart = useCallback(() => {
     router.push("/");
-  };
+  }, [router]);

   return (
     {/* ... */}
   );
 };

Based on coding guidelines, useCallback의 적절한 사용이 권장됩니다.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 546e990 and 3d3008e.

⛔ Files ignored due to path filters (6)
  • apps/web/public/login/divide.svg is excluded by !**/*.svg
  • apps/web/public/login/minus.svg is excluded by !**/*.svg
  • apps/web/public/login/multiply.svg is excluded by !**/*.svg
  • apps/web/public/login/pencil.svg is excluded by !**/*.svg
  • apps/web/public/login/plus.svg is excluded by !**/*.svg
  • apps/web/public/login/vector-14.svg is excluded by !**/*.svg
📒 Files selected for processing (3)
  • apps/web/src/app/login/login-decorations.tsx
  • apps/web/src/app/login/login.css.ts
  • apps/web/src/app/login/page.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/src/**

⚙️ CodeRabbit configuration file

**/src/**: 공통 코드 리뷰 시:

기본 규칙

  • 모든 컴포넌트는 반드시 TypeScript로 작성
  • 스타일은 반드시 Vanilla Extract(.css.ts)로 작성
  • 절대 경로 임포트 사용
  • index를 key로 사용하지 않기
  • var 사용 금지

네이밍 컨벤션

  • 폴더명, 파일명은 kebab-case 사용
  • 컴포넌트와 클래스는 PascalCase 사용
  • 변수와 함수는 camelCase 사용
  • 상수는 BIG_SNAKE_CASE 사용
  • Props 타입은 컴포넌트명 + Props 형식
  • API Response 타입은 XXXResponse 형식
  • 함수 네이밍에 get/create/check/handle/is/has/can 접두사 활용
  • TanStack Query 훅: use + 행위 + 대상 + Query/Mutation (ex. useGetUserListQuery)

보안/성능

  • 환경 변수 사용(API 키나 시크릿을 하드코딩 X)
  • React.memo, useMemo, useCallback의 적절한 사용

Files:

  • apps/web/src/app/login/login-decorations.tsx
  • apps/web/src/app/login/login.css.ts
  • apps/web/src/app/login/page.tsx
**/src/**/*.css.ts

⚙️ CodeRabbit configuration file

**/src/**/*.css.ts: 스타일(Vanilla Extract) 파일 리뷰 시:

  • 디자인 토큰 활용 확인
  • recipe와 variant 적절한 사용
  • 반응형 스타일 구현 방식
  • 불필요한 중복 스타일 존재 여부

Files:

  • apps/web/src/app/login/login.css.ts
🧬 Code graph analysis (2)
apps/web/src/app/login/login.css.ts (2)
apps/web/src/shared/styles/typography.css.ts (1)
  • typo (4-159)
apps/web/src/shared/styles/color.css.ts (1)
  • color (4-44)
apps/web/src/app/login/page.tsx (3)
apps/web/src/app/login/login-decorations.tsx (1)
  • LoginDecorations (4-62)
apps/web/src/app/login/login.css.ts (1)
  • header (35-42)
apps/web/src/shared/components/button/button/button.tsx (1)
  • Button (20-44)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: chromatic
🔇 Additional comments (1)
apps/web/src/app/login/page.tsx (1)

12-18: 소셜 로그인 핸들러가 플레이스홀더입니다.

현재 Kakao와 Apple 로그인 버튼이 모두 홈("/")으로 이동하는 플레이스홀더 구현입니다.

실제 OAuth 구현 시 다음을 확인하세요:

  • OAuth 리다이렉트 URL은 환경 변수에서 관리 (process.env.NEXT_PUBLIC_KAKAO_AUTH_URL 등)
  • 에러 처리 로직 추가
  • 로딩 상태 관리
  • 보안: CSRF 토큰, state 파라미터 등

퍼블리싱 작업으로는 적절합니다. 실제 OAuth 연동은 별도 이슈로 관리되고 있나요?

@Central-MakeUs Central-MakeUs deleted a comment from coderabbitai bot Jan 8, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
apps/web/src/shared/styles/color.css.ts (1)

88-90: bgGradient 내보내기 패턴이 color/bgColor와 다릅니다.

colorbgColorstyle() 함수로 클래스를 생성하지만, bgGradient는 테마 변수를 직접 내보냅니다. 이는 CSS 속성에 직접 사용하기 위한 의도로 보이지만, 일관성을 위해 JSDoc이나 주석으로 사용 의도를 명시하는 것을 권장합니다.

예:

/**
 * 그라디언트 값 (CSS 속성에 직접 사용)
 * @example background: bgGradient["login-bg"]
 */
export const bgGradient = {
  "login-bg": vars.color.login.bgGradient,
} as const;
apps/web/src/app/login/login.css.ts (2)

35-42: 상단 패딩에 safe-area-inset-top 사용을 권장합니다.

현재 paddingTop: "4.8rem"으로 고정되어 있는데, 다양한 디바이스의 상태바 높이 차이를 고려하여 calc(env(safe-area-inset-top) + 4.8rem) 형태로 변경하는 것을 검토해보세요. (하단 actions에서는 이미 사용 중)

♻️ 제안하는 수정안
 export const header = style({
-  paddingTop: "4.8rem",
+  paddingTop: "calc(env(safe-area-inset-top) + 4.8rem)",
   paddingLeft: "1.6rem",
   paddingRight: "1.6rem",
   display: "flex",
   flexDirection: "column",
   gap: "1.6rem",
 });

74-126: 로그인 페이지 장식 요소의 반응형 대응이 부재합니다.

프로젝트는 모바일 우선 설계(370-430px)이면서도 431px 이상의 더 큰 뷰포트를 지원합니다(global.css.ts 참조). 현재 로그인 장식 요소들은 고정된 rem 값으로만 배치되어, 태블릿/데스크톱 뷰포트에서 위치가 올바르지 않을 가능성이 높습니다.

개선 제안:

  • Vanilla Extract의 recipevariant를 활용하여 반응형 스타일 추가
  • 프로젝트의 미디어 쿼리 패턴(@media (min-width: 431px))에 맞춰 조정
  • 다른 컴포넌트(app-bar, toggle 등)처럼 반응형 대응
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d3008e and 45482b2.

📒 Files selected for processing (4)
  • apps/web/src/app/login/login-decorations.tsx
  • apps/web/src/app/login/login.css.ts
  • apps/web/src/shared/styles/color.css.ts
  • apps/web/src/shared/styles/theme.css.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/app/login/login-decorations.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/src/**/*.css.ts

⚙️ CodeRabbit configuration file

**/src/**/*.css.ts: 스타일(Vanilla Extract) 파일 리뷰 시:

  • 디자인 토큰 활용 확인
  • recipe와 variant 적절한 사용
  • 반응형 스타일 구현 방식
  • 불필요한 중복 스타일 존재 여부

Files:

  • apps/web/src/shared/styles/color.css.ts
  • apps/web/src/shared/styles/theme.css.ts
  • apps/web/src/app/login/login.css.ts
**/src/**

⚙️ CodeRabbit configuration file

**/src/**: 공통 코드 리뷰 시:

기본 규칙

  • 모든 컴포넌트는 반드시 TypeScript로 작성
  • 스타일은 반드시 Vanilla Extract(.css.ts)로 작성
  • 절대 경로 임포트 사용
  • index를 key로 사용하지 않기
  • var 사용 금지

네이밍 컨벤션

  • 폴더명, 파일명은 kebab-case 사용
  • 컴포넌트와 클래스는 PascalCase 사용
  • 변수와 함수는 camelCase 사용
  • 상수는 BIG_SNAKE_CASE 사용
  • Props 타입은 컴포넌트명 + Props 형식
  • API Response 타입은 XXXResponse 형식
  • 함수 네이밍에 get/create/check/handle/is/has/can 접두사 활용
  • TanStack Query 훅: use + 행위 + 대상 + Query/Mutation (ex. useGetUserListQuery)

보안/성능

  • 환경 변수 사용(API 키나 시크릿을 하드코딩 X)
  • React.memo, useMemo, useCallback의 적절한 사용

Files:

  • apps/web/src/shared/styles/color.css.ts
  • apps/web/src/shared/styles/theme.css.ts
  • apps/web/src/app/login/login.css.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: chromatic
🔇 Additional comments (7)
apps/web/src/shared/styles/theme.css.ts (2)

39-39: 테마 계약에 bgGradient 추가 - LGTM!

로그인 테마 토큰이 올바르게 확장되었습니다.


173-176: 그라디언트 색상 값 확인을 권장합니다.

하드코딩된 색상 값(#ffdbd6)이 기존 디자인 토큰과 연결되지 않습니다. 디자인 시스템의 일관성을 위해 피그마 디자인과 색상 팔레트를 확인하시기 바랍니다.

참고: #ffffffgrayscale.0와 동일하며, #ffdbd6main-50(#ffefed)이나 main-100(#ffcec7)과 유사하지만 정확히 일치하지 않습니다.

apps/web/src/app/login/login.css.ts (5)

5-25: 페이지 레이아웃 구조는 좋으나 반응형 고려가 필요합니다.

100dvh 사용은 모바일 뷰포트 대응에 적절합니다. 다만 ::before 그라디언트 영역의 고정 높이(34.3rem)가 다양한 화면 크기에서 어떻게 보일지 확인이 필요합니다.

다양한 디바이스에서 그라디언트 영역 높이가 의도대로 표시되는지 테스트해주세요.


27-33: 콘텐츠 레이어링 - LGTM!

z-index를 통한 레이어 분리가 적절하게 구현되었습니다.


44-50: 타이포그래피 토큰 사용 - LGTM!

디자인 토큰을 잘 활용하고 있습니다. fontWeight 오버라이드는 한 곳에서만 사용되므로 문제없습니다.


52-60: 하단 액션 영역 - LGTM!

marginTop: autosafe-area-inset-bottom 활용이 적절합니다.


62-68: 장식 요소 레이어 처리 - 훌륭합니다!

pointer-events: none과 적절한 z-index로 장식 요소가 사용자 상호작용을 방해하지 않도록 잘 구현되었습니다.

@Dubabbi Dubabbi requested a review from kimkimjunjun January 9, 2026 01:14
Copy link
Collaborator

@kimkimjunjun kimkimjunjun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반복으로 재사용되는 아이콘들만 sprite svg로 사용하고 지금처럼 한번만 사용되는 것들은 public에 넣는게 불필요한 자원 차지하지 않아서 더 나은 것 같습니다 !
로그인 페이지 퍼블리싱하느라 고생하셨습니다 !

@Dubabbi Dubabbi merged commit 70c11f6 into develop Jan 9, 2026
4 checks passed
@Dubabbi Dubabbi deleted the feat/#45/login branch January 11, 2026 02:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Login 페이지 퍼블리싱

3 participants