Skip to content

[fix] 모바일 나의CD 볼륨 버튼 렌더링 및 기타 QA 수정#139

Merged
maylh merged 6 commits intodevelopfrom
fix/#135/mo-unmute
Nov 7, 2025
Merged

[fix] 모바일 나의CD 볼륨 버튼 렌더링 및 기타 QA 수정#139
maylh merged 6 commits intodevelopfrom
fix/#135/mo-unmute

Conversation

@maylh
Copy link
Collaborator

@maylh maylh commented Nov 7, 2025

🛰️ 관련 이슈


✨ 주요 변경 사항

  • 모바일 나의CD 볼륨 버튼 렌더링
  • MO 무한스크롤 안되는 이슈 수정
  • play pause 렌더링 시간 수정
  • 탭 전환 시 아이템 초기화 안 되는 이슈 수정

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

  • 없음

🗯️ PR 포인트


🚀 알게된 점


📖 참고 자료 (선택)

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 모바일 동영상 재생 시 노출되는 볼륨 버튼 추가
    • 재생/일시정지 상태에 따라 플레이 버튼 아이콘이 동적으로 변경
    • 외부에서 음소거 상태를 읽고 변경할 수 있는 컨트롤 노출
  • 개선 사항

    • 캐러셀 탐색 시 다음 페이지를 더 일찍 사전 로드하도록 조정
    • 코치마크 오버레이가 컨테이너 여백을 넘어 전체 너비를 덮도록 확장
    • 플레이 버튼 숨김 딜레이를 재생 상태에 따라 조정하여 표시 동작 개선

@maylh maylh self-assigned this Nov 7, 2025
@maylh maylh added the HIGH 빠르게 처리해야 하는 높은 우선순위 label Nov 7, 2025
@maylh maylh added this to the 1차 스프린트 QA milestone Nov 7, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 7, 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

PlayerProvider가 내부의 자동 unmute 추적을 제거하고 isMuted/setIsMuted를 컨텍스트로 노출합니다. MyCdLayout은 모바일에서 음소거 상태를 캡처해 VolumeButton을 조건부 렌더링하며, 플레이어 UI/네비게이션(Discover, PlayButton, PlaylistLayout 등)에 소소한 동작·스타일 변경이 적용됩니다.

Changes

Cohort / File(s) 요약
플레이어 컨텍스트
src/app/providers/PlayerProvider.tsx
hasUnmutedOnceRef 제거, isMutedsetIsMuted를 컨텍스트 값으로 추가; unmuteOnce는 더 이상 추적 플래그를 수정하지 않고 단순히 unMute()와 playVideo()만 호출
모바일 플레이어 UI
src/pages/mycd/MyCdLayout.tsx
useDevice() 사용으로 모바일 감지, 모바일 전용 isMuted 상태 캡처, YoutubePlayer onReady에서 mute 상태 읽기, 비디오 로드 시 모바일에서 VolumeButton 조건부 렌더
플레이리스트 컨트롤
src/widgets/playlist/PlayButton.tsx, src/widgets/playlist/PlaylistLayout.tsx
PlayButtonisPlaying prop 추가(아이콘 토글), PlaylistLayout에서 클릭 후 숨김 지연을 isPlaying에 따라 동적 duration으로 설정
디스커버 페이징/네비게이션
src/pages/discover/index.tsx, src/pages/mycd/index.tsx
discover: 캐러셀에서 fetchNextPage 트리거를 length - 2로 조정(조기 페이징); mycd: 탭 선택 시 centerItem을 초기화해 경로 생성에 영향
UI 스타일 조정
src/pages/discover/ui/DiscoverCoachMark.tsx
오버레이 너비를 calc(100% + 40px)로 확장하고 margin: 0 -20px 적용해 풀블리드 커버리지 확보

Sequence Diagram(s)

