-
Notifications
You must be signed in to change notification settings - Fork 1
[FIX] 코인토스 플로우 추가 및 버그 해결 #364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Caution Review failedThe pull request is closed. WalkthroughTableOverviewPage에 로컬 코인 상태( Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor 사용자 as User
participant Page as TableOverviewPage
participant Modal as TeamSelectionModal
participant Audio as Sound
User->>Page: "팀 선정하기" 클릭
Page->>Page: modalCoinState = 'initial'
Page->>Modal: open(initialCoinState, onEdit, onCoinStateChange)
Note over Modal: 초기 화면 ('initial') 표시
User->>Modal: "동전 던지기"
Modal->>Modal: coinState = 'tossing'
Modal->>Audio: 토스 사운드 재생
Modal-->>Modal: 대기 (~2s) 후 결과 결정
Modal->>Modal: coinState = 'front' / 'back'
Modal->>Audio: 결과 사운드 재생 (한 번만)
Modal->>Page: onCoinStateChange(state)
alt 수정 선택
User->>Modal: "토론 정보 수정하기"
Modal->>Modal: close
Modal->>Page: onEdit()
Page->>Page: 라우팅 (게스트/일반)
else 바로 시작
User->>Modal: "토론 바로 시작하기"
Modal->>Modal: close
Page->>Page: 토론 시작 흐름
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Assessment against linked issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/page/TableOverviewPage/TableOverviewPage.tsx (1)
201-201: text-natural-1000가 Tailwind 설정에 정의되어 있지 않습니다. 프로젝트에 해당 토큰이 없으므로text-neutral-1000으로 오타를 수정하거나tailwind.config에natural-1000색상을 추가하세요.
- src/page/TableOverviewPage/TableOverviewPage.tsx:201
- src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx:125
src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (1)
33-39: 언마운트 시 오디오 정리 누락모달이 닫힐 때(언마운트) 결과음이 재생 중이면 계속 들릴 수 있습니다. 전역 언마운트 클린업을 추가해 주세요.
다음 훅을 추가:
const coinTossSound = useMemo(() => new Audio('/sounds/cointoss.mp3'), []); const coinResultSound = useMemo( () => new Audio('/sounds/cointoss-result.mp3'), [], ); + + // 컴포넌트 언마운트 시 모든 사운드 정지/리셋 + useEffect(() => { + return () => { + coinTossSound.pause(); + coinTossSound.currentTime = 0; + coinResultSound.pause(); + coinResultSound.currentTime = 0; + }; + }, [coinTossSound, coinResultSound]);
🧹 Nitpick comments (4)
src/page/TableOverviewPage/TableOverviewPage.tsx (2)
28-33: 모달 오픈 시 상태 초기화 전략 적절open 전 'initial'로 리셋해 재오픈 시 단계가 유지되지 않도록 한 점 좋습니다. 방어적으로 close 시점에서도 초기화가 필요하면 closeModal 호출부에서 setModalCoinState('initial') 추가를 고려해도 됩니다.
66-77: 편집 라우팅 분기 로직 적절게스트/비게스트 플로우 분기와 state step 전달이 명확합니다. 하단 푸터의 편집 버튼(onClick)과 로직이 중복되므로, 동일 핸들러(handleEdit)로 통일하면 유지보수성이 더 좋아집니다.
src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (2)
22-31: 상태 동기화 헬퍼 적절 — 추가 동기화 여지updateCoinState로 로컬/부모 동시 업데이트가 명료합니다. 부모가 모달 오픈 중에 initialCoinState를 갱신할 가능성이 있다면 아래 동기화 훅을 고려해 주세요.
다음 코드를 coinState 선언 아래에 추가:
+ useEffect(() => { + setCoinState(initialCoinState); + }, [initialCoinState]);
132-147: 결과 표시 UI 적절이미지/라벨 조합으로 상태 전달이 명확합니다. alt 텍스트가 동일("동전")이라 접근성 측면에서 앞/뒤 구분을 반영하면 더 좋습니다.
예:
alt={coinState === 'front' ? '동전 앞면' : '동전 뒷면'}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/page/TableOverviewPage/TableOverviewPage.tsx(5 hunks)src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx(5 hunks)src/type/type.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/page/TableOverviewPage/TableOverviewPage.tsx (3)
src/hooks/useModal.tsx (1)
useModal(15-87)src/type/type.ts (1)
CoinState(5-5)src/util/sessionStorage.ts (1)
isGuestFlow(29-31)
src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (1)
src/type/type.ts (1)
CoinState(5-5)
🔇 Additional comments (11)
src/type/type.ts (1)
5-5: CoinState 타입 도입 적절합니다문맥에 맞는 리터럴 유니온입니다. 다른 파일들과의 사용도 일관적입니다.
src/page/TableOverviewPage/TableOverviewPage.tsx (4)
10-10: 타입/훅 import 정합성 OKCoinState, useState/useCallback 도입이 아래 변경들과 잘 맞습니다.
Also applies to: 21-21
35-37: 상태 리프팅 콜백 안정성 OKuseCallback으로 부모 상태 동기화 콜백을 안정화한 점 좋습니다.
133-133: 모달 오픈 핸들러로 교체한 점 👍직접 openModal 대신 handleOpenModal을 사용해 초기화-오픈 순서를 보장합니다.
205-207: TeamSelectionModal 신규 props 연계 정상onEdit/initialCoinState/onCoinStateChange 전달과 부모 상태 연동이 의도와 맞습니다.
src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (6)
1-1: 타입 import로 단일 소스화 Good로컬 타입 제거하고 공용 타입 사용으로 일관성 확보되었습니다.
Also applies to: 5-5
10-13: 컴포넌트 인터페이스 확장 타당onEdit/initialCoinState/onCoinStateChange 추가가 플로우 요구사항을 충족합니다.
76-85: 탭 복귀 시 결과음 중복 방지 로직 적절초기 props와 동일 결과 상태 진입 시 재생 금지 플래그를 세팅한 점 좋습니다.
87-96: 콜투액션 핸들러 종료 순서 OK모달 먼저 닫고 상위 액션 트리거하여 이중 포커스/스크롤 이슈를 예방합니다.
105-112: 초기 안내 UI 명확지시문이 분명하고 가독성 있는 타이포그래피입니다.
150-176: CTA 배치/카피 적절결과 단계에서 편집/시작 2분기 제공이 UX에 부합합니다.
src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx
Show resolved
Hide resolved
i-meant-to-be
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다! 수정 필요해 보이는 리뷰 한 건 있어서 RC 남기고 갑니당
| setTimeout(() => { | ||
| if (!hasResultSoundPlayedRef.current) { | ||
| coinResultSound.currentTime = 0; | ||
| coinResultSound.play(); | ||
| hasResultSoundPlayedRef.current = true; | ||
| } | ||
| }, 100); // 약간의 딜레이로 자연스럽게 연결 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
권장: 결과 효과음 타이머도 언마운트 후 free 해주기
CodeRabbit 리뷰가 적절한 부분을 알려준 것 같습니다. 2000 ms 타이머는 const hasResultSoundPlayedRef = useRef(false)로 레퍼런스가 지정되어 언마운트 시 free되지만, 2000 ms 타이머 안의 결과 효과음 타이머인 100 ms 타이머는 그렇지 않습니다. 100 ms 타이머도 레퍼런스를 만들어서 언마운트 시에 free 함수를 붙여주는 게 좋을 것 같아요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
타이머 별로 useEffect를 두 개로 분리도 해보고, 코드래빗의 리뷰도 반영해 보았지만 두 방법 모두 코인토스 결과 효과음이 안 울리는 더 큰 문제가 생기더라구요 😂
원인을 파악해보니, coinState가 바뀔 때 cleanup 함수가 너무 빨리 실행돼서 결과음 타이머를 미리 꺼버리는 것 같습니다 ..
이게 딱 0.1초 사이에 모달을 닫을 때만 생기는 문제라 대부분의 경우에는 모달을 닫았을 때 결과 효과음이 울리는 경우는 아주 드물 것 같습니다 !!! 일단 더 큰 버그가 발생하니 .. 요 아니는 그대로 두겠습니다 ! 추후에 더 좋은 다른 방법이 생긴다면 리팩토링 해 보면 좋을 것 같아요.
꼼꼼하게 체크해 주셔서 감사합니다 숀 !!!!! 👍
jaeml06
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코인 토스 플로우가 요구 사항대로 제대로 흘러가는지 확인해 주세요. ✅
토론 정보 수정하기, 토론 하기 등 진입점이 제대로 연결되어 있는지 확인해 주세요. ✅
동전 던지는 사운드가 동전 던지기 결과가 나왔음에도 겹쳐서 들리지 않는지 확인해 주세요. ✅
다른 탭에 갔다가 다시 돌아왔을 때 모달이 재렌더링 되면서 진행 단계가 초기화 되지 않는지 확인해 주세요. ✅
다른 탭에 갔다가 다시 돌아왔을 때 동전 던지기 결과 효과음이 다시 울리지 않는지 확인해 주세요. ✅
버그 수정 고생하셨습니다. 체크 사항 확인했을 때, 문제 없었습니다.
나머지 수정사항은 숀과 코드레빗이 남겨준 것 확인하면 될 것 같습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (1)
40-74: 중첩 타이머/오디오 클린업 이슈 — 결과음이 모달 언마운트 후 재생될 수 있습니다현재 2000ms 타이머 내부에서 다시 100ms 타이머를 만들고, 클린업에서는 외부 타이머만 해제합니다. 모달을 닫거나 탭 전환 등으로 언마운트 시 내부 타이머에 의해 결과음이 재생될 수 있습니다. 또한
play()Promise 미처리로 브라우저 정책에 따른 Unhandled rejection 가능성이 있습니다.아래처럼 “던지기”와 “결과음 재생”을 분리된 useEffect로 나누면,
- 결과 상태 전환 후 클린업 타이밍 경쟁 없이 안정적으로 결과음 재생
- 언마운트 시 결과음도 확실히 중단
play()Promise 에러 무시로 콘솔 경고 방지
가 가능합니다.useEffect(() => { if (coinState === 'tossing') { // 동전 던질 때 false로 초기화 hasResultSoundPlayedRef.current = false; coinTossSound.currentTime = 0; - coinTossSound.play(); + void coinTossSound.play().catch(() => {}); - const timer = setTimeout(() => { + const tossTimer = window.setTimeout(() => { // 다음 화면 상태 전환 직전 사운드 명시적 정지 coinTossSound.pause(); coinTossSound.currentTime = 0; // 결과 결정 및 상태 업데이트 const result = Math.random() < 0.5 ? 'front' : 'back'; updateCoinState(result); - // 결과 소리 바로 재생 - setTimeout(() => { - if (!hasResultSoundPlayedRef.current) { - coinResultSound.currentTime = 0; - coinResultSound.play(); - hasResultSoundPlayedRef.current = true; - } - }, 100); // 약간의 딜레이로 자연스럽게 연결 - }, 2000); + }, 2000); return () => { - clearTimeout(timer); + clearTimeout(tossTimer); coinTossSound.pause(); coinTossSound.currentTime = 0; + // tossing 중 닫힐 때 혹시 재생 중인 결과음도 정지 + coinResultSound.pause(); + coinResultSound.currentTime = 0; }; } }, [coinState, coinTossSound, coinResultSound, updateCoinState]); +// 결과 상태 진입 시 한 번만 결과음 재생 +useEffect(() => { + if ((coinState === 'front' || coinState === 'back') && !hasResultSoundPlayedRef.current) { + coinResultSound.currentTime = 0; + void coinResultSound.play().catch(() => {}); + hasResultSoundPlayedRef.current = true; + + return () => { + coinResultSound.pause(); + coinResultSound.currentTime = 0; + }; + } +}, [coinState, coinResultSound]);검증 체크리스트:
- 동전 던지기 후 2초 내 모달을 닫아도(오버레이/닫기 버튼) 어떤 결과음도 재생되지 않음.
- 결과 화면에서 모달을 닫았다가 다시 열면 초기 상태로 시작 또는(요구 따라) 마지막 상태 복구.
- 탭 전환(숨김→복귀) 후 결과음이 중복 재생되지 않음.
🧹 Nitpick comments (3)
src/page/TableOverviewPage/TableOverviewPage.tsx (2)
66-77: 게스트/비게스트 분기 네비게이션 OK, 중복 옵션 최소화 여지로직은 정확합니다. 사소한 개선으로 동일한
state: { step: 'NameAndType' }를 상수화하거나useCallback으로 핸들러 메모이제이션하면 자식에 프롭으로 넘길 때 리렌더를 줄일 수 있습니다.- const handleEdit = () => { + const handleEdit = useCallback(() => { if (isGuestFlow()) { navigate(`/composition?mode=edit&type=CUSTOMIZE`, { state: { step: 'NameAndType' }, }); } else { navigate(`/composition?mode=edit&tableId=${tableId}&type=CUSTOMIZE`, { state: { step: 'NameAndType' }, }); } - }; + }, [navigate, tableId]);
201-201: 닫기 버튼 색상 변경 OK다만 useModal 기본값은 hover 색이 포함되어 있습니다. 동일한 hover 가시성이 필요하면 클래스에 hover 색도 함께 지정하는 것을 권장합니다.
-<ModalWrapper closeButtonColor="text-neutral-1000"> +<ModalWrapper closeButtonColor="text-neutral-1000 hover:text-neutral-700">src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (1)
132-147: 결과 이미지의 대체 텍스트 접근성 개선 제안스크린 리더를 위해 동적으로 “동전 앞면/뒷면”을 노출하면 좋습니다.
- <img - src={coinState === 'front' ? CoinFront : CoinBack} - alt="동전" - className="h-full w-full object-contain" - /> + <img + src={coinState === 'front' ? CoinFront : CoinBack} + alt={coinState === 'front' ? '동전 앞면' : '동전 뒷면'} + className="h-full w-full object-contain" + />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/page/TableOverviewPage/TableOverviewPage.tsx(5 hunks)src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx(5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/page/TableOverviewPage/TableOverviewPage.tsx (4)
src/hooks/useModal.tsx (1)
useModal(15-87)src/type/type.ts (1)
CoinState(5-5)src/util/sessionStorage.ts (1)
isGuestFlow(29-31)src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (1)
TeamSelectionModal(15-179)
src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (1)
src/type/type.ts (1)
CoinState(5-5)
🔇 Additional comments (13)
src/page/TableOverviewPage/TableOverviewPage.tsx (5)
10-11: 타입/유틸 임포트 정리 잘 됨
CoinState도입과isGuestFlow활용이 명확합니다.
21-21: 훅 임포트 추가 적절
useState,useCallback추가 OK.
30-34: 모달 오픈 시 단계를 항상 'initial'로 리셋 — 의도 확인 필요이 PR의 목표가 “재렌더링/재마운트 시 단계 초기화 방지”라면, 모달 “재오픈” 시에도 진행 단계를 복구해야 하는지 비즈니스 요구 확인 바랍니다. 현재 구현은 재오픈 때 무조건 초기화합니다.
원하는 UX가 “재오픈 시에도 마지막 결과 화면 유지”라면
handleOpenModal에서 조건부 리셋(예: tossing일 때만 초기화 등)으로 바꾸는 옵션을 고려해 보세요. 필요 시 패치 제안 드리겠습니다.
133-134: 모달 오픈 트리거 교체 적절
openModal직접 호출에서handleOpenModal로 교체하여 초기 상태 리셋 의도가 반영되었습니다.
205-208: 새 프롭 전달 정확
onEdit,initialCoinState,onCoinStateChange전달 모두 일치합니다.src/page/TableOverviewPage/components/TeamSelectionModal/TeamSelectionModal.tsx (8)
1-6: 임포트/타입 정리 이상 없음
CoinState외부 타입 사용으로 중복 제거.
10-13: 컴포넌트 퍼블릭 API 확장 합리적부모 제어형 초기값/콜백 패턴 적합합니다.
22-31: 상태 동기화 헬퍼 깔끔함
updateCoinState로 로컬/부모 동시 업데이트 구조 적절.
76-85: 초기값과 동일한 결과 상태에서 결과음 억제 로직, 의도에 부합리마운트 시 중복 재생 방지에 유효합니다. 위 권장 리팩터와 함께 사용해도 문제 없습니다.
87-96: 닫고 진행(편집/시작) 순서 OK모달 먼저 닫은 뒤 후속 액션 실행으로 UX 깔끔.
105-111: 'initial' 화면 카피/타이포그래피 적절가이드 텍스트 명확합니다.
113-130: 'tossing' 화면 상태 전환 UI 적절상태 안내 텍스트와 애니메이션 이미지 배치 합리적입니다.
151-176: CTA 그룹 구성 적절초기/결과 단계별 버튼 노출 전환이 명확합니다.
🚩 연관 이슈
closed #362
📝 작업 내용
디자인 작업 반영
써니가 요청한 요소 뱃지 크기, 버튼 크기 조정과 버튼 호버 효과를 반영했습니다.
코인토스 설명 플로우 추가 및 변경
팀 선정하기 클릭 -> 코인토스 설명 및 동전 던지기 버튼 화면 -> 동전 던지기 버튼 클릭 -> 동전 던지기 화면 -> 2초 뒤 -> 동전 던지기 결과 화면 및 토론 정보 수정하기, 토론 시작하기 버튼
아래 피그마를 참고하셔요 !
동전 던지기 결과가 나왔는데도 동전 던지기 소리가 계속 나오는 문제 해결
콜리가 말씀해 주셨던 문제인데요!
그냥 음원을 2초로 자를까 하다가 동전 던지기 결과 화면으로 전환 전에 사운드를 명시적으로 정지하도록 하여 해결했습니다.
모달이 재렌더링 되면서 코인 토스의 진행 단계가 초기화 되는 문제
모달이 재렌더링 되면서 상태가 모두 초기화 되어 동전을 던졌음에도 불구하고 다시 던지는 문제가 발생했습니다.
이를 해결하기 위해
동전 던지기 결과 사운드가 다른 탭에 있다가 왔을 때 다시 울리는 문제
위의 문제를 해결하고 나니 모달 내부의 화면은 유지하지만 사운드는 다시 울리는 문제를 발견했습니다.
모달이 재마운트되면서 다시 back또는 front 상태에 진입했다고 여겨 사운드가 울리는 것이 원인이었습니다.
처음에 ref로 해결하려고 했을 때 아예 소리가 안 나게 되는 새로운 버그가 ^^ ..
동전 던지기와 연결해서 바로 나오도록 하니 문제가 해결되더라고요..
이제는 동전 던지기 후 결과 알림은 나오고 그 상태에서 탭 전환 후 돌아와도 결과 알림이 또 울리지 않습니다 !!!
원래는 계속 띵동! 띵동! 했다는 ..
🏞️ 스크린샷 (선택)
default.mov
🗣️ 리뷰 요구사항 (선택)
언제나 꼼꼼하게 봐주셔서 감사합니다☺️ !!!!!!!
Summary by CodeRabbit
신기능
버그 수정 / 개선