Skip to content

[fix] 모바일 QA 반영#130

Merged
maylh merged 21 commits intodevelopfrom
fix/#129/1sp-qa-mobile
Oct 31, 2025
Merged

[fix] 모바일 QA 반영#130
maylh merged 21 commits intodevelopfrom
fix/#129/1sp-qa-mobile

Conversation

@maylh
Copy link
Collaborator

@maylh maylh commented Oct 30, 2025

🛰️ 관련 이슈


✨ 주요 변경 사항

1차 스프린트 QA 리스트 중 모바일에서 발생하는 이슈 사항들을 수정했습니다

  • 둘러보기 > 음악 재생/멈춤 버튼 활성화 잘 안됨
  • 검색 시, 입력 텍스트 잘려보임
  • 프로그레스 바 컨트롤러 사이즈 수정 + 드래그 가능하게
  • 모바일에서 홈페이지 하단 캐러셀 이미지 흐릿하게 보이는 이슈 수정
  • 댓글 작성 후 삭제 시 댓글 복사되는 이슈 수정
  • 둘러보기 MO 레이아웃 수정
  • 나의CD MO 레이아웃 수정
  • 둘러보기 프로그레스 바 컨트롤러 잘리는 이슈 수정
  • 재생, 멈춤 버튼 수정사항 반영
  • 나의CD 버튼 텍스트 삭제
  • 좋아요 탭 이동시 존재하지 않는 플레이리스트라고 뜨는 이슈 수정
  • 좋아요 isEmpty 페이지 적용

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

  • 없음

🗯️ PR 포인트

  • 회의 때 말씀드렸던 미해결 QA는 따로 이슈 파서 진행 예정입니다 !

🚀 알게된 점

  • 태그를 이용하면 모바일 사파리 svg 깨짐 이슈를 해결할 수 있다.. (<iframe>, 도 가능)

    📖 참고 자료 (선택)

    Summary by CodeRabbit

    릴리스 노트

    • 새로운 기능

      • 프로그레스 바 드래그(스크럽)로 직접 탐색 지원
      • 재생 버튼의 일시적 표시 애니메이션 추가
      • 빈 상태 페이지 및 로딩 처리 추가
    • 개선사항

      • 모바일·경로에 따른 레이아웃·간격 최적화
      • 검색 입력 안내 문구 개편
      • 플레이어의 기기별 음소거 동작 개선
      • 채팅 메시지 중복 제거로 안정성 향상
      • 일부 공유·카테고리 버튼 UI 간소화 및 접근성 개선

@maylh maylh self-assigned this Oct 30, 2025
@maylh maylh added the HIGH 빠르게 처리해야 하는 높은 우선순위 label Oct 30, 2025
@coderabbitai
Copy link

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

기기 및 라우트 인식에 따른 레이아웃/간격 조정, Playlist CD 응답 필드명 변경(onlyCdResponse → cdResponse), 마이CD 로딩/빈상태 처리 추가, 프로그레스바 드래그 구현, 여러 UI 컴포넌트(PlayButton, Cd, CategoryButton 등) 및 기기별 동작(볼륨/유튜브 뮤트) 수정이 포함되어 있습니다.

Changes

