Skip to content

[FEAT] 오늘 탭 API 연동 - #185

Merged
ehye1 merged 10 commits into
developfrom
feat/web/180-today-todolist-api-integration
Jul 14, 2026
Merged

[FEAT] 오늘 탭 API 연동#185
ehye1 merged 10 commits into
developfrom
feat/web/180-today-todolist-api-integration

Conversation

@ehye1

@ehye1 ehye1 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

ISSUE 🔗

close #180



What is this PR? 🔍

`/api/v1/home/today` 엔드포인트를 today 탭에 연동하고, 투두 생성 API를 연결하며 아이콘 표시와 하위 투두 체크박스 정렬을 구현했습니다. 추가로 완료 투두 하단 정렬과 카드 클릭 시 상세 모달 진입을 구현했습니다.

배경

  • 기존 구조: `useTodayTodoList`가 하드코딩된 mock 배열(`todayTodoMocks`)을 `useState` 초기값으로 사용하는 구조였습니다.
  • 발생 문제: 서버 데이터와 무관하게 항상 같은 목 데이터가 표시되었고, `todoSchema` 등 응답 파싱 스키마가 home 도메인 내부(`home/_types/todo-type.ts`)에 있어 today가 이를 import하면 `structure.md`의 "도메인 간 직접 import 금지" 규칙을 위반하는 상황이었습니다.
  • 해결 방향: 공유 스키마를 `api/common/todo-schema.ts`로 이동한 뒤, today 전용 zod 스키마와 `useSuspenseQuery` 훅을 작성해 실제 API 데이터를 연동했습니다.

공유 스키마 이동 (`api/common/todo-schema.ts`)

  • 변경 요약: home 도메인에만 있던 `todoSchema`, `dayOfWeekSchema` 등 응답 파싱 스키마를 앱 공유 위치로 이동했습니다.
  • 이유: today 도메인이 동일한 스키마를 필요로 하는데, home 폴더에서 직접 import하면 도메인 간 경계 규칙을 어기기 때문입니다.
  • 구현 방식: `api/common/todo-schema.ts`에 `todoSchema`, `todoTimerStatusSchema`, `todoTagSchema`, `todoSubtaskSchema`, `todoCreateResponseSchema`, `dayOfWeekSchema`를 추가했습니다. 기존 `home/_types/todo-type.ts`는 re-export 배럴로 변환해 home 내부 import를 그대로 유지했습니다. `home/_types/home-view-type.ts`의 `apiDayOfWeekSchema`도 공유 위치에서 import하도록 수정했습니다.

today 탭 조회 API 연동

  • 변경 요약: `/api/v1/home/today` 조회 API를 `useSuspenseQuery`로 연동하고 mock 데이터를 제거했습니다.
  • 이유: 실제 서버 데이터 없이 고정 mock이 표시되는 상태를 해소하기 위해서입니다.
  • 구현 방식: `today/_types/today-type.ts`에 `todayTodoSchema`(= `todoSchema` + `date` 필드)와 `todayDataSchema`를 작성해 zod 검증 레이어를 추가했습니다. `today/_queries/use-today.ts`에서 orval 생성 `getToday` fetcher와 `getGetTodayQueryKey`를 직접 조립해 `useSuspenseQuery`에 연결하고, `select`에서 `BaseResponse.data`를 언랩한 뒤 로컬 스키마로 파싱합니다. 생성된 `getGetTodayQueryOptions` 팩토리를 쓰지 않은 이유는 `UseSuspenseQueryOptions`와의 타입 충돌을 피하기 위해서입니다. `staleTime: 0`으로 설정해 탭 이동 시 항상 최신 데이터를 가져오도록 했습니다. `completedCount`/`totalCount`는 서버 응답값 대신 로컬 `todos` state에서 파생해 체크/언체크 즉시 반영되도록 했습니다.
  • 경계 · 제약: `TodayTodoListContainer`를 `AsyncBoundary`로 감싸 `useSuspenseQuery`의 로딩·에러를 상위에서 처리합니다.

