Skip to content

feat(mobile): 다크/라이트 모드 전환 기능 구현#110

Merged
hijjoy merged 8 commits intomainfrom
feature/theme
Feb 5, 2026
Merged

feat(mobile): 다크/라이트 모드 전환 기능 구현#110
hijjoy merged 8 commits intomainfrom
feature/theme

Conversation

@hijjoy
Copy link
Member

@hijjoy hijjoy commented Feb 5, 2026

📋 개요

다크/라이트/시스템 테마 전환 기능을 구현합니다.

🏷️ 변경 유형

  • feat - 새로운 기능 추가
  • ♻️ refactor - 코드 리팩토링
  • 📝 docs - 문서 수정
  • 🐛 fix - 버그 수정

📦 영향 범위

  • apps/mobile - Expo 모바일 앱

📝 변경 내용

  • ThemeProvider 구현 (SecureStore로 테마 설정 영속화)
  • 테마 설정 화면 추가 (라이트/다크/시스템 모드 선택)
  • 다크모드 하드코딩 색상을 테마 변수로 전환
  • 회원가입 헤더를 네이티브 Stack 헤더로 전환
  • 커스텀 tv/cn 유틸리티로 twMerge 충돌 방지
  • 애니메이션 상수 사용 가이드 추가

✅ 체크리스트

작성자 확인

  • 코드가 프로젝트의 코딩 컨벤션을 따릅니다
  • pnpm check (Biome) 검사를 통과했습니다
  • 모든 테스트가 통과합니다 (pnpm test)
  • 빌드가 성공합니다 (pnpm build)
  • 필요한 경우 문서를 업데이트했습니다
  • 커밋 메시지가 Conventional Commits 규칙을 따릅니다

🔗 관련 이슈

Closes #109

스크린샷

2026-02-05.13.59.09.mov

hijjoy and others added 5 commits February 5, 2026 11:58
- 커스텀 tv.ts 생성: createTV로 twMergeConfig 설정
- cn.ts 확장: extendTailwindMerge로 커스텀 클래스 그룹 등록
- text-size, text-input 그룹 분리로 text-gray-* 색상과 충돌 방지
- 모든 variants 파일 커스텀 tv import로 변경
- 컴포넌트에서 clsx를 cn으로 통일

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
커스텀 헤더 대신 Stack Navigator의 빌트인 헤더를 사용하여
페이지 전환 시 헤더 점프 문제 해결. 설정 레이아웃과 동일한 패턴 적용.

- auth _layout: 네이티브 헤더 옵션 추가 (fontSize 16, headerLeft)
- sign-up: Stack.Screen options로 동적 타이틀 설정
- settings _layout: fontSize 16 통일, theme 화면 라우트 추가
- 다크모드 contentStyle 적용 (페이지 전환 흰색 플래시 방지)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ThemeProvider로 라이트/다크/시스템 테마 전환 지원
- SecureStore에 테마 설정 영속화
- 마이페이지에 테마 설정 메뉴 추가
- Sun/Moon/Device 아이콘 및 StyledIconType 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@hijjoy hijjoy linked an issue Feb 5, 2026 that may be closed by this pull request
@hijjoy hijjoy self-assigned this Feb 5, 2026
@hijjoy hijjoy added type: feat 🚀 신규 기능 - 사용자에게 새로운 비즈니스 가치를 제공하는 작업 scope: mobile 📱 모바일 - Expo 기반 모바일 앱 UI/UX 및 클라이언트 로직 관련 type: docs 📝 문서화 - README, API 가이드 등 팀 내 협업 효율을 위한 문서 작업 labels Feb 5, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello @hijjoy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 모바일 애플리케이션에 포괄적인 다크/라이트 모드 지원을 도입합니다. ThemeProvider를 통해 테마 상태를 전역적으로 관리하고, SecureStore를 사용하여 사용자 설정을 영속화합니다. 이를 통해 앱 전반의 시각적 일관성을 향상시키고, 사용자가 선호하는 테마 환경을 선택할 수 있도록 새로운 설정 화면을 제공합니다. 또한, 기존의 하드코딩된 색상들을 테마 변수로 전환하고, twMerge 충돌을 방지하기 위한 커스텀 유틸리티를 적용하여 스타일링 시스템을 더욱 견고하게 만들었습니다.

