Skip to content

Conversation

@i-meant-to-be
Copy link
Contributor

@i-meant-to-be i-meant-to-be commented Aug 24, 2025

🚩 연관 이슈

closed #348

📝 작업 내용

첫 번째 오류

🐞 상세 내용

image

1회당 발언 시간이 없는 시간 총량제 타이머의 남은 시간 텍스트 크기가, 작은 적응형 화면에서 비정상적으로 커 보였던 문제

🔍 원인

다른 타이머 UI 요소와는 다르게, 1회당 발언 시간 없는 시간 총량제 타이머의 텍스트에만 적응형이 적용되지 않았었음

⚒️ 해결

image

적응형 적용하여 큰 화면에서는 110 px(써니가 넘겨준 원래 규격), 작은 화면에서는 90 px로 렌더링되도록 수정

두 번째 오류

🐞 상세 내용

시간 총량제 타이머 발언 시간이 끝난 상태여도, 프로그레스 바가 원래대로 복원되었던 문제

🔍 원인

  • 타이머 애니메이션 진행도(단위 %)는 시작할 때에는 0%이고, 완료될 때에는 100%임
  • 그러나 현재 로직은 완료 시 100%가 아닌 0%로 초기화하도록 짜여져 있었음 (나의 실수 😢)

⚒️ 해결

2025-08-24.180541.mp4

타이머가 종료됐을 때, 타이머 애니메이션 진행도가 0%가 아닌 100%로 초기화되도록 수정

그 외 변경 사항

TailwindCSS의 tabular-nums 태그를 두 타이머 - 시간 총량제 타이머와 일반 타이머 - 모두에 적용하여, 숫자가 동일한 너비를 차지하게 해 UI가 튀는 상황을 방지할 수 있게 했어요.

🏞️ 스크린샷 (선택)

위에 첨부하였으므로 생략

🗣️ 리뷰 요구사항 (선택)

없음

Summary by CodeRabbit

  • 신기능
    • 타이머 진행률 계산 로직 개선으로 팀별/발언별 기준에 따른 진행률이 더 정확히 표시됩니다.
  • 스타일
    • CircularTimer의 “1회당 발언 시간 X” 글자 크기와 패딩 조정으로 가독성 향상.
    • 숫자 표시 전반에 tabular-nums 적용으로 자릿수 정렬이 일관되게 개선되었습니다.
  • 버그 수정
    • 총 타이머 또는 발언 타이머가 없거나 0일 때의 진행률 처리 문제 수정되었습니다.

@i-meant-to-be i-meant-to-be requested review from jaeml06 and useon August 24, 2025 09:07
@i-meant-to-be i-meant-to-be self-assigned this Aug 24, 2025
@i-meant-to-be i-meant-to-be added the fix 버그 수정 label Aug 24, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 24, 2025

Walkthrough

타이머 진행률 계산(initRawProgress)을 speakingTimer 존재 여부 기준으로 재구성하고, 숫자 폰트(tabular-nums)·크기·패딩 등 타이포그래피를 조정하며 일부 포매팅(useMemo 도입, 공백 라인 추가)을 적용했습니다.

Changes

Cohort / File(s) Change Summary
Progress 계산 로직
src/page/TimerPage/components/TimeBasedTimer.tsx
initRawProgress를 speakingTimer null 여부로 분기하도록 재작성. 총량제(totalTimer)와 발언제(speakingTimer)에 따른 각각의 퍼센트 계산식으로 정리하고 불필요한 분기(이전 조건 일부 및 최종 return 0)를 제거.
UI 타이포/레이아웃 조정
src/page/TimerPage/components/TimeBasedTimer.tsx
CircularTimer 내부 숫자 크기(text-[110px]→text-[90px], xl:text-[110px]), space-x 제거, 패딩 단순화(p-[16px]) 등 레이아웃/타이포 조정. 여러 텍스트에 tabular-nums 추가.
소규모 표시 변경
src/page/TimerPage/components/NormalTimer.tsx
타이머 숫자 출력에 tabular-nums 클래스 추가(시각적/타이포 변화, 로직 불변).
포맷팅/리팩터링
src/page/TimerPage/components/TimeBasedTimer.tsx
구조분해 후 공백 라인 추가, useMemo 도입 및 사소한 포매팅 정리(비기능적 변경).