Cohort / File(s) Summary
앱 레이아웃 / 라우트 감지
src/App.tsx
deviceType 기반 isMobile 도입, 경로(/mycd, /discover) 기준 isMobileView 계산, 하단 여백 동적 계산(LAYOUT_BOTTOM_GAP 제거 → 16/34 동적)
플레이리스트 타입 변경
src/entities/playlist/types/playlist.ts
PlaylistInfoonlyCdResponse?cdResponse?로 교체(내부 { cdItems: CdCustomData[] } 유지)
공유·액션바·재생 버튼 변경
src/features/share/ui/ShareButton.tsx, src/widgets/playlist/ActionBar.tsx, src/widgets/playlist/PlayButton.tsx
Cd variant 변경(share → customize), ActionBar/ShareButton의 조건부 텍스트 제거, PlayButton에 show prop 및 fadeZoom 애니메이션 추가
마이CD 페이징 및 캐러셀
src/pages/mycd/index.tsx, src/pages/mycd/ui/PlaylistCarousel.tsx
MY/LIKE 탭별 로딩·빈 상태 처리 추가, 데이터 소스 분리, 모바일 인식(useDevice)에 따른 padding/variant(mycd_mo) 적용, key를 playlistId로 변경
검색 UI 텍스트
src/pages/search/index.tsx, src/pages/search/SearchResultPage.tsx
검색 placeholder 문구 변경: "플레이리스트명 또는 닉네임으로 검색" → "듣고 싶은 키워드로 검색"
둘러보기(Discover) UI/플레이어 변경
src/pages/discover/index.tsx, src/widgets/playlist/YoutubePlayer.tsx
showCoachmark 영향으로 isPlaying 전달 조건 변경, YoutubePlayer에서 기기별 mute 옵션 적용(모바일 mute), Slide에 position: relative 추가
홈 카테고리 버튼 및 배경 렌더링
src/pages/home/index.tsx, src/shared/ui/CategoryButton.tsx
Slide → CategoryButton 교체(크기/텍스트/bgImage props), CategoryButton의 배경을 object로 렌더링(SVG 데이터), 텍스트에 $size prop 적용
Cd 컴포넌트 variant/스타일
src/shared/ui/Cd.tsx
CdProps.variant에서 'share' 제거, 'mycd_mo' 추가 및 sizeMap 업데이트(240, borderRadius 0), sticker img에 crossOrigin 적용
Input 스타일 조정
src/shared/ui/Input.tsx
StyledInput에서 height: 100% 제거
플레이리스트 레이아웃 동작 및 ActionBar 스타일
src/widgets/playlist/PlaylistLayout.tsx
Overlay 클릭 핸들 변경(handleOverlayClick)으로 onPlayPause 호출 및 1초간 PlayButton 표시, cdResponse.cdItems 우선 사용, ActionBarContainer$isMobile prop 추가, Overlay height 100%로 조정
프로그레스바 드래그 및 핸들 포털 렌더링
src/widgets/playlist/ProgressBar.tsx
포인터 기반 드래그(isDragging, dragTime), barRect 계산, 포탈을 통한 Handle 렌더링, 드래그 중 자동 업데이트 중지 및 포인터 이벤트 전역 관리
채팅 메시지 중복 제거 로직
src/widgets/chat/ChatBottomSheet.tsx
ChatMessage 타입 임포트 추가 및 historyMessages: ChatMessage[] 선언, Map으로 병합해 messageId 기준 중복 제거 후 sentAt 정렬
SwipeCarousel 명칭 수정
src/features/swipe/ui/SwipeCarousel.tsx
VerticaContainerVerticalContainer로 명칭 수정

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant Overlay as Overlay (클릭)
    participant PlaylistLayout as PlaylistLayout
    participant PlayButton as PlayButton

    User->>Overlay: 클릭
    Overlay->>PlaylistLayout: handleOverlayClick()
    PlaylistLayout->>PlaylistLayout: onPlayPause()
    PlaylistLayout->>PlaylistLayout: showPlayButton = true
    PlaylistLayout->>PlayButton: render show=true
    PlayButton->>User: fadeZoom 시각적 표시
    Note right of PlaylistLayout: 1000ms 후
    PlaylistLayout->>PlaylistLayout: showPlayButton = false
    PlaylistLayout->>PlayButton: render show=false
Loading
sequenceDiagram
    autonumber
    participant User as 사용자 포인터
    participant ProgressBar as ProgressBar
    participant Portal as document.body (Portal)
    participant Handle as 핸들 UI

    User->>ProgressBar: onPointerDown (handlePointerDown)
    ProgressBar->>ProgressBar: isDragging=true, barRect 저장
    ProgressBar->>Portal: Handle 렌더(포탈)
    User->>ProgressBar: pointermove
    ProgressBar->>ProgressBar: dragTime 계산, accPercent 업데이트
    ProgressBar->>Handle: 위치/시간 업데이트
    User->>ProgressBar: pointerup
    ProgressBar->>ProgressBar: isDragging=false, onClick 호출 (최종 시간 적용)
    ProgressBar->>Portal: Handle 제거
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50–70 minutes

특히 검토가 필요한 파일 및 포인트:

  • src/widgets/playlist/ProgressBar.tsx: 포인터 이벤트의 등록/해제, 바운더리 계산, 포털 위치 정확성, 터치/데스크톱 호환성
  • src/pages/mycd/index.tsx: 탭별 데이터 흐름, 빈 상태 UI와 네비게이션 연계
  • src/entities/playlist/types/playlist.ts 및 소비처(PlaylistLayout, PlaylistCarousel 등): onlyCdResponsecdResponse 명칭 변경의 모든 호출부 일관성
  • src/widgets/playlist/PlaylistLayout.tsx: Overlay 클릭 흐름 변경과 PlayButton 표시 타이밍
  • src/shared/ui/CategoryButton.tsx: object 태그 기반 SVG 배경이 브라우저 환경에서 정상 렌더링되는지

Possibly related PRs

Suggested reviewers

  • hansololiviakim

Poem