Highlights

  • 다크/라이트 모드 전환 기능 구현: 모바일 앱에 다크, 라이트, 시스템 테마 전환 기능을 추가했습니다. 사용자의 테마 설정은 SecureStore를 통해 영속적으로 저장됩니다.
  • 테마 설정 화면 추가: 사용자가 직접 테마를 선택할 수 있는 '화면 테마' 설정 화면을 마이페이지에 추가했습니다.
  • 하드코딩된 색상 테마 변수로 전환: 기존에 하드코딩되어 있던 색상 값들을 Tailwind CSS 변수로 전환하여 테마 변경 시 자동으로 색상이 적용되도록 개선했습니다. 관련하여 UI 컴포넌트 문서도 업데이트되었습니다.
  • 회원가입 헤더 네이티브 Stack 헤더로 전환: 회원가입 화면의 커스텀 헤더를 Expo Router의 네이티브 Stack 헤더로 전환하여 일관된 UI와 동작을 제공합니다.
  • 커스텀 tv/cn 유틸리티 도입: Tailwind CSS의 twMerge 충돌을 방지하기 위해 커스텀 tv (tailwind-variants) 및 cn (clsx + twMerge) 유틸리티를 도입하여 Tailwind 클래스 병합 로직을 개선했습니다.
  • 애니메이션 상수 사용 가이드 추가: React Native Reanimated 애니메이션에서 durationdelay 값에 ANIMATION 상수를 사용하도록 가이드를 추가하고 관련 문서를 업데이트했습니다.