투두 생성 API 연동

  • 변경 요약: today 탭의 할 일 추가를 로컬 state 방식에서 `POST /api/v1/todos` 실제 API 호출로 교체했습니다.
  • 이유: 기존 `useCreateTodoSubmit`(today 전용)이 `buildTodoFromRequest`로 가짜 `TodayTodo` 객체를 만들어 로컬 state에 추가하는 방식이어서, 태그 이름이 빈 문자열로 표시되고 새로고침 시 생성 항목이 사라지는 문제가 있었습니다.
  • 구현 방식: `useCreateTodo` 뮤테이션을 호출하고, 성공 시 `getGetTodayQueryKey()`를 invalidate해 today 쿼리를 리패치합니다. `useTodayTodoList`에 `useEffect(() => { setTodos(initialTodos); }, [initialTodos])`를 추가해 리패치된 서버 데이터가 로컬 state에 즉시 반영되도록 했습니다. 에러 발생 시 `AnimatedToast`로 실패 메시지를 표시합니다.
  • 경계 · 제약: check·play·delete 뮤테이션은 이번 PR 범위에서 제외하며 로컬 state로만 동작합니다(`// TODO: API`). 공유 `CreateTodoModalContainer`의 `onSubmit` 오버라이드 패턴을 유지해 today 도메인의 invalidation 로직을 독립적으로 관리합니다.

today 투두 아이콘 표시

  • 변경 요약: `todo.icon` 값에 따라 `IconGraphic` 컴포넌트를 체크박스 오른쪽에 렌더링했습니다.
  • 이유: Figma 스펙(노드 1101-76345)에서 상위 투두 제목 앞에 `Ic_timo` 아이콘(24×24)이 표시됩니다.
  • 구현 방식: `renderTodoIcon`이 `todo.icon`이 `TODO_ICON_VALUES` 배열에 포함되는지 런타임 체크한 뒤 `size-6` 래퍼 안에 `IconGraphic`을 렌더링합니다. API 응답 스키마의 `icon` 필드가 `z.string().nullish()`로 느슨하게 정의되어 있어 enum 체크를 런타임에 수행합니다.

