Skip to content

feat: #47 다크모드 지원 및 컬러 토큰 리뉴얼#48

Merged
kangddong merged 28 commits into
developfrom
feat/47-dark-mode-support
Jun 6, 2026
Merged

feat: #47 다크모드 지원 및 컬러 토큰 리뉴얼#48
kangddong merged 28 commits into
developfrom
feat/47-dark-mode-support

Conversation

@kangddong

Copy link
Copy Markdown
Collaborator

About this PR

⚓ Related Issue


🥥 Contents

DoriDesignSystem 컬러 토큰을 의미 기반으로 리뉴얼하고 라이트/다크 모드를 지원한다.

컬러 토큰 (의미 기반 12종 신설)

  • bgPrimary, bgSecondary, bgScrim, textPrimary, textSecondary, textDisabled, textPlaceholder, borderDefault, borderInput, brandMain, onBrand, feedbackTextError
  • 각 colorset은 universal(light) + dark appearance 두 variant — SwiftUI가 자동 전환
  • 기존 프리미티브(main, doriWhite, doriBlack, grey50~grey900)는 물리 제거
  • secondary@available(*, deprecated) 부착해 보존. Figma에 brand secondary 정의가 없어 디자이너 합의 후 후속 처리

디자인 시스템 + 피처 코드 마이그레이션 (~90개소)

  • DoriDesignSystem 내부 컴포넌트 ~12 파일, Feature 측 ~22 파일 모두 의미 토큰 호출로 치환
  • Color.black.opacity(0.4) / (0.2) 스크림 5건을 bgScrim으로 통일
  • DoriToastView info 배경만 의도적 Color.black.opacity(0.8) 하드코딩 (라이트/다크 모두 어두워야)
  • PrimaryButton 커스텀 모디파이어(.backgroundColor/.foregroundColor/.strokeColor(.X)) 13건도 같이 정리

문서화

  • Projects/Core/DoriDesignSystem/DESIGN.md 신설 — YAML front matter에 라이트/다크 hex, 의미 토큰 표, deprecation 안내, Do's/Don'ts
  • Tuist/ResourceSynthesizers/Assets.stencil — legacy color case에 @available(*, deprecated) 자동 부착 분기

