[Setting/#7] design system#8
Conversation
- `settings.gradle.kts`에 신규 모듈인 `:core:coroutine`을 추가하였습니다.
- `core:coroutine` 모듈을 신규 생성하고 기본 빌드 설정(`build.gradle.kts`) 및 `.gitignore`를 추가하였습니다. - `kindl.android.library` 및 `kindl.hilt` 컨벤션 플러그인을 적용하고 네임스페이스를 `core.coroutine`으로 설정하였습니다. - 코루틴 디스패처 의존성 주입을 위한 `@IoDispatcher` 한정자(Qualifier)를 정의하였습니다. - `DispatcherModule`을 추가하여 `Dispatchers.IO`를 `SingletonComponent` 내에서 제공하도록 구현하였습니다.
- `ForbiddenAppRepository` 인터페이스와 `GetInstalledAppsUseCase`의 호출 방식을 `suspend` 함수로 변경하였습니다. - `ForbiddenAppRepositoryImpl`에서 `PackageManager`를 통한 앱 목록 조회 시 `IoDispatcher`를 사용하여 I/O 스레드에서 동작하도록 개선하였습니다. - `data:forbidden` 모듈의 의존성에 `core:coroutine` 프로젝트를 추가하였습니다. - `ForbiddenAppRepositoryImpl` 생성자에 Hilt의 `@IoDispatcher`를 통한 `CoroutineDispatcher` 주입 로직을 추가하였습니다.
- `core:designsystem` 모듈의 컬러 시스템을 대폭 확장하였습니다.
- Slate(기본), Coral(포인트), Blue/Teal/Amber(보조) 등 상세 팔레트를 정의하였습니다.
- `KindlColors` 데이터 클래스를 통해 Surface, Interactive, State, Form, Chart 등 역할 기반 컬러 시스템을 구축하였습니다.
- 라이트 및 다크 테마별 색상 값을 구체적으로 설정하고 `staticCompositionLocalOf`를 통해 접근 가능하도록 구현하였습니다.
- 커스텀 타이포그래피 시스템을 구축하였습니다.
- `Pretendard` 폰트 패밀리를 적용하고 Regular, SemiBold, Bold 등 웨이트별 토큰(Body, Title, Headline)을 정의하였습니다.
- `PlatformTextStyle(includeFontPadding = false)`를 적용하여 폰트 상하단 패딩 문제를 해결하였습니다.
- `KindlTheme` 설정을 업데이트하였습니다.
- `MaterialTheme`와 연동되는 `KindlDarkColorScheme` 및 `KindlLightColorScheme`을 정의하였습니다.
- `ProvideKindlColorsAndTypography`를 통해 커스텀 컬러 및 타이포그래피를 `CompositionLocal`로 제공하도록 개선하였습니다.
- `KindlTheme` 싱글톤 객체를 추가하여 컴포저블 내에서 `KindlTheme.colors`와 같이 스타일 참조가 용이하도록 변경하였습니다.
- `UrlImage` 컴포넌트의 `url` 매개변수 타입을 `Any?`에서 `String?`으로 타입을 구체화하였습니다.
- `PermissionType`에서 `ACCESSIBILITY` 권한의 필수 여부(`isFocusRequired`)를 `true`에서 `false`로 변경하였습니다. - `ForbiddenAppItem` 컴포넌트의 이미지 로딩 방식을 `UrlImage`에서 `Image` 및 `Bitmap` 변환 방식으로 변경하고 `ContentScale.Crop`을 적용하였습니다. - `ForbiddenAppItem` 내 앱 명칭(`appName`)의 텍스트 스타일과 색상을 `KindlTheme` 가이드라인에 맞춰 업데이트하였습니다. - `HomeViewModel`에 `Timber` 로그 라이브러리 import를 추가하였습니다.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthrough코루틴 DI 모듈을 추가하고 디자인 시스템을 색상·타이포그래피 토큰으로 재구성했으며, Repository를 suspend로 전환하고 UI에 새로운 테마 스타일을 적용했습니다. Changes디자인 시스템 및 Coroutine 통합
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
- CodeRabbit 자동 리뷰 설정을 위한 `.coderabbit.yaml` 파일을 신규 생성하였습니다. - 리뷰 언어를 한국어(`ko-KR`)로 설정하고, `develop` 및 `main` 브랜치에 대해 자동 리뷰가 동작하도록 구성하였습니다. - 빌드 산출물, `.gradle`, 생성된 코드 및 이미지 파일 등을 리뷰 대상에서 제외하도록 경로 필터(`path_filters`)를 설정하였습니다. - Kotlin 소스 코드(`.kt`)에 대해 Compose 모범 사례, Hilt 의존성 주입, 코루틴 사용 및 네이밍 컨벤션 등의 구체적인 리뷰 지침을 정의하였습니다. - Gradle 설정 파일(`build.gradle.kts`)에 대해 `libs.versions.toml` 활용 및 의존성 적절성 확인 지침을 추가하였습니다.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (6)
core/coroutine/src/main/java/com/kindl/coroutine/di/DispatcherModule.kt (1)
15-17: ⚡ Quick win
@Singleton스코프를 명시적으로 추가하는 것을 권장합니다.
SingletonComponent에 설치되어 있어 암시적으로 싱글톤 스코프가 적용되지만,@Singleton어노테이션을 명시하면 의도가 더 명확해지고 향후 유지보수성이 향상됩니다.♻️ 제안하는 수정
+import javax.inject.Singleton + `@Module` `@InstallIn`(SingletonComponent::class) object DispatcherModule { + `@Singleton` `@IoDispatcher` `@Provides` fun providesIoDispatcher(): CoroutineDispatcher = Dispatchers.IO }🤖 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 `@core/coroutine/src/main/java/com/kindl/coroutine/di/DispatcherModule.kt` around lines 15 - 17, 현재 DispatcherModule의 providesIoDispatcher()에 싱글톤을 명시하지 않아 스코프가 암묵적입니다; DispatcherModule 안의 providesIoDispatcher 함수를 찾아 `@Singleton` 어노테이션을 추가하여(예: annotate providesIoDispatcher with `@Singleton`) 제공되는 CoroutineDispatcher가 애플리케이션 전역에서 싱글톤으로 사용되도록 명확히 하고, 필요하면 `@Singleton의` 올바른 import를 추가하세요.core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Type.kt (1)
33-71: 💤 Low value
sealed interface사용 방식 확인
TypographyTokens가sealed interface로 선언되었으나 내부data class들이 이를 구현하지 않습니다. 현재는 네임스페이스 용도로만 사용되고 있어object로 변경해도 동일하게 동작합니다.현재 구조가 의도된 것이라면 무시해도 됩니다.
🤖 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 `@core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Type.kt` around lines 33 - 71, TypographyTokens is declared as a sealed interface but its nested data classes (Regular, SemiBold, Bold) do not implement it, which is misleading; either make the nested classes implement the interface (e.g., declare data class Regular(...) : TypographyTokens) if you intend a sealed hierarchy, or convert TypographyTokens into an object/namespace (replace "sealed interface TypographyTokens" with "object TypographyTokens") if you only want a namespace; update the declarations of Regular, SemiBold, and Bold accordingly to match the chosen approach (implement the interface or remain simple nested data classes under the object).core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Theme.kt (1)
65-65: ⚡ Quick win
darkTheme기본값이true로 하드코딩됨기존에는
isSystemInDarkTheme()를 기본값으로 사용했으나, 현재는darkTheme: Boolean = true로 변경되어 시스템 테마를 따르지 않습니다. 이것이 의도된 동작인지 확인이 필요합니다.시스템 테마를 따르도록 하려면:
+import androidx.compose.foundation.isSystemInDarkTheme + `@Composable` fun KindlTheme( - darkTheme: Boolean = true, + darkTheme: Boolean = isSystemInDarkTheme(), content: `@Composable` () -> Unit, )🤖 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 `@core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Theme.kt` at line 65, The Theme composable currently hardcodes darkTheme: Boolean = true which forces dark mode; change the default to follow system settings by using isSystemInDarkTheme() as the default (i.e., set darkTheme's default to isSystemInDarkTheme()), ensuring the Theme function (Theme in Theme.kt) imports and calls androidx.compose.foundation.isSystemInDarkTheme() so the UI respects system theme unless an explicit value is passed.presentation/home/src/main/java/com/kindl/presentation/home/component/ForbiddenAppItem.kt (1)
18-18: 💤 Low value사용되지 않는 import
UrlImage가 import되었으나 코드에서 사용되지 않습니다.-import com.kindl.core.designsystem.component.UrlImage🤖 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 `@presentation/home/src/main/java/com/kindl/presentation/home/component/ForbiddenAppItem.kt` at line 18, The import com.kindl.core.designsystem.component.UrlImage in ForbiddenAppItem.kt is unused; remove the UrlImage import to clean up unused imports and avoid warnings. Locate the top of the file where UrlImage is referenced in the import list and delete that import line, leaving imports for symbols actually used by the ForbiddenAppItem class or file.core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Color.kt (1)
36-36: 💤 Low value네이밍 일관성:
White에Kindl접두사 누락다른 색상들(
KindlSlate*,KindlCoral*,KindlBlue500등)은 모두Kindl접두사를 사용하고 있으나,White만 접두사가 없습니다.🔧 수정 제안
-val White = Color(0xFFFFFFFF) +val KindlWhite = Color(0xFFFFFFFF)
lightKindlColors와darkKindlColors에서 참조하는White도 함께 변경 필요합니다.🤖 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 `@core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Color.kt` at line 36, Rename the top-level color constant White to KindlWhite and update all usages to the new name: change the declaration val White = Color(0xFFFFFFFF) to val KindlWhite = Color(0xFFFFFFFF) and update references inside lightKindlColors and darkKindlColors (and any other consumers) to use KindlWhite so naming is consistent with KindlSlate*, KindlCoral*, KindlBlue500, etc.; ensure any imports or references are adjusted to the new symbol Name.presentation/home/src/main/java/com/kindl/presentation/home/HomeViewModel.kt (1)
32-32: ⚡ Quick winRepository 레이어가 Dispatcher를 처리하므로 ViewModel에서 Dispatchers.IO 지정이 불필요합니다.
PR 목표에 따르면
ForbiddenAppRepositoryImpl이 이제@IoDispatcher를 주입받아 I/O 작업을 처리합니다. 따라서 ViewModel에서 명시적으로Dispatchers.IO를 지정할 필요가 없습니다.Repository/UseCase 레이어가 적절한 디스패처에서 실행되도록 책임을 가지므로, ViewModel은 기본 디스패처(Main)에서 launch하고 context switching은 하위 레이어에 위임하는 것이 권장됩니다.
♻️ 제안하는 리팩토링
private fun loadApps() { - viewModelScope.launch(Dispatchers.IO) { + viewModelScope.launch { val pm = context.packageManager val uiModels = getInstalledAppsUseCase().map { app ->🤖 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 `@presentation/home/src/main/java/com/kindl/presentation/home/HomeViewModel.kt` at line 32, The ViewModel is launching coroutines on Dispatchers.IO (see viewModelScope.launch(Dispatchers.IO)) while the repository (ForbiddenAppRepositoryImpl) already receives `@IoDispatcher` and handles I/O; remove the explicit Dispatchers.IO from the ViewModel coroutine launch so the ViewModel uses viewModelScope.launch { ... } on the default (Main) dispatcher and let the repository/use-case layers switch context internally.
🤖 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
`@core/designsystem/src/main/java/com/kindl/core/designsystem/component/UrlImage.kt`:
- Line 18: Change UrlImage.url back to a flexible type (Any?) so the UrlImage
composable can accept the same range of Coil AsyncImage model types it
previously supported: locate the UrlImage composable and update the url
parameter's type from String? to Any? and adjust any local usages/preview
arguments accordingly; also remove the now-unused UrlImage import from
ForbiddenAppItem (clean up the import list) to avoid dead imports and warnings.
In `@core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Type.kt`:
- Line 14: Remove or update the stale TODO on KindlFont.semiBold: the font
resources (pretendard_semibold|bold|regular|medium.otf) already exist, so delete
the comment "// TODO: 실제 폰트 리소스명으로 교체" from the val semiBold =
FontFamily(Font(R.font.pretendard_semibold)) line (or replace it with a brief
explanatory comment that the resource is present) to avoid misleading TODOs.
In
`@presentation/home/src/main/java/com/kindl/presentation/home/component/ForbiddenAppItem.kt`:
- Around line 35-42: The current call item.icon?.toBitmap()?.asImageBitmap()
inside ForbiddenAppItem causes a new Bitmap on every recomposition; wrap the
conversion in remember so the Bitmap/ ImageBitmap is cached (e.g., remember
keyed by item.icon) and then use the remembered value in the Image composable;
update the code that references item.icon, toBitmap, asImageBitmap and
iconModifier so the Image uses the remembered image and avoid per-recomposition
allocations.
In
`@presentation/home/src/main/java/com/kindl/presentation/home/HomeViewModel.kt`:
- Line 16: Remove the unused import of Timber in HomeViewModel.kt: delete the
line importing timber.log.Timber since the HomeViewModel class does not
reference Timber anywhere (no Timber.d/e/i calls), ensuring imports are cleaned
up and the file compiles without unused imports.
---
Nitpick comments:
In `@core/coroutine/src/main/java/com/kindl/coroutine/di/DispatcherModule.kt`:
- Around line 15-17: 현재 DispatcherModule의 providesIoDispatcher()에 싱글톤을 명시하지 않아
스코프가 암묵적입니다; DispatcherModule 안의 providesIoDispatcher 함수를 찾아 `@Singleton` 어노테이션을
추가하여(예: annotate providesIoDispatcher with `@Singleton`) 제공되는 CoroutineDispatcher가
애플리케이션 전역에서 싱글톤으로 사용되도록 명확히 하고, 필요하면 `@Singleton의` 올바른 import를 추가하세요.
In `@core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Color.kt`:
- Line 36: Rename the top-level color constant White to KindlWhite and update
all usages to the new name: change the declaration val White = Color(0xFFFFFFFF)
to val KindlWhite = Color(0xFFFFFFFF) and update references inside
lightKindlColors and darkKindlColors (and any other consumers) to use KindlWhite
so naming is consistent with KindlSlate*, KindlCoral*, KindlBlue500, etc.;
ensure any imports or references are adjusted to the new symbol Name.
In `@core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Theme.kt`:
- Line 65: The Theme composable currently hardcodes darkTheme: Boolean = true
which forces dark mode; change the default to follow system settings by using
isSystemInDarkTheme() as the default (i.e., set darkTheme's default to
isSystemInDarkTheme()), ensuring the Theme function (Theme in Theme.kt) imports
and calls androidx.compose.foundation.isSystemInDarkTheme() so the UI respects
system theme unless an explicit value is passed.
In `@core/designsystem/src/main/java/com/kindl/core/designsystem/theme/Type.kt`:
- Around line 33-71: TypographyTokens is declared as a sealed interface but its
nested data classes (Regular, SemiBold, Bold) do not implement it, which is
misleading; either make the nested classes implement the interface (e.g.,
declare data class Regular(...) : TypographyTokens) if you intend a sealed
hierarchy, or convert TypographyTokens into an object/namespace (replace "sealed
interface TypographyTokens" with "object TypographyTokens") if you only want a
namespace; update the declarations of Regular, SemiBold, and Bold accordingly to
match the chosen approach (implement the interface or remain simple nested data
classes under the object).
In
`@presentation/home/src/main/java/com/kindl/presentation/home/component/ForbiddenAppItem.kt`:
- Line 18: The import com.kindl.core.designsystem.component.UrlImage in
ForbiddenAppItem.kt is unused; remove the UrlImage import to clean up unused
imports and avoid warnings. Locate the top of the file where UrlImage is
referenced in the import list and delete that import line, leaving imports for
symbols actually used by the ForbiddenAppItem class or file.
In
`@presentation/home/src/main/java/com/kindl/presentation/home/HomeViewModel.kt`:
- Line 32: The ViewModel is launching coroutines on Dispatchers.IO (see
viewModelScope.launch(Dispatchers.IO)) while the repository
(ForbiddenAppRepositoryImpl) already receives `@IoDispatcher` and handles I/O;
remove the explicit Dispatchers.IO from the ViewModel coroutine launch so the
ViewModel uses viewModelScope.launch { ... } on the default (Main) dispatcher
and let the repository/use-case layers switch context internally.
🪄 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: CHILL
Plan: Pro Plus
Run ID: 42965a87-fa0a-48fa-9f0f-3ebb77716629
📒 Files selected for processing (20)
.coderabbit.yaml.idea/deploymentTargetSelector.xml.idea/gradle.xml.idea/inspectionProfiles/Project_Default.xmlcore/coroutine/.gitignorecore/coroutine/build.gradle.ktscore/coroutine/src/main/java/com/kindl/coroutine/di/DispatcherModule.ktcore/coroutine/src/main/java/com/kindl/coroutine/qualifier/IoDispatcher.ktcore/designsystem/src/main/java/com/kindl/core/designsystem/component/UrlImage.ktcore/designsystem/src/main/java/com/kindl/core/designsystem/theme/Color.ktcore/designsystem/src/main/java/com/kindl/core/designsystem/theme/Theme.ktcore/designsystem/src/main/java/com/kindl/core/designsystem/theme/Type.ktcore/permission/src/main/kotlin/com/kindl/core/permission/PermissionType.ktdata/forbidden/build.gradle.ktsdata/forbidden/src/main/java/com/kindl/data/forbidden/repositoryimpl/ForbiddenAppRepositoryImpl.ktdomain/forbidden/src/main/java/com/kindl/domain/forbidden/repository/ForbiddenAppRepository.ktdomain/forbidden/src/main/java/com/kindl/domain/forbidden/usecase/GetInstalledAppsUseCase.ktpresentation/home/src/main/java/com/kindl/presentation/home/HomeViewModel.ktpresentation/home/src/main/java/com/kindl/presentation/home/component/ForbiddenAppItem.ktsettings.gradle.kts
- `ForbiddenAppItem` 컴포넌트에서 `Drawable`을 `ImageBitmap`으로 변환하는 로직에 `remember`를 적용하여 리컴포지션 시 불필요한 연산을 방지하도록 최적화하였습니다. - `ForbiddenAppItem.kt` 내 사용하지 않는 `UrlImage` 임포트 구문을 제거하였습니다. - `KindlFont` 설정 파일에서 폰트 리소스 관련 `TODO` 주석을 삭제하였습니다.
ISSUE
❗ WORK DESCRIPTION
디자인 시스템 세팅
색상, 타이포그래피, 다크 모드-라이트 모드
core:coroutine 세팅
PackageManager를 통한 앱 목록 조회 시IoDispatcher를 사용하여 I/O 스레드에서 동작하도록 개선Summary by CodeRabbit
New Features
Refactor
Bug Fixes
Chores