-
Notifications
You must be signed in to change notification settings - Fork 0
Feat: Login 페이지 퍼블리싱 #47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Walkthrough로그인 페이지 관련 코드 추가 및 확장: 데코레이션용 React 컴포넌트, vanilla-extract 스타일 모듈(그래디언트·절대위치 장식 요소 포함), 로그인 페이지 클라이언트 컴포넌트 및 테마 색상(로그인 배경 그래디언트) 필드가 추가되었습니다. Changes
Sequence Diagram(s)(생성 조건에 부합하지 않아 생략) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
🔺 세모-STORYBOOK |
There was a problem hiding this 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으로 감싸세요.
onKakaoStart와onAppleStart가 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
⛔ Files ignored due to path filters (6)
apps/web/public/login/divide.svgis excluded by!**/*.svgapps/web/public/login/minus.svgis excluded by!**/*.svgapps/web/public/login/multiply.svgis excluded by!**/*.svgapps/web/public/login/pencil.svgis excluded by!**/*.svgapps/web/public/login/plus.svgis excluded by!**/*.svgapps/web/public/login/vector-14.svgis excluded by!**/*.svg
📒 Files selected for processing (3)
apps/web/src/app/login/login-decorations.tsxapps/web/src/app/login/login.css.tsapps/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.tsxapps/web/src/app/login/login.css.tsapps/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 연동은 별도 이슈로 관리되고 있나요?
There was a problem hiding this 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와 다릅니다.
color와bgColor는style()함수로 클래스를 생성하지만,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의
recipe와variant를 활용하여 반응형 스타일 추가- 프로젝트의 미디어 쿼리 패턴(
@media (min-width: 431px))에 맞춰 조정- 다른 컴포넌트(
app-bar,toggle등)처럼 반응형 대응
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/web/src/app/login/login-decorations.tsxapps/web/src/app/login/login.css.tsapps/web/src/shared/styles/color.css.tsapps/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.tsapps/web/src/shared/styles/theme.css.tsapps/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.tsapps/web/src/shared/styles/theme.css.tsapps/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)이 기존 디자인 토큰과 연결되지 않습니다. 디자인 시스템의 일관성을 위해 피그마 디자인과 색상 팔레트를 확인하시기 바랍니다.참고:
#ffffff는grayscale.0와 동일하며,#ffdbd6는main-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: auto와safe-area-inset-bottom활용이 적절합니다.
62-68: 장식 요소 레이어 처리 - 훌륭합니다!
pointer-events: none과 적절한z-index로 장식 요소가 사용자 상호작용을 방해하지 않도록 잘 구현되었습니다.
kimkimjunjun
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
반복으로 재사용되는 아이콘들만 sprite svg로 사용하고 지금처럼 한번만 사용되는 것들은 public에 넣는게 불필요한 자원 차지하지 않아서 더 나은 것 같습니다 !
로그인 페이지 퍼블리싱하느라 고생하셨습니다 !
🔗 관련 이슈
Closes #45
💡 작업 내용
로그인 페이지 UI 퍼블리싱을 추가했습니다.
그래픽은 레이아웃과 분리해서
LoginDecorations컴포넌트로 분리했고, 페이지 위에 absolute로 얹되 클릭이나 스크롤에 영향이 없도록pointer-events: none처리했습니다. 각 svg는next/image의fill+objectFit: contain으로 감싸서 컨테이너 박스 안에서 비율 깨짐 없이 렌더링되도록 했습니다.또한 피그마 상단 기준값에서 상태바 높이(4.6rem)를 뺀 위치값으로 맞췄습니다.
그래픽 요소를 sprite가 아니라
public/login/에 둔 이유이번 그래픽 이미지들은 “아이콘”처럼 여러 화면에서 반복 재사용되는 성격이라기보다, 로그인 화면에서만 쓰이는 큰 배경/데코 SVG에 가깝다고 생각했어요. 스프라이트에 넣으면 전체 스프라이트에 포함되어 초기 로드 비용이 늘어날 수 있고 실제로는 로그인에서만 필요한 리소스인데도 전역으로 함께 관리되는 구조가 되어 유지보수에 좋지 않습니다,,,
반대로
public/login/에 파일로 분리해두면, 로그인 전용 리소스를 한곳에서 관리할 수 있고(추후 디자인 교체 용이..!), 렌더링도next/image로 컨테이너 기준 배치가 가능해서 화면별 그래픽 요소 관리가 명확해지는 장점이 있어서 이 방식으로 정리했습니다.💬 원하는 리뷰 방식(선택)
그래픽 요소 처리 방식이 괜찮은지 의견 부탁드려요!
📸 Screenshots or Video(선택)
Summary by CodeRabbit
릴리스 노트
New Features
Style
✏️ Tip: You can customize this high-level summary in your review settings.