sequenceDiagram
  participant User as 사용자
  participant UI as VolumeButton / Controls
  participant Context as PlayerProvider (context)
  participant Player as YoutubePlayer

  rect rgb(235,245,255)
  Note right of UI: 모바일에서 VolumeButton 클릭
  User->>UI: 클릭 (unmute 요청)
  UI->>Context: setIsMuted(false) / unmuteOnce()
  end

  rect rgb(245,255,235)
  Context->>Player: unMute()
  Context->>Player: playVideo()
  Player-->>Context: 상태 변경 이벤트 (isPlaying/isMuted)
  Context-->>UI: 컨텍스트 값(isMuted, isPlaying) 업데이트 (구성요소가 반응)
  Note right of Context: unmuteOnce는 플래그를 영구 변경하지 않음
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • 주의 깊게 검토할 파일/부분:
    • src/app/providers/PlayerProvider.tsx — 컨텍스트 표면 변경과 unmuteOnce 동작(부작용 및 동시성)
    • src/pages/mycd/MyCdLayout.tsx — 모바일에서 YoutubePlayer API 사용(호환성/비동기 타이밍)
    • src/widgets/playlist/PlaylistLayout.tsx — 동적 setTimeout 타이밍과 UI 플리커 가능성
    • src/pages/discover/index.tsx — 조기 페이징 변경이 페이징 로직에 미치는 영향

Possibly related PRs

Suggested reviewers

  • hansololiviakim

Poem

🐇 풀브라이트 토끼가 말하길:
음소거 풀고 노래 틀렸더니,
모바일에서도 소리 남았네 🎶
작은 버튼 하나, 큰 웃음 하나,
토끼가 깡충—플레이어는 반짝 ✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 모바일 나의CD 볼륨 버튼 렌더링 및 기타 QA 수정을 다루며, 변경 사항의 주요 내용을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 관련 이슈를 명시하고 4가지 주요 변경 사항을 나열하고 있으며, 템플릿의 필수 섹션들을 대부분 포함하고 있습니다.
Linked Issues check ✅ Passed PR의 변경 사항들이 #135의 모바일 unmute 유지 문제를 해결하는 코드 변경을 포함하고 있으며, PlayerProvider와 MyCdLayout의 수정이 이를 구현하고 있습니다.
Out of Scope Changes check ✅ Passed 무한스크롤 수정(discover/index.tsx), play/pause 렌더링 시간 수정(PlayButton, PlaylistLayout), 탭 전환 초기화(mycd/index.tsx), UI 레이아웃 조정(DiscoverCoachMark) 등이 포함되어 있으며 이들은 모두 명시된 주요 변경 사항에 해당합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/#135/mo-unmute

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.

@gemini-code-assist
Copy link

Summary of Changes

Hello @maylh, 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은 모바일 환경에서의 사용자 경험을 개선하고 여러 QA 이슈를 해결하는 데 중점을 둡니다. 주요 변경 사항으로는 모바일 나의CD 페이지에서 볼륨 버튼 렌더링 문제를 해결하고, 모바일 무한 스크롤 오류를 수정하며, 플레이어의 재생/일시정지 UI 렌더링 시간을 조정하고, 탭 전환 시 아이템 초기화 문제를 개선하는 내용이 포함됩니다.

Highlights

  • 모바일 나의CD 볼륨 버튼 렌더링: 모바일 환경에서 나의CD 페이지에 볼륨 버튼이 올바르게 렌더링되도록 수정했습니다.
  • MO 무한스크롤 이슈 수정: 모바일 환경에서 무한 스크롤이 제대로 작동하지 않던 문제를 해결했습니다.
  • 플레이/일시정지 렌더링 시간 수정: 플레이어의 재생 및 일시정지 UI 렌더링 시간을 조정하여 사용자 경험을 개선했습니다.
  • 탭 전환 시 아이템 초기화 이슈 수정: 탭을 전환할 때 이전 탭의 아이템 정보가 초기화되지 않던 문제를 해결했습니다.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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.

@github-actions
Copy link

github-actions bot commented Nov 7, 2025

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

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

이번 PR은 모바일 환경에서의 CD 볼륨 버튼 렌더링 문제를 해결하고, 무한 스크롤, 재생/일시정지 UI, 탭 전환 로직 등 여러 QA 사항을 수정한 것으로 보입니다. 전반적으로 플레이어의 상태 관리와 사용자 경험을 개선하는 좋은 변경이라고 생각합니다. 다만, 코드에 남아있는 디버깅용 console.logz-index 매직 넘버 사용에 대한 의견을 몇 가지 댓글로 남겼으니 확인 부탁드립니다.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/pages/mycd/index.tsx (1)

