Skip to content

[FIX] 설정 태그 생성 개수 제한 추가#245

Merged
kimminna merged 6 commits into
developfrom
fix/web/242-setting-tag-count
Jul 16, 2026
Merged

[FIX] 설정 태그 생성 개수 제한 추가#245
kimminna merged 6 commits into
developfrom
fix/web/242-setting-tag-count

Conversation

@yumin-kim2

Copy link
Copy Markdown
Contributor

ISSUE 🔗

close #242



What is this PR? 🔍

설정 화면에서 사용자 생성 태그가 최대 4개까지만 생성되도록 제한했습니다.

  • 사용자 생성 태그가 4개 이상이면 태그 추가 버튼이 노출되지 않도록 변경했습니다
  • 태그 생성 요청 전 최대 개수 검증을 추가했습니다
  • 설정 태그 생성 제한 안내 토스트 문구를 추가했습니다



To Reviewers

기본 태그는 삭제할 수 없는 태그라서, 최대 생성 개수는 isDefault === false인 사용자 생성 태그 기준으로 계산했습니다.


Screenshot 📷



Test Checklist ✔

  • 사용자 생성 태그가 4개 미만일 때 태그 추가 버튼이 노출되는지 확인했습니다
  • 사용자 생성 태그가 4개 이상일 때 태그 추가 버튼이 숨겨지는지 확인했습니다
  • 태그 생성 요청 전 최대 개수 검증이 동작하는지 확인했습니다
  • pnpm lint:web를 통과했습니다
  • pnpm check-types:web를 통과했습니다

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

Request Review

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

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

커스텀 태그 최대 생성 수를 4개로 통합했습니다. 기본 태그를 제외해 한도를 검사하며, 초과 시 생성 흐름을 중단하고 동적 개수가 포함된 토스트를 표시합니다.

Changes

설정 커스텀 태그 제한