하위 투두 체크박스 정렬 수정

  • 변경 요약: `TodayTodoCard`의 sub-todo 리스트에서 `pl-8`(32px)을 제거해 상위 투두와 체크박스 시작 위치를 맞췄습니다.
  • 이유: Figma에서 sub-todo 컨테이너에 별도 left padding이 없으며 상위 투두 체크박스와 같은 x 위치에서 시작합니다.
  • 구현 방식: `
      `에서 `pl-8` 제거.

    완료 투두 하단 정렬

    • 변경 요약: 투두 체크 시 완료된 항목이 목록 하단으로 이동하도록 정렬 로직을 추가했습니다.
    • 이유: 기존에는 체크 여부와 무관하게 순서가 유지되어 완료·미완료 항목이 섞여 표시되었습니다. Home의 API 응답이 완료 항목을 하단에 반환하는 것과 동일한 UX를 맞추기 위해서입니다.
    • 구현 방식: `useTodayTodoList`의 `handleCheck`에서 상태 업데이트 후 `[...updated].sort((a, b) => Number(a.completed) - Number(b.completed))`로 정렬합니다. `Number(false)=0`, `Number(true)=1`이므로 미완료가 앞에, 완료가 뒤에 오며 각 그룹 내 기존 순서는 JavaScript 안정 정렬로 유지됩니다.
    • 경계 · 제약: Home은 API 성공 후 쿼리 무효화로 서버 정렬 결과를 받아옵니다. today는 check API가 아직 미연동(`// TODO: API`)이라 클라이언트 정렬로 동일 효과를 구현했습니다.

    today 투두 카드 클릭 시 상세 모달 연결

    • 변경 요약: 투두 카드를 `DetailTodoModalContainer`로 감싸 클릭 시 상세 조회 모달이 열리도록 연결했습니다.
    • 이유: today 탭 투두에도 Home과 동일하게 카드 클릭 → 상세 모달 진입 흐름이 필요합니다.
    • 구현 방식: PR #164에서 도입된 `DetailTodoModalContainer`(render-prop 패턴)를 `TodayTodoListContainer`에서 재사용합니다. `key`를 `DetailTodoModalContainer`로 올리고, `openDetailTodoModal` 콜백을 `TodayTodoCardContainer`의 `onCardClick`에 연결했습니다. `TodayTodo`는 `Todo`의 슈퍼셋(`date` 필드 추가)이라 타입 변환 없이 그대로 넘길 수 있습니다. `handleDelete`도 함께 노출해 모달 내 삭제 버튼과 연결했습니다.



    To Reviewers

    `todoSchema`를 `api/common/todo-schema.ts`로 이동하면서 기존 `home/_types/todo-type.ts`를 re-export 배럴로만 남겼는데, 추후 home 내부 파일들도 직접 `api/common/todo-schema.ts`를 바라보도록 정리가 필요합니다.

    today 탭의 체크·재생·삭제 뮤테이션은 현재 로컬 state만 변경하고 있어 새로고침 시 원상복구됩니다. 뮤테이션 API 연동 PR에서 `// TODO: API` 주석 위치에 붙이면 됩니다.

    `useTodayTodoList`의 `useEffect` sync는 서버 refetch 후 로컬 check/play 상태를 초기화합니다. 현재는 check·play가 로컬 only여서 영향이 없지만, 뮤테이션 API 연동 시점에 optimistic update 전략과 함께 재검토가 필요합니다.



    Screenshot 📷



    Test Checklist ✔

    • `pnpm lint` 통과 (lint-staged 확인)
    • `pnpm check-types` — 미실행
    • 브라우저에서 today 탭 진입 시 실제 서버 데이터 표시 확인 — 미실행
    • 홈 탭에서 체크 후 today 탭 재진입 시 데이터 갱신 확인 — 미실행
    • today 탭에서 할 일 추가 후 서버 데이터로 목록 갱신 확인 — 미실행
    • icon 설정된 투두에 아이콘 표시 확인 — 미실행
    • 투두 체크 시 완료 항목이 하단으로 이동 확인 — 미실행
    • 투두 카드 클릭 시 상세 모달 진입 확인 — 미실행

ehye1 added 3 commits July 14, 2026 11:57
- home 도메인에 있던 todoSchema, dayOfWeekSchema 등 응답 파싱 스키마를 api/todo/todo-schema.ts로 이동했습니다
- home/_types/todo-type.ts를 re-export 배럴로 변환해 기존 home 내부 import를 유지했습니다
- home/_types/home-view-type.ts의 apiDayOfWeekSchema를 공유 위치에서 import하도록 수정했습니다
- 도메인 간 직접 import 금지 규칙(structure.md)을 준수했습니다
- /api/v1/home/today 엔드포인트를 useSuspenseQuery로 연동했습니다
- today/_types/today-type.ts에 todayTodoSchema, todayDataSchema를 작성해 응답을 zod로 검증했습니다
- today/_queries/use-today.ts를 작성해 API 데이터를 가져오고 BaseResponse를 언랩했습니다
- useTodayTodoList 초기값을 mock에서 API 데이터로 교체했습니다
- completedCount/totalCount를 로컬 todos state 기반으로 계산해 체크 즉시 반영되도록 수정했습니다
- TodoMock 의존성을 제거하고 TodayTodo 타입으로 통일했습니다
- TodayTodoListContainer를 AsyncBoundary로 감쌌습니다
- 탭 이동 시 항상 최신 데이터를 가져오도록 staleTime을 0으로 설정했습니다
@vercel

vercel Bot commented Jul 14, 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 14, 2026 11:58am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

공통 Todo Zod 스키마와 타입을 중앙화하고, Today 페이지가 오늘 데이터를 API에서 조회·검증해 목록에 전달하도록 변경했습니다. 목 데이터 기반 상태와 생성 타입을 실제 Today 응답 타입으로 전환하고 비동기 렌더링 경계를 추가했습니다.

Changes

Today TODO API 연동