85-94: 탭 전환 시 플레이리스트 ID가 유실되는 버그

87번 라인에서 centerItem을 초기화한 직후 89번 라인에서 centerItem.playlistId를 사용하고 있습니다. 이로 인해 basePath는 항상 /mycd가 되어 플레이리스트 ID가 경로에 포함되지 않습니다.

다음과 같이 수정하여 현재 플레이리스트 ID를 보존하세요:

 const handleTabSelect = (tab: MyCdTab) => {
+  const currentPlaylistId = centerItem.playlistId
   setSelectedTab(tab)
   setCenterItem({ playlistId: null, playlistName: '' })
 
-  const basePath = centerItem.playlistId ? `/mycd/${centerItem.playlistId}` : '/mycd'
+  const basePath = currentPlaylistId ? `/mycd/${currentPlaylistId}` : '/mycd'
 
   const path = tab === 'LIKE' ? `${basePath}?type=LIKE` : basePath
 
   navigate(path, { replace: true })
 }
src/app/providers/PlayerProvider.tsx (2)

5-24: 타입 정의에 isMuted와 setIsMuted 추가 필요

129-130번 라인에서 컨텍스트 value에 isMutedsetIsMuted를 추가했지만, PlaylistContextType 타입 정의에는 포함되지 않았습니다. 이는 타입 안전성을 해치며 컨슈머에서 타입 에러가 발생합니다.

타입 정의를 다음과 같이 업데이트하세요:

 type PlaylistContextType = {
   currentPlaylist: PlaylistInfo | null
   currentTrackIndex: number
   currentTime: number
   isPlaying: boolean
+  isMuted: boolean
+  setIsMuted: (value: boolean) => void
   setPlaylist: (
     playlist: PlaylistInfo,
     trackIndex?: number,
     time?: number,
     autoPlay?: boolean
   ) => void
   play: () => void
   pause: () => void
   nextTrack: () => void
   prevTrack: () => void
   updateCurrentTime: (time: number) => void
   playerRef: React.MutableRefObject<YT.Player | null>
   handlePlayerStateChange: (event: YT.OnStateChangeEvent) => void
   unmuteOnce: () => void
 }

80-88: 불필요한 의존성 제거 필요

nextTrack 함수의 의존성 배열(88번 라인)에 isMuted가 포함되어 있지만, 함수 본문에서는 사용되지 않습니다. 이는 불필요한 재생성을 유발합니다.

다음과 같이 의존성 배열을 수정하세요:

-  }, [currentPlaylist, currentTrackIndex, isMuted])
+  }, [currentPlaylist, currentTrackIndex])
src/pages/mycd/MyCdLayout.tsx (1)

19-30: 컨텍스트의 isMuted 상태를 사용해야 함

PlayerProvider에서 isMutedsetIsMuted를 컨텍스트로 노출하고 있지만, 여기서는 로컬 상태를 사용하고 있습니다. 이는 전역 음소거 상태 관리를 깨뜨리며, 컴포넌트 간 상태 동기화가 되지 않습니다.

