Skip to content

[feat] 마이페이지 > 플레이리스트 추가 UI 구현#49

Merged
hansololiviakim merged 4 commits intodevelopfrom
feature/#40/playlist-add
Aug 17, 2025
Merged

[feat] 마이페이지 > 플레이리스트 추가 UI 구현#49
hansololiviakim merged 4 commits intodevelopfrom
feature/#40/playlist-add

Conversation

@hansololiviakim
Copy link
Member

@hansololiviakim hansololiviakim commented Aug 17, 2025

🛰️ 관련 이슈


✨ 주요 변경 사항

1️⃣ 마이페이지 > 플레이리스트 생성 UI 임시 구현
2️⃣ 플레이리스트 CD 커스텀 UI 임시 구현


🔍 테스트 방법 / 체크리스트

  • 없음

🗯️ PR 포인트

  • 플레이리스트 생성 플로우 기획/디자인 수정 중, CD 커스텀 페이지 디자인 그래픽 작업 중으로,
    프로토타입 제출용 임시 UI만 구현하였습니다.
    실제 배포용은 아니며, 세부 디자인, 기능은 다른 이슈에서 수정 및 추가 작업 예정입니다.
  • 따라서 @coderabbitai, @gemini-code-assist는 리뷰를 자세하게 하지 않아도 됩니다.

🚀 알게된 점

  • 추후 정리 예정

📖 참고 자료 (선택)

  • 없음

🖼️ Demo

ScreenRecording_08-17-2025.20-31-48_1.MP4

Summary by CodeRabbit

  • New Features

    • 테마 커스터마이즈 화면 추가(뒤로가기/저장, 탭·그리드, 반응형 CD 미리보기).
    • 플레이리스트 생성 화면 추가(장르 선택, 제목·링크 입력, 유효성 검사, 커스텀으로 이동 가능한 편집).
    • 마이페이지 플레이리스트 그리드의 “추가” 버튼으로 생성 화면으로 이동하도록 내비게이션 추가.
  • Style

    • 대형 버튼(L) 가로 폭 명시로 레이아웃 일관성 개선.
    • 신규 아이콘 추가로 UI 표현 강화(다운애로우·연필·핀·공유·휴지통·도움말·드래그 등).
  • Chores

    • 관련 라우트 연결 및 장르 목록(초기값) 구성 추가.

@hansololiviakim hansololiviakim self-assigned this Aug 17, 2025
@hansololiviakim hansololiviakim requested a review from maylh as a code owner August 17, 2025 11:30
@coderabbitai
Copy link

coderabbitai bot commented Aug 17, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

새 아이콘 8종을 아이콘 인덱스에 추가했고, 플레이리스트 생성 페이지(/mypage/create)와 테마 커스터마이즈 페이지(/customize)를 새로 추가하여 라우팅에 연결했습니다. 마이페이지 그리드의 추가 버튼은 생성 페이지로 네비게이트하도록 변경되었고, 플레이리스트 생성은 장르 선택, 제목/링크 입력, 저장 유효성 검사를 포함합니다.

Changes

Cohort / File(s) Summary
Icon exports
src/assets/icons/index.ts
8개 SVG 리액트 컴포넌트 재익스포트 추가: DownArrow, PencilPrimary, Pin, PinPrimary, Share, Trash, HelpCircle, Drag.
Customize page
src/pages/customize/index.tsx
테마 커스터마이즈 페이지 신규 추가(헤더, CD 베이스, 테마 탭/그리드, 반응형 스타일).
MyPage Create flow
src/pages/myPage/ui/create/index.tsx, src/pages/myPage/ui/components/PlaylistGrid.tsx
플레이리스트 생성 페이지 신규 추가(장르 BottomSheet, 제목/링크 입력, 저장 유효성, CD 편집 네비게이션 등). PlaylistGrid의 추가 버튼에 navigate('/mypage/create') 연결.
Routes
src/shared/config/routesConfig.ts
/customize/mypage/create 라우트에 lazy 로드 컴포넌트 연결 추가.
Music genres config
src/shared/config/musicGenres.ts
MUSIC_GENRES 상수 및 MusicGenreId/MusicGenreLabel/MusicGenre 타입 추가.
UI style tweak
src/shared/ui/Button.tsx
버튼 L 사이즈 스타일에 width: 100% 명시 추가(스타일 수정).

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant PG as PlaylistGrid
  participant R as Router
  participant C as Create Page

  U->>PG: "추가" 버튼 클릭
  PG->>R: navigate('/mypage/create')
  R-->>C: Create 페이지 렌더
  U->>C: 장르 선택 / 제목 입력 / 링크 입력
  U->>C: 저장 클릭 (유효성 통과)
  C->>R: navigate('/mypage')
  R-->>U: MyPage 렌더
