Skip to content

[FIX] 반복일정 투두의 타이머 카드 동기화 오류 수정#241

Merged
kimminna merged 4 commits into
developfrom
fix/web/236-recurring-todo-timer-sync
Jul 16, 2026
Merged

[FIX] 반복일정 투두의 타이머 카드 동기화 오류 수정#241
kimminna merged 4 commits into
developfrom
fix/web/236-recurring-todo-timer-sync

Conversation

@jjangminii

Copy link
Copy Markdown
Contributor

ISSUE 🔗

close #236



What is this PR? 🔍

반복일정으로 설정된 투두가 같은 todoId를 공유하는 다른 날짜에서도 타이머가 실행 중인 것처럼 잘못 표시되던 문제를 수정했습니다.

배경

  • 기존 구조: 클라이언트는 활성 타이머와 화면에 그려진 투두를 오직 todoId로만 매칭해서 "지금 이 투두의 타이머가 실행 중인지"를 판단하고 있었습니다.
  • 발생 문제: 반복일정 투두는 여러 날짜에 걸쳐 같은 todoId를 공유하는데, 한 날짜에서 타이머를 재생하면 같은 todoId를 가진 다른 날짜의 투두 카드들도 전부 실행 중으로 표시됐습니다.
  • 해결 방향: 서버가 타이머 시작/활성 조회 응답에 date(타이머가 귀속되는 날짜) 필드를 추가했고, 클라이언트에서도 활성 타이머와 투두를 (todoId, date) 조합으로 매칭하도록 전 화면의 비교 로직을 수정했습니다.

타이머-투두 매칭 로직

  • 변경 요약: Home/Today/Focus 탭과 할 일 수정 모달에서 활성 타이머와 투두를 매칭할 때 todoId 단독 비교 대신 todoId + date 조합으로 비교하도록 수정했습니다.
  • 이유: /v3/api-docs에서 실제 응답 스펙을 확인해보니 startTimer/getActiveTimer 두 엔드포인트 모두 date가 신규 필수 필드로 추가돼 있었고, API 설명에도 "반복 투두는 여러 날짜에 같은 todoId로 노출되므로, 실행중 표시는 todoId가 아닌 (todoId, date) 조합으로 구분해야 합니다"라고 명시돼 있었습니다.
  • 구현 방식: pnpm gen:api로 orval 코드를 재생성해 TimerActiveResponse/TimerStartResponsedate: string을 반영했습니다(이번 작업과 무관하게 함께 딸려온 다른 도메인 재생성분은 되돌려 diff에서 제외했습니다). 로컬 zod 스키마 activeTimerSchema(schemas/timer/timer-schema.ts)에도 date를 추가해 응답을 한 번 더 검증하도록 했습니다. 이후 activeTimer.todoId === todo.todoId 형태의 비교가 있던 7개 지점(use-focus-session.ts, use-home-todos-by-date.ts 2곳, useTodayTodoList.ts 2곳, HomeTodoContainer.tsx, TodayTodoListContainer.tsx, DetailTodoModalContainer.tsx 2곳)에 activeTimer.date === <해당 스코프의 날짜> 비교를 추가했습니다. Focus 탭은 개별 투두에 날짜가 없어 focusView.date(조회 중인 날짜)와 비교했고, 나머지는 각 화면이 이미 들고 있는 dateKey/todo.date와 비교했습니다.
  • 경계 · 제약: TimeboxPanel.tsx의 타임박스-활성타이머 매칭은 이미 timerId(세션마다 고유)로 비교하고 있어 todoId만으로 인한 모호함이 없었으므로 그대로 뒀습니다.



To Reviewers

activeTimer.date와 비교하는 기준 날짜가 화면마다 다릅니다(Home/Today는 투두가 속한 날짜, Focus는 조회 중인 날짜). 각 지점에서 비교 기준으로 쓴 날짜 값이 맞는지 한 번씩 봐주시면 좋을 것 같습니다.



Screenshot 📷