다음과 같이 컨텍스트 상태를 사용하도록 수정하세요:

 const Content = () => {
   const {
     playerRef,
     currentPlaylist,
     currentTrackIndex,
     currentTime,
     isPlaying,
     handlePlayerStateChange,
+    isMuted,
+    setIsMuted,
   } = usePlaylist()
-  const [isMuted, setIsMuted] = useState<boolean | null>(null)
   const deviceType = useDevice()
   const isMobile = deviceType === 'mobile'
🧹 Nitpick comments (1)
src/pages/mycd/MyCdLayout.tsx (1)

66-70: z-index 리팩토링 TODO 추적

TODO 코멘트에서 언급한 대로 매직 넘버 999를 theme의 z-index 상수로 대체해야 합니다.

이 작업을 위한 별도 이슈를 생성하여 추적하시겠습니까?

📜 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 468b61e and 90082d3.

📒 Files selected for processing (7)
  • src/app/providers/PlayerProvider.tsx (1 hunks)
  • src/pages/discover/index.tsx (1 hunks)
  • src/pages/discover/ui/DiscoverCoachMark.tsx (1 hunks)
  • src/pages/mycd/MyCdLayout.tsx (3 hunks)
  • src/pages/mycd/index.tsx (1 hunks)
  • src/widgets/playlist/PlayButton.tsx (1 hunks)
  • src/widgets/playlist/PlaylistLayout.tsx (2 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/pages/discover/ui/DiscoverCoachMark.tsx
  • src/pages/discover/index.tsx
  • src/widgets/playlist/PlaylistLayout.tsx
  • src/app/providers/PlayerProvider.tsx
  • src/pages/mycd/MyCdLayout.tsx
  • src/widgets/playlist/PlayButton.tsx
  • src/pages/mycd/index.tsx
🧠 Learnings (1)
📚 Learning: 2025-08-20T05:59:48.729Z
Learnt from: maylh
Repo: dnd-side-project/dnd-13th-8-frontend PR: 55
File: src/widgets/playlist/BackgroundPlayer.tsx:55-83
Timestamp: 2025-08-20T05:59:48.729Z
Learning: BackgroundPlayer 컴포넌트에서 네비게이션 후 컨트롤 버튼이 작동하지 않는 버그는 주로 다음 원인들로 발생한다: 1) DOM ID 충돌 (고정값 'yt-player' 사용), 2) window.YT가 이미 존재할 때 새 플레이어를 생성하지 않음, 3) onStateChange 의존성으로 인한 useEffect 재실행과 전역 콜백 덮어쓰기, 4) 리마운트 시 ref 상태 불일치. 해결책으로는 고유 DOM ID 생성, initPlayer 함수 분리를 통한 즉시 초기화, 콜백 ref 사용으로 의존성 최소화, 플레이리스트 변경 시 상태 초기화 등이 필요하다.

Applied to files:

  • src/app/providers/PlayerProvider.tsx
  • src/pages/mycd/MyCdLayout.tsx
🧬 Code graph analysis (1)
src/pages/mycd/MyCdLayout.tsx (1)
src/shared/lib/useDevice.ts (1)
  • useDevice (14-17)
🔇 Additional comments (5)
src/pages/mycd/MyCdLayout.tsx (1)

56-60: 첫 번째 트랙에서 볼륨 버튼을 숨기는 이유 확인 필요

볼륨 버튼이 currentTrackIndex !== 0 조건으로 첫 번째 트랙에서는 렌더링되지 않습니다. 이 비즈니스 로직이 의도된 것인지, 첫 번째 트랙에서도 사용자가 음소거를 해제할 수 있어야 하는지 확인이 필요합니다.

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

114-126: 무한 스크롤 프리페칭 개선 확인

페이지네이션 트리거를 마지막 아이템 대신 마지막에서 두 번째 아이템에서 발동하도록 변경했습니다. 이는 사용자가 끝에 도달하기 전에 다음 페이지를 미리 로드하여 UX를 개선하는 좋은 접근입니다.

src/widgets/playlist/PlaylistLayout.tsx (1)

75-77: 재생 상태 기반 UI 개선 확인

PlayButtonisPlaying prop을 전달하여 재생/일시정지 아이콘을 동적으로 표시하고, 상태에 따라 버튼 표시 시간을 다르게 설정한 것은 좋은 UX 개선입니다.

src/widgets/playlist/PlayButton.tsx (1)

1-20: 재생 상태 기반 아이콘 전환 구현 확인

isPlaying prop을 추가하여 재생/일시정지 아이콘을 동적으로 전환하는 구현이 깔끔하고 타입 안전하게 되어 있습니다.

src/pages/discover/ui/DiscoverCoachMark.tsx (1)

43-44: 리뷰 코멘트가 잘못된 우려를 제시합니다

DiscoverCoachMark의 오버레이 확장은 올바르게 구현되었습니다:

  • Page 컴포넌트: position: relative 설정으로 Overlay의 절대 위치 기준점이 명확
  • 네거티브 마진 기법: width: calc(100% + 40px) + margin: 0 -20px는 의도대로 각 측면을 20px 확장
  • overflow 설정이 없는 것은 의도된 설계: 오버레이가 정상적으로 확장되도록 필요한 구조