🐇 깡총, 코드 밭을 건너와서 고쳤네
터치로 끌면 바늘처럼 움직이는 바, 드래그하네
모바일이냐 데스크톱이냐 따라 소리와 틈을 바꿔
작은 버튼 하나가 1초 동안 반짝이며 손을 반겨
당근보다 빠르게 배포되길, 토끼가 응원하네 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 "[fix] 모바일 QA 반영"은 주요 변경 내용과 명확하게 관련이 있습니다. 제목은 이 PR이 1차 스프린트 모바일 QA 항목들을 수정한다는 의도를 정확하게 전달하고 있으며, 코드 변경 내용의 중심축인 모바일 관련 버그 수정 및 레이아웃 조정을 요약합니다. 다소 일반적인 표현이지만, 팀원이 커밋 기록을 훑어볼 때 주요 변경 사항을 충분히 이해할 수 있는 수준입니다.
Linked Issues Check ✅ Passed 이슈 #129에 나열된 완료 항목들(음악 재생/멈춤 버튼 활성화, 검색 입력 텍스트 클리핑, 프로그레스 바 드래그 기능, 캐러셀 이미지 화질, 댓글 복제 문제, 레이아웃 수정 등)이 코드 변경에서 확인됩니다. ProgressBar.tsx의 드래그 기능 추가, PlayButton.tsx 수정, discover/mycd 레이아웃 변경, CategoryButton.tsx의 object 태그 사용 등이 각 QA 항목을 해결합니다. 미해결 항목(음소거 버튼 미노출, 공유 이미지 저장 그래픽 누락)은 PR 설명에서 별도 이슈로 처리 예정임이 명시되어 있습니다.
Out of Scope Changes Check ✅ Passed 모든 코드 변경이 이슈 #129의 모바일 QA 수정 범위 내에 있습니다. App.tsx의 레이아웃 조정, mycd/discover 페이지 수정, ProgressBar 드래그 기능, SearchInput 텍스트 클리핑 수정, 채팅 메시지 중복 제거, 캐러셀 이미지 개선 등이 모두 언급된 QA 항목들과 대응됩니다. ShareButton.tsx의 Cd 컴포넌트 variant 변경(share → customize)은 Cd.tsx에서 'share' variant가 제거된 것에 따른 필수 유지보수 변경입니다.
Description Check ✅ Passed PR 설명은 저장소 템플릿의 모든 필수 섹션을 포함하고 있습니다. 관련 이슈 #129가 명시되어 있고, 주요 변경 사항은 12개 항목으로 상세하게 나열되었으며, 테스트 방법, PR 포인트, 배운 점, 참고 자료가 적절히 작성되었습니다. 설명의 구조와 내용이 템플릿 요구사항을 충족하고 있습니다.
✨ 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/#129/1sp-qa-mobile

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은 1차 스프린트 QA에서 발견된 모바일 관련 문제점들을 해결하고 사용자 경험을 향상시키는 데 중점을 둡니다. 둘러보기 및 나의CD 페이지의 레이아웃과 기능적 결함을 수정하고, 프로그레스 바에 드래그 기능을 추가하여 편의성을 높였습니다. 또한, SVG 이미지 렌더링 방식을 개선하여 모바일 환경에서의 시각적 품질을 확보하고, 채팅 메시지 처리 로직을 최적화했습니다.

Highlights

  • 모바일 QA 개선: 1차 스프린트 QA에서 발견된 모바일 관련 이슈들을 수정하여 전반적인 모바일 사용자 경험을 개선했습니다. 여기에는 둘러보기 페이지의 재생/멈춤 버튼 활성화 문제, 검색 입력 텍스트 잘림, 프로그레스 바 컨트롤러 개선, 캐러셀 이미지 흐림 현상 수정 등이 포함됩니다.
  • 둘러보기 및 나의CD 페이지 레이아웃 및 기능 개선: 둘러보기(Discover) 및 나의CD(MyCD) 페이지의 모바일 레이아웃을 수정하고, 프로그레스 바 컨트롤러가 잘리는 문제를 해결했습니다. 또한, 나의CD 페이지에서 좋아요한 플레이리스트가 없을 때의 빈 화면(empty state)을 적용하고, 좋아요 탭 이동 시 플레이리스트가 존재하지 않는다고 뜨는 이슈를 수정했습니다.
  • 프로그레스 바 드래그 기능 추가: 플레이리스트 프로그레스 바에 드래그 기능을 추가하여 사용자가 재생 위치를 더욱 쉽게 조절할 수 있도록 개선했습니다. 컨트롤러의 크기도 모바일 환경에 맞춰 조정되었습니다.
  • SVG 이미지 렌더링 개선: 홈페이지 하단 캐러셀 이미지의 흐림 현상을 해결하기 위해 <img> 태그 대신 <object> 태그를 사용하여 SVG 이미지를 렌더링하도록 변경했습니다. 이는 특히 모바일 Safari에서 발생하는 SVG 깨짐 이슈를 해결하는 데 도움이 됩니다.
  • 채팅 메시지 중복 제거 및 정렬: 채팅 바텀시트에서 히스토리 메시지와 실시간 메시지를 합칠 때 중복을 제거하고, 메시지를 시간 순서대로 정확하게 정렬하도록 로직을 개선했습니다.
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 Oct 30, 2025