Test Checklist ✔

  • pnpm check-types 통과
  • pnpm lint 통과
  • 반복일정 투두를 한 날짜에서 재생했을 때 다른 날짜의 같은 투두가 더 이상 실행 중으로 표시되지 않는지 실제 dev 서버에서 확인

- 타이머 시작/활성 조회 API 응답에 추가된 date 필드를 반영하도록 orval 코드를 재생성했습니다
- 활성 타이머와 투두를 매칭할 때 todoId뿐 아니라 date까지 함께 비교하도록 수정해, 반복일정 투두가 다른 날짜에서도 실행 중으로 표시되던 문제를 해결했습니다
@vercel

vercel Bot commented Jul 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
timo Ready Ready Preview, Comment Jul 16, 2026 3:23am

Request Review

@github-actions github-actions Bot added the ⏰ Timo-web Timo 웹 서비스 label Jul 15, 2026
@github-actions
github-actions Bot requested review from ehye1 and kimminna July 15, 2026 18:25
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5e1294d5-1f6b-4286-bfd9-38e97d3a2741

📥 Commits

Reviewing files that changed from the base of the PR and between 1fe631c and 930d44b.

📒 Files selected for processing (5)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts
  • apps/timo-web/app/[locale]/(main)/focus/_hooks/use-focus-session.ts
  • apps/timo-web/messages/en.json

Walkthrough

활성 타이머 스키마에 날짜를 추가하고, 타이머 상호작용과 화면 표시에서 todoId와 날짜를 함께 비교하도록 변경했습니다. 반복 투두의 다른 날짜 항목은 해당 활성 타이머로 처리되지 않습니다.

Changes

날짜 기반 활성 타이머 매칭

Layer / File(s) Summary
활성 타이머 날짜 계약
apps/timo-web/schemas/timer/timer-schema.ts
activeTimerSchema에 필수 date 문자열 필드를 추가했습니다.
타이머 상호작용 날짜 검증
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts, apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts
완료 처리와 재생·일시정지·재개 분기가 todoId와 날짜가 모두 일치할 때만 실행됩니다.
타이머 상태 및 표시 검증
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx, apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx, apps/timo-web/app/[locale]/(main)/focus/_hooks/use-focus-session.ts, apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx, apps/timo-web/messages/en.json
활성 상태, 포커스 타이머 선택, 재생 하이라이트와 타이머 상태 계산에 날짜 조건을 적용하고 중지 모달 버튼 문구를 Finish로 변경했습니다.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

  • Team-Timo/ Timo-Server#177 — 서버가 제공하는 활성 타이머 날짜를 클라이언트의 타이머 액션 매칭에 함께 사용하도록 요구한 이슈와 직접 연결됩니다.

Possibly related PRs

Suggested reviewers: kimminna, ehye1

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 문제 수정과 무관한 en.json의 Switch→Finish 문구 변경이 함께 포함되어 있습니다. 해당 문구 변경은 별도 PR로 분리하거나, 실제 기능 변경과 직접 연관된 경우에만 유지하세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 반복일정 투두의 타이머 카드 동기화 오류 수정이라는 핵심 변경을 정확히 담고 있습니다.
Description check ✅ Passed 설명이 반복일정 투두의 타이머 매칭을 todoId+date로 바꾸는 변경과 문제 배경을 잘 설명합니다.
Linked Issues check ✅ Passed 연결된 #236의 요구사항인 날짜 기반 매칭과 서버 응답 반영이 코드 변경에 반영되었습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/web/236-recurring-todo-timer-sync

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.

@github-actions github-actions Bot added 🐛 Bug 기능이 정상적으로 작동하지 않는 문제 수정 ♠️ 정민 정민양 labels Jul 15, 2026
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

Timo Performance Report