Changelog
  • apps/mobile/.claude/ui-components.md
    • 테마 색상 사용 섹션을 '테마 색상 사용 (다크/라이트 모드)'로 업데이트하고, CSS 변수 사용의 중요성을 강조하는 내용을 추가했습니다.
    • 사용 가능한 색상 변수 목록을 상세하게 추가했습니다.
    • JS에서 색상값이 필요한 경우 useResolveClassNames 사용 예시를 업데이트했습니다.
    • 애니메이션 상수 사용 가이드를 추가하고, ANIMATION 상수의 종류와 용도를 설명했습니다.
    • 금지 사항 섹션에 '색상 하드코딩 금지' 항목을 추가하여 Tailwind 클래스 사용을 의무화했습니다.
  • apps/mobile/app/(app)/(tabs)/_layout.tsx
    • Android 하단 탭에서 tabBarInactiveTintColoruseResolveClassNames를 사용하여 테마에 따라 동적으로 설정하도록 변경했습니다.
  • apps/mobile/app/(app)/(tabs)/feed/_layout.tsx
    • 피드 화면 헤더의 배경색을 useResolveClassNames를 통해 테마에 따라 동적으로 설정하도록 변경했습니다.
  • apps/mobile/app/(app)/(tabs)/home/index.tsx
    • KeyboardAvoidingViewbackgroundColor를 하드코딩된 'white'에서 className="bg-white"로 변경하여 테마를 따르도록 했습니다.
  • apps/mobile/app/(app)/(tabs)/mypage/index.tsx
    • 마이페이지에 '화면 테마' 설정 항목을 추가하고, 해당 화면으로 이동하는 라우터를 연결했습니다.
    • SettingNavigationItemArrowRightIcon colorClassNameaccent-gray-6에서 text-gray-6으로 변경했습니다.
  • apps/mobile/app/(app)/_layout.tsx
    • useTheme 훅을 사용하여 현재 테마를 가져오고, StackcontentStyle에 테마에 맞는 배경색을 적용했습니다.
  • apps/mobile/app/(app)/settings/_layout.tsx
    • 설정 화면 헤더의 fontSize를 18에서 16으로 조정했습니다.
    • 설정 스택에 'theme' 화면을 추가하여 '화면 테마' 설정으로 이동할 수 있도록 했습니다.
  • apps/mobile/app/(app)/settings/theme.tsx
    • 새로운 파일로, 라이트/다크/시스템 모드를 선택할 수 있는 테마 설정 화면을 구현했습니다.
    • useTheme 훅을 사용하여 테마 모드를 관리하고, RadioGroup 컴포넌트를 통해 사용자 선택을 반영합니다.
    • 테마 선택 시 애니메이션 효과를 적용했습니다.
  • apps/mobile/app/(auth)/_layout.tsx
    • useTheme 훅을 사용하여 현재 테마를 가져오고, StackcontentStyle 및 헤더 스타일에 테마에 맞는 배경색과 텍스트 색상을 적용했습니다.
    • 회원가입 화면(sign-up)에 headerShown: true 옵션을 추가하여 네이티브 헤더를 표시하도록 했습니다.
    • 헤더에 뒤로가기 버튼을 추가했습니다.
  • apps/mobile/app/(auth)/login.tsx
    • 소셜 로그인 버튼(카카오, 구글, 애플)에 다크 모드 스타일링을 추가하여 테마에 따른 시각적 일관성을 확보했습니다.
    • SocialLoginButton 컴포넌트에 labelClassName prop을 추가하여 텍스트 색상을 동적으로 제어할 수 있도록 했습니다.
  • apps/mobile/app/(auth)/sign-up.tsx
    • 기존의 커스텀 헤더 구현을 제거하고, 부모 _layout.tsx에서 설정된 네이티브 Stack 헤더를 사용하도록 변경했습니다.
    • 루트 View의 배경색을 bg-white에서 bg-background로 변경하여 테마를 따르도록 했습니다.
  • apps/mobile/app/_layout.tsx
    • 애플리케이션의 최상위 레벨에 ThemeProvider를 추가하여 전역적으로 테마를 관리하도록 했습니다.
    • AuthGateLayout에서 useTheme 훅을 사용하여 StackcontentStyle에 테마에 맞는 배경색을 적용했습니다.
  • apps/mobile/assets/icons/ic_device.svg
    • 시스템 테마를 나타내는 새로운 SVG 아이콘을 추가했습니다.
  • apps/mobile/assets/icons/ic_moon.svg
    • 다크 모드를 나타내는 새로운 SVG 아이콘을 추가했습니다.
  • apps/mobile/assets/icons/ic_sun.svg
    • 라이트 모드를 나타내는 새로운 SVG 아이콘을 추가했습니다.
  • apps/mobile/global.css
    • @source "./src/shared/ui/**/*.variants.ts";를 추가하여 커스텀 UI 컴포넌트의 Tailwind 변형을 인식하도록 했습니다.
    • CSS 변수에 --white를 추가하고, 다크 모드에서 --white의 값을 조정했습니다.
  • apps/mobile/src/features/todo/presentations/components/Calendar/CalendarNavigation.tsx
    • 달력 네비게이션 아이콘의 colorClassNameaccent-gray-6에서 text-gray-6으로 변경했습니다.
  • apps/mobile/src/shared/providers/theme-provider.tsx
    • 새로운 파일로, ThemeContextThemeProvider를 구현하여 앱의 테마 모드(light, dark, system)를 관리하고, SecureStore를 통해 사용자 설정을 저장 및 로드합니다.
    • useTheme 훅을 제공하여 컴포넌트에서 테마 상태에 접근할 수 있도록 했습니다.
  • apps/mobile/src/shared/ui/Button/Button.tsx
    • clsx 대신 커스텀 cn 유틸리티를 사용하도록 변경했습니다.
    • 버튼 텍스트 색상 로직을 업데이트하여 다크 모드에서 fill variant의 텍스트 색상이 text-white 대신 dark:text-gray-9를 따르도록 했습니다.
  • apps/mobile/src/shared/ui/Button/Button.variants.ts
    • tailwind-variants 임포트 경로를 커스텀 tv 유틸리티로 변경했습니다.
    • 버튼 fillweak variant에 다크 모드 스타일링을 추가했습니다.
  • apps/mobile/src/shared/ui/Flex/Flex.variants.ts
    • tailwind-variants 임포트 경로를 커스텀 tv 유틸리티로 변경했습니다.
  • apps/mobile/src/shared/ui/Icon/createStyledIcon.ts
    • 예시 코드의 colorClassNameaccent-gray-6에서 text-gray-6으로 변경했습니다.
    • StyledIcon 타입을 내보내도록 추가했습니다.
  • apps/mobile/src/shared/ui/Icon/icons.ts
    • 새로운 아이콘 SVG 파일(ic_device.svg, ic_moon.svg, ic_sun.svg)을 임포트하고, DeviceIcon, MoonIcon, SunIcon으로 내보내도록 추가했습니다.
  • apps/mobile/src/shared/ui/Icon/index.ts
    • createStyledIcon에서 StyledIcon 타입을 StyledIconType으로 내보내도록 변경했습니다.
    • 새로 추가된 DeviceIcon, MoonIcon, SunIcon을 내보내도록 추가했습니다.
  • apps/mobile/src/shared/ui/Input/Input.tsx
    • clsx 대신 커스텀 cn 유틸리티를 사용하도록 변경했습니다.
    • TextInput 컴포넌트를 withUniwind로 래핑한 StyledTextInput을 사용하도록 변경했습니다.
    • 입력 필드의 텍스트 색상을 text-foreground로 설정하여 테마를 따르도록 했습니다.
  • apps/mobile/src/shared/ui/Input/Input.variants.ts
    • tailwind-variants 임포트 경로를 커스텀 tv 유틸리티로 변경했습니다.
  • apps/mobile/src/shared/ui/ListRow/ListRowImage.tsx
    • 이미지 컨테이너의 하드코딩된 backgroundColor를 제거하고 className="bg-gray-3"를 추가하여 테마를 따르도록 했습니다.
  • apps/mobile/src/shared/ui/Text/Text.tsx
    • clsx 대신 커스텀 cn 유틸리티를 사용하도록 변경했습니다.
  • apps/mobile/src/shared/ui/Text/Text.variants.ts
    • tailwind-variants 임포트 경로를 커스텀 tv 유틸리티로 변경했습니다.
    • twMerge: false 옵션을 제거했습니다. (커스텀 tv에서 처리)
  • apps/mobile/src/shared/ui/TextButton/TextButton.tsx
    • clsx 대신 커스텀 cn 유틸리티를 사용하도록 변경했습니다.
    • ArrowRightIconcolorClassNameaccent-gray-6에서 text-gray-6으로 변경했습니다.
  • apps/mobile/src/shared/ui/TextButton/TextButton.variants.ts
    • tailwind-variants 임포트 경로를 커스텀 tv 유틸리티로 변경했습니다.
  • apps/mobile/src/shared/ui/VoiceTextField/VoiceTextField.tsx
    • useResolveClassNames 훅을 사용하여 recognizingPlaceholderColor, micIconColor, recordingIconColor의 기본값을 테마에 따라 동적으로 설정하도록 변경했습니다.
    • 입력 필드의 텍스트 색상을 text-foreground로 설정하여 테마를 따르도록 했습니다.
  • apps/mobile/src/shared/utils/cn.ts
    • twMerge 대신 extendTailwindMerge를 사용하여 customTwMerge를 정의했습니다.
    • 커스텀 text-inputtext-size 클래스 그룹을 customClassGroups에 추가하여 twMerge 충돌을 방지하도록 했습니다.
  • apps/mobile/src/shared/utils/tv.ts
    • 새로운 파일로, createTV를 사용하여 커스텀 tv 인스턴스를 정의했습니다.
    • twMergeConfigtext-inputtext-size 클래스 그룹을 확장하여 tailwind-variantstwMerge 간의 충돌을 방지하도록 했습니다.