Loading
sequenceDiagram
  participant U as User
  participant C as Create Page
  participant R as Router
  participant Z as Customize Page

  U->>C: CD 편집 버튼 클릭
  C->>R: navigate('/customize')
  R-->>Z: Customize 페이지 렌더
  U->>Z: 뒤로/저장 클릭
  Z->>R: navigate(-1)
  R-->>U: 이전 페이지 복귀
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
마이페이지 > 플레이리스트 추가 UI 구현 (#40)
마이페이지에서 추가 버튼으로 생성 페이지 라우팅 연결 (#40)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
커스터마이즈 페이지 신규 추가 (src/pages/customize/index.tsx) 이슈 #40는 마이페이지 플레이리스트 추가 UI가 목적이며 커스터마이즈 화면 구현은 명시된 목표에 포함되어 있지 않음.
커스터마이즈 라우트 추가 (src/shared/config/routesConfig.ts, route '/customize') 라우트 추가는 이슈 요구사항에 포함되지 않은 별도 페이지 등록임.
Button L 사이즈 스타일 변경 (src/shared/ui/Button.tsx) 전역 버튼 스타일 변경은 플레이리스트 추가 UI 요구사항과 직접적인 관련이 없음.
아이콘 재익스포트 추가 다수 (src/assets/icons/index.ts) 플레이리스트 생성에 필요한 아이콘 일부는 관련되나, 대량 추가는 이슈 범위를 초과할 가능성이 있음.

Possibly related PRs

Suggested reviewers

  • maylh

Poem

토끼가 깡충, 키보드 위를 뛰네 🐇
장르 꾹, 제목 쓱, 링크 톡 넣고
저장하면 /mypage 로 폴짝!
CD 빛나고 아이콘도 반짝 ✨
함께 코드를 쓱쓱, 행복한 배포 날개


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9e0c275 and 110a795.

📒 Files selected for processing (1)
  • src/pages/customize/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/customize/index.tsx
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/#40/playlist-add

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @hansololiviakim, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 마이페이지에 플레이리스트 추가 및 CD 커스텀 기능을 위한 임시 UI를 구현합니다. 사용자가 새로운 플레이리스트를 만들고, CD 디자인을 개인화할 수 있도록 기본적인 인터페이스를 제공하는 것이 목표입니다. 이는 향후 기능 확장을 위한 프로토타입 단계의 작업입니다.

Highlights

  • 플레이리스트 생성 UI 구현: 마이페이지 내에서 새로운 플레이리스트를 생성할 수 있는 임시 사용자 인터페이스가 구현되었습니다. 이 UI는 플레이리스트의 장르와 제목을 설정하고, 관련 링크를 추가할 수 있는 기능을 제공합니다.
  • CD 커스텀 UI 구현: 플레이리스트 생성 과정에서 CD의 외형을 커스터마이징할 수 있는 임시 UI가 추가되었습니다. 사용자는 다양한 테마를 선택하고 CD 디자인을 미리 볼 수 있습니다.
  • 새로운 SVG 아이콘 추가: 새로운 UI 요소들을 지원하기 위해 다양한 SVG 아이콘(예: 다운 화살표, 드래그, 도움말, 연필, 핀, 공유, 휴지통 등)이 프로젝트에 추가되었으며, 이들은 index.ts 파일을 통해 쉽게 접근할 수 있도록 내보내졌습니다.
  • 라우팅 설정 업데이트: 새로 구현된 플레이리스트 생성 및 CD 커스텀 페이지가 애플리케이션의 라우팅 설정에 통합되어, 해당 기능에 접근할 수 있는 경로가 활성화되었습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

마이페이지의 플레이리스트 추가 및 커스터마이징 UI 구현에 대한 PR을 리뷰했습니다. 전반적으로 임시 UI 구현이라는 점을 감안하더라도, 코드의 안정성과 유지보수성을 높일 수 있는 몇 가지 개선점을 발견했습니다.

주요 피드백 사항은 다음과 같습니다:

  • react-router-domnavigate 함수 사용법 오류 수정
  • 매직 넘버 및 매직 스트링을 테마 변수나 상수로 대체하여 코드 일관성 및 유지보수성 향상
  • useCallback을 사용한 불필요한 렌더링 방지
  • CSS의 불안정한 위치 지정 방식 개선

자세한 내용은 각 파일의 리뷰 코멘트를 참고해주세요.

Comment on lines +71 to +79
const ThemeContainer = styled.div`
margin: 0 -20px;
width: calc(100% + 40px);
flex: 1;
border-radius: 12px 12px 0 0;
background-color: ${({ theme }) => theme.COLOR['gray-700']};
overflow-y: auto;
padding: 20px;
`

Choose a reason for hiding this comment

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

medium

ThemeContainer를 포함한 여러 스타일 컴포넌트에서 20px, 40px와 같은 매직 넘버를 사용하고 있습니다. 스타일 가이드에 따라 일관성 있는 디자인 시스템을 유지하고 유지보수성을 높이기 위해 테마에 정의된 간격(spacing) 변수를 사용하는 것을 권장합니다.1 예를 들어, theme.SPACING.lg와 같이 사용할 수 있습니다.

Style Guide References

Footnotes

  1. 전역적인 스타일(색상, 폰트 크기, 간격 등)은 Styled Components의 테마 시스템을 통해 관리하고 일관성 있게 사용하도록 안내해주세요. 하드코딩된 값 대신 테마 변수 사용을 권장해주세요. (link)

Comment on lines +38 to +41
const onGenreClick = (genre: MusicGenre) => {
setMetaGenre(genre)
setIsBottomSheetOpen(false)
}

Choose a reason for hiding this comment

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

medium

onGenreClick 함수는 컴포넌트가 렌더링될 때마다 새로 생성됩니다. 이 함수는 BottomSheet 내부의 많은 EachGenre 컴포넌트에 전달되므로, 불필요한 리렌더링을 방지하기 위해 useCallback으로 감싸는 것이 좋습니다. 이는 스타일 가이드에서 권장하는 성능 최적화 방법입니다.1

  const onGenreClick = useCallback((genre: MusicGenre) => {
    setMetaGenre(genre)
    setIsBottomSheetOpen(false)
  }, [])

Style Guide References

Footnotes

  1. memo, useCallback, useMemo와 같은 React 최적화 기법이 적절하게 사용되었는지 확인하고, 불필요한 리렌더링을 줄일 수 있는 기회를 찾아 제안해주세요. (link)

@github-actions
Copy link

github-actions bot commented Aug 17, 2025

🎵 Storybook Link 🎵
🔗 https://689dbb45f8d09aea7832eeb1-uxhrbnbeql.chromatic.com/

@hansololiviakim hansololiviakim added the HIGH 빠르게 처리해야 하는 높은 우선순위 label Aug 17, 2025
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: 1

🧹 Nitpick comments (11)
src/shared/ui/Button.tsx (1)

29-38: L 사이즈: width: 100% + flex: 1 병행은 의도와 다르게 동작할 수 있음

flex: 1은 flex-basis: 0%를 내포해서 width/min/max 제어가 무시되거나 주변 요소까지 밀어낼 수 있습니다. L 사이즈에서 폭 제어를 width/min/max로 일관되게 가져가려면 flex를 끄는 쪽이 안전합니다.

Create/Customize 페이지 컨테이너에서 기대 레이아웃(한 줄 가득 채움, min/max 폭 유지)이 맞는지 한번 확인 부탁드립니다.

   L: css`
     min-width: ${BUTTON_STYLES.L.minWidth};
     width: ${BUTTON_STYLES.L.width};
     max-width: ${BUTTON_STYLES.L.maxWidth};
     padding: ${BUTTON_STYLES.L.padding};
     border-radius: ${BUTTON_STYLES.L.borderRadius};
     ${({ theme }) => theme.FONT['body1-normal']}
-    flex: 1;
+    /* flex-basis: 0을 유발하는 flex: 1 대신 명시적으로 고정 */
+    flex: 0 0 auto;
   `,
src/shared/config/musicGenres.ts (1)

1-1: TODO 코멘트 문구/형식 정돈 제안

가이드에 맞춰 TODO 형식을 통일하고, 맞춤법(아니여서 → 아니어서)을 보완하면 좋겠습니다.

-// TODO: 장르는 아직 확정 데이터 아니여서 임시로 넣어둠, 차주 변경 예정
+// TODO: 확정 장르 데이터로 교체 (차주 예정) - @hansololiviakim
src/pages/myPage/ui/components/PlaylistGrid.tsx (1)

30-35: 접근성: 추가 버튼에 aria-label 부여 권장

아이콘 버튼은 텍스트가 없어 스크린리더에서 목적이 모호합니다. aria-label을 추가해 주세요. 또한 CdBackground에서 & > button { width/height: 100% } 규칙이 있다면 SvgButton의 width/height 프롭이 버튼 박스 크기와 충돌할 수 있어 의도한 것이 맞는지도 확인 부탁드립니다.

           <SvgButton
             icon={Plus}
             width={40}
             height={40}
+            aria-label="플레이리스트 추가"
             onClick={() => navigate('/mypage/create')}
           />
src/shared/config/routesConfig.ts (1)

5-5: 경로 별칭 통일 권장 (@/ 사용으로 맞춤)

현재 파일 내에서 @/pages@pages가 혼용됩니다. 가이드에 맞춰 절대 경로 별칭을 통일하면 인지부하와 설정 이슈를 줄일 수 있습니다.

-const Customize = lazy(() => import('@pages/customize'))
+const Customize = lazy(() => import('@/pages/customize'))
 ...
-const Create = lazy(() => import('@pages/myPage/ui/create'))
+const Create = lazy(() => import('@/pages/myPage/ui/create'))

Also applies to: 7-7

src/pages/customize/index.tsx (3)

63-66: 모바일 사이즈 clamp의 중간값 개선 제안

현재 clamp의 중간값이 고정 px(300px)라 반응형 이점이 거의 없습니다. vw 기반 중간값으로 변경하면 다양한 모바일 폭에서 더 자연스러운 크기 조절이 됩니다.

적용 diff:

-  width: ${({ $deviceType }) =>
-    $deviceType === 'mobile' ? 'clamp(280px, 300px, 335px)' : '335px'};
-  height: ${({ $deviceType }) =>
-    $deviceType === 'mobile' ? 'clamp(280px, 300px, 335px)' : '335px'};
+  width: ${({ $deviceType }) =>
+    $deviceType === 'mobile' ? 'clamp(280px, 35vw, 335px)' : '335px'};
+  height: ${({ $deviceType }) =>
+    $deviceType === 'mobile' ? 'clamp(280px, 35vw, 335px)' : '335px'};

36-38: 접근성: “테마 추가” 버튼에 aria-label 추가

아이콘만 있는 버튼은 스크린 리더에서 의미를 알기 어렵습니다. aria-label을 추가해 주세요.

적용 diff:

-          <AddThemeButton>
+          <AddThemeButton aria-label="테마 추가">
             <span>+</span>
           </AddThemeButton>

100-104: 그리드 반응형 개선 제안

고정 4열은 작은 화면에서 아이템이 과도하게 작아질 수 있습니다. auto-fill/minmax로 보다 유연한 레이아웃을 고려해보세요.

적용 diff:

-  grid-template-columns: repeat(4, 1fr);
+  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
src/pages/myPage/ui/create/index.tsx (4)

34-36: 불리언이 아닌 값 반환으로 인한 가독성/타입 안전성 저하

isValidate가 string | undefined를 반환할 수 있어 의도 파악이 어렵습니다. 명확히 boolean을 반환하도록 개선해 주세요. trim으로 공백 입력도 방지하면 UX가 좋아집니다.

적용 diff:

-  const isValidate = () => {
-    return metaGenre?.id && metaTitle && link
-  }
+  const isValidate = (): boolean => {
+    return Boolean(metaGenre?.id && metaTitle.trim() && link.trim())
+  }

74-81: 입력 컨트롤을 비제어에서 제어 컴포넌트로 전환 권장

defaultValue를 쓰면 상태(metaTitle)와 DOM 값이 분리될 수 있습니다. value를 사용한 제어 컴포넌트로 통일하면 예측 가능성이 높아집니다.

적용 diff:

-            <Input
-              type="text"
-              placeholder="플레이리스트명"
-              defaultValue={metaTitle ?? ''}
-              maxLength={24}
-              onChange={(e) => setMetaTitle(e.target.value)}
-            />
+            <Input
+              type="text"
+              placeholder="플레이리스트명"
+              value={metaTitle}
+              maxLength={24}
+              onChange={(e) => setMetaTitle(e.target.value)}
+            />

124-128: URL 입력도 제어 컴포넌트로 통일

link 입력 역시 value를 지정해 상태와 동기화해 주세요.

적용 diff:

-            <Input
-              type="url"
-              placeholder="링크를 입력해주세요"
-              onChange={(e) => setLink(e.target.value)}
-            />
+            <Input
+              type="url"
+              placeholder="링크를 입력해주세요"
+              value={link}
+              onChange={(e) => setLink(e.target.value)}
+            />

176-187: CD 배경 컨테이너 사이즈 명시 및 불필요 자식 선택자 정리

CdBackground에 width/height가 없어 부모(124px)에 맞게 확실히 채우지 못할 수 있습니다. 또한 & > button 규칙은 현 구조에서 불필요할 가능성이 큽니다.

적용 diff:

 const CdBackground = styled.div`
   position: relative;
   ${flexRowCenter}
   margin-bottom: 10px;
-
-  border-radius: 10px;
-  background-color: ${({ theme }) => theme.COLOR['gray-600']};
-
-  & > button {
-    width: 100%;
-    height: 100%;
-  }
+  width: 100%;
+  height: 100%;
+  border-radius: 10px;
+  background-color: ${({ theme }) => theme.COLOR['gray-600']};
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 658a965 and 9e0c275.

⛔ Files ignored due to path filters (8)
  • src/assets/icons/icn_down_arrow.svg is excluded by !**/*.svg
  • src/assets/icons/icn_drag.svg is excluded by !**/*.svg
  • src/assets/icons/icn_help_circle.svg is excluded by !**/*.svg
  • src/assets/icons/icn_pencil_primary.svg is excluded by !**/*.svg
  • src/assets/icons/icn_pin.svg is excluded by !**/*.svg
  • src/assets/icons/icn_pin_primary.svg is excluded by !**/*.svg
  • src/assets/icons/icn_share.svg is excluded by !**/*.svg
  • src/assets/icons/icn_trash.svg is excluded by !**/*.svg
📒 Files selected for processing (7)
  • src/assets/icons/index.ts (1 hunks)
  • src/pages/customize/index.tsx (1 hunks)
  • src/pages/myPage/ui/components/PlaylistGrid.tsx (2 hunks)
  • src/pages/myPage/ui/create/index.tsx (1 hunks)
  • src/shared/config/musicGenres.ts (1 hunks)
  • src/shared/config/routesConfig.ts (2 hunks)
  • src/shared/ui/Button.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit Configuration File

**/*.{ts,tsx,js,jsx}: ## 1. 일반적인 코딩 컨벤션

포맷팅

  • .prettierrc 설정에 따라 포맷팅 확인
  • 들여쓰기: 2칸 스페이스
  • 최대 줄 길이: 100자
  • 세미콜론 사용 안함
  • 따옴표: 작은따옴표 사용
  • 괄호 안 공백: 있음
  • 화살표 함수 괄호: 항상 사용
  • 줄바꿈: LF 사용

네이밍 컨벤션

  • 컴포넌트: PascalCase (예: UserProfile)
  • 유틸리티/훅/변수: camelCase (예: getUserData, useUserInfo)
  • 상수: UPPER_SNAKE_CASE (예: API_BASE_URL)
  • 이미지 파일: kebab-case (예: user-profile-icon.png)

주석 사용

  • 복잡한 로직에만 주석 추가
  • 불필요한 주석 지양 (코드로 설명 가능한 것)
  • TODO/FIXME 형식: // TODO: 설명 - 작성자

가독성

  • 매직 넘버 지양, 의미있는 상수 사용
  • 함수는 하나의 책임만 가지도록 작성 (최대 20줄 권장)
  • 중첩 깊이 최소화 (3단계 이하 권장)

2. React 모범 사례

컴포넌트 작성

  • 최신 React hooks 사용 권장
  • 컴포넌트는 단일 책임 원칙 준수
  • Presentational/Container 컴포넌트 분리
  • 성능 최적화: memo, useCallback, useMemo 적절히 사용
  • 대용량 리스트는 가상화 라이브러리 사용 고려

상태 관리

  • Zustand와 Tanstack Query를 일관되게 사용
  • 상태 구조는 정규화된 형태로 관리
  • 에러 처리: Error Boundary와 try-catch 또는 onError 콜백 활용

3. 스타일링

Styled Components

  • Styled Components 일관되게 사용
  • 스타일드 컴포넌트명은 의미있게 작성
  • 동적 스타일링은 props나 CSS 변수 활용
  • 테마 시스템 활용하여 글로벌 스타일 관리
  • 재사용 가능한 스타일은 mixin이나 확장으로 관리
  • CSS 포맷팅 가독성 유지
  • 사용하지 않는 스타일이나 중복 스타일 제거

4. Vite 및 빌드 최적화

  • 모듈 import 최적화 (tree-shaking 고려)
  • 환경변수는 .env 파일로 관리
  • vite.config.ts에서 빌드 성능 튜닝 (sourcemap 설정, 플러그인 최적화 등)

5. 아키텍처 및 개발 환경

폴더 구조

  • Feature-Sliced Design (FSD) 구조 준수
  • 레이어별 참조 규칙 엄격히 적용

타입스크립트

  • strict 모드 사용
  • 타입 명시적으로 작성 (any 사용 지양)
  • path alias (@/_) 절대 경로 import 사용

Git 훅

  • Husky 설정으로 pre-commit, commit-msg 린팅 확인

6. 기타 가이드라인

  • 충분한 근거와 함께 리뷰 제공
  • 정보 검증 후 답변
  • 간결하고 명확한 응답
  • 필요시 추가 컨텍스트 요청
  • 검증되지 않은 주장 지양
  • 가능한 경우 출처 명시
  • 별도 언급 없으면 JavaScript 기준
  • 한국어로 응답
  • 대부분 브라우저에서 지원하는 ES6+ 기능 활용
  • 코드 리뷰를 통한 유지보수성 향상에 적극 활용

Files:

  • src/assets/icons/index.ts
  • src/shared/ui/Button.tsx
  • src/shared/config/routesConfig.ts
  • src/pages/customize/index.tsx
  • src/pages/myPage/ui/components/PlaylistGrid.tsx
  • src/pages/myPage/ui/create/index.tsx
  • src/shared/config/musicGenres.ts
🧬 Code Graph Analysis (1)
src/pages/customize/index.tsx (2)
src/shared/hooks/useDevice.ts (2)
  • useDevice (14-17)
  • DeviceType (3-3)
src/shared/styles/theme.ts (1)
  • theme (3-116)
⏰ 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: Run Chromatic
🔇 Additional comments (7)
src/shared/config/musicGenres.ts (1)

14-17: 타입 추출 방식 적절합니다

리터럴 좁은 타입에서 파생 타입을 추출하는 패턴이 깔끔하고 재사용성도 좋습니다. 이후 API 연동 시에도 변경 범위를 최소화할 수 있겠습니다.

src/pages/myPage/ui/components/PlaylistGrid.tsx (1)

23-23: 추가 버튼 네비게이션 연결 깔끔합니다

SvgButton → /mypage/create 라우팅 연결이 명확하고 의도가 분명합니다. 라우트도 routesConfig에 추가되어 일관됩니다.

Also applies to: 30-35

src/shared/config/routesConfig.ts (1)

37-37: Create 페이지의 nav 노출 정책 확인 요청

Customize는 hideNav: true로 설정되어 있으나 Create는 기본값(노출)입니다. 프로토타입 기준 의도된 UX인지 확인 부탁드립니다. 필요 시 hideNav: true를 추가해 주세요.

Also applies to: 43-43

src/assets/icons/index.ts (2)

15-26: 아이콘 export 패턴 일관성 좋습니다

기존 방식과 동일한 네이밍/패턴으로 신규 아이콘이 추가되어 사용처에서도 혼란이 없겠습니다.


15-26: SVG 자산 및 export 검증 완료
추가된 모든 SVG 파일이 src/assets/icons에 존재하며, index.ts에도 정상적으로 export되어 있습니다. 추가 조치가 필요하지 않습니다.

src/pages/customize/index.tsx (1)

71-79: 토큰/스타일 사용 일관성과 구조는 좋습니다

ThemeContainer 영역의 토큰 활용과 스크롤/라운딩 처리 등이 일관적이며, 프로토타입 목적에 적합합니다.

src/pages/myPage/ui/create/index.tsx (1)

100-116: 도움말 Popover 전환 처리 깔끔합니다

AnimatePresence와 motion을 통한 진입/퇴장 애니메이션 처리가 간결하고 의도에 부합합니다.

Copy link
Collaborator

@maylh maylh left a comment

Choose a reason for hiding this comment

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

수고하셨습니다 ^_^ 다음주는 더 화이팅해보아요 ... 💪🏻💪🏻💪🏻💪🏻

<SvgButton icon={Share} width={20} height={20} />
</LeftActions>
<RightAction type="button">
<Pin />
Copy link
Collaborator

Choose a reason for hiding this comment

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

나중에 대표 플리 설정 여부에 따라 아이콘 바꿔줄 때

<Pin fill={theme.COLOR['primary-normal']} />

로 컬러 입혀주면 Pin, PinPrimary 둘 다 import 하지 않아도 될 것 같습니다 ! (이 경우 icn_pin.svg의 fill 속성 삭제 필요)

@hansololiviakim hansololiviakim merged commit 6f4d71b into develop Aug 17, 2025
5 checks passed
@hansololiviakim
Copy link
Member Author

📢 Resolve 되지 않은 리뷰들은 타 이슈에서 진행 예정입니다! 📢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

HIGH 빠르게 처리해야 하는 높은 우선순위

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 마이페이지 > 플레이리스트 추가 UI 구현

2 participants