Bundle Size — timo-web
라우트 크기 First Load JS
/[locale]/home 211.42 kB 🔴 417.28 kB
/[locale]/today 195.62 kB 🔴 401.48 kB
/[locale]/focus 160.66 kB 🔴 366.52 kB
/[locale]/settings 167.19 kB 🔴 373.05 kB
/[locale]/statistics 233.45 kB 🔴 439.31 kB
/[locale]/[...rest] 0 B 🟡 205.86 kB
/[locale]/login 212.96 kB 🔴 418.82 kB
/[locale]/oauth/callback 119.66 kB 🟡 325.52 kB
/[locale]/onboarding 233.44 kB 🔴 439.30 kB
/[locale] 118.97 kB 🟡 324.83 kB
/[locale]/policy 125.09 kB 🟡 330.96 kB

공유 번들: 205.86 kB
🟢 < 200kB  |  🟡 < 350kB  |  🔴 ≥ 350kB (First Load JS · gzip)

Lighthouse — timo-web
URL Perf A11y LCP CLS TBT
/en/home 🔴 65 🟢 95 🔴 15.6s 🟢 0.000 🟡 372ms
/en/today 🔴 64 🟢 95 🔴 15.6s 🟢 0.000 🟡 422ms
/en/focus 🔴 65 🟢 95 🔴 15.3s 🟢 0.000 🟡 392ms
/en/statistics 🔴 62 🟢 95 🔴 15.2s 🟢 0.000 🟡 498ms

Perf ≥ 70 / A11y ≥ 85 목표
LCP 🟢 < 2.5s 🟡 < 4s 🔴 ≥ 4s  |  CLS 🟢 < 0.1 🟡 < 0.25 🔴 ≥ 0.25  |  TBT 🟢 < 200ms 🟡 < 600ms 🔴 ≥ 600ms

Image Optimization — timo-web
파일 크기 포맷 상태
favicon.png 27.84 kB PNG ⚠️ 🟢
images/google-calendar.png 36.20 kB PNG ⚠️ 🟢
images/google-logo.png 26.79 kB PNG ⚠️ 🟢

총 3개 · 90.84 kB  |  🟢 < 200KB  |  🟡 < 500KB  |  🔴 ≥ 500KB
⚠️ 3개 파일 WebP/AVIF 변환 권장

측정 커밋: 4c65fd5

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts:
- Around line 98-102: The activeTimer condition must explicitly narrow the
nullable value before accessing its properties. Update the condition in
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
lines 98-102,
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts
lines 84-88, and
apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx lines
75-77 to use activeTimer && followed by the todoId and date comparisons,
preserving the existing completed and matching-date behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a2aed907-ba6d-4bff-8241-7f742c74e628

📥 Commits

Reviewing files that changed from the base of the PR and between dd18e8a and 1fe631c.