Activity
  • 이 Pull Request는 다크/라이트 모드 전환 기능 구현을 목표로 생성되었습니다.
  • 테마 설정 및 관련 UI/UX 개선 작업이 진행되었습니다.
  • 코드베이스 전반에 걸쳐 하드코딩된 색상 값을 테마 변수로 전환하는 리팩토링이 이루어졌습니다.
  • 새로운 아이콘 및 유틸리티 파일이 추가되었습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

다크/라이트/시스템 모드 전환 기능 구현을 위한 PR 잘 보았습니다. ThemeProvider, SecureStore, Uniwind를 활용한 테마 시스템 구현이 훌륭합니다. 하드코딩된 색상을 테마 변수로 전환하고, tailwind-merge 충돌을 해결하기 위해 커스텀 cn, tv 유틸리티를 도입한 점 등 코드 품질과 유지보수성을 크게 향상시키는 좋은 변경 사항들이 많습니다. 다만, 일부 화면의 배경색이 여전히 하드코딩되어 있어 테마 전환이 완벽하게 동작하지 않는 치명적인 문제가 발견되었습니다. 이는 브랜드별 색상 값을 테마 변수로 정의해야 한다는 규칙(Rule 3)과도 관련이 있습니다. 이 부분을 수정하면 더욱 완성도 높은 기능이 될 것 같습니다. 전반적으로 훌륭한 기여입니다.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@hijjoy hijjoy requested review from dydals3440 and removed request for dydals3440 February 5, 2026 05:44
Copy link
Contributor

@dydals3440 dydals3440 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다~!! 제안 하나정도만 남겨보았습니다!

@dydals3440
Copy link
Contributor

이상없으면 머지해주세요~!!

- react-native-mmkv 도입으로 동기 읽기 가능
- 비동기 로딩 상태(isLoading) 제거로 테마 깜빡임 해소
- 테마 설정 화면 로딩 스피너 제거

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@hijjoy
Copy link
Member Author

hijjoy commented Feb 5, 2026

이상없으면 머지해주세요~!!

빌드해보고 확인후에 이상없으면 머지하겠습미다

@hijjoy hijjoy merged commit a58b28b into main Feb 5, 2026
3 checks passed
@dydals3440 dydals3440 deleted the feature/theme branch February 5, 2026 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: mobile 📱 모바일 - Expo 기반 모바일 앱 UI/UX 및 클라이언트 로직 관련 type: docs 📝 문서화 - README, API 가이드 등 팀 내 협업 효율을 위한 문서 작업 type: feat 🚀 신규 기능 - 사용자에게 새로운 비즈니스 가치를 제공하는 작업

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: 다크/라이트 모드 전환 기능 구현

2 participants