Sequence Diagram(s)

sequenceDiagram
  participant UI as TimerPage UI
  participant T as TimeBasedTimer
  participant S as Timers (speakingTimer, totalTimer)

  UI->>T: 렌더링 요청
  T->>S: speakingTimer, totalTimer 조회
  alt speakingTimer == null
    alt item.timePerTeam && totalTimer 존재 및 >0
      T->>T: progress = (item.timePerTeam - totalTimer) / item.timePerTeam * 100
    else
      T->>T: progress = 100
    end
  else speakingTimer != null
    alt item.timePerSpeaking && speakingTimer 존재 및 >0
      T->>T: progress = (item.timePerSpeaking - speakingTimer) / item.timePerSpeaking * 100
    else
      T->>T: progress = 100
    end
  end
  T-->>UI: 렌더링 데이터 (progress, 숫자 스타일 변경)
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Assessment against linked issues

Objective Addressed Explanation
작은 크기에서 숫자가 너무 큰 문제 수정 (#348)
발언 시간이 끝난 상태에서 프로그레스 바 복원 문제 수정 (#348)

Possibly related PRs

Suggested reviewers

  • useon
  • jaeml06

Poem

깡총깡총, 초침 뛰며 코드를 뜯네 🐇
숫자들 줄여 입혀, 흐름은 멈추지 않네 ⏱️
말할 시간 끝나면, 다시는 뒤돌지 않게
깡총—작지만 단단한 시간의 발자국.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/#348

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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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

@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 (3)
src/page/TimerPage/components/TimeBasedTimer.tsx (3)

58-69: 완료/오버타임 경계 처리 보강 제안(음수 잔여 시간 포함)

현재 조건이 totalTimer의 truthy 여부에 의존해 0일 때만 100%로 전환합니다. 타이머가 0 아래로 내려가는(오버타임) 순간에는 100%를 넘는 값이 계산될 수 있습니다. 훅(useCircularTimerAnimation)에서 0–100으로 clamp된다는 러닝 메모는 알고 있으나, 원값을 100으로 고정하면 불필요한 점프/보간을 줄일 수 있습니다.

제안 diff:

-      if (item.timePerTeam && totalTimer && item.timePerTeam > 0) {
-        // 팀당 발언 시간 타이머가 정상 동작 중이고 남은 시간이 있을 경우, 진행도를 계산
-        return ((item.timePerTeam - totalTimer) / item.timePerTeam) * 100;
+      if (item.timePerTeam && item.timePerTeam > 0 && totalTimer !== null && totalTimer !== undefined) {
+        if (totalTimer <= 0) {
+          // 완료 또는 오버타임 시 100% 고정
+          return 100;
+        }
+        return ((item.timePerTeam - totalTimer) / item.timePerTeam) * 100;
       } else {
         // 팀당 발언 시간 타이머가 멈추거나 완료된 경우,
         // 완료(100%)에 해당하는 진행도를 반환
         return 100;
       }

71-85: 말풍선(1회당) 진행도 계산에서 totalTimer 의존 제거 검토

1회당 발언 시간의 진행도는 speakingTimeritem.timePerSpeaking만으로 결정 가능합니다. 현재는 totalTimer까지 truthy 여야 계산하도록 되어 있어, 드물게 전체 타이머가 0이 된 프레임에서 speakingTimer가 아직 0이 아니라도 100%로 튀는 상황이 생길 여지가 있습니다. 안정성을 위해 의존 제거를 권합니다.

제안 diff:

-      if (
-        item.timePerSpeaking &&
-        speakingTimer &&
-        totalTimer &&
-        item.timePerSpeaking > 0
-      ) {
-        // 1회당 발언 시간 타이머가 정상 동작 중이고 남은 시간이 있을 경우, 진행도를 계산
-        return (
-          ((item.timePerSpeaking - speakingTimer) / item.timePerSpeaking) * 100
-        );
+      if (
+        item.timePerSpeaking &&
+        item.timePerSpeaking > 0 &&
+        speakingTimer !== null &&
+        speakingTimer !== undefined
+      ) {
+        if (speakingTimer <= 0) {
+          return 100;
+        }
+        return ((item.timePerSpeaking - speakingTimer) / item.timePerSpeaking) * 100;
       } else {
         // 1회당 발언 시간 타이머가 멈추거나 완료된 경우,
         // 완료(100%)에 해당하는 진행도를 반환
         return 100;
       }

검증 포인트:

  • 전체 타이머가 0에 도달하는 프레임과 1회당 타이머가 0이 되는 프레임이 엇갈릴 수 있는지.
  • 만약 항상 동시에 0이 된다면(동기화 보장), 위 변경은 체감 영향이 없고 방어적 개선입니다.

133-137: 작은 화면에서 타이포그래피 축소 적용 LGTM + 숫자 정렬 가독성 향상 제안

text-[90px] (xl:110px)로의 조정은 요구사항에 부합합니다. 추가로 숫자 폭을 고정하면 점프/깜빡임이 줄어듭니다.

미세 개선 diff(선택):

-          <span className="flex w-full flex-row items-center justify-center p-[16px] text-[90px] font-bold text-default-black xl:text-[110px]">
+          <span className="flex w-full flex-row items-center justify-center p-[16px] text-[90px] font-bold text-default-black tabular-nums xl:text-[110px]">

Tailwind 기본 tabular-nums 유틸이 활성화되어 있다면 적용 가능하며, 없으면 무시하셔도 됩니다.

📜 Review details

Configuration used: CodeRabbit UI

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 e6d68d9 and e20beee.

📒 Files selected for processing (1)
  • src/page/TimerPage/components/TimeBasedTimer.tsx (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-08T14:21:17.745Z
Learnt from: i-meant-to-be
PR: debate-timer/debate-timer-fe#335
File: src/page/TimerPage/components/NormalTimer.tsx:50-54
Timestamp: 2025-08-08T14:21:17.745Z
Learning: Progress 퍼센트(원형 게이지)는 컴포넌트가 아닌 훅(src/page/TimerPage/hooks/useCircularTimerAnimation.ts)에서 0–100으로 clamp한다. 향후 리뷰에서는 컴포넌트 레벨에서의 중복 clamp 제안 대신 훅 사용을 권장한다.

Applied to files:

  • src/page/TimerPage/components/TimeBasedTimer.tsx
🪛 GitHub Check: test
src/page/TimerPage/components/TimeBasedTimer.tsx

[failure] 10-10:
'useMemo' is defined but never used

🪛 GitHub Actions: frontend-CI
src/page/TimerPage/components/TimeBasedTimer.tsx

[error] 10-10: ESLint: 'useMemo' is defined but never used. (no-unused-vars). Step: eslint .

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

🧹 Nitpick comments (2)
src/page/TimerPage/components/NormalTimer.tsx (1)

151-157: 불필요한 래핑 화살표 함수 제거로 미세 최적화

onReset={() => resetTimer()} 대신 핸들러를 그대로 넘겨도 됩니다. 불필요한 클로저 생성을 줄입니다.

적용 제안:

-          onReset={() => resetTimer()}
+          onReset={resetTimer}
src/page/TimerPage/components/TimeBasedTimer.tsx (1)

60-69: truthy 검사 대신 명시적 number 가드로 안전성 향상

totalTimer/speakingTimer에 대한 truthy 검사는 0을 의도적으로 “완료”로 처리하는 데에는 맞지만, 명시적 타입 가드가 가독성과 안전성(예: NaN)에서 더 낫습니다. 또한 speakingTimer 분기에서도 <= 0 처리 일관성을 맞추면 의도가 더 명확합니다.

제안 diff:

-      if (item.timePerTeam && totalTimer && item.timePerTeam > 0) {
-        // 팀당 발언 시간 타이머가 정상 동작 중이고 남은 시간이 있을 경우, 진행도를 계산
-        if (totalTimer <= 0) {
-          return 100;
-        }
-        return ((item.timePerTeam - totalTimer) / item.timePerTeam) * 100;
-      } else {
+      if (
+        typeof totalTimer === 'number' &&
+        Number.isFinite(totalTimer) &&
+        item.timePerTeam &&
+        item.timePerTeam > 0
+      ) {
+        if (totalTimer <= 0) return 100;
+        return ((item.timePerTeam - totalTimer) / item.timePerTeam) * 100;
+      } else {
         // 팀당 발언 시간 타이머가 멈추거나 완료된 경우,
         // 완료(100%)에 해당하는 진행도를 반환
         return 100;
       }
 …
-      if (item.timePerSpeaking && speakingTimer && item.timePerSpeaking > 0) {
-        // 1회당 발언 시간 타이머가 정상 동작 중이고 남은 시간이 있을 경우, 진행도를 계산
-        return (
-          ((item.timePerSpeaking - speakingTimer) / item.timePerSpeaking) * 100
-        );
-      } else {
+      if (
+        typeof speakingTimer === 'number' &&
+        Number.isFinite(speakingTimer) &&
+        item.timePerSpeaking &&
+        item.timePerSpeaking > 0
+      ) {
+        if (speakingTimer <= 0) return 100;
+        return (
+          ((item.timePerSpeaking - speakingTimer) / item.timePerSpeaking) * 100
+        );
+      } else {
         // 1회당 발언 시간 타이머가 멈추거나 완료된 경우,
         // 완료(100%)에 해당하는 진행도를 반환
         return 100;
       }

Also applies to: 72-81

📜 Review details

Configuration used: CodeRabbit UI

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 e20beee and 0d4fb7f.

📒 Files selected for processing (2)
  • src/page/TimerPage/components/NormalTimer.tsx (1 hunks)
  • src/page/TimerPage/components/TimeBasedTimer.tsx (5 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-08T14:21:17.745Z
Learnt from: i-meant-to-be
PR: debate-timer/debate-timer-fe#335
File: src/page/TimerPage/components/NormalTimer.tsx:50-54
Timestamp: 2025-08-08T14:21:17.745Z
Learning: Progress 퍼센트(원형 게이지)는 컴포넌트가 아닌 훅(src/page/TimerPage/hooks/useCircularTimerAnimation.ts)에서 0–100으로 clamp한다. 향후 리뷰에서는 컴포넌트 레벨에서의 중복 clamp 제안 대신 훅 사용을 권장한다.

Applied to files:

  • src/page/TimerPage/components/TimeBasedTimer.tsx
🔇 Additional comments (6)
src/page/TimerPage/components/NormalTimer.tsx (1)

136-139: tabular-nums 적용과 소형 화면 폰트 다운스케일링이 목적에 부합 — LGTM

  • 숫자 폭을 고정(tabular-nums)해 자리수 변화 시 레이아웃 점프를 방지한 점이 좋습니다.
  • 기본 text-[70px], xl:text-[110px]로의 반응형 조정도 의도(작은 화면에서 과대 표시 방지)에 맞습니다.
src/page/TimerPage/components/TimeBasedTimer.tsx (5)

57-86: 타이머 종료 시 진행도를 100%로 유지하도록 수정 — 핵심 버그 해결됨

  • speakingTimer null(= 1회당 발언 시간 X)·not null(= O) 각각에서 “타이머 종료·멈춤·미설정” 시 100%를 반환하는 분기 덕분에, 완료 직후 0%로 돌아가던 문제를 해소했습니다.
  • 참고: 이전 러닝(2025-08-08)대로 진행도 clamp(0–100)는 useCircularTimerAnimation 훅에서 처리하므로, 컴포넌트 레벨 중복 clamp가 없다는 점도 적절합니다.

128-135: 소형 화면 90px / XL 110px로의 반응형 조정 — PR 목적 1 충족

작은 화면에서의 과대 표시 이슈를 해소하면서, XL에서는 기존 가독성(110px)을 유지한 구성으로 보입니다. 숫자 컨테이너에도 padding만 남기고 space-x를 제거해 밀집도를 안정화한 점도 👍


128-135: 오버타임(음수) 표기 정책 확인 요청

현재 X 케이스(1회당 발언 시간 없음)에서 minute/secondMath.abs로 렌더링되고 음수 기호는 표시하지 않습니다. NormalTimer는 음수일 때 별도 -를 노출하는데, TimeBasedTimer에서 의도적으로 숨기는 것인지 확인이 필요합니다. 오버타임 가시성이 필요하다면 아래처럼 일관화할 수 있습니다.

적용 예시(diff):

-        {speakingTimer === null && (
-          <span className="flex w-full flex-row items-center justify-center p-[16px] text-[90px] font-bold tabular-nums text-default-black xl:text-[110px]">
-            <p className="flex flex-1 items-center justify-center">{minute}</p>
-            <p className="flex items-center justify-center">:</p>
-            <p className="flex flex-1 items-center justify-center">{second}</p>
-          </span>
-        )}
+        {speakingTimer === null && (
+          <span
+            className={clsx(
+              'flex w-full flex-row items-center justify-center p-[16px] text-[90px] font-bold tabular-nums text-default-black xl:text-[110px]',
+              { 'space-x-[8px]': (totalTimer ?? 0) < 0 },
+              { 'space-x-[16px]': (totalTimer ?? 0) >= 0 },
+            )}
+          >
+            {(totalTimer ?? 0) < 0 && (
+              <p className="flex items-center justify-center">-</p>
+            )}
+            <p className="flex flex-1 items-center justify-center">{minute}</p>
+            <p className="flex items-center justify-center">:</p>
+            <p className="flex flex-1 items-center justify-center">{second}</p>
+          </span>
+        )}

디자인 정책상 음수 미표시가 맞다면, 이 코멘트는 무시하셔도 됩니다.


143-151: 전체 시간 블록에 tabular-nums 적용 — 숫자 폭 일관성 확보

자릿수 변동(예: 10→9초) 시 레이아웃 점프를 방지합니다. 고정 폭 컨테이너(w-[80/120px])와도 잘 어울립니다.


165-172: 현재 시간 블록에도 tabular-nums 적용 — 시각적 안정성 개선

가장 큰 숫자 영역에 적용되어 효과가 큽니다. 반응형 폰트 사이즈(ld/xl)와 고정 폭 컨테이너의 조합도 적절합니다.

Copy link
Contributor

@jaeml06 jaeml06 left a comment

Choose a reason for hiding this comment

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

넵 확인했습니다. 정상작동되는 것 확인했습니다

Copy link
Contributor

@useon useon left a comment

Choose a reason for hiding this comment

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

크기 줄어든거랑 시간이 종료되어도 회색으로 유지되는 것 확인했습니다 !!!! 👍

@i-meant-to-be i-meant-to-be merged commit 1f8c384 into develop Aug 28, 2025
2 checks passed
@i-meant-to-be i-meant-to-be deleted the fix/#348 branch August 28, 2025 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix 버그 수정

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[FIX] 타이머 오류 해결

4 participants