Layer / File(s) Summary
공통 Todo 스키마와 타입 계약
apps/timo-web/api/common/todo-schema.ts, apps/timo-web/app/.../home/_types/home-view-type.ts, apps/timo-web/app/.../home/_types/todo-type.ts
Todo 응답용 Zod 스키마와 추론 타입을 공통 모듈에 추가하고, 홈 타입 모듈은 이를 재내보내거나 참조하도록 변경했습니다.
Today 데이터 조회와 목록 초기화
apps/timo-web/app/.../today/_types/today-type.ts, apps/timo-web/app/.../today/_queries/use-today.ts, apps/timo-web/app/.../today/page.tsx, apps/timo-web/app/.../today/_containers/TodayTodoListContainer.tsx, apps/timo-web/app/.../today/_hooks/useTodayTodoList.ts
Today 응답을 스키마로 검증하는 쿼리를 추가하고, API의 todos를 목록 초기값과 카드 우선순위에 사용하도록 변경했습니다.
Today TODO 생성 타입 정렬
apps/timo-web/app/.../today/_containers/TodayDateHeaderContainer.tsx, apps/timo-web/app/.../today/_hooks/todo-modal/use-create-todo-submit.ts
TODO 생성 콜백과 생성 결과를 TodayTodo 타입으로 전환하고 아이콘, 우선순위, 태그 기본값 처리를 조정했습니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TodayPage
  participant AsyncBoundary
  participant TodayTodoListContainer
  participant useToday
  participant TodayAPI

  TodayPage->>AsyncBoundary: 목록 컨테이너 렌더링
  AsyncBoundary->>TodayTodoListContainer: 비동기 콘텐츠 렌더링
  TodayTodoListContainer->>useToday: 오늘 데이터 조회
  useToday->>TodayAPI: getToday 요청
  TodayAPI-->>useToday: Today 응답
  useToday->>useToday: todayDataSchema.parse
  useToday-->>TodayTodoListContainer: 검증된 TodayData
  TodayTodoListContainer->>TodayTodoListContainer: data.todos로 목록 초기화
Loading

Possibly related PRs

  • Team-Timo/Timo-client#124: 홈 뷰와 Todo 로컬 스키마를 처음 추가한 변경으로, 이번 공통 스키마 중앙화와 직접 연결됩니다.
  • Team-Timo/Timo-client#160: 홈 Todo 타입의 필드와 기본값 변환을 수정한 변경으로, 동일한 타입 정의 영역을 다룹니다.

Suggested labels: ✨ Feature, ♦️ 민아

Suggested reviewers: kimminna

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed #180의 요구사항인 today API 연동, mock 제거, 훅/컨테이너 수정, 로딩·에러 처리까지 반영되었습니다.
Out of Scope Changes check ✅ Passed 공유 스키마 이동과 today 타입/쿼리 추가는 모두 today API 연동을 위한 범위 안의 변경입니다.
Title check ✅ Passed 오늘 탭에 API를 연동하는 핵심 변경을 짧고 명확하게 담고 있습니다.
Description check ✅ Passed today 탭 API 연동, mock 제거, 스키마 이동, 로딩/에러 처리 등 변경 내용과 목적이 일치합니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/web/180-today-todolist-api-integration

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.