Layer / File(s) Summary
커스텀 태그 한도 계약
apps/timo-web/schemas/tag/tag-schema.ts, apps/timo-web/app/.../toast/TagLimitToastContainer.tsx, apps/timo-web/messages/*.json
최대 커스텀 태그 수를 4개로 정의하고, 토스트가 동적 개수와 종료 콜백을 지원하도록 변경했습니다.
태그 생성 흐름 제한
apps/timo-web/hooks/todo-modal/common/use-tag-field.tsx, apps/timo-web/app/.../use-settings-profile.ts
기본 태그를 제외한 커스텀 태그 수가 한도에 도달하면 태그 생성 모달 또는 뮤테이션 실행을 중단합니다.
태그 한도 토스트 연결
apps/timo-web/app/.../SettingsProfileContainer.tsx, apps/timo-web/components/todo-modal/{create,detail}/*
설정 및 Todo 화면에서 한도 도달 상태에 따라 공통 토스트를 렌더링하고 닫기 동작을 연결합니다.

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

Possibly related PRs

Suggested labels: ✨ Feature, ♻ Refactor

Suggested reviewers: kimminna

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 설정 화면의 태그 생성 개수 제한이라는 핵심 변경을 간결하게 잘 요약합니다.
Description check ✅ Passed 설명은 태그 최대 4개 제한, 검증 추가, 안내 토스트 추가를 포함해 변경 내용과 잘 맞습니다.
Linked Issues check ✅ Passed [#242] 기본 태그를 제외한 사용자 생성 태그 기준으로 4개 이상 추가 생성을 막아 요구사항을 충족합니다.
Out of Scope Changes check ✅ Passed 공통 토스트와 훅, 문구 조정은 제한 기능 구현에 필요한 연계 변경으로 보이며 별도 무관한 범위는 보이지 않습니다.
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/242-setting-tag-count

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.

@yumin-kim2 yumin-kim2 changed the title [QA] 설정 태그 생성 개수 제한 추가 [FIX] 설정 태그 생성 개수 제한 추가 Jul 15, 2026
@github-actions github-actions Bot added the ♣️ 유민 유민양 label Jul 15, 2026
@yumin-kim2 yumin-kim2 added 🐛 Bug 기능이 정상적으로 작동하지 않는 문제 수정 🚬 QA QA 반영 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 212.13 kB 🔴 417.99 kB
/[locale]/today 196.32 kB 🔴 402.18 kB
/[locale]/focus 160.93 kB 🔴 366.79 kB
/[locale]/settings 167.49 kB 🔴 373.34 kB
/[locale]/statistics 154.86 kB 🔴 360.72 kB
/[locale]/[...rest] 0 B 🟡 205.86 kB
/[locale]/login 212.98 kB 🔴 418.83 kB
/[locale]/oauth/callback 119.67 kB 🟡 325.53 kB
/[locale]/onboarding 233.45 kB 🔴 439.31 kB
/[locale] 118.99 kB 🟡 324.84 kB
/[locale]/policy 125.11 kB 🟡 330.97 kB

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

Lighthouse — timo-web
URL Perf A11y LCP CLS TBT
/en/home 🔴 68 🟢 95 🔴 15.8s 🟢 0.000 🟡 254ms
/en/today 🔴 59 🟢 95 🔴 15.6s 🟢 0.000 🟡 590ms
/en/focus 🔴 60 🟢 95 🔴 15.3s 🟢 0.000 🟡 574ms
/en/statistics 🔴 62 🟢 95 🔴 15.2s 🟢 0.000 🟡 507ms

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 ⚠️ 🟢
og.png 437.44 kB PNG ⚠️ 🟡

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

측정 커밋: a145261

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

🤖 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)/settings/_containers/account/SettingsTagsSectionContainer.tsx:
- Around line 62-69: Review the canAddTag condition in
SettingsTagsSectionContainer and keep the “태그 추가” PillButton rendered when the
custom-tag limit is reached. Ensure onAddTag remains responsible for showing the
limit-exceeded toast on click, while preserving the existing enabled behavior
when tags can still be added.

In
`@apps/timo-web/app/`[locale]/(main)/settings/_hooks/account/use-settings-profile.ts:
- Around line 30-31: 중복 선언된 MAX_SETTING_CUSTOM_TAG_COUNT를 단일 공유 상수로 통합하세요.
apps/timo-web/app/[locale]/(main)/settings/_hooks/account/use-settings-profile.ts:30-31에서는
해당 상자를 export하고,
apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsTagsSectionContainer.tsx:14-15와
apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx:13-14에서는
로컬 선언을 제거한 뒤 훅 파일의 상수를 import하여 사용하세요.
🪄 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: 495d55a9-3864-4943-be44-a93eab92eb58

📥 Commits

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

📒 Files selected for processing (5)
  • apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx
  • apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsTagsSectionContainer.tsx
  • apps/timo-web/app/[locale]/(main)/settings/_hooks/account/use-settings-profile.ts
  • apps/timo-web/messages/en.json
  • apps/timo-web/messages/ko.json

Comment thread apps/timo-web/app/[locale]/(main)/settings/_hooks/account/use-settings-profile.ts Outdated

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

현재 토스트가 뜨지 않아서 코드래빗 내용 한 번 확인해주세요!

@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)/settings/_containers/account/SettingsProfileContainer.tsx:
- Around line 95-101: Remove the TagLimitToastContainer import and replace its
usage in SettingsProfileContainer with the already-used AnimatedToast,
preserving the isTagLimitToastOpen visibility state,
MAX_SETTING_CUSTOM_TAG_COUNT message/count, and close behavior via
setIsTagLimitToastOpen(false).
🪄 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: 69e2a85a-a52f-407e-9822-3515a911aa3c

📥 Commits

Reviewing files that changed from the base of the PR and between 8760647 and 34ab3ce.

📒 Files selected for processing (7)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/toast/TagLimitToastContainer.tsx
  • apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx
  • apps/timo-web/app/[locale]/(main)/settings/_hooks/account/use-settings-profile.ts
  • apps/timo-web/components/todo-modal/create/CreateTodoModalContent.tsx
  • apps/timo-web/components/todo-modal/detail/DetailTodoModalContent.tsx
  • apps/timo-web/messages/en.json
  • apps/timo-web/messages/ko.json

Comment on lines +95 to +101
{isTagLimitToastOpen && (
<TagLimitToastContainer
count={MAX_SETTING_CUSTOM_TAG_COUNT}
onClose={() => setIsTagLimitToastOpen(false)}
/>
)}

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 | 🟠 Major | ⚡ Quick win

도메인 간 직접 임포트를 피하고 AnimatedToast를 직접 활용해 보세요!

home 도메인에 있는 TagLimitToastContainersettings 도메인에서 직접 가져와 사용하는 것은 도메인 간 강결합을 유발합니다. 아키텍처 규칙("도메인 간 직접 import 금지")에 위배되기도 해요.

대신 이 파일 하단에서 이미 사용 중인 AnimatedToast를 직접 활용해 토스트를 렌더링하는 것을 추천합니다. 이렇게 하면 상태(state)가 이중으로 관리되는 문제도 예방할 수 있어 코드가 훨씬 깔끔해진답니다. React 공식 문서의 컴포넌트 독립성 유지를 참고해 보세요! ✨

♻️ 도메인 의존성을 제거하는 수정 제안
-      {isTagLimitToastOpen && (
-        <TagLimitToastContainer
-          count={MAX_SETTING_CUSTOM_TAG_COUNT}
-          onClose={() => setIsTagLimitToastOpen(false)}
-        />
-      )}
+      <AnimatedToast
+        isOpen={isTagLimitToastOpen}
+        onClose={() => setIsTagLimitToastOpen(false)}
+        message={
+          <p className="mb-0">
+            {tToast.rich("tagLimit", {
+              count: MAX_SETTING_CUSTOM_TAG_COUNT,
+              blue: (chunks) => (
+                <span className="text-timo-blue-300">{chunks}</span>
+              ),
+            })}
+          </p>
+        }
+      />

파일 상단의 TagLimitToastContainer 임포트도 함께 제거해 주세요:

// 7번 라인의 다음 코드를 삭제합니다.
import { TagLimitToastContainer } from "`@/app/`[locale]/(main)/(with-time-sidebar)/home/_containers/toast/TagLimitToastContainer";
🤖 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)/settings/_containers/account/SettingsProfileContainer.tsx
around lines 95 - 101, Remove the TagLimitToastContainer import and replace its
usage in SettingsProfileContainer with the already-used AnimatedToast,
preserving the isTagLimitToastOpen visibility state,
MAX_SETTING_CUSTOM_TAG_COUNT message/count, and close behavior via
setIsTagLimitToastOpen(false).

Source: Path instructions

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

♻️ Duplicate comments (1)
apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx (1)

93-96: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

도메인 간 직접 임포트를 피하고 AnimatedToast를 일관되게 활용해 보세요!

이전 리뷰에서도 안내해 드렸듯이, home 도메인의 TagLimitToastContainer를 다른 도메인(settings, todo-modal 등)에서 임포트하여 사용하는 것은 도메인 간 강결합을 유발합니다. 또한 토스트를 &&로 조건부 렌더링하면 부모와 자식 컴포넌트 간에 isOpen 상태 관리가 이중으로 발생하여 일관된 사용 패턴을 해치게 됩니다.

기존 코드의 에러 토스트처럼 각 컴포넌트 내부에서 AnimatedToast를 직접 렌더링해 보세요. 상태 관리가 단일화되고 애니메이션 종료 처리도 훨씬 자연스러워집니다. React 공식 문서의 컴포넌트 독립성 유지도 참고해 보세요! ✨

  • apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx#L93-L96: TagLimitToastContainer 임포트 및 조건부 렌더링을 제거하고, AnimatedToast를 직접 렌더링하세요.
  • apps/timo-web/components/todo-modal/create/CreateTodoModalContent.tsx#L218-L220: TagLimitToastContainer 대신 MAX_CUSTOM_TAG_COUNT를 임포트하고, AnimatedToast를 사용해 토스트를 렌더링하세요.
  • apps/timo-web/components/todo-modal/detail/DetailTodoModalContent.tsx#L296-L298: TagLimitToastContainer 대신 MAX_CUSTOM_TAG_COUNT를 임포트하고, AnimatedToast를 사용해 토스트를 렌더링하세요.

As per path instructions, ensure the toast component and any state/interaction logic live in the appropriate container/hook layer within the same domain path rather than being placed in unrelated global locations.

💡 `AnimatedToast` 적용 예시 (SettingsProfileContainer 기준)
-      {isTagLimitToastOpen && (
-        <TagLimitToastContainer onClose={() => setIsTagLimitToastOpen(false)} />
-      )}
+      <AnimatedToast
+        isOpen={isTagLimitToastOpen}
+        onClose={() => setIsTagLimitToastOpen(false)}
+        message={
+          <p className="mb-0">
+            {tToast.rich("tagLimit", {
+              count: MAX_CUSTOM_TAG_COUNT,
+              blue: (chunks) => (
+                <span className="text-timo-blue-300">{chunks}</span>
+              ),
+            })}
+          </p>
+        }
+      />
🤖 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)/settings/_containers/account/SettingsProfileContainer.tsx
around lines 93 - 96, Remove the cross-domain TagLimitToastContainer imports and
conditional rendering, and render AnimatedToast directly with single-source
isOpen/onClose state handling. In
apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx
lines 93-96, update SettingsProfileContainer accordingly; in
apps/timo-web/components/todo-modal/create/CreateTodoModalContent.tsx lines
218-220 and
apps/timo-web/components/todo-modal/detail/DetailTodoModalContent.tsx lines
296-298, replace TagLimitToastContainer with AnimatedToast and import
MAX_CUSTOM_TAG_COUNT for the existing limit message. Keep each toast’s state and
interaction logic within its respective component or hook layer.

Source: Path instructions

🤖 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.

Duplicate comments:
In
`@apps/timo-web/app/`[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx:
- Around line 93-96: Remove the cross-domain TagLimitToastContainer imports and
conditional rendering, and render AnimatedToast directly with single-source
isOpen/onClose state handling. In
apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx
lines 93-96, update SettingsProfileContainer accordingly; in
apps/timo-web/components/todo-modal/create/CreateTodoModalContent.tsx lines
218-220 and
apps/timo-web/components/todo-modal/detail/DetailTodoModalContent.tsx lines
296-298, replace TagLimitToastContainer with AnimatedToast and import
MAX_CUSTOM_TAG_COUNT for the existing limit message. Keep each toast’s state and
interaction logic within its respective component or hook layer.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 64505dee-92e7-4c2a-9b7a-00f7f70ea229

📥 Commits

Reviewing files that changed from the base of the PR and between 34ab3ce and 062e29a.

📒 Files selected for processing (7)
  • apps/timo-web/app/[locale]/(main)/(with-time-sidebar)/home/_containers/toast/TagLimitToastContainer.tsx
  • apps/timo-web/app/[locale]/(main)/settings/_containers/account/SettingsProfileContainer.tsx
  • apps/timo-web/app/[locale]/(main)/settings/_hooks/account/use-settings-profile.ts
  • apps/timo-web/components/todo-modal/create/CreateTodoModalContent.tsx
  • apps/timo-web/components/todo-modal/detail/DetailTodoModalContent.tsx
  • apps/timo-web/hooks/todo-modal/common/use-tag-field.tsx
  • apps/timo-web/schemas/tag/tag-schema.ts

@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 daddb6c into develop Jul 16, 2026
12 checks passed
@kimminna kimminna deleted the fix/web/242-setting-tag-count branch July 16, 2026 05:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIX] 태그 최대 생성 개수 제한 오류 QA 반영

3 participants