빌드 인프라

  • TCA from: "1.0.0"from: "1.25.5" — Swift 6.0 strict concurrency 빌드 차단 해소 (TCA PR #3844: WritableKeyPath_SendableWritableKeyPath)
  • swift-snapshot-testing 1.18+ 추가 (DoriDesignSystem 테스트 타깃에만)

스냅샷 회귀 가드 (14 baseline)

  • Tests/Snapshot/ 신설. 컴포넌트 단위 라이트/다크 페어:
    • ColorTokenSnapshotTests — 12 토큰 swatch 시트 × 2
    • PrimaryButtonSnapshotTests — enabled/disabled × 2
    • DoriCommonAlertSnapshotTests — × 2
    • DoriToastViewSnapshotTests — success/error/info × 2
  • replay 검증 14/14 통과 (0.87초)

📸 Screenshot

라이트/다크 토큰의 실제 렌더 결과는 Projects/Core/DoriDesignSystem/Tests/Snapshot/__Snapshots__/ 의 14장 PNG로 확인 가능. PR Files 탭에서 다이렉트로 렌더된다. 시뮬레이터 캡처는 별도 첨부 없음.


Other information 🔥

  • 머지 직후 빌드에서 secondary 사용 8건이 deprecation 경고로 표출됨 — 의도된 신호. 디자이너 확정 후 후속 PR에서 처리.
  • TCA 1.23.1 → 1.25.5는 본 PR에서 가장 위험도 높은 변경이지만 그 사이 release note에 breaking change 없음(deprecation만), 우리 코드의 BindingState/BindingReducer(Action.view)/BindingViewState/BindingViewStore 사용 0건 확인.
  • 스냅샷 baseline은 iPhone 16 시뮬레이터 + Xcode 26.4에 종속. CI 도입 시 동일 환경 강제 필요.
  • plan/ 워크플로 정립 변경(AGENTS/ARCHITECTURE/docs 정리)은 본 PR 범위 밖. 별도 PR로 분리 예정.

kangddong and others added 15 commits May 14, 2026 12:55
- bg/text/border/brand/feedback/onBrand 의미 토큰 12종 신설 (라이트/다크 variant)
- 기존 Grey/Brand 프리미티브 팔레트 물리 제거, `secondary`만 deprecated로 보존
- DoriDesignSystem + Feature 코드 ~90개소를 의미 토큰으로 마이그레이션
- Color.black.opacity 스크림/오버레이 5건을 `bgScrim`으로 통일
- TCA `from: "1.0.0"` → `from: "1.25.5"`: Swift 6.0 strict concurrency 빌드 차단 해소 (TCA PR #3844)
- swift-snapshot-testing 도입, 컴포넌트 단위 14개 baseline (light/dark)
- DESIGN.md 신설, Assets.stencil에 deprecation 자동 부착 분기

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documents the (3) Feature 카탈로그 다크모드 스냅샷 작업 — sibling
of validateDarkMode/. PLAN defines P0/P1/P2 catalog (~106 baseline),
Implementation lays out 5-phase execution with snapshot-testing
specific record/replay/회귀 시나리오 종료기준.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- DoriModules.testSupport case + Projects/Core target wired with
  DoriCore + ComposableArchitecture deps
- Dori+Mock (mockJudori, mockBaddori, mock, mockList: 4건)
- PartnerSummary+Mock (mock, mockList: 3건)
- PartnerDoriList+Mock (mock, mockEmpty)

Feature snapshot tests will import this for stable mock state.
Missing previewValue for AuthTokenStoreClient / KakaoServerLoginClient /
UserNotificationSettingsClient — added JIT in Phase D as tests
require them.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- doriUnitTests for Onboarding/AddDori/Calendar/MyPage with
  TestSupport + ComposableArchitecture + snapshotTesting deps
- History existing test target deps 보강 (snapshotTesting + TestSupport)
- Placeholder.swift per feature so Tuist's Tests/** glob is non-empty
  (real snapshot tests land in Tests/Snapshot/ from Phase D1)
- Disable AddDoriFeatureTests.swift (stale State references, pre-existing,
  out of scope for snapshot work) — file renamed to .disabled, recovery
  via git history.

All 5 feature schemes (Onboarding/AddDori/Calendar/History/MyPage)
TEST BUILD SUCCEEDED.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Onboarding: SplashSnapshotTests, IntroSnapshotTests
- AddDori: AddDoriRootSnapshotTests (step1 진입)
- Calendar: CalendarGridSnapshotTests (currentMonth 고정 2025-05-01)
- History: DoriListSnapshotTests (empty state)
- MyPage: MyPageSnapshotTests (default)

각 TC 명시적 두 어설션 (.light/.dark UITraitCollection).
Layout .fixed(393, 852) — iPhone 16 size.

검증:
- Record 1회차: 12/12 fail with "Automatically recorded snapshot"
- Replay 2회차: 12/12 PASS
- 회귀 시나리오 (SplashSnapshotTests test_splash_light layout 변경) →
  "Snapshot does not match reference" → detection 살아있음 확인 → 원복

Side effect: FeatureHistory 의 사전 Swift Testing 테스트
(SearchFeatureTests, EditDoriMemoFieldTests) 가 deps 그래프 변경 후
crash/timeout. 본 PR 범위 외라 .disabled 로 비활성화.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previously the workspace's DerivedData was redirected to ./build/
via Xcode IDE's Custom build location setting (since reverted, but
folder remained as stale artifact). Our xcodebuild calls use the
default ~/Library/Developer/Xcode/DerivedData path. Ignoring the
root build/ prevents accidental commits if anyone re-toggles the
Xcode setting.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Onboarding (1 TC):
- IntroLoadingSnapshotTests: state.isLoading=true spinner

AddDori (4 TC):
- AddDoriPage1SnapshotTests: emptySearch (query without results) + searchResults
  (populated via Dori.mockList from DoriTestSupport)
- AddDoriPage3SnapshotTests: amountError (feedbackTextError) + datePickerOpen (bgScrim)

History (3 TC):
- DoriListPopulatedSnapshotTests: PartnerSummary.mockList from DoriTestSupport
- EditDoriSnapshotTests: default + datePickerOpen (bgScrim)

MyPage (5 TC):
- MyPageLogoutAlertSnapshotTests: isLogoutAlertPresented=true (DoriCommonAlert)
- NotificationSettingsSnapshotTests: allOn + allOff (toggle knob onBrand)
- DoriToggleSwitchSnapshotTests: on + off direct component snapshot

검증:
- Record 1회차: 26/26 fail with "Automatically recorded snapshot"
- Replay 2회차: 5/5 schemes TEST SUCCEEDED, 38/38 baseline total PASS
  (P0 12 + P1 26)

PLAN의 P1 17 TC 중 4 TC deferred to D3 (Calendar populated/DayDetailSheet
single+multiple/PartnerDoriDetail default — CalendarMonthlyData·CalendarDori
복합 state 구성 필요).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PLAN(2). 다크모드 검증의 페어 누락을 구조적으로 방지하는 얇은 헬퍼와
test-strategy 의 컨벤션 한 줄을 추가한다. 기존 4개 TC 마이그레이션은 별도 PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
kangddong and others added 11 commits June 4, 2026 21:19
Page1 selected, Page2 default/birthday/customEventInput, Page3 amountTyped/amountZero,
Root step3. 회귀 시나리오 1건 (Page2 wedding → funeral) 통과 — detection 확인 후 원복.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DoriSegmentControl judori/baddori, dayDetailSheet empty. 회귀 시나리오 1건
(judori → baddori) 통과 — detection 확인 후 원복.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NotificationSettings partialEnabled, FCMPushTest default/loading. 회귀 시나리오
1건 (FCMPushTest title 변경) 통과 — detection 확인 후 원복.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Search empty/typedNoResults/typedWithResults, PartnerDoriHistory all/judoriOnly/baddoriOnly,
DoriBarGraph zero/judoriHeavy/balanced, PersonCard collapsed, TransactionRow judori/baddori,
EditDori amountError, PartnerDoriDetail deleteAlert. 회귀 시나리오 1건 (DoriBarGraph zero
givenAmount 1000 변경) 통과 — detection 확인 후 원복.

PersonCard expanded 는 internal @State 로 외부 토글 불가. 컴포넌트 binding 리팩터 후
별도 PR 에서 추가. PLAN(3) P2 의 15 TC 중 14 TC 진행, 1 TC 구조적 제약으로 보류.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PLAN(3) P2 27 TC commit 4건 + replay 통과 로그 + 회귀 시나리오 4건 기록.
PersonCard expanded 보류, Calendar P1 누락, 사람-눈 sweep 미수행을 명시.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude multimodal 13/27 dark PNG sweep:
- FCMPushTest TextField text contrast 부족 (다크 토큰 미적용 의심) — 높음
- TransactionRow baddori 아이콘 배경 light gray — 낮음 (디자인 결정 필요)

잔여 14장 사용자 직접 확인 영역.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 sweep 발견 결함 B. 취소 버튼 .foregroundColor(.black) → .textPrimary.
다크에서 검은 글씨 → 흰 글씨 (#FDFDFD). DoriCommonAlert/LogoutAlert/
DeleteAlert baseline re-record.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 sweep 발견 결함 C. brandMain 위에 올라가는 onBrand 토큰을 다크에서
#111111 (검정) 으로 변경. 영향: DoriBarGraph 의 "주도리" 텍스트, DoriToggleSwitch
의 thumb, PrimaryButton 의 모든 brand 텍스트, DoriSegmentButton 의 선택
상태 텍스트 등 brand 위 글씨/원 일괄.

38장 dark baseline re-record (DoriDesignSystem swatch/Alert/Toast/Button +
Onboarding Intro + AddDori 전체 + Calendar segment + History BarGraph 등 +
MyPage ToggleSwitch 등).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 sweep 발견 결함 E. FCMPushTest 의 TextField text 가 다크에서 시스템
기본색을 못 받아 검은색으로 박히는 의심. .foregroundStyle(.textPrimary)
명시로 다크 토큰 강제 적용. baseline re-record.

비고: 시각적 결과가 placeholder-회색 톤으로 보이는 건 SwiftUI TextField
text 색 modulation 한계 또는 mock binding 동기화 별건 가능성. 토큰 적용
자체는 완료.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 sweep 시뮬 실행 후 발견. 카카오 가이드라인상 KakaoYellow 배경 위 텍스트는
#212223 brand-fixed 인데 .textPrimary 토큰을 박아 다크에서 흰 글씨가 됨.
Brand/KakaoOnYellow.colorset 신규 (light/dark 동일 #212223) + IntroView 의
foregroundStyle 교체. Intro/IntroLoading baseline 4장 재기록.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
kangddong added 2 commits June 6, 2026 14:38
feat: PLAN(2) assertSnapshotPair 헬퍼
test: PLAN(3) Feature 카탈로그 다크 스냅샷 + sweep fix
@kangddong kangddong merged commit ae6c546 into develop Jun 6, 2026
1 check passed
@kangddong kangddong linked an issue Jun 30, 2026 that may be closed by this pull request
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

다크모드 지원

1 participant