⛔ Files ignored due to path filters (4)
  • apps/timo-web/api/generated/endpoints/timer/timer.ts is excluded by !**/generated/**
  • apps/timo-web/api/generated/endpoints/timer/timer.zod.ts is excluded by !**/generated/**
  • apps/timo-web/api/generated/models/timerActiveResponse.ts is excluded by !**/generated/**
  • apps/timo-web/api/generated/models/timerStartResponse.ts is excluded by !**/generated/**
📒 Files selected for processing (7)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/HomeTodoContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts
  • apps/timo-web/app/[locale]/(main)/focus/_hooks/use-focus-session.ts
  • apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx
  • apps/timo-web/schemas/timer/timer-schema.ts

Comment on lines +98 to +102
if (
completed &&
activeTimer?.todoId === todoId &&
activeTimer.date === dateKey
) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

activeTimer 타입 좁히기(Type Narrowing) 및 코드 일관성 개선

동일한 파일 내 다른 핸들러(예: handleTogglePlay)에서는 activeTimer && activeTimer.todoId === todoId 형태로 안전하게 타입을 좁히고 있습니다. 반면 아래 코드들에서는 옵셔널 체이닝(?.)을 사용한 후 다시 activeTimer.date에 직접 접근하고 있어 코드의 일관성이 떨어지며, TypeScript 환경에 따라 타입 좁히기가 완벽하게 동작하지 않아 컴파일 에러가 발생할 여지가 있습니다. (참고: TypeScript: Type Narrowing)
안전하고 통일성 있는 코드를 위해 명시적 Null 체크 방식으로 맞춰주시는 것을 추천해요! 🛠️

  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts#L98-L102: activeTimer && activeTimer.todoId === todoId && activeTimer.date === dateKey 구조로 수정하세요.
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts#L84-L88: 위와 동일하게 수정하세요.
  • apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx#L75-L77: activeTimer && activeTimer.todoId === todoId && activeTimer.date === date 구조로 수정하세요.
📍 Affects 3 files
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts#L98-L102 (this comment)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts#L84-L88
  • apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx#L75-L77
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
around lines 98 - 102, The activeTimer condition must explicitly narrow the
nullable value before accessing its properties. Update the condition in
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
lines 98-102,
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts
lines 84-88, and
apps/timo-web/containers/todo-modal/detail/DetailTodoModalContainer.tsx lines
75-77 to use activeTimer && followed by the todoId and date comparisons,
preserving the existing completed and matching-date behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx:
- Around line 121-124: In the todo rendering loop, update the code around the
date properties to call parseDateKey(todo.date) once, store its
fallback-resolved result in a parsedDate variable, and reuse that variable for
both date and dateValue instead of repeating the parseDateKey invocation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5e1294d5-1f6b-4286-bfd9-38e97d3a2741

📥 Commits

Reviewing files that changed from the base of the PR and between 1fe631c and 930d44b.

📒 Files selected for processing (5)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts
  • apps/timo-web/app/[locale]/(main)/focus/_hooks/use-focus-session.ts
  • apps/timo-web/messages/en.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx:
- Around line 121-124: In the todo rendering loop, update the code around the
date properties to call parseDateKey(todo.date) once, store its
fallback-resolved result in a parsedDate variable, and reuse that variable for
both date and dateValue instead of repeating the parseDateKey invocation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5e1294d5-1f6b-4286-bfd9-38e97d3a2741

📥 Commits

Reviewing files that changed from the base of the PR and between 1fe631c and 930d44b.

📒 Files selected for processing (5)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_hooks/use-home-todos-by-date.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts
  • apps/timo-web/app/[locale]/(main)/focus/_hooks/use-focus-session.ts
  • apps/timo-web/messages/en.json
🛑 Comments failed to post (1)
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx (1)

121-124: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

parseDateKey 중복 호출 최적화

정규식을 사용하는 parseDateKey 함수가 불필요하게 두 번 호출되고 있네요! 렌더링 루프 내에서의 성능 최적화를 위해 변수로 한 번만 추출해서 재사용하면 더 좋을 것 같습니다. 성능 향상을 위한 좋은 습관입니다! 🚀 (참고: React Rendering Behavior)

♻️ 제안하는 리팩토링

컴포넌트의 return 윗부분에 변수를 선언해 주세요.

const parsedDate = parseDateKey(todo.date) ?? new Date();

그 후 아래와 같이 속성을 수정해 주세요.

-                    date: formatShortDateLabel(
-                      parseDateKey(todo.date) ?? new Date(),
-                    ),
-                    dateValue: parseDateKey(todo.date) ?? new Date(),
+                    date: formatShortDateLabel(parsedDate),
+                    dateValue: parsedDate,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx
around lines 121 - 124, In the todo rendering loop, update the code around the
date properties to call parseDateKey(todo.date) once, store its
fallback-resolved result in a parsedDate variable, and reuse that variable for
both date and dateValue instead of repeating the parseDateKey invocation.

@ehye1 ehye1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

반복 일정 타이머 분리돼서 작동하는 거 확인했습니다.
수고하셨습니다!

@kimminna kimminna left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

확인했습니다!

@kimminna
kimminna merged commit b6b277c into develop Jul 16, 2026
14 checks passed
@kimminna
kimminna deleted the fix/web/236-recurring-todo-timer-sync branch July 16, 2026 05:24
@kimminna kimminna mentioned this pull request Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⏰ Timo-web Timo 웹 서비스 ♠️ 정민 정민양 🐛 Bug 기능이 정상적으로 작동하지 않는 문제 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIX] 반복일정 투두의 타이머 카드 동기화 오류 수정

3 participants