🎵 Storybook Link 🎵
🔗 https://689dbb45f8d09aea7832eeb1-hpokudjjla.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은 모바일 QA에서 발견된 다양한 이슈들을 성공적으로 해결해주셨습니다. 레이아웃 조정, 컴포넌트 수정부터 드래그 가능한 프로그레스 바, 재생/일시정지 피드백 애니메이션과 같은 UX 개선까지 폭넓은 수정이 이뤄졌네요. CategoryButton 컴포넌트 리팩토링이나 채팅 메시지 중복 제거 등 코드가 더 깔끔하고 안정적으로 개선된 점도 좋습니다. 리뷰 과정에서 '나의 CD' 페이지의 플레이리스트 생성자 정보 처리 로직에 잠재적인 버그와 몇 가지 코드 정리 포인트를 발견했습니다. 전반적으로 훌륭한 수정 작업이었습니다!

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: 4

Caution

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

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

131-145: 좋아요 탭에서 플레이리스트 소유자 정보가 덮어씌워져요

선택된 탭이 LIKE일 때도 convertedPlaylist.creator가 항상 로그인한 사용자 정보로 덮어써져서, ActionBar나 이후 로직이 해당 플레이리스트를 내 소유물로 잘못 인식하게 됩니다. 좋아요한 다른 사람의 CD에서도 편집/공개 전환 같은 소유자 전용 액션이 노출될 수 있어요. 전달받은 playlistDetail에 이미 작성자 식별자가 들어있다면 그것을 우선 사용하도록 수정이 필요합니다.