@ehye1 ehye1 changed the title [FEAT] today 탭 API 연동 (#180) [FEAT] 오늘 탭 API 연동 Jul 14, 2026

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

🤖 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/api/todo/todo-schema.ts`:
- Around line 121-136: Apply the type-naming convention at
apps/timo-web/api/todo/todo-schema.ts:121-136 by renaming the literal/union
alias TodoIcon to TodoIconTypes and declaring object-shaped inferred types such
as Todo and TodoTag as interfaces extending their corresponding Zod-inferred
schemas; preserve existing exports and usages. At
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_types/today-type.ts:17-18,
convert the object types TodayTodo and TodayData from type aliases to interfaces
without changing their shapes.
- Around line 105-111: Update the durationSeconds and sortOrder fields in the
todo schema to handle null values before applying their zero fallback, matching
the nullish transform pattern used by priority and tag. Preserve the existing
numeric validation and ensure both undefined and null inputs resolve to 0
instead of causing a ZodError.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx:
- Around line 11-19: Synchronize the local todos state in useTodayTodoList with
refreshed server data instead of using data.todos only as the initial state. Add
an effect keyed by the incoming todos argument to update the hook’s todos state
whenever useToday provides new data, while preserving the existing local todo
interactions.

In
`@apps/timo-web/app/`[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts:
- Around line 7-8: When the backend mutation APIs are integrated, remove the
local todos state and useState-based updates from useTodayTodoList, making the
React Query cache the single source of truth. Implement check, replay, and
delete optimistic updates by updating the relevant query cache directly while
preserving immediate UI feedback.
🪄 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: 076b8a84-8729-44ce-a004-2fffdaeaf229

📥 Commits

Reviewing files that changed from the base of the PR and between 91fea28 and 628899b.

📒 Files selected for processing (11)
  • apps/timo-web/api/todo/todo-schema.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_types/home-view-type.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_types/todo-type.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayDateHeaderContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/TodayTodoListContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_containers/todo-modal/CreateTodoModalContainer.tsx
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/todo-modal/use-create-todo-submit.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_hooks/useTodayTodoList.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_queries/use-today.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_types/today-type.ts
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/page.tsx

Comment on lines +105 to +111
durationSeconds: z.number().default(0),
priority: todoPrioritySchema.nullish().transform((v) => v ?? "MEDIUM"),
tag: todoTagSchema.nullish().transform((v) => v ?? undefined),
hasMemo: z.boolean(),
isRepeated: z.boolean(),
timerStatus: todoTimerStatusSchema,
sortOrder: z.number().default(0),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Zod .default()null 처리 주의

Zod 4에서 .default()는 필드 값이 undefined일 때만 동작하며, null에는 적용되지 않습니다. 서버 API 응답에서 durationSecondssortOrder가 빈 값으로 null을 반환할 경우 파싱 에러(ZodError)가 발생하게 됩니다.

안전한 폴백 처리를 위해 다른 필드(priority, tag)처럼 .nullish().transform()을 사용하거나 .catch()를 활용하는 것을 권장합니다! 😉

🛠️ 제안하는 수정안
-  durationSeconds: z.number().default(0),
+  durationSeconds: z.number().nullish().transform((v) => v ?? 0),
   priority: todoPrioritySchema.nullish().transform((v) => v ?? "MEDIUM"),
   tag: todoTagSchema.nullish().transform((v) => v ?? undefined),
   hasMemo: z.boolean(),
   isRepeated: z.boolean(),
   timerStatus: todoTimerStatusSchema,
-  sortOrder: z.number().default(0),
+  sortOrder: z.number().nullish().transform((v) => v ?? 0),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
durationSeconds: z.number().default(0),
priority: todoPrioritySchema.nullish().transform((v) => v ?? "MEDIUM"),
tag: todoTagSchema.nullish().transform((v) => v ?? undefined),
hasMemo: z.boolean(),
isRepeated: z.boolean(),
timerStatus: todoTimerStatusSchema,
sortOrder: z.number().default(0),
durationSeconds: z.number().nullish().transform((v) => v ?? 0),
priority: todoPrioritySchema.nullish().transform((v) => v ?? "MEDIUM"),
tag: todoTagSchema.nullish().transform((v) => v ?? undefined),
hasMemo: z.boolean(),
isRepeated: z.boolean(),
timerStatus: todoTimerStatusSchema,
sortOrder: z.number().nullish().transform((v) => v ?? 0),
🤖 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/api/todo/todo-schema.ts` around lines 105 - 111, Update the
durationSeconds and sortOrder fields in the todo schema to handle null values
before applying their zero fallback, matching the nullish transform pattern used
by priority and tag. Preserve the existing numeric validation and ensure both
undefined and null inputs resolve to 0 instead of causing a ZodError.

Comment on lines 121 to +136
export type CreateTodoRequest = z.infer<typeof createTodoRequestSchema>;
export type RecommendDurationResponseData = z.infer<
typeof recommendDurationResponseSchema
>;

export type TodoIcon = z.infer<typeof todoIconSchema>;
export type TodoPriority = z.infer<typeof todoPrioritySchema>;
export type TodoPriorityTypes = TodoPriority;
export type TodoRepeatType = z.infer<typeof todoRepeatTypeSchema>;
export type TodoRepeatWeekday = z.infer<typeof todoRepeatWeekdaySchema>;
export type DayOfWeek = z.infer<typeof dayOfWeekSchema>;
export type TodoTimerStatusTypes = z.infer<typeof todoTimerStatusSchema>;
export type TodoTag = z.infer<typeof todoTagSchema>;
export type TodoSubtask = z.infer<typeof todoSubtaskSchema>;
export type Todo = z.infer<typeof todoSchema>;
export type TodoCreateResponseData = z.infer<typeof todoCreateResponseSchema>;

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 | 💤 Low value

타입 선언 및 명명 규칙 컨벤션 확인

가이드라인(경로 지침)에 따르면 '객체(Props 등) 타입은 interface로 선언', **'type alias는 유니언·튜플·리터럴에만 사용하며 접미사 Types 추가'**라는 명명 규칙이 명시되어 있습니다. Zod를 통해 추론(z.infer)된 타입들에도 해당 팀 컨벤션을 엄격하게 적용할지 가볍게 검토해 보시면 좋을 것 같습니다! 😊

  • apps/timo-web/api/todo/todo-schema.ts#L121-L136: TodoIconTodoIconTypes로 변경하거나, TodoTodoTag 같은 객체 타입은 export interface Todo extends z.infer<typeof todoSchema> {} 형태로 확장을 고려해 볼 수 있습니다.
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_types/today-type.ts#L17-L18: 동일하게 TodayTodo, TodayData 객체 타입도 interface로 선언을 고려해 볼 수 있습니다.
📍 Affects 2 files
  • apps/timo-web/api/todo/todo-schema.ts#L121-L136 (this comment)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_types/today-type.ts#L17-L18
🤖 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/api/todo/todo-schema.ts` around lines 121 - 136, Apply the
type-naming convention at apps/timo-web/api/todo/todo-schema.ts:121-136 by
renaming the literal/union alias TodoIcon to TodoIconTypes and declaring
object-shaped inferred types such as Todo and TodoTag as interfaces extending
their corresponding Zod-inferred schemas; preserve existing exports and usages.
At
apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/today/_types/today-type.ts:17-18,
convert the object types TodayTodo and TodayData from type aliases to interfaces
without changing their shapes.

Source: Path instructions

Comment on lines +7 to +8
export const useTodayTodoList = (initialTodos: TodayTodo[]) => {
const [todos, setTodos] = useState<TodayTodo[]>(initialTodos);

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 | 💤 Low value

서버 상태와 로컬 상태 동기화 관련 안내 (단일 출처 원칙)

가이드라인(경로 지침)에 따르면 서버 상태(API 데이터)는 React Query가 단일 출처(Single Source of Truth)가 되어야 합니다. 현재 PR 설명에 언급된 대로 체크/재생/삭제 기능의 빠른 시각적 피드백을 위해 임시로 useState를 활용하신 것으로 파악됩니다.

추후 백엔드 Mutation API 연동이 완료되면, 해당 useState를 걷어내고 React Query의 캐시 데이터를 직접 조작(Optimistic Update)하여 단일 출처 원칙을 복구하시기를 추천합니다! 👍

🤖 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/_hooks/useTodayTodoList.ts
around lines 7 - 8, When the backend mutation APIs are integrated, remove the
local todos state and useState-based updates from useTodayTodoList, making the
React Query cache the single source of truth. Implement check, replay, and
delete optimistic updates by updating the relevant query cache directly while
preserving immediate UI feedback.

Source: Path instructions

- formatDate, convertDurationToTimeText import 경로를 재구성된 utils 폴더 구조에 맞게 수정했습니다
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

Timo Performance Report

Bundle Size — timo-web
라우트 크기 First Load JS
/[locale]/home 206.98 kB 🔴 412.84 kB
/[locale]/today 191.32 kB 🔴 397.17 kB
/[locale]/focus 159.44 kB 🔴 365.30 kB
/[locale]/settings 168.29 kB 🔴 374.15 kB
/[locale]/statistics 155.99 kB 🔴 361.85 kB
/[locale]/[...rest] 0 B 🟡 205.86 kB
/[locale]/login 215.52 kB 🔴 421.38 kB
/[locale]/oauth/callback 122.17 kB 🟡 328.03 kB
/[locale]/onboarding 235.00 kB 🔴 440.86 kB
/[locale] 121.55 kB 🟡 327.41 kB
/[locale]/policy 127.65 kB 🟡 333.51 kB

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

Lighthouse — timo-web
URL Perf A11y LCP CLS TBT
/en/home 🔴 59 🟢 95 🔴 15.5s 🟢 0.000 🟡 583ms
/en/today 🔴 59 🟢 95 🔴 15.3s 🟢 0.000 🔴 629ms
/en/focus 🔴 61 🟢 95 🔴 15.0s 🟢 0.000 🟡 524ms
/en/statistics 🔴 69 🟢 95 🔴 15.2s 🟢 0.000 🟡 278ms

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

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

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

측정 커밋: 0f3491e

- api/todo/todo-schema를 api/common/todo-schema로 이동한 develop 변경에 맞게 import 경로를 수정했습니다
- today 도메인 CreateTodoModalContainer를 공유 위치로 이동한 develop 변경을 수락했습니다
ehye1 added 2 commits July 14, 2026 16:57
- 로컬 state 방식 대신 useCreateTodo 뮤테이션으로 실제 API를 호출했습니다
- 생성 성공 시 today 쿼리를 invalidate해 서버 데이터를 반영했습니다
- 서버 refetch 후 로컬 state 동기화를 위해 useEffect를 추가했습니다
- handleAddTodo 제거 및 onCreateTodo prop 의존성을 제거했습니다
- todo.icon 값에 따라 IconGraphic을 렌더링했습니다
- sub-todo 리스트의 pl-8을 제거해 상위 투두와 체크박스 시작 위치를 맞췄습니다
@ehye1 ehye1 self-assigned this Jul 14, 2026
@ehye1 ehye1 added 🌟 API API 연동 작업 ♥️ 혜원 혜원양 labels Jul 14, 2026
@ehye1
ehye1 requested review from jjangminii and kimminna July 14, 2026 10:58
ehye1 added 2 commits July 14, 2026 20:43
- 투두 완료 체크 시 completed 항목이 목록 하단으로 정렬되도록 수정했습니다
- 투두 카드를 DetailTodoModalContainer로 감싸 클릭 시 상세 모달이 열리도록 연결했습니다
@ehye1 ehye1 changed the title [FEAT] 오늘 탭 API 연동 [FEAT] 오늘 탭 API 연동 및 투두 상호작용 개선 Jul 14, 2026
@github-actions github-actions Bot added ✨ Feature 새로운 기능(기능성) 구현 and removed 🌟 API API 연동 작업 labels Jul 14, 2026
- handleCheck에서 updated 변수를 분리하면서 timerStatus 리터럴이 string으로
  추론되던 문제를 as const 및 명시적 타입 주석으로 해결했습니다

@jjangminii jjangminii 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.

체크아웃해서 로직 확인했습니다~

@ehye1 ehye1 changed the title [FEAT] 오늘 탭 API 연동 및 투두 상호작용 개선 [FEAT] 오늘 탭 API 연동 Jul 14, 2026
@ehye1
ehye1 merged commit 40555ec into develop Jul 14, 2026
13 checks passed
@kimminna kimminna mentioned this pull request Jul 14, 2026
@kimminna
kimminna deleted the feat/web/180-today-todolist-api-integration branch July 14, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능(기능성) 구현 ⏰ Timo-web Timo 웹 서비스 ♥️ 혜원 혜원양

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 오늘 TODO 조회 API 연동

2 participants