Conversation
Walkthrough마이페이지 UI를 위한 새로운 컴포넌트 구조와 스타일이 대거 추가되었습니다. Profile, Banner, MenuList 등 주요 UI 컴포넌트와 그에 따른 CSS, 타입, 상수 파일이 신설되었으며, 레이아웃 및 페이지 파일도 새로 작성되었습니다. 일부 기존 아이콘 사용처가 새로운 아이콘으로 교체되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ProfilePage
participant Profile
participant Banner
participant MenuList
User->>ProfilePage: 페이지 접근
ProfilePage->>Profile: Suspense로 프로필 정보 로딩
Profile->>Profile: 회원 정보 fetch 및 표시
ProfilePage->>Banner: 배너 컴포넌트 렌더링
ProfilePage->>MenuList: 메뉴 리스트 렌더링
Possibly related PRs
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
src/app/(auth)/login/page.tsxOops! Something went wrong! :( ESLint: 9.27.0 ESLint couldn't find the plugin "eslint-plugin-react-hooks". (The package "eslint-plugin-react-hooks" was not found when loaded as a Node module from the directory "".) It's likely that the plugin isn't installed correctly. Try reinstalling by running the following: The plugin "eslint-plugin-react-hooks" was referenced from the config file in " » eslint-config-next/core-web-vitals » /node_modules/.pnpm/eslint-config-next@15.3.2_eslint@9.27.0_jiti@2.4.2__typescript@5.8.3/node_modules/eslint-config-next/index.js". If you still can't figure out the problem, please see https://eslint.org/docs/latest/use/troubleshooting. src/app/member/profile/_components/Banner/index.tsOops! Something went wrong! :( ESLint: 9.27.0 ESLint couldn't find the plugin "eslint-plugin-react-hooks". (The package "eslint-plugin-react-hooks" was not found when loaded as a Node module from the directory "".) It's likely that the plugin isn't installed correctly. Try reinstalling by running the following: The plugin "eslint-plugin-react-hooks" was referenced from the config file in " » eslint-config-next/core-web-vitals » /node_modules/.pnpm/eslint-config-next@15.3.2_eslint@9.27.0_jiti@2.4.2__typescript@5.8.3/node_modules/eslint-config-next/index.js". If you still can't figure out the problem, please see https://eslint.org/docs/latest/use/troubleshooting. src/app/member/profile/_components/Banner/Banner.css.tsOops! Something went wrong! :( ESLint: 9.27.0 ESLint couldn't find the plugin "eslint-plugin-react-hooks". (The package "eslint-plugin-react-hooks" was not found when loaded as a Node module from the directory "".) It's likely that the plugin isn't installed correctly. Try reinstalling by running the following: The plugin "eslint-plugin-react-hooks" was referenced from the config file in " » eslint-config-next/core-web-vitals » /node_modules/.pnpm/eslint-config-next@15.3.2_eslint@9.27.0_jiti@2.4.2__typescript@5.8.3/node_modules/eslint-config-next/index.js". If you still can't figure out the problem, please see https://eslint.org/docs/latest/use/troubleshooting.
📜 Recent review detailsConfiguration used: CodeRabbit UI ⛔ Files ignored due to path filters (6)
📒 Files selected for processing (25)
🚧 Files skipped from review as they are similar to previous changes (25)
⏰ 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). (2)
✨ 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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
🎨 Storybook Preview: https://685a32a1c0bbd269fdb67af4-bmyeebvpjl.chromatic.com/ |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (13)
src/app/member/profile/_constants/menuList.constants.ts (1)
1-1: TODO 주석은 이슈 번호로 연결하거나FIXME로 구체화하세요
작업이 미뤄진 상태를 명확히 추적할 수 있도록 Jira‧GitHub Issue 번호를 포함하거나FIXME:형태로 변환해 주세요.src/app/member/profile/layout.css.ts (1)
11-17:button클래스 이름이 지나치게 범용적입니다
컴포넌트 레벨에서만 쓰인다고 해도 전역 충돌 위험이 있습니다.backButton등 의미를 담은 네이밍으로 변경을 고려해 주세요.src/app/member/profile/page.tsx (1)
7-7: 불필요한 async 키워드 제거이 컴포넌트는 비동기 작업을 수행하지 않으므로
async키워드가 불필요합니다.-export default async function ProfilePage() { +export default function ProfilePage() {src/app/member/profile/layout.tsx (1)
35-40: 중복된 onClick 핸들러 제거아이콘에 별도의
onClick핸들러가 있는 것은 불필요합니다. 버튼의onClick으로 충분합니다.<LeftArrowIcon width={24} height={24} - onClick={handleClick} className={styles.icon} />src/app/member/profile/_components/MenuList/MenuList.tsx (1)
28-28: 로그아웃 모달 구현 계획TODO 코멘트에 명시된 로그아웃 모달 기능을 구현하시겠습니까? 이슈를 생성하여 추적하는 것을 도울 수 있습니다.
src/app/member/profile/_components/Profile/Profile.tsx (2)
13-13: 에러 처리 추가 고려현재 로딩 상태만 처리하고 있습니다. 데이터 fetch 실패 시 에러 처리도 추가하는 것을 고려해보세요.
- const { data: member, isLoading } = useQuery(memberQueryOptions); + const { data: member, isLoading, error } = useQuery(memberQueryOptions);그리고 에러 상태에 대한 UI 처리를 추가할 수 있습니다.
15-15: 로딩 UI 개선 계획TODO 코멘트에 명시된 로딩 스피너나 스켈레톤 UI 구현을 도와드릴 수 있습니다.
src/app/member/profile/_components/MenuList/MenuList.css.ts (1)
5-7: 패딩 값 하드코딩 대신 디자인 토큰 사용 제안
"1.6rem"을 직접 기입하기보다는 디자인 시스템의 spacing 토큰(예:spacing[16])을 사용하면 전역 일관성이 높아집니다.src/app/member/profile/_components/Banner/Banner.css.ts (2)
5-8: 배경·패딩 값도 토큰으로 치환 권장
colors.redOrange[90],"1.4rem 2.4rem"모두 하드코딩보다 디자인 토큰을 사용하면 테마 변경 시 유지보수가 쉬워집니다.
10-14: 링크 요소에 커서 스타일 추가 고려
linkWrapper는a태그지만 flex wrapper라 사용자 포인터가pointer로 드러나지 않을 수도 있습니다. 명시적으로cursor: pointer를 부여하면 UX 가 향상됩니다.src/app/member/profile/_components/Banner/Banner.tsx (3)
17-22: 이미지alt문구 구체화 권장
'가게 이미지'는 스크린리더에서 의미가 모호합니다. 예:'등록된 가게 대표 이미지'처럼 더 구체적으로 작성해 주세요.
24-26: 텍스트 하드코딩 국제화 고려
Korean 문자열이 직접 삽입되어 있습니다. I18n 전략(예:next-intl)을 도입 중이라면 메시지 파일로 분리해 주세요.
28-32: 앵커 접근성 속성 추가 제안
링크 텍스트가 충분하긴 하나, 아이콘만 클릭될 때 스크린리더가 인지하지 못할 수 있습니다.-<Link href='/' className={styles.linkWrapper}> +<Link href='/' className={styles.linkWrapper} aria-label='가게 등록하기'>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
public/images/store.pngis excluded by!**/*.pngsrc/assets/logo/front-bapurit.svgis excluded by!**/*.svgsrc/assets/right-arrow.svgis excluded by!**/*.svg
📒 Files selected for processing (13)
src/app/member/profile/_components/Banner/Banner.css.ts(1 hunks)src/app/member/profile/_components/Banner/Banner.tsx(1 hunks)src/app/member/profile/_components/Banner/index.ts(1 hunks)src/app/member/profile/_components/MenuList/MenuList.css.ts(1 hunks)src/app/member/profile/_components/MenuList/MenuList.tsx(1 hunks)src/app/member/profile/_components/MenuList/index.ts(1 hunks)src/app/member/profile/_components/Profile/Profile.css.ts(1 hunks)src/app/member/profile/_components/Profile/Profile.tsx(1 hunks)src/app/member/profile/_components/Profile/index.ts(1 hunks)src/app/member/profile/_constants/menuList.constants.ts(1 hunks)src/app/member/profile/layout.css.ts(1 hunks)src/app/member/profile/layout.tsx(1 hunks)src/app/member/profile/page.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (6)
src/app/member/profile/_constants/menuList.constants.ts (3)
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to src/app/**/_constants/*.{ts,tsx} : 도메인별 상수 정의는 `_constants` 폴더에 위치해야 한다.
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to src/constants/*.{ts,tsx} : 전역 상수 정의는 `constants/` 폴더에 위치해야 한다.
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to {src/constants/*.{ts,tsx},src/app/**/_constants/*.{ts,tsx}} : 상수 파일은 camelCase로 네이밍해야 한다 (예: `domain.constants.ts`).
src/app/member/profile/_components/Banner/Banner.tsx (1)
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to {src/app/**/_components/*.{ts,tsx},src/components/**/*.{ts,tsx}} : 컴포넌트 파일은 PascalCase로 네이밍해야 한다 (예: `Button.tsx`, `DomainLayout.tsx`).
src/app/member/profile/_components/Banner/Banner.css.ts (2)
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to **/*.css.ts : vanilla-extract 스타일 파일은 camelCase로, `.css.ts` 확장자를 사용해야 하며, 해당 컴포넌트와 같은 폴더에 배치해야 한다.
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to src/constants/*.{ts,tsx} : 전역 상수 정의는 `constants/` 폴더에 위치해야 한다.
src/app/member/profile/_components/MenuList/MenuList.css.ts (2)
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to **/*.css.ts : vanilla-extract 스타일 파일은 camelCase로, `.css.ts` 확장자를 사용해야 하며, 해당 컴포넌트와 같은 폴더에 배치해야 한다.
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: 스타일 근접성: vanilla-extract 스타일 파일은 해당 컴포넌트와 같은 폴더에 배치해야 한다.
src/app/member/profile/layout.css.ts (2)
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to **/*.css.ts : vanilla-extract 스타일 파일은 camelCase로, `.css.ts` 확장자를 사용해야 하며, 해당 컴포넌트와 같은 폴더에 배치해야 한다.
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: 스타일 근접성: vanilla-extract 스타일 파일은 해당 컴포넌트와 같은 폴더에 배치해야 한다.
src/app/member/profile/_components/Profile/Profile.css.ts (1)
Learnt from: CR
PR: YAPP-Github/26th-Web-Team-1-FE#0
File: .cursor/rules/nextjs-folder-structure.mdc:0-0
Timestamp: 2025-06-30T08:25:30.684Z
Learning: Applies to **/*.css.ts : vanilla-extract 스타일 파일은 camelCase로, `.css.ts` 확장자를 사용해야 하며, 해당 컴포넌트와 같은 폴더에 배치해야 한다.
🧬 Code Graph Analysis (3)
src/app/member/profile/_components/MenuList/MenuList.tsx (2)
src/app/member/profile/_components/MenuList/index.ts (1)
MenuList(1-1)src/app/member/profile/_constants/menuList.constants.ts (1)
MENU_LIST(2-7)
src/app/member/profile/layout.tsx (1)
src/app/member/profile/layout.css.ts (1)
button(11-17)
src/app/member/profile/_components/Profile/Profile.tsx (2)
src/app/member/profile/_components/Profile/index.ts (1)
Profile(1-1)src/app/member/_api/member.queries.ts (1)
memberQueryOptions(44-49)
⏰ 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: test
🔇 Additional comments (13)
src/app/member/profile/layout.css.ts (1)
19-21:semantic.icon.black컬러 토큰 존재 여부 확인 요청
토큰이 제거되거나 변경되면 빌드 타임에 오류가 나지 않습니다. 존재 여부를 한 번 더 확인하고, 없을 경우 공통 색상 토큰으로 교체해 주세요.src/app/member/profile/_components/Profile/index.ts (1)
1-1: 배럴(export) 패턴 적용 확인 완료
컴포넌트 재사용성을 높이는 적절한 패턴입니다.src/app/member/profile/_components/MenuList/index.ts (1)
1-1: 배럴(export) 패턴 적용 확인 완료src/app/member/profile/_components/Banner/index.ts (1)
1-1: 배럴(export) 패턴 적용 확인 완료src/app/member/profile/page.tsx (1)
8-14: 컴포넌트 구조가 잘 설계되었습니다
VStack을 사용한 레이아웃 구성과 컴포넌트 분리가 깔끔하게 구현되었습니다. 각 컴포넌트의 역할이 명확하게 분리되어 있어 유지보수성이 좋습니다.src/app/member/profile/layout.tsx (1)
29-33: 접근성 고려가 잘 되어있습니다
aria-label속성으로 스크린 리더 사용자를 위한 접근성이 잘 구현되었습니다.src/app/member/profile/_components/Profile/Profile.css.ts (1)
1-19: CSS 스타일링이 잘 구현되었습니다디자인 토큰을 활용한 일관된 스타일링과 vanilla-extract 사용이 적절합니다. 원형 아바타 배경 스타일링도 올바르게 구현되었습니다.
src/app/member/profile/_components/MenuList/MenuList.tsx (1)
13-27: 메뉴 리스트 구조가 잘 설계되었습니다시멘틱 HTML과 조건부 렌더링을 활용한 메뉴 구현이 깔끔합니다. 키 속성과 스타일 적용도 적절히 처리되었습니다.
src/app/member/profile/_components/Profile/Profile.tsx (1)
31-45: 데이터 렌더링이 안전하게 구현되었습니다옵셔널 체이닝을 사용하여 안전한 데이터 접근이 구현되었고, 컴포넌트 구조도 깔끔합니다.
src/app/member/profile/_components/MenuList/MenuList.css.ts (1)
9-11: 중첩 패딩 정의 여부 확인 필요
wrapper와list가 모두 상·하 패딩을 지정하고 있어 실제 트리 구조에서 중복 적용될 수 있습니다. 의도된 중첩인지 한쪽만 필요한지 한 번 더 점검해 주세요.src/app/member/profile/_components/Banner/Banner.css.ts (1)
16-18: 아이콘 색상 지정 방식 점검
SVG 아이콘이fill속성을 사용한다면color가 적용되지 않을 수 있습니다. 필요 시fill또는stroke토큰 사용을 검토해 주세요.src/app/member/profile/_components/Banner/Banner.tsx (2)
27-33: TODO 경로 미정 – 실서비스 노출 위험
href='/'는 홈으로 이동해 기능이 사라집니다. 릴리즈 전에 반드시 실제 등록 페이지로 교체하거나disabled처리해 주세요.
15-15:inline={20}단위 명확화
Bleed컴포넌트가 어떤 단위를 기대하는지 확인 필요합니다. 디자인 토큰 기반 spacing 값이면 변수로 치환해 주세요.
| {menu.label} | ||
| </button> | ||
| ) : ( | ||
| <Link href={menu.link!} className={styles.menuItem}> |
There was a problem hiding this comment.
🛠️ Refactor suggestion
안전한 타입 처리 개선
menu.link!에서 non-null assertion 연산자 사용은 런타임 오류를 발생시킬 수 있습니다. 타입 가드나 기본값 사용을 고려해보세요.
- <Link href={menu.link!} className={styles.menuItem}>
+ <Link href={menu.link || '/'} className={styles.menuItem}>또는 타입 정의에서 link 속성을 isLogout이 false일 때 필수로 만드는 방법도 있습니다.
🤖 Prompt for AI Agents
In src/app/member/profile/_components/MenuList/MenuList.tsx at line 21, avoid
using the non-null assertion operator on menu.link as it can cause runtime
errors. Instead, add a type guard to check if menu.link exists before using it
or provide a safe default value. Alternatively, adjust the type definitions so
that the link property is required only when isLogout is false, ensuring safer
type handling.
Seojunhwan
left a comment
There was a problem hiding this comment.
수빈님 고생하셨어요! 코멘트 조금 남겨뒀습니다!
There was a problem hiding this comment.
P3: 수빈님 요것 피그마 아이콘 이름을 그대로 따라가는 것은 어떨까요?! chevron-right 요런 거로?,,
There was a problem hiding this comment.
34deddc
오!! 좋은거 같습니다 ㅎㅎ 다른 아이콘들도 모두 피그마에 맞게 변경해두었어요!
There was a problem hiding this comment.
P3: useSuspenseQuery, suspense, error boundary로 loading, error 처리의 관심을 분리해보는 건 어떨까요?!
There was a problem hiding this comment.
deaed52
오.. 그렇게 분리하면 컴포넌트에서는 성공한 상태만 관리하면 되니 좋군요..!! 수정했습니다 ~ . ~👍🏻👍🏻
There was a problem hiding this comment.
한가지 궁금한 점이 있습니다 ~ . ~
닉네임과 전화번호만 필요한 데이터라 해당 부분만 스켈레톤 처리가 필요해서 ProfileLayout을 상위에 따로 생성하고 컴포넌트와 Skeleton을 따로 선언해서 사용했는데요!!
일부 데이터만 로딩 처리가 필요한 경우엔 보통 어떤 방식으로 처리하시나용?!
There was a problem hiding this comment.
수빈님 하신 것처럼 처리하기도 합니다!
최대한 먼저 보여줄 수 있는 부분은 보여주는 것이 경험에 더 좋아서, 적절히 영역을 나눠서 처리하면 좋아요~! ex) a 데이터 가져온 후 b 데이터 가져와서 a+b를 보여줄 때, a 데이터를 먼저 보여줘도 괜찮으면 그거 먼저 보여주고 b 로딩되면 b도 보여주고,,
이 질문이 맞으실까요?,,
There was a problem hiding this comment.
오 정확히 맞습니다~!~! Profile 전체를 처리할지, 아니면 필요한 부분만 레아이웃으로 분리해서 관리하는지 궁금해서 여쭤봤습니다 ㅎㅎ
감사해요!!🙇🏻♀️👍🏻
| {member?.nickname} | ||
| </Text> | ||
| <Text typo='caption1Md' color='neutral.50'> | ||
| {member?.email} |
There was a problem hiding this comment.
P3: isLoading,isError 처리를 하거나, useSuspenseQuery를 사용하면 data가 optional하지 않다고 판단할 수 있을 것 같아요!
There was a problem hiding this comment.
deaed52
여기도 수정했습니다!! 꼼꼼한 확인 매우 감사드립니돠 🙇🏻♀️
| {menu.label} | ||
| </button> | ||
| ) : ( | ||
| <Link href={menu.link!} className={styles.menuItem}> |
There was a problem hiding this comment.
P2: non-null assertion 대신 메뉴의 타입을 조금 명확하게 처리해보는 것은 어떨까요? union타입 사용하거나 다른 방법으로 개선해볼 수 있을 것 같아요!
| export const MENU_LIST = [ | ||
| { id: "notice", label: "공지사항", link: "/" }, | ||
| { id: "customer_service", label: "고객센터", link: "/" }, | ||
| { id: "guide", label: "잇다 이용가이드", link: "/" }, | ||
| { id: "logout", label: "로그아웃", isLogout: true }, | ||
| ]; |
There was a problem hiding this comment.
P2: 래빗 or 아래처럼 개선해보는 것은 어떨까요? 혹은 로그아웃만 따로 렌더링해도 괜찮아요~!
// 1. 메뉴 타입 정의
type LinkMenu = {
type: 'link';
id: string;
label: string;
link: string;
};
type ActionMenu = {
type: 'action';
id: string;
label: string;
onClick: () => void;
};
// 2. Union 타입으로 묶기
export type MenuListItem = LinkMenu | ActionMenu;
// 3. 메뉴 리스트 선언
export const MENU_LIST: readonly MenuListItem[] = [
{ type: 'link', id: 'notice', label: '공지사항', link: '/' },
{ type: 'link', id: 'customer_service', label: '고객센터', link: '/' },
{ type: 'link', id: 'guide', label: '잇다 이용가이드', link: '/' },
{
type: 'action',
id: 'logout',
label: '로그아웃',
onClick: () => {
// 로그아웃 로직
alert('로그아웃!');
},
},
] as const;There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/components/ui/AlertModal/AlertModal.tsx (1)
58-58: 트리거 요소 처리 방식을 개선할 수 있습니다.현재
trigger가 없으면AlertDialog.Trigger가 렌더링되지 않아 모달을 열 수 없습니다. 외부에서AlertDialog.Root의open상태를 제어할 수 있도록 하거나, 기본 트리거를 제공하는 것을 고려해보세요.다음과 같이
open과onOpenChangeprops를 추가하여 외부 상태 제어를 가능하게 할 수 있습니다:export type AlertModalProps = { + /** 모달의 열림/닫힘 상태 */ + open?: boolean; + /** 모달 상태 변경 핸들러 */ + onOpenChange?: (open: boolean) => void; /** 모달의 제목 */ title?: string; // ... 기존 props }; export const AlertModal = ({ + open, + onOpenChange, title, trigger, content, footer, }: AlertModalProps) => { return ( - <AlertDialog.Root> + <AlertDialog.Root open={open} onOpenChange={onOpenChange}> {trigger && <AlertDialog.Trigger asChild>{trigger}</AlertDialog.Trigger>} // ... 나머지 코드src/app/member/profile/page.tsx (1)
10-20: Suspense를 활용한 깔끔한 페이지 구조입니다.Profile 컴포넌트를 Suspense로 감싸고 ProfileSkeleton을 fallback으로 사용하는 구조가 적절합니다. 로딩 상태 처리가 잘 되어있습니다.
향후 에러 상태 처리를 위해 Error Boundary 추가를 고려해보세요:
<Suspense fallback={<ProfileSkeleton />}> <ErrorBoundary fallback={<ProfileError />}> <Profile /> </ErrorBoundary> </Suspense>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlsrc/assets/chevron-left.svgis excluded by!**/*.svgsrc/assets/chevron-right.svgis excluded by!**/*.svgsrc/assets/circle-close.svgis excluded by!**/*.svgsrc/assets/logo-wordmark.svgis excluded by!**/*.svg
📒 Files selected for processing (30)
package.json(1 hunks)src/app/(auth)/login/page.tsx(2 hunks)src/app/member/onboarding/_components/NicknameStep/NicknameStep.tsx(2 hunks)src/app/member/onboarding/_components/PhoneNumberStep/PhoneNumberStep.tsx(2 hunks)src/app/member/onboarding/layout.tsx(2 hunks)src/app/member/profile/_components/Banner/Banner.tsx(1 hunks)src/app/member/profile/_components/MenuList/MenuList.tsx(1 hunks)src/app/member/profile/_components/Profile/Profile.tsx(1 hunks)src/app/member/profile/_components/Profile/ProfileLayout.tsx(1 hunks)src/app/member/profile/_components/Profile/ProfileSkeleton.tsx(1 hunks)src/app/member/profile/_constants/index.ts(1 hunks)src/app/member/profile/_constants/menuList.constants.ts(1 hunks)src/app/member/profile/layout.tsx(1 hunks)src/app/member/profile/page.tsx(1 hunks)src/app/member/profile/types/index.ts(1 hunks)src/app/member/profile/types/menuList.types.ts(1 hunks)src/components/ui/AlertModal/AlertModal.css.ts(1 hunks)src/components/ui/AlertModal/AlertModal.stories.tsx(1 hunks)src/components/ui/AlertModal/AlertModal.tsx(1 hunks)src/components/ui/AlertModal/index.ts(1 hunks)src/components/ui/GNB/GNB.css.ts(2 hunks)src/components/ui/GNB/GNB.stories.tsx(6 hunks)src/components/ui/Skeleton/Skeleton.css.ts(1 hunks)src/components/ui/Skeleton/Skeleton.stories.tsx(1 hunks)src/components/ui/Skeleton/Skeleton.tsx(1 hunks)src/components/ui/Skeleton/index.ts(1 hunks)src/components/ui/TextButton/TextButton.stories.tsx(2 hunks)src/components/ui/TextField/TextField.stories.tsx(2 hunks)src/styles/reset.css.ts(1 hunks)src/styles/zIndex.css.ts(1 hunks)
✅ Files skipped from review due to trivial changes (22)
- src/components/ui/Skeleton/index.ts
- src/app/member/profile/types/index.ts
- src/app/(auth)/login/page.tsx
- src/app/member/profile/_constants/index.ts
- package.json
- src/components/ui/GNB/GNB.stories.tsx
- src/components/ui/TextButton/TextButton.stories.tsx
- src/components/ui/Skeleton/Skeleton.css.ts
- src/app/member/profile/_components/Profile/ProfileSkeleton.tsx
- src/components/ui/AlertModal/index.ts
- src/app/member/profile/_components/Profile/ProfileLayout.tsx
- src/components/ui/GNB/GNB.css.ts
- src/styles/zIndex.css.ts
- src/styles/reset.css.ts
- src/app/member/onboarding/_components/NicknameStep/NicknameStep.tsx
- src/components/ui/TextField/TextField.stories.tsx
- src/app/member/onboarding/_components/PhoneNumberStep/PhoneNumberStep.tsx
- src/app/member/profile/types/menuList.types.ts
- src/components/ui/Skeleton/Skeleton.stories.tsx
- src/components/ui/AlertModal/AlertModal.css.ts
- src/components/ui/AlertModal/AlertModal.stories.tsx
- src/app/member/onboarding/layout.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
- src/app/member/profile/_constants/menuList.constants.ts
- src/app/member/profile/layout.tsx
- src/app/member/profile/_components/MenuList/MenuList.tsx
- src/app/member/profile/_components/Banner/Banner.tsx
🧰 Additional context used
📓 Path-based instructions (2)
{src/app/**/_components/**/*.tsx,src/components/**/*.tsx}
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- .cursor/rules/nextjs-folder-structure.mdc
src/**/*.{ts,tsx}
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- .cursor/rules/nextjs-folder-structure.mdc
🧬 Code Graph Analysis (2)
src/app/member/profile/page.tsx (2)
src/app/member/profile/_components/Profile/ProfileSkeleton.tsx (1)
ProfileSkeleton(6-13)src/app/member/profile/_components/Profile/Profile.tsx (1)
Profile(10-23)
src/components/ui/Skeleton/Skeleton.tsx (1)
src/lib/utils/coerceCssRemValue.ts (1)
coerceCssRemValue(12-14)
⏰ 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). (2)
- GitHub Check: storybook-preview
- GitHub Check: test
🔇 Additional comments (6)
src/components/ui/AlertModal/AlertModal.tsx (4)
1-4: 임포트 구조가 깔끔하게 구성되어 있습니다.Radix UI와 React 타입, 그리고 스타일 파일을 논리적으로 그룹화하여 임포트했습니다. 명명 규칙도 적절합니다.
6-30: 타입 정의가 잘 구성되어 있습니다.각 props에 대한 한국어 JSDoc 주석이 명확하고, footer prop에 대한 사용 예시가 특히 도움이 됩니다. 모든 props가 optional로 설정되어 유연한 사용이 가능합니다.
32-49: JSDoc 예제가 매우 유용합니다.실제 사용 예시를 통해 컴포넌트 사용법을 명확히 보여주고 있습니다. 다만 예제의 Button 컴포넌트가 실제 프로젝트의 Button 컴포넌트와 일치하는지 확인이 필요할 수 있습니다.
50-75: 컴포넌트 구현이 올바르게 되어 있습니다.Radix UI AlertDialog의 패턴을 정확히 따르고 있으며, 조건부 렌더링도 적절합니다. 컴포넌트 구조가 논리적이고 접근성도 고려되어 있습니다.
src/components/ui/Skeleton/Skeleton.tsx (1)
1-44: 잘 구현된 재사용 가능한 Skeleton 컴포넌트입니다.TypeScript 타입 정의, JSDoc 문서화, vanilla-extract를 활용한 동적 스타일링이 모두 적절히 구현되어 있습니다.
coerceCssRemValue유틸리티를 통한 CSS 값 변환도 깔끔하게 처리되었습니다.src/app/member/profile/_components/Profile/Profile.tsx (1)
1-24: useSuspenseQuery를 올바르게 활용한 구현입니다.Suspense와 함께 사용되어 data가 optional하지 않다는 점이 잘 처리되었습니다. 이전 리뷰 코멘트에서 제기된 로딩/에러 처리에 대한 관심사 분리도 Suspense 패턴으로 적절히 해결되었습니다.
20127e5 to
deaed52
Compare
✅ 이슈 번호
close #43
🪄 작업 내용 (변경 사항)
/member/profile📸 스크린샷
💡 설명
Profile,Banner,MenuList3개의 컴포넌트로 분리하여 페이지를 구성했습니다.🗣️ 리뷰어에게 전달 사항
로그아웃은 다음 PR에서 진행할 예정입니다 ~ . ~!!
📍 트러블 슈팅
Summary by CodeRabbit
신규 기능
스타일
아이콘 및 UI 개선