-      const convertedPlaylist = {
-        creator: {
-          creatorId: userInfo.userId,
-          creatorNickname: userInfo.username,
-        },
+      const creatorId =
+        playlistDetail.creator?.creatorId ??
+        playlistDetail.creatorId ??
+        userInfo.userId
+      const creatorNickname =
+        playlistDetail.creator?.creatorNickname ??
+        playlistDetail.creatorNickname ??
+        userInfo.username
+
+      const convertedPlaylist = {
+        creator: {
+          creatorId,
+          creatorNickname,
+        },
src/widgets/playlist/PlaylistLayout.tsx (1)

1-108: 재생 버튼 토스트 타이머 정리 필요

클릭할 때마다 setTimeout을 새로 만들지만 이전 타이머를 해제하지 않아 연속 클릭 시 버튼이 빨리 사라지고, 언마운트 직후에는 경고가 발생할 수 있습니다. 타이머 ref를 도입해 마지막 클릭만 유지하고 컴포넌트 언마운트 시 정리해 주세요.

-import { useCallback, useState } from 'react'
+import { useCallback, useEffect, useRef, useState } from 'react'
@@
-  const [showPlayButton, setShowPlayButton] = useState(false)
+  const [showPlayButton, setShowPlayButton] = useState(false)
+  const playButtonTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
@@
-    setShowPlayButton(true)
-    setTimeout(() => setShowPlayButton(false), 1000)
+    setShowPlayButton(true)
+    if (playButtonTimerRef.current) {
+      clearTimeout(playButtonTimerRef.current)
+    }
+    playButtonTimerRef.current = setTimeout(() => {
+      setShowPlayButton(false)
+      playButtonTimerRef.current = null
+    }, 1000)
   }
 
+  useEffect(() => {
+    return () => {
+      if (playButtonTimerRef.current) {
+        clearTimeout(playButtonTimerRef.current)
+      }
+    }
+  }, [])
📜 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 4b015ca and d277911.

📒 Files selected for processing (20)
  • src/App.tsx (1 hunks)
  • src/entities/playlist/types/playlist.ts (1 hunks)
  • src/features/share/ui/ShareButton.tsx (1 hunks)
  • src/features/swipe/ui/SwipeCarousel.tsx (2 hunks)
  • src/pages/discover/index.tsx (3 hunks)
  • src/pages/home/index.tsx (2 hunks)
  • src/pages/mycd/index.tsx (8 hunks)
  • src/pages/mycd/ui/PlaylistCarousel.tsx (4 hunks)
  • src/pages/search/SearchResultPage.tsx (1 hunks)
  • src/pages/search/index.tsx (1 hunks)
  • src/shared/ui/CategoryButton.tsx (2 hunks)
  • src/shared/ui/Cd.tsx (2 hunks)
  • src/shared/ui/Input.tsx (0 hunks)
  • src/widgets/chat/ChatBottomSheet.tsx (2 hunks)
  • src/widgets/playlist/ActionBar.tsx (0 hunks)
  • src/widgets/playlist/PlayButton.tsx (2 hunks)
  • src/widgets/playlist/PlaylistLayout.tsx (6 hunks)
  • src/widgets/playlist/ProgressBar.tsx (5 hunks)
  • src/widgets/playlist/VolumeButton.tsx (1 hunks)
  • src/widgets/playlist/YoutubePlayer.tsx (2 hunks)
💤 Files with no reviewable changes (2)
  • src/shared/ui/Input.tsx
  • src/widgets/playlist/ActionBar.tsx
🧰 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/search/SearchResultPage.tsx
  • src/widgets/playlist/YoutubePlayer.tsx
  • src/shared/ui/Cd.tsx
  • src/features/swipe/ui/SwipeCarousel.tsx
  • src/widgets/playlist/VolumeButton.tsx
  • src/entities/playlist/types/playlist.ts
  • src/widgets/playlist/PlayButton.tsx
  • src/pages/home/index.tsx
  • src/widgets/playlist/ProgressBar.tsx
  • src/shared/ui/CategoryButton.tsx
  • src/features/share/ui/ShareButton.tsx
  • src/pages/search/index.tsx
  • src/pages/mycd/ui/PlaylistCarousel.tsx
  • src/widgets/chat/ChatBottomSheet.tsx
  • src/App.tsx
  • src/pages/mycd/index.tsx
  • src/widgets/playlist/PlaylistLayout.tsx
  • src/pages/discover/index.tsx
🧠 Learnings (2)
📚 Learning: 2025-08-26T02:41:55.110Z
Learnt from: hansololiviakim
PR: dnd-side-project/dnd-13th-8-frontend#61
File: src/shared/ui/Error.tsx:4-17
Timestamp: 2025-08-26T02:41:55.110Z
Learning: src/shared/ui/index.ts에서 re-export된 컴포넌트는 `import { ComponentName } from '@/shared/ui'` 형태로 named import될 수 있으므로, 컴포넌트명 변경 시 해당 패턴의 import도 함께 확인해야 함

Applied to files:

  • src/pages/search/SearchResultPage.tsx
  • src/features/swipe/ui/SwipeCarousel.tsx
  • src/pages/home/index.tsx
  • src/features/share/ui/ShareButton.tsx
  • src/pages/search/index.tsx
📚 Learning: 2025-08-20T05:59:48.729Z
Learnt from: maylh
PR: dnd-side-project/dnd-13th-8-frontend#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/widgets/playlist/YoutubePlayer.tsx
  • src/widgets/playlist/VolumeButton.tsx
  • src/pages/mycd/index.tsx
  • src/pages/discover/index.tsx
🧬 Code graph analysis (8)
src/widgets/playlist/YoutubePlayer.tsx (1)
src/shared/lib/useDevice.ts (1)
  • useDevice (14-17)
src/pages/home/index.tsx (1)
src/assets/card/index.ts (1)
  • CARD_IMAGES_LARGE (35-46)
src/widgets/playlist/ProgressBar.tsx (2)
src/shared/lib/getAccTime.ts (1)
  • getAccTime (1-3)
src/shared/styles/theme.ts (1)
  • theme (3-122)
src/shared/ui/CategoryButton.tsx (1)
src/shared/styles/theme.ts (1)
  • theme (3-122)
src/pages/mycd/ui/PlaylistCarousel.tsx (2)
src/shared/lib/useDevice.ts (1)
  • useDevice (14-17)
src/shared/styles/mixins.ts (1)
  • flexRowCenter (3-8)
src/widgets/chat/ChatBottomSheet.tsx (1)
src/features/chat/model/sendMessage.ts (1)
  • ChatMessage (6-15)
src/App.tsx (2)
src/features/auth/store/authStore.ts (1)
  • useAuthStore (7-52)
src/features/auth/model/useAuth.ts (1)
  • useAnonymousLogin (13-18)
src/pages/mycd/index.tsx (5)
src/entities/playlist/model/useMyCd.ts (1)
  • useMyCdActions (29-68)
src/entities/playlist/model/usePlaylists.ts (1)
  • usePlaylistDetail (45-51)
src/entities/playlist/types/playlist.ts (1)
  • Creator (43-46)
src/shared/styles/theme.ts (1)
  • theme (3-122)
src/shared/styles/mixins.ts (1)
  • flexColCenter (10-15)
🔇 Additional comments (30)
src/pages/search/index.tsx (1)

41-41: 모바일 텍스트 잘림 문제 해결 승인

placeholder 텍스트가 더 간결하고 명확해졌습니다. 이전 텍스트("플레이리스트명 또는 닉네임으로 검색")보다 짧아져 모바일 화면에서 텍스트 잘림 현상을 효과적으로 방지할 수 있습니다.

src/pages/search/SearchResultPage.tsx (1)

149-149: 일관된 placeholder 개선 승인

검색 페이지(src/pages/search/index.tsx)와 동일하게 placeholder가 개선되어 일관된 사용자 경험을 제공합니다. 모바일 환경에서의 텍스트 잘림 문제를 효과적으로 해결합니다.

src/features/swipe/ui/SwipeCarousel.tsx (1)

69-69: 타이포 수정이 올바르게 적용되었습니다 - 추가 조치 불필요

검증 결과:

  • VerticaContainer (오류 표기)에 대한 참조는 전혀 남아있지 않음 ✓
  • 정의(83줄)와 사용(69줄) 모두 VerticalContainer로 일관되게 수정됨 ✓
  • 해당 컴포넌트는 파일 내부에만 존재하는 로컬 styled component로, 외부 영향 없음 ✓
src/widgets/chat/ChatBottomSheet.tsx (2)

9-9: LGTM: 타입 전용 import 사용

타입 전용 import를 명시적으로 사용하여 코드의 의도가 명확하고 번들 최적화에도 도움이 됩니다.


38-38: LGTM: 명시적 타입 선언

historyMessages에 명시적으로 타입을 선언하여 가독성과 타입 안전성이 향상되었습니다.

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

7-18: 잘 구현되었습니다!

show prop 추가와 컴포넌트 시그니처 업데이트가 명확하고 타입 안전하게 구현되었습니다. 모바일 QA 요구사항(재생/일시정지 버튼의 일관된 활성화)을 지원하기 위한 적절한 변경입니다.


21-42: 애니메이션 구현이 적절합니다.

페이드 인/아웃과 스케일 효과를 결합한 fadeZoom 애니메이션이 잘 구현되었습니다. 20-80% 구간에서 완전히 표시된 상태를 유지하여 사용자에게 충분한 시각적 피드백을 제공합니다.


44-64: 조건부 애니메이션 적용이 올바릅니다.

$show prop에 따라 애니메이션을 조건부로 적용하는 로직이 깔끔합니다. forwards fill-mode를 사용하여 애니메이션 종료 후 최종 상태를 유지하는 것이 적절합니다.

src/widgets/playlist/YoutubePlayer.tsx (2)

5-6: 디바이스 감지 로직이 적절합니다.

useDevice 훅을 사용하여 모바일 디바이스를 감지하는 로직이 명확합니다. PR 목표인 모바일 QA 개선을 위한 기반을 제공합니다.

Also applies to: 15-16


21-21: 모바일 자동재생 정책을 올바르게 처리합니다.

모바일에서는 음소거 상태로 시작하고 데스크톱에서는 음소거 해제 상태로 시작하는 로직이 적절합니다. 이는 iOS의 자동재생 정책 요구사항을 준수하며, VolumeButton의 "탭하여 음소거 해제" 기능과 연계됩니다.

src/App.tsx (2)

30-30: 디바이스 플래그 도입이 코드를 개선합니다.

isMobile 플래그를 도입하여 반복적인 deviceType === 'mobile' 비교를 제거한 것이 좋습니다. 가독성과 유지보수성이 향상되었습니다.

Also applies to: 37-37


39-41: 라우트별 모바일 레이아웃 조정이 적절합니다.

특정 라우트(/mycd, /discover)에서 모바일 디바이스일 때 하단 간격을 16px로 줄이는 로직이 잘 구현되었습니다. 이는 PR 목표인 "모바일 레이아웃 조정"을 반영합니다.

src/features/share/ui/ShareButton.tsx (2)

30-30: Cd 컴포넌트 variant 업데이트가 올바릅니다.

Cd.tsx에서 "share" variant가 제거되고 "customize"가 유지되는 변경사항과 일치합니다. 기능적으로는 동일한 사이즈를 유지합니다.


60-62: 버튼 텍스트 제거로 UI가 간결해졌습니다.

MY 타입 버튼에서 "공유" 텍스트를 제거하여 아이콘만 표시하도록 변경한 것이 적절합니다. 이는 PR 목표인 "나의CD 버튼 텍스트 제거"를 반영하며 모바일 UI를 개선합니다.

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

167-167: 코치마크 표시 중 재생 상태 처리가 적절합니다.

코치마크가 표시되는 동안 isPlaying 상태를 false로 처리하여 온보딩 중 혼란스러운 UI를 방지합니다. 사용자 경험이 개선되었습니다.


182-196: YoutubePlayer 조건부 렌더링과 onReady 로직이 개선되었습니다.

코치마크 표시 중 YoutubePlayer를 렌더링하지 않아 성능과 UX가 개선됩니다. onReady 콜백에서 자동 재생 로직을 제거하고 필요할 때만 일시정지하는 보수적인 접근 방식이 적절합니다.


203-206: Slide 컴포넌트에 positioning context가 추가되었습니다.

position: relative를 추가하여 자식 요소(예: PlayButton 오버레이)의 절대 위치 지정을 위한 기준을 제공합니다. 표준적인 CSS 레이아웃 패턴입니다.

src/shared/ui/Cd.tsx (2)

141-141: 모바일 사이즈 설정이 적절합니다.

mycd_mo variant의 사이즈(240px)가 일반 mycd(260px)보다 약간 작아 모바일 화면에 적합합니다. borderRadius: 0으로 동일한 스타일을 유지합니다.


13-25: 모바일 전용 variant 추가가 올바르게 구현되었습니다.

검증 결과, mycd_mo variant가 타입 정의 및 sizeMap에 올바르게 추가되었고, share variant는 타입 정의, sizeMap, 그리고 모든 사용처에서 완전히 제거되었습니다. 코드 변경이 타입 안정성을 유지하며 적절하게 구현되었습니다.

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

17-32: 음소거 해제 후 재생 재개 로직이 올바르게 구현되었습니다.

YouTube IFrame API에서 플레이어 상태 값 1은 재생 중(playing) 상태를 나타내므로, 음소거 해제 후 플레이어 상태를 확인하여 재생 중이 아닐 때만 playVideo()를 호출하는 이 로직은 정확합니다. 모바일 환경에서 음소거 상태로 시작한 비디오가 음소거 해제 후 자동으로 재생되며, 이미 재생 중인 경우 중복 호출을 방지합니다.

src/entities/playlist/types/playlist.ts (1)

69-72: 모든 코드 변경사항이 정상적으로 적용되었습니다.

검증 결과:

  • onlyCdResponse 사용처가 없음 ✓
  • cdResponse가 20개 이상의 파일에서 올바르게 사용 중 ✓
  • OnlyCdResponse 인터페이스는 여전히 CdMetaResponse 타입과 PlaylistDetailResponse 인터페이스에서 활발히 사용 중 ✓
  • PlaylistInfocdResponsecdItems 이중 속성 구조로 하위 호환성 유지 ✓

인터페이스 변경이 완전하고 일관되게 적용되었으며, 모든 소비처가 새로운 구조에 맞추어 업데이트되었습니다.

src/shared/ui/CategoryButton.tsx (1)

13-47: 배경 오브젝트 전환 검토 완료

object 태그로 전환하면서 pointer-events를 끄고 z-index를 분리해 버튼 상호작용과 시각 효과가 모두 안전하게 유지되는 게 확인됐습니다.

src/pages/mycd/ui/PlaylistCarousel.tsx (1)

68-89: 모바일 전용 변형 적용 좋아요

모바일에서는 mycd_mo 변형과 패딩 제거로 공간 활용을 최적화한 덕분에 캐러셀 뷰가 안정적으로 보일 것으로 기대됩니다.

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

68-77: 카테고리 버튼 교체 확인

CategoryButton으로 교체하면서 size·bgImage·text 프로퍼티를 모두 채워 넣어 기존 UX를 그대로 유지한 점이 좋습니다.

src/widgets/playlist/ProgressBar.tsx (6)

44-53: LGTM!

useLayoutEffect를 사용하여 초기 핸들 위치 설정과 리사이즈 대응을 구현한 것이 적절합니다. 레이아웃 측정이 페인트 전에 이루어지도록 보장합니다.


58-64: 드래그 중 시간 업데이트 방지 로직 적절

isDragging 상태를 활용하여 드래그 중에는 자동 시간 업데이트를 일시 중지하는 로직이 올바르게 구현되었습니다.


67-68: LGTM!

드래그 중일 때와 일반 재생 중일 때의 시간 계산을 적절하게 분기 처리했습니다.


112-149: Portal을 활용한 핸들 렌더링 구현 우수

createPortal을 사용하여 핸들을 document.body에 렌더링하는 접근 방식이 적절합니다. 이를 통해 부모 요소의 overflow 제약을 받지 않고 정확한 위치에 핸들을 표시할 수 있습니다.


159-168: 터치 동작 방지 속성 추가 적절

touch-action: none을 추가하여 터치 기기에서 드래그 중 의도하지 않은 스크롤을 방지한 것이 좋습니다.


192-201: 핸들 스타일링 구현 우수

드래그 상태에 따른 핸들 크기 변화와 pointer-events: none 설정이 적절합니다. 드래그 중 핸들이 커져서 시각적 피드백을 제공하는 것은 좋은 UX입니다.

Line 198의 TODO 주석에 언급된 대로, 추후 z-index를 theme 시스템으로 통합하는 리팩토링을 고려하세요. theme.Z_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

♻️ Duplicate comments (1)
src/widgets/playlist/ProgressBar.tsx (1)

55-55: 디버깅 로그를 제거해야 합니다.

프로덕션 코드에 남아 있는 console.log는 제거해 주세요. 이전 리뷰에서도 동일하게 지적됐습니다.

-  console.log(barRect)
🧹 Nitpick comments (2)
src/widgets/playlist/ProgressBar.tsx (1)

41-74: setter 이름을 상태와 일치시켜 주세요.

상태 값이 barRect인데 setter가 setBarRef라서 가독성이 떨어집니다. 일관된 네이밍으로 정리해 주세요.

- const [barRect, setBarRef] = useState<DOMRect | null>(null)
+ const [barRect, setBarRect] = useState<DOMRect | null>(null)
...
-      setBarRef(handleRef.current.getBoundingClientRect())
+      setBarRect(handleRef.current.getBoundingClientRect())
...
-    setBarRef(rect) // portal 위치용
+    setBarRect(rect) // portal 위치용
src/features/chat/model/sendMessage.ts (1)

28-28: 환경변수를 사용하여 API URL을 관리하는 것을 권장합니다.

WebSocket URL이 하드코딩되어 있습니다. 환경별(개발/스테이징/프로덕션)로 다른 엔드포인트를 사용할 수 있도록 환경변수로 관리하는 것이 좋습니다.

다음과 같이 수정할 수 있습니다:

-    const client = new Client({
-      webSocketFactory: () => new SockJS('https://api.deulak.com/chat/ws') as unknown as WebSocket,
-      debug: (str) => console.log('[STOMP]', str),
-    })
+    const client = new Client({
+      webSocketFactory: () => new SockJS(`${import.meta.env.VITE_API_URL}/chat/ws`) as unknown as WebSocket,
+      debug: (str) => console.log('[STOMP]', str),
+    })

.env 파일에 다음을 추가:

VITE_API_URL=https://api.deulak.com
📜 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 d277911 and d0f99b6.

📒 Files selected for processing (3)
  • src/features/chat/model/sendMessage.ts (1 hunks)
  • src/shared/ui/Cd.tsx (3 hunks)
  • src/widgets/playlist/ProgressBar.tsx (5 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/features/chat/model/sendMessage.ts
  • src/widgets/playlist/ProgressBar.tsx
  • src/shared/ui/Cd.tsx
🧠 Learnings (1)
📓 Common learnings
Learnt from: maylh
PR: dnd-side-project/dnd-13th-8-frontend#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 사용으로 의존성 최소화, 플레이리스트 변경 시 상태 초기화 등이 필요하다.
🧬 Code graph analysis (1)
src/widgets/playlist/ProgressBar.tsx (2)
src/shared/lib/getAccTime.ts (1)
  • getAccTime (1-3)
src/shared/styles/theme.ts (1)
  • theme (3-122)
🔇 Additional comments (2)
src/shared/ui/Cd.tsx (2)

25-25: 모바일 변형 추가가 적절하게 구현되었습니다.

mycd_mo 변형이 타입과 sizeMap에 일관되게 추가되었으며, 크기 설정(240x240)이 모바일 레이아웃에 적합합니다.

Also applies to: 141-141


92-92: 검증을 완료했습니다.

공유 이미지 저장 기능에서 crossOrigin="anonymous" 설정이 필요한 이유 확인

코드에서 html-to-image 라이브러리의 toPng 함수를 사용하여 DOM을 이미지로 변환합니다. 이 과정에서 Canvas API의 toDataURL() 호출 시 CORS 정책이 적용되므로, 외부 도메인의 이미지에 crossOrigin="anonymous" 속성이 필수입니다.

현재 상태:

  • CdCustomData.imageUrl은 API 응답에서 오는 외부 이미지 URL입니다
  • Cd.tsx의 모든 img 요소에 crossOrigin="anonymous"가 설정되어 있습니다 (올바른 조치)
  • THEME_IMAGES_MAP의 로컬 에셋도 함께 처리되고 있습니다

필수 확인 사항:
외부 imageUrl API 엔드포인트에서 다음 CORS 헤더가 응답에 포함되어 있는지 확인하세요:

  • Access-Control-Allow-Origin (예: * 또는 현재 도메인)
  • Access-Control-Allow-Credentials (필요시)

이 헤더들이 없으면 브라우저가 캔버스 접근을 차단하여 이미지 저장 시 그래픽이 누락될 수 있습니다.

API 서버 설정에서 imageUrl을 제공하는 엔드포인트의 CORS 헤더 설정을 확인해 주세요.

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 fa8eef2 into develop Oct 31, 2025
4 checks passed
@hansololiviakim hansololiviakim deleted the fix/#129/1sp-qa-mobile 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] 모바일 QA 반영

2 participants