원본 리뷰의 "overflow: hidden이 없으면 수평 스크롤 발생"이라는 우려는 부정확합니다. Page의 width: 100%는 뷰포트 기준이므로 레이아웃 제약 내에서 작동하며, 실제 수평 스크롤 문제가 없습니다.

Likely an incorrect or invalid review comment.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/widgets/playlist/PlaylistLayout.tsx (1)

90-90: ActionBar type prop 하드코딩 문제 확인됨

검증 결과, ActionBar 컴포넌트는 'MY' | 'DISCOVER' 타입을 기대하지만, PlaylistLayout'My' | 'Discover' 타입을 받고 있습니다. 문제는 type prop의 값이 무시되고 항상 "DISCOVER"가 하드코딩되어 있다는 점입니다.

type='My'로 렌더링될 때도 ActionBar'DISCOVER' 타입으로 동작하여 잘못된 네비게이션 또는 스타일 처리가 발생할 수 있습니다.

다음과 같이 수정해야 합니다:

  <ActionBar
    playlistId={data.playlistId}
    creatorId={data.creator.creatorId}
    stickers={data?.cdResponse?.cdItems ?? data?.cdItems ?? []}
-   type="DISCOVER"
+   type={type.toUpperCase() as 'MY' | 'DISCOVER'}
  />
🧹 Nitpick comments (1)
src/widgets/playlist/PlaylistLayout.tsx (1)

24-25: 사용하지 않는 props 정리 고려

isMutedsetIsMuted props가 인터페이스에 정의되어 있지만 컴포넌트 내에서 사용되지 않습니다.

이 props들이 향후 사용 예정이거나 다른 컴포넌트 변형에서 필요한 경우가 아니라면, 인터페이스에서 제거하여 API를 명확히 하는 것을 고려해보세요.

📜 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 90082d3 and 3053065.

📒 Files selected for processing (1)
  • src/widgets/playlist/PlaylistLayout.tsx (2 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/widgets/playlist/PlaylistLayout.tsx
🔇 Additional comments (2)
src/widgets/playlist/PlaylistLayout.tsx (2)

56-57: console.log 제거 확인 및 duration 로직 검증 필요

이전 리뷰에서 요청된 console.log 제거가 반영되었습니다.

다만 duration 로직을 검증해주세요. 현재 구현에서는:

  • 재생 중 클릭 → isPlaying=true → 1000ms 동안 버튼 표시
  • 일시정지 중 클릭 → isPlaying=false → 2000ms 동안 버튼 표시

onPlayPause()가 먼저 호출되지만 React 상태 업데이트는 비동기이므로, isPlaying은 클릭 시점의 이전 상태를 반영합니다. 결과적으로 재생 버튼이 일시정지 버튼보다 2배 더 오래 표시됩니다. 이것이 의도된 UX인지 확인이 필요합니다.

더 명확한 의도 전달을 위해 변수명을 개선하거나 주석을 추가하는 것을 고려해보세요:

  const handleOverlayClick = () => {
    onPlayPause()
    setShowPlayButton(true)
-   const duration = isPlaying ? 1000 : 2000
+   // 재생 시작 시 2초, 일시정지 시 1초 동안 피드백 표시
+   const duration = isPlaying ? 1000 : 2000
    setTimeout(() => setShowPlayButton(false), duration)
  }

74-76: PlayButton에 isPlaying prop 전달 확인

PlayButton 컴포넌트에 isPlaying prop을 전달하여 재생/일시정지 상태에 따라 올바른 아이콘을 표시하도록 개선되었습니다. 관련 PR 변경사항과 일치합니다.

Copy link
Member

@hansololiviakim hansololiviakim left a comment

Choose a reason for hiding this comment

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

. ┌○┐
  │ 짱|ハ,,ハ
  │ 이|゚ω゚ )
  │ 다 | //
 └○┘ (⌒)
    し⌒

@maylh maylh merged commit fce3f87 into develop Nov 7, 2025
4 checks passed
@hansololiviakim hansololiviakim deleted the fix/#135/mo-unmute branch November 7, 2025 13:02
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.

[fix] 모바일 unmute 유지 안되는 문제 해결

2 participants