-
Notifications
You must be signed in to change notification settings - Fork 0
[INIT/#1] 프로젝트 기초 세팅 #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
znayeonzn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수고하셨습니다~~!
app/build.gradle.kts
Outdated
| compileSdk = 35 | ||
|
|
||
| defaultConfig { | ||
| applicationId = "com.android.heartz" | ||
| applicationId = "com.heartz.app" | ||
| minSdk = 28 | ||
| targetSdk = 35 | ||
| versionCode = 1 | ||
| versionName = "1.0" | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p1
버전 관리 하드코딩 말고 버전 카탈로그 방식으로 libs.version.toml에서 관리하는 거 어떨까요?!
compileSdk = libs.versions.compileSdk.get().toInt()
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = libs.versions.versionCode.get().toInt()
versionName = libs.versions.versionName.get()There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
버전 카탈로그 좋은 것 같아요! 반영하겠습니다!!
app/build.gradle.kts
Outdated
| // TODO: kakao social login | ||
| buildConfigField( | ||
| "String", | ||
| "KAKAO_NATIVE_APP_KEY", | ||
| properties["kakao.native.app.key"].toString() | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3
단순 궁금.. 우리 이거 나중에 스프린트 위해서 안 지우는 거 맞죠?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사실 앱잼 내에 진행할 줄 알고 만든 필드인데 굳이 앱잼 후에 스프린트한다면 남겨 둘 필요는 없어보이네요!
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.composed | ||
|
|
||
| inline fun Modifier.noRippleClickable(crossinline onClick: () -> Unit = {}): Modifier = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3
crossinline을 처음 봐서 찾아봤는데 람다에서 non-local return을 막아주는 역할을 하는 거구뇽 배우 ㅓ 가요 ! 🙇♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline함수를 쓰면서 정말 많이 나오는 부분 같아요! 앱잼하면서 런캐칭으로 오류처리 할 때 Timber 찍는 거 같이 내부함수로 만들면서 고민해봐요!
민재형 블로그 참고 https://angrypodo.tistory.com/7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 이거 저도 공부해보겠습니다~~신기하네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p2
파일명 ServiceModule은 어때요?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@znayeonzn 👍️👍️
| val response = | ||
| dummyService.getDummies( | ||
| request = request.toData() | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p2
한 줄로 가도 되지 않을까요??
| val response = | |
| dummyService.getDummies( | |
| request = request.toData() | |
| ) | |
| val response = dummyService.getDummies(request = request.toData()) |
| visible = navigator.showBottomBar(), | ||
| tabs = MainNavTab.entries.toImmutableList(), | ||
| currentTab = navigator.currentTab, | ||
| onTabSelected = navigator::navigate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3
👍👍👍👍
| } | ||
|
|
||
| fun navigateUp() { | ||
| navController.navigateUp() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p1
성능 최적화를 위해서 이렇게 해줘야 한다고 알고 있습니다!
| navController.navigateUp() | |
| navController::navigateUp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@znayeonzn 이 부분은 함수 참조(::navigateUp)와 함수 호출(navigateUp())의 차이에 대해 한 번 공부해보면 좋을 것 같아요! 😊
예를 들어 Button의 onClick처럼 버튼이 눌렸을 때 동작해야 하는 상황에서는 다음처럼 함수 참조를 사용해요
fun navigateUp(): Boolean {
return navController.navigateUp()
}
Button(onClick = ::navigateUp) // 버튼을 누를 때 실행 됨.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아하~ 종리드 천재. 떠먹어주셔서 감사합니다 🤩
| Icon( | ||
| imageVector = ImageVector.vectorResource(tab.icon), | ||
| contentDescription = stringResource(tab.contentDescription), | ||
| tint = bottomItemColor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p2
icon 사이즈는 설정 안 해도 되나요?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@znayeonzn 이 부분은 이미지 벡터에서 따로 사이즈를 설정하고 있습니다! 근데 아직 확정 아이콘이 아니라 변동사항이 있을 것 같아요~~
| contentDescription = ic_mypage_desc, | ||
| route = Mypage | ||
| ) | ||
| ; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p1
위로 붙여주자!!
|
|
||
| @Composable | ||
| fun HomeScreen(viewModel: HomeViewModel = hiltViewModel()) { | ||
| val uiState by viewModel.uiState.collectAsState() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p2
collectAsStateWithLifecycle()??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이런 부분까지 알고 계시는 군요! 많이 공부해보겠습니다. 항상 생각없이 상태 수집을 collectAsState()로만 했었는데 감사합니다 공부해볼게요!
sohee6989
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수고하셨습니다~~
| ) { | ||
| QUEST( | ||
| icon = ic_folder_open, | ||
| contentDescription = ic_quest_desc, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3: tab 바에서만 string 추출해서 쓰는걸까요??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sohee6989 탭 바에 보통 텍스트가 같이 포함된 UI가 많은데 초기 세팅할 때는 텍스트가 없길래 추출만 해두고, 추후에 생긴다면 반영하려고 뒀습니다! 탭 바 전용 string리소스가 맞는거 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분 제가 말을 애매하게 썼네요..!ㅜㅜ
저희 string 추출 안 하기로 했었는데 이 부분 string 추출 해놓았길래 질문드린거였습니다!ㅎㅎ
| */ | ||
| @RunWith(AndroidJUnit4::class) | ||
| class ExampleInstrumentedTest { | ||
| @Test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3: 얘도 테스트코드인건가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이부분은 안드로이드 Instrumented 테스트 코드입니다! 저도 unit test만 해보고 요런 테스트에 대해서는 처음 공부해봤는데 이 차이점은 나중에 같이 공부해보면 좋을 것 같아요! 여기서 수정이 일어난 이유는 ktlint에서 import * 이런식으로 와일드카드 쓰는 것을 지양하기 때문에 수정했습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오오 Instrumented 테스트 코드 이 부분 저도 한 번 미리 공부해보겠습니다~~
| super.onCreate() | ||
|
|
||
| initTimber() | ||
| setDayMode() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p3: 다크 모드 확장하는 거 물어봐주는거 까먹지 말기~~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sohee6989 앱잼 기간 동안에는 일단 안하는걸루!
|
""" Walkthrough이 변경 사항은 안드로이드 프로젝트의 초기 세팅을 광범위하게 수행합니다. Gradle 설정, 버전 관리, 의존성 관리, 코드 스타일 도구, 네트워크 및 DI 모듈, 기본 도메인/데이터/프레젠테이션 구조, 네비게이션, 테마, UI 컴포넌트, 리소스 파일 등이 대규모로 추가 및 구성되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MainActivity
participant MainScreen
participant MainNavigator
participant NavHost
participant HomeViewModel
participant DummyRepository
participant DummyService
User->>MainActivity: 앱 실행
MainActivity->>MainScreen: setContent(HeartzTheme)
MainScreen->>MainNavigator: rememberMainNavigator()
MainScreen->>NavHost: MainNavHost(navigator)
NavHost->>HomeViewModel: (Home 탭 진입 시) getDummies()
HomeViewModel->>DummyRepository: getDummies(Dummy)
DummyRepository->>DummyService: getDummies(RequestDummyDto)
DummyService-->>DummyRepository: DummyBaseResponse
DummyRepository-->>HomeViewModel: Result<DummyResultModel>
HomeViewModel-->>MainScreen: uiState 업데이트
MainScreen-->>User: 결과 UI 표시
Assessment against linked issues
Assessment against linked issues: Out-of-scope changes(해당 변경 사항 내에서는 명확히 범위를 벗어난 기능적 코드 변경이 발견되지 않았습니다.) Poem
""" 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms (1)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 20
♻️ Duplicate comments (4)
app/src/main/java/com/heartz/app/data/repositoryimpl/DummyRepositoryImpl.kt (1)
18-19: 코드를 더 간결하게 만들 수 있습니다.이전 리뷰 코멘트와 동일하게, 한 줄로 작성하는 것이 더 깔끔할 것 같습니다:
- val response = dummyService.getDummies(request = request.toData()) - response.data.toDomain() + dummyService.getDummies(request = request.toData()).data.toDomain()app/src/main/java/com/heartz/app/presentation/main/component/MainBottomBar.kt (1)
94-98: 아이콘 크기를 명시적으로 설정하는 것을 고려하세요.이미 이전 리뷰에서 논의되었지만, 일관성 있는 UI를 위해 아이콘 크기를 명시적으로 설정하는 것을 고려해볼 수 있습니다.
app/build.gradle.kts (1)
20-27: 버전 카탈로그 사용이 잘 적용되었습니다.이전 리뷰에서 제안했던 버전 카탈로그 방식이 잘 적용되었습니다.
app/src/main/java/com/heartz/app/presentation/main/MainNavigator.kt (1)
59-61: navigateUp 함수 구현이 적절합니다.이전 리뷰에서 논의된 함수 참조 vs 함수 호출에 대한 내용으로, 현재 구현이 적절합니다.
🧹 Nitpick comments (20)
app/src/main/java/com/heartz/app/core/navigation/Route.kt (1)
1-3: Route 인터페이스를sealed interface로 변경 고려
sealed interface Route로 선언하면when식 사용 시 컴파일러가 분기 누락 여부를 체크해줄 수 있어 안전성이 높아집니다.
추후 하위 Route 가 객체·data class 등으로 다양해질 경우 유용합니다.settings.gradle.kts (1)
19-20: 외부 Maven 저장소 범위 제한 권장카카오 사설 저장소를 전체 Maven 저장소로 추가하면 불필요한 아티팩트 해상도 시간이 증가하고, 잠재적으로 의도치 않은 그룹이 내려올 수 있습니다.
maven { url = uri("https://devrepo.kakao.com/nexus/content/groups/public") content { includeGroup("com.kakao") } // 예시: 사용 그룹만 한정 }필요 그룹만 필터링하도록
content블록을 설정해 보시는 것을 권장드립니다.app/src/main/res/values/strings.xml (1)
4-8: 다국어 리소스 분리 및 키 네이밍 통일 제안
values/strings.xml은 기본(영어) 리소스이므로, 한글 문구는values-ko/strings.xml로 분리하면 다국어 준비가 수월합니다.- 키 접두사를
bottom_bar_*_desc등으로 통일하면 검색성이 향상됩니다.예시:
<!-- values/strings.xml --> <string name="bottom_bar_home_desc">Home</string> <!-- values-ko/strings.xml --> <string name="bottom_bar_home_desc">홈</string>app/src/main/res/drawable/ic_folder_open.xml (1)
1-10: 하드코딩 색상 → 테마 속성 적용 권장Vector Drawable 내부에 고정 HEX 색상
#FAAEAE가 박혀있어 다크모드·테마 변경 시 일관성이 깨질 수 있습니다.-android:fillColor="#FAAEAE" +android:fillColor="?attr/colorPrimary"색상을 테마 속성으로 치환해 UI 일관성과 유지보수성을 높여주세요.
app/src/main/java/com/heartz/app/core/state/UiState.kt (1)
12-14: 에러 처리를 위한 추가 정보 제공을 고려해보세요.현재
Failure상태는 문자열 메시지만 포함하고 있습니다. 더 구체적인 에러 처리를 위해 에러 코드나 예외 타입을 추가하는 것을 고려해보세요.data class Failure( - val msg: String + val msg: String, + val errorCode: String? = null, + val throwable: Throwable? = null ) : UiState<Nothing>gradle/libs.versions.toml (1)
55-61: 공백 라인 정리가 필요합니다.버전 정의 섹션에 불필요한 공백 라인이 있어 가독성이 떨어집니다.
#Third Party ksp = "2.0.21-1.0.25" - - - ktlint = "11.6.1" - -app/src/main/java/com/heartz/app/core/navigation/MainTabRoute.kt (1)
1-3: 인터페이스 목적에 대한 문서화를 추가해보세요.마커 인터페이스의 역할과 사용법을 명확히 하기 위해 KDoc 주석을 추가하는 것을 권장합니다.
package com.heartz.app.core.navigation +/** + * 메인 탭 네비게이션을 위한 마커 인터페이스 + * 이 인터페이스를 구현하는 객체들은 메인 탭의 네비게이션 대상이 됩니다. + */ interface MainTabRoute : Routeapp/src/main/java/com/heartz/app/domain/model/Dummy.kt (1)
3-6: 실제 도메인 모델로의 점진적 교체를 고려해보세요.현재는 더미 데이터 모델로 적절하지만, 향후 실제 비즈니스 요구사항에 맞는 도메인 모델로 점진적으로 교체하는 것을 권장합니다. 이때 데이터 검증 로직이나 비즈니스 룰도 함께 추가하는 것을 고려해보세요.
app/src/main/java/com/heartz/app/domain/model/DummyResultModel.kt (1)
3-5: 도메인 모델에 대한 최소한의 문서화 필요
DummyResultModel이 어떤 목적과 제약(예:info리스트가 비어있을 수 있는지)에 대한 설명이 전혀 없습니다. 간단한 KDoc을 추가해두면 이후 모델 변경 / 확장 시 혼란을 줄일 수 있습니다./** * 서버에서 내려오는 더미 데이터의 결과 모델. * @param info 표시용 문자열 리스트 */ data class DummyResultModel( val info: List<String> )app/src/main/java/com/heartz/app/data/mapper/todata/DummyMapper.kt (1)
6-10: 매핑 누락/변경 감지용 테스트 추가 권장확장 함수 구현은 간단하지만, 필드가 추가·변경될 때 컴파일이 통과되면서 런타임에 누락이 발생할 위험이 있습니다.
Mapper 단위 테스트를 작성해Dummy(id, email)→RequestDummyDto변환이 정확한지 검증해 두면 리팩터링 시 안전망이 됩니다.app/src/main/java/com/heartz/app/presentation/mypage/MypageScreen.kt (1)
3-12: Modifier 체이닝 컨벤션
Modifier체이닝을 매 줄마다.로 시작하도록 정렬하면 가독성이 높습니다.modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background)app/src/main/java/com/heartz/app/core/designsystem/ui/theme/TypoGraphy.kt (1)
9-18: 변수명 충돌 방지:Typography→HeartzTypography등으로 변경 제안동일한 이름의 타입(
androidx.compose.material3.Typography)과 프로퍼티가 공존하면 IDE 자동완성에서 혼란을 야기할 수 있습니다. 프로젝트 전역에서 사용할 커스텀 타이포그래피는HeartzTypography같이 고유한 이름으로 선언하는 편이 명확합니다.-val Typography = +val HeartzTypography = Typography( bodyLarge = TextStyle(변경 후
HeartzTheme등에서 해당 프로퍼티를 참조하도록 수정해 주세요.app/src/main/java/com/heartz/app/presentation/graph/FigureScreen.kt (1)
15-27: 테마 시스템을 사용하여 일관성을 개선하세요.하드코딩된 색상 대신 테마 시스템을 사용하면 일관성과 유지보수성이 향상됩니다.
다음과 같이 테마 색상을 사용하도록 수정하는 것을 권장합니다:
-import androidx.compose.ui.graphics.Color +import androidx.compose.material3.MaterialTheme @Composable fun FigureScreen() { Column( modifier = Modifier .fillMaxSize() - .background(Color.White), + .background(MaterialTheme.colorScheme.background), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( text = "figure Screen", - color = Color.Black + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.bodyLarge ) } }app/src/main/java/com/heartz/app/presentation/home/HomeState.kt (1)
6-8: 상태 불변성을 위해 val 사용을 고려해보세요.현재
user프로퍼티가var로 선언되어 있는데, 상태 관리에서는 불변성을 유지하는 것이 좋습니다.val로 변경하고 상태 업데이트 시copy()메서드를 사용하는 것을 권장합니다.data class HomeState( - var user: UiState<DummyResultModel> = UiState.Loading + val user: UiState<DummyResultModel> = UiState.Loading )app/src/main/java/com/heartz/app/data/datasource/local/DummyLocalDataSource.kt (1)
5-12: 인터페이스 설계가 적절합니다.Flow를 사용한 반응형 로그인 상태 관리와 suspend 함수를 통한 비동기 처리가 잘 설계되었습니다. TODO 주석에 따라 임시 코드로 보이니, 추후 리팩토링 시점을 고려해주세요.
app/src/main/java/com/heartz/app/presentation/main/MainNavHost.kt (1)
18-30: 기본 네비게이션 구조가 잘 설계되었습니다모듈러 방식으로 각 기능별 네비게이션 그래프가 분리되어 있어 유지보수성이 좋습니다.
향후 사용자 경험 개선을 위해 적절한 전환 애니메이션 추가를 고려해보시면 좋을 것 같습니다.
app/src/main/java/com/heartz/app/data/di/NetworkModule.kt (1)
21-26: 로깅 인터셉터 레벨을 빌드 타입에 따라 조정하는 것을 고려해보세요.현재
HttpLoggingInterceptor.Level.BODY로 설정되어 있어 디버깅에는 유용하지만, 프로덕션 환경에서는 성능과 보안상 적절하지 않을 수 있습니다.다음과 같이 빌드 타입에 따라 로깅 레벨을 조정하는 것을 권장합니다:
@Provides @Singleton fun providesLoggingInterceptor() = HttpLoggingInterceptor().apply { - level = HttpLoggingInterceptor.Level.BODY + level = if (BuildConfig.DEBUG) { + HttpLoggingInterceptor.Level.BODY + } else { + HttpLoggingInterceptor.Level.NONE + } }app/src/main/java/com/heartz/app/presentation/main/component/MainBottomBar.kt (2)
44-48: 애니메이션 전환 효과를 개선하세요.현재
EnterTransition.None과ExitTransition.None을 사용하여 애니메이션이 전혀 없어 사용자 경험이 좋지 않을 수 있습니다.AnimatedVisibility( visible = visible, - enter = EnterTransition.None, - exit = ExitTransition.None + enter = slideInVertically( + initialOffsetY = { it }, + animationSpec = tween(300) + ), + exit = slideOutVertically( + targetOffsetY = { it }, + animationSpec = tween(300) + ) )
59-59: 하드코딩된 패딩 값을 테마나 상수로 관리하세요.
21.dp와 같은 매직 넘버가 하드코딩되어 있어 일관성 있는 디자인 시스템 구축에 문제가 될 수 있습니다.앱의 디자인 시스템에 spacing 상수들을 정의하고 사용하는 것을 권장합니다.
// DesignSystem.kt object Spacing { val bottomBarVertical = 21.dp val bottomBarItemSpacing = 1.dp }app/src/main/java/com/heartz/app/presentation/main/MainNavigator.kt (1)
27-31: currentTab 계산 최적화를 고려하세요.매번
MainNavTab.find를 호출하는 것보다 더 효율적인 방법을 고려해볼 수 있습니다.val currentTab: MainNavTab? @Composable get() = - MainNavTab.find { tab -> - currentDestination?.hasRoute(tab::class) == true - } + currentDestination?.route?.let { route -> + MainNavTab.entries.firstOrNull { tab -> + currentDestination?.hasRoute(tab.route::class) == true + } + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (56)
app/build.gradle.kts(2 hunks)app/src/androidTest/java/com/android/heartz/ExampleInstrumentedTest.kt(1 hunks)app/src/main/AndroidManifest.xml(2 hunks)app/src/main/java/com/heartz/app/Heartz.kt(1 hunks)app/src/main/java/com/heartz/app/core/designsystem/ui/theme/Color.kt(1 hunks)app/src/main/java/com/heartz/app/core/designsystem/ui/theme/Theme.kt(1 hunks)app/src/main/java/com/heartz/app/core/designsystem/ui/theme/TypoGraphy.kt(1 hunks)app/src/main/java/com/heartz/app/core/navigation/MainTabRoute.kt(1 hunks)app/src/main/java/com/heartz/app/core/navigation/Route.kt(1 hunks)app/src/main/java/com/heartz/app/core/state/UiState.kt(1 hunks)app/src/main/java/com/heartz/app/core/util/ModifierExt.kt(1 hunks)app/src/main/java/com/heartz/app/data/datasource/local/DummyLocalDataSource.kt(1 hunks)app/src/main/java/com/heartz/app/data/datasource/remote/DummyRemoteDataSource.kt(1 hunks)app/src/main/java/com/heartz/app/data/datasourceimpl/local/DummyLocalDataSourceImpl.kt(1 hunks)app/src/main/java/com/heartz/app/data/datasourceimpl/remote/DummyRemoteDataSourceImpl.kt(1 hunks)app/src/main/java/com/heartz/app/data/di/DataSourceModule.kt(1 hunks)app/src/main/java/com/heartz/app/data/di/NetworkModule.kt(1 hunks)app/src/main/java/com/heartz/app/data/di/RepositoryModule.kt(1 hunks)app/src/main/java/com/heartz/app/data/di/ServiceModule.kt(1 hunks)app/src/main/java/com/heartz/app/data/dto/base/DummyBaseResponse.kt(1 hunks)app/src/main/java/com/heartz/app/data/dto/base/DummyNullableBaseResponse.kt(1 hunks)app/src/main/java/com/heartz/app/data/dto/request/RequestDummyDto.kt(1 hunks)app/src/main/java/com/heartz/app/data/dto/response/ResponseDummyDto.kt(1 hunks)app/src/main/java/com/heartz/app/data/mapper/todata/DummyMapper.kt(1 hunks)app/src/main/java/com/heartz/app/data/mapper/todomain/ResponseDummyDtoMapper.kt(1 hunks)app/src/main/java/com/heartz/app/data/repositoryimpl/DummyRepositoryImpl.kt(1 hunks)app/src/main/java/com/heartz/app/data/service/DummyService.kt(1 hunks)app/src/main/java/com/heartz/app/domain/model/Dummy.kt(1 hunks)app/src/main/java/com/heartz/app/domain/model/DummyResultModel.kt(1 hunks)app/src/main/java/com/heartz/app/domain/repository/DummyRepository.kt(1 hunks)app/src/main/java/com/heartz/app/domain/usecase/DummyUseCase.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/graph/FigureScreen.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/graph/navigation/FigureNavigation.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/home/HomeScreen.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/home/HomeState.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/home/HomeViewModel.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/home/navigation/HomeNavigation.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/main/MainActivity.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/main/MainNavHost.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/main/MainNavTab.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/main/MainNavigator.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/main/MainScreen.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/main/component/MainBottomBar.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/mypage/MypageScreen.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/mypage/navigation/MypageNavigation.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/quest/QuestScreen.kt(1 hunks)app/src/main/java/com/heartz/app/presentation/quest/navigation/QuestNavigation.kt(1 hunks)app/src/main/res/drawable/ic_folder_open.xml(1 hunks)app/src/main/res/drawable/ic_graph.xml(1 hunks)app/src/main/res/drawable/ic_home.xml(1 hunks)app/src/main/res/drawable/ic_user.xml(1 hunks)app/src/main/res/values/strings.xml(1 hunks)app/src/test/java/com/android/heartz/ExampleUnitTest.kt(1 hunks)build.gradle.kts(1 hunks)gradle/libs.versions.toml(1 hunks)settings.gradle.kts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
app/src/main/java/com/heartz/app/presentation/main/MainActivity.kt (2)
app/src/main/java/com/heartz/app/core/designsystem/ui/theme/Theme.kt (1)
HeartzTheme(6-13)app/src/main/java/com/heartz/app/presentation/main/MainScreen.kt (1)
MainScreen(14-36)
app/src/main/java/com/heartz/app/presentation/quest/navigation/QuestNavigation.kt (2)
app/src/main/java/com/heartz/app/presentation/main/MainNavigator.kt (1)
navigate(33-51)app/src/main/java/com/heartz/app/presentation/quest/QuestScreen.kt (1)
QuestScreen(13-27)
app/src/main/java/com/heartz/app/presentation/main/MainNavHost.kt (4)
app/src/main/java/com/heartz/app/presentation/home/navigation/HomeNavigation.kt (1)
homeGraph(15-19)app/src/main/java/com/heartz/app/presentation/quest/navigation/QuestNavigation.kt (1)
questGraph(15-19)app/src/main/java/com/heartz/app/presentation/graph/navigation/FigureNavigation.kt (1)
figureGraph(15-19)app/src/main/java/com/heartz/app/presentation/mypage/navigation/MypageNavigation.kt (1)
mypageGraph(15-19)
app/src/main/java/com/heartz/app/presentation/mypage/navigation/MypageNavigation.kt (2)
app/src/main/java/com/heartz/app/presentation/main/MainNavigator.kt (1)
navigate(33-51)app/src/main/java/com/heartz/app/presentation/mypage/MypageScreen.kt (1)
MypageScreen(13-27)
app/src/main/java/com/heartz/app/presentation/main/MainScreen.kt (3)
app/src/main/java/com/heartz/app/presentation/main/MainNavigator.kt (1)
rememberMainNavigator(64-69)app/src/main/java/com/heartz/app/presentation/main/component/MainBottomBar.kt (1)
MainBottomBar(37-76)app/src/main/java/com/heartz/app/presentation/main/MainNavHost.kt (1)
MainNavHost(13-31)
app/src/main/java/com/heartz/app/presentation/graph/navigation/FigureNavigation.kt (2)
app/src/main/java/com/heartz/app/presentation/main/MainNavigator.kt (1)
navigate(33-51)app/src/main/java/com/heartz/app/presentation/graph/FigureScreen.kt (1)
FigureScreen(13-27)
app/src/main/java/com/heartz/app/presentation/main/component/MainBottomBar.kt (1)
app/src/main/java/com/heartz/app/core/designsystem/ui/theme/Theme.kt (1)
HeartzTheme(6-13)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (33)
build.gradle.kts (1)
6-11: 플러그인 설정이 적절합니다최신 Android 개발에 필요한 플러그인들을 올바르게 추가했습니다:
- Compose 지원을 위한 kotlin.compose
- JSON 직렬화를 위한 kotlin.serialization
- 의존성 주입을 위한 hilt
- 코드 생성을 위한 ksp
- 데이터 클래스 최적화를 위한 kotlin.parcelize
- 코드 스타일 검사를 위한 ktlint
apply false를 사용하여 하위 모듈에서 선택적으로 적용할 수 있도록 한 것도 좋은 접근입니다.app/src/main/java/com/heartz/app/core/state/UiState.kt (1)
3-15: UI 상태 관리를 위한 잘 설계된 sealed interface입니다.타입 안전성을 보장하면서 다양한 UI 상태를 명확히 표현할 수 있는 구조입니다. 코드가 간결하고 이해하기 쉽습니다.
gradle/libs.versions.toml (2)
123-164: 번들 구성이 잘 되어 있습니다.관련된 라이브러리들을 논리적으로 그룹화하여 의존성 관리를 효율적으로 할 수 있도록 구성했습니다. 이는 모듈화된 빌드 설정에 도움이 됩니다.
11-11: ```shell
#!/bin/bashAGP 8.9.2 버전 존재 여부 확인 (Google Maven)
curl -s "https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/maven-metadata.xml"
| grep -o '8.9.2' || echo "버전 없음"</details> <details> <summary>app/src/main/java/com/heartz/app/core/navigation/MainTabRoute.kt (1)</summary> `3-3`: **네비게이션 구조를 위한 적절한 마커 인터페이스입니다.** 메인 탭 네비게이션을 위한 타입 안전성을 제공하는 깔끔한 설계입니다. </details> <details> <summary>app/src/main/java/com/heartz/app/domain/model/Dummy.kt (1)</summary> `3-6`: **테스트용 도메인 모델이 적절하게 구성되었습니다.** 간단하고 명확한 구조로 초기 개발 단계에서 사용하기에 적합합니다. </details> <details> <summary>app/src/androidTest/java/com/android/heartz/ExampleInstrumentedTest.kt (1)</summary> `13-15`: **`applicationId` 확인 필요** `assertEquals("com.android.heartz", appContext.packageName)`가 실제 `applicationId`와 일치하지 않으면 테스트가 바로 실패합니다. `build.gradle`의 `namespace` / `applicationId`가 `com.heartz.app`와 같이 달라졌다면 값도 함께 수정해 주세요. </details> <details> <summary>app/src/main/java/com/heartz/app/core/designsystem/ui/theme/Theme.kt (1)</summary> `6-13`: **잘 구현된 테마 설정입니다.** MaterialTheme을 올바르게 래핑하여 커스텀 컬러 스킴과 타이포그래피를 적용하는 깔끔한 구현입니다. Compose 테마 패턴을 잘 따르고 있습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/domain/repository/DummyRepository.kt (1)</summary> `6-8`: **깔끔한 리포지토리 인터페이스 설계입니다.** 도메인 레이어의 리포지토리 패턴을 올바르게 구현했습니다. suspend 함수와 Result<T> 타입을 사용한 에러 핸들링이 적절합니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/mapper/todomain/ResponseDummyDtoMapper.kt (1)</summary> `6-9`: **간단하고 명확한 매퍼 구현입니다.** DTO에서 도메인 모델로의 변환이 깔끔하게 구현되어 있습니다. 현재 구조에서는 적절한 직접 매핑입니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/dto/response/ResponseDummyDto.kt (1)</summary> `6-10`: **적절한 DTO 클래스 구현입니다.** Kotlin Serialization을 올바르게 사용하여 API 응답 구조를 정의했습니다. @SerialName 어노테이션과 @Serializable 사용이 적절합니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/dto/request/RequestDummyDto.kt (1)</summary> `6-12`: **요청 DTO 구현이 적절합니다.** kotlinx serialization을 올바르게 사용하고 있으며, @SerialName을 통한 JSON 매핑도 명확합니다. 데이터 클래스 패턴을 잘 따르고 있네요. </details> <details> <summary>app/src/main/java/com/heartz/app/data/datasource/remote/DummyRemoteDataSource.kt (1)</summary> `7-9`: **원격 데이터 소스 인터페이스 구현이 깔끔합니다.** suspend 함수를 사용한 비동기 네트워크 처리와 제네릭 베이스 응답 래퍼를 활용한 설계가 좋습니다. Repository 패턴을 잘 따르고 있네요. </details> <details> <summary>app/src/main/java/com/heartz/app/core/util/ModifierExt.kt (1)</summary> `9-17`: **리플 효과 없는 클릭 가능한 Modifier 확장 함수가 잘 구현되었습니다.** `composed`와 `remember`를 적절히 사용하여 재구성 시에도 효율적이고, `indication = null`로 리플 효과를 제거하는 로직이 정확합니다. UI/UX 요구사항에 따라 유용하게 활용될 것 같네요. </details> <details> <summary>app/src/main/java/com/heartz/app/presentation/main/MainActivity.kt (1)</summary> `10-21`: **깔끔한 MainActivity 구현입니다.** Hilt를 사용한 의존성 주입, Compose 설정, 그리고 edge-to-edge 디스플레이 활성화가 올바르게 구현되어 있습니다. 초기 프로젝트 설정으로 적절한 구조를 갖추고 있습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/di/ServiceModule.kt (1)</summary> `11-19`: **Hilt 의존성 주입 모듈이 올바르게 구현되었습니다.** SingletonComponent 스코프와 @Singleton 어노테이션을 사용하여 DummyService를 제공하는 방식이 적절합니다. Retrofit 인스턴스를 통해 서비스를 생성하는 패턴도 표준적입니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/dto/base/DummyBaseResponse.kt (1)</summary> `6-16`: **잘 구조화된 API 응답 래퍼 클래스입니다.** 제네릭 타입을 사용하여 재사용 가능하도록 설계되었고, @SerialName 어노테이션을 통한 JSON 매핑도 올바르게 구현되어 있습니다. 표준적인 API 응답 구조(success, code, message, data)를 따르고 있어 좋습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/di/RepositoryModule.kt (1)</summary> `11-17`: **Repository 바인딩이 올바르게 구현되었습니다.** @Binds 어노테이션을 사용하여 구현체를 인터페이스에 바인딩하는 방식이 효율적이고 적절합니다. Singleton 스코프로 Repository 패턴을 올바르게 적용했습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/dto/base/DummyNullableBaseResponse.kt (1)</summary> `6-16`: **API 응답 기본 구조가 잘 설계되었습니다** nullable 데이터를 처리하기 위한 기본 응답 클래스가 깔끔하게 구현되었습니다. Serializable 어노테이션과 SerialName을 적절히 사용하여 JSON 직렬화가 잘 설정되어 있습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/Heartz.kt (1)</summary> `8-24`: **Application 클래스 초기화가 적절하게 구현되었습니다** Hilt DI 설정과 기본 초기화 로직이 깔끔하게 분리되어 있습니다. DEBUG 빌드에서만 Timber를 활성화하는 것도 좋은 패턴입니다. 향후 다크모드 지원을 고려할 때는 사용자 설정이나 시스템 설정을 따르도록 개선할 수 있을 것 같습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/presentation/home/navigation/HomeNavigation.kt (1)</summary> `11-22`: **type-safe 네비게이션이 잘 구현되었습니다** Kotlin Serialization을 활용한 type-safe 네비게이션과 확장 함수를 통한 모듈화가 적절하게 구현되었습니다. 다른 기능 모듈들과 일관된 패턴을 유지하고 있어 좋습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/datasourceimpl/remote/DummyRemoteDataSourceImpl.kt (1)</summary> `10-19`: **Clean Architecture 패턴이 적절히 구현되었습니다** 데이터소스 구현체가 단일 책임 원칙을 잘 따르고 있으며, Hilt를 통한 의존성 주입과 코루틴을 활용한 비동기 처리가 적절하게 설정되어 있습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/presentation/main/MainScreen.kt (1)</summary> `14-36`: **잘 구현된 메인 스크린 구조입니다!** Scaffold를 사용한 구조가 깔끔하고, MainNavigator를 통한 네비게이션 상태 관리도 적절합니다. 하단 네비게이션의 가시성 제어와 ImmutableList 사용도 좋은 패턴입니다. </details> <details> <summary>app/src/main/java/com/heartz/app/presentation/quest/navigation/QuestNavigation.kt (1)</summary> `11-22`: **타입 안전 네비게이션이 잘 구현되었습니다!** Kotlin Serialization을 사용한 타입 안전 네비게이션과 확장 함수 패턴이 일관성 있게 적용되어 있습니다. MainTabRoute 인터페이스 구현도 적절합니다. </details> <details> <summary>app/src/main/java/com/heartz/app/presentation/mypage/navigation/MypageNavigation.kt (1)</summary> `11-22`: **Quest 네비게이션과 일관된 패턴으로 잘 구현되었습니다!** 다른 탭 네비게이션 모듈들과 동일한 패턴을 사용하여 일관성을 유지하고 있으며, 타입 안전 네비게이션이 적절히 적용되어 있습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/presentation/graph/navigation/FigureNavigation.kt (1)</summary> `1-22`: **네비게이션 구현이 올바르게 작성되었습니다.** 다른 탭 네비게이션들과 일관된 패턴을 따르고 있으며, 타입 안전한 네비게이션을 위한 Kotlinx Serialization을 적절히 활용하고 있습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/presentation/home/HomeScreen.kt (2)</summary> `14-19`: **`collectAsStateWithLifecycle()` 사용이 올바르게 적용되었습니다.** 이전 리뷰에서 언급된 라이프사이클 인식 상태 수집 권장사항이 잘 반영되었습니다. 이를 통해 컴포저블이 비활성 상태일 때 불필요한 리컴포지션을 방지할 수 있습니다. --- `28-46`: **UI 상태 처리가 포괄적으로 구현되었습니다.** Loading, Success, Failure, Empty 상태를 모두 처리하여 사용자에게 명확한 피드백을 제공하고 있습니다. </details> <details> <summary>app/src/main/AndroidManifest.xml (3)</summary> `5-5`: **네트워크 권한이 적절히 추가되었습니다.** 애플리케이션에서 네트워크 통신을 위한 INTERNET 권한이 올바르게 선언되었습니다. --- `8-8`: **애플리케이션 클래스 설정이 올바릅니다.** Hilt를 사용하기 위한 애플리케이션 클래스가 적절히 설정되었습니다. --- `18-28`: **메인 액티비티가 올바르게 선언되었습니다.** 런처 액티비티로서 필요한 모든 속성과 인텐트 필터가 적절히 구성되어 있습니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/datasourceimpl/local/DummyLocalDataSourceImpl.kt (1)</summary> `16-37`: **DataStore 구현이 올바르게 작성되었습니다.** DataStore Preferences를 사용한 로컬 데이터 저장소 구현이 베스트 프랙티스를 따르고 있습니다. 의존성 주입과 인터페이스 구현도 적절합니다. </details> <details> <summary>app/src/main/java/com/heartz/app/data/di/NetworkModule.kt (1)</summary> `28-52`: **네트워크 모듈 구성이 올바르게 작성되었습니다.** OkHttpClient, Retrofit, 그리고 Kotlinx Serialization 컨버터가 적절히 구성되어 있으며, 의존성 주입 설정도 올바릅니다. </details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
| // / TODO: usecase는 생각이 많은데 고민을 조금 해봐야 겠습니다! | ||
|
|
||
| interface DummyUseCase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
구현 없이 비어있는 UseCase 인터페이스는 혼란을 유발합니다
현재 DummyUseCase는 메서드가 전혀 없어서 실제 도메인 레이어의 계약을 정의하지 못하고 있습니다. 추후 구현 의도가 명확해질 때까지는 파일을 아예 제거하거나, 최소한 invoke() 시그니처만이라도 정의해 두는 편이 좋습니다.
아래는 일반적인 Clean Architecture 패턴에 맞춰 fun interface 형태로 간략히 제안한 예시입니다.
-interface DummyUseCase
+/**
+ * 더미 데이터를 가져오는 도메인 계층 UseCase.
+ */
+fun interface DummyUseCase {
+ /**
+ * 도메인 계층에서 더미 데이터를 조회합니다.
+ */
+ suspend operator fun invoke(): DummyResultModel
+}- 불필요한 TODO 주석 대신 KDoc을 이용해 의도를 명시했습니다.
fun interface+operator fun invoke()형태로 사용 시 DI 주입 후 간결하게dummyUseCase()로 호출할 수 있습니다.- 반환형
DummyResultModel은 예시이므로 실제 모델 타입에 맞게 수정해 주세요.
🤖 Prompt for AI Agents
In app/src/main/java/com/heartz/app/domain/usecase/DummyUseCase.kt around lines
3 to 5, the DummyUseCase interface is empty, which can cause confusion as it
does not define any contract. To fix this, either remove the file until the
implementation is clear or define at least a minimal function signature, such as
an operator fun invoke() method, to clarify its intended use. Additionally,
replace the TODO comment with a KDoc explaining the interface's purpose, and
consider using a fun interface with a proper return type matching your domain
model.
| package com.android.heartz | ||
|
|
||
| import org.junit.Assert.assertEquals | ||
| import org.junit.Test | ||
|
|
||
| import org.junit.Assert.* | ||
|
|
||
| /** | ||
| * Example local unit test, which will execute on the development machine (host). | ||
| * | ||
| * See [testing documentation](http://d.android.com/tools/testing). | ||
| */ | ||
| class ExampleUnitTest { | ||
| @Test | ||
| fun addition_isCorrect() { | ||
| assertEquals(4, 2 + 2) | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
패키지 네이밍 일관성 확보 필요
테스트 코드가 com.android.heartz 패키지에 위치해 있으나, 실제 소스는 com.heartz.app 네임스페이스를 사용합니다.
패키지가 불일치하면 IDE-기반 코드 탐색, 커버리지 집계 등이 꼬일 수 있으니 동일한 루트 패키지로 정렬해 주세요.
🤖 Prompt for AI Agents
In app/src/test/java/com/android/heartz/ExampleUnitTest.kt lines 1 to 11, the
package declaration is com.android.heartz, but the main source code uses the
com.heartz.app namespace. To fix this, change the package declaration at the top
of the test file to match the main source root package, specifically to
com.heartz.app, ensuring consistency for IDE navigation and coverage tools.
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| android:width="18dp" | ||
| android:height="19dp" | ||
| android:viewportWidth="18" | ||
| android:viewportHeight="19"> | ||
| <path | ||
| android:pathData="M0,10.262C0,8.314 -0,7.339 0.334,6.478C0.502,6.044 0.73,5.635 1.013,5.264C1.573,4.528 2.406,4.014 4.072,2.987L4.252,2.875C6.299,1.613 7.322,0.981 8.445,0.857C8.814,0.816 9.186,0.816 9.554,0.857C10.677,0.981 11.701,1.613 13.748,2.875L13.928,2.987C15.594,4.014 16.427,4.528 16.987,5.264C17.27,5.635 17.498,6.044 17.667,6.478C18,7.339 18,8.314 18,10.262C18,13.627 18,15.309 17.214,16.532C16.823,17.14 16.303,17.656 15.691,18.045C14.46,18.826 12.767,18.826 9.382,18.826H8.618C5.232,18.826 3.54,18.826 2.309,18.045C1.697,17.656 1.177,17.14 0.786,16.532C-0,15.309 0,13.627 0,10.262ZM10.999,17.331C10.518,17.335 9.983,17.336 9.382,17.336H8.618C8.017,17.336 7.482,17.335 7.001,17.331V13.699C7.001,12.595 7.896,11.7 9,11.7C10.104,11.7 10.999,12.595 10.999,13.699V17.331ZM12.499,17.295V13.699C12.499,11.767 10.932,10.2 9,10.2C7.067,10.2 5.501,11.767 5.501,13.699V17.295C5.25,17.282 5.018,17.266 4.802,17.245C3.916,17.159 3.45,17.001 3.116,16.789C2.688,16.517 2.324,16.155 2.05,15.73C1.837,15.398 1.678,14.935 1.591,14.054C1.502,13.15 1.5,11.974 1.5,10.262C1.5,8.196 1.524,7.555 1.733,7.013C1.851,6.709 2.011,6.423 2.209,6.164C2.562,5.701 3.097,5.343 4.863,4.253L5.044,4.142C6.088,3.497 6.794,3.063 7.378,2.766C7.939,2.481 8.295,2.373 8.612,2.338C8.87,2.309 9.13,2.309 9.388,2.338C9.705,2.373 10.061,2.481 10.622,2.766C11.205,3.063 11.912,3.497 12.956,4.142L13.137,4.253C14.903,5.343 15.438,5.701 15.791,6.164C15.989,6.423 16.149,6.709 16.267,7.013C16.476,7.555 16.5,8.196 16.5,10.262C16.5,11.974 16.498,13.15 16.409,14.054C16.322,14.935 16.163,15.398 15.95,15.73C15.676,16.155 15.312,16.517 14.884,16.789C14.55,17.001 14.084,17.159 13.198,17.245C12.982,17.266 12.75,17.282 12.499,17.295Z" | ||
| android:fillColor="#FFB0B0" | ||
| android:fillType="evenOdd"/> | ||
| </vector> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
벡터 드로어블 구조와 일관성 검토 필요
아이콘의 기본 구조는 올바르지만 몇 가지 개선사항이 있습니다:
- 크기가 18x19dp로 비대칭적입니다 - 일반적으로 아이콘은 정사각형(예: 24x24dp)을 사용합니다
- 색상이 하드코딩되어 있어 테마 변경에 대응하기 어렵습니다
다음과 같이 개선을 권장합니다:
- android:width="18dp"
- android:height="19dp"
- android:viewportWidth="18"
- android:viewportHeight="19">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
android:pathData="M0,10.262C0,8.314 -0,7.339 0.334,6.478C..."
- android:fillColor="#FFB0B0"
+ android:fillColor="?attr/colorOnPrimary"📝 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.
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | |
| android:width="18dp" | |
| android:height="19dp" | |
| android:viewportWidth="18" | |
| android:viewportHeight="19"> | |
| <path | |
| android:pathData="M0,10.262C0,8.314 -0,7.339 0.334,6.478C0.502,6.044 0.73,5.635 1.013,5.264C1.573,4.528 2.406,4.014 4.072,2.987L4.252,2.875C6.299,1.613 7.322,0.981 8.445,0.857C8.814,0.816 9.186,0.816 9.554,0.857C10.677,0.981 11.701,1.613 13.748,2.875L13.928,2.987C15.594,4.014 16.427,4.528 16.987,5.264C17.27,5.635 17.498,6.044 17.667,6.478C18,7.339 18,8.314 18,10.262C18,13.627 18,15.309 17.214,16.532C16.823,17.14 16.303,17.656 15.691,18.045C14.46,18.826 12.767,18.826 9.382,18.826H8.618C5.232,18.826 3.54,18.826 2.309,18.045C1.697,17.656 1.177,17.14 0.786,16.532C-0,15.309 0,13.627 0,10.262ZM10.999,17.331C10.518,17.335 9.983,17.336 9.382,17.336H8.618C8.017,17.336 7.482,17.335 7.001,17.331V13.699C7.001,12.595 7.896,11.7 9,11.7C10.104,11.7 10.999,12.595 10.999,13.699V17.331ZM12.499,17.295V13.699C12.499,11.767 10.932,10.2 9,10.2C7.067,10.2 5.501,11.767 5.501,13.699V17.295C5.25,17.282 5.018,17.266 4.802,17.245C3.916,17.159 3.45,17.001 3.116,16.789C2.688,16.517 2.324,16.155 2.05,15.73C1.837,15.398 1.678,14.935 1.591,14.054C1.502,13.15 1.5,11.974 1.5,10.262C1.5,8.196 1.524,7.555 1.733,7.013C1.851,6.709 2.011,6.423 2.209,6.164C2.562,5.701 3.097,5.343 4.863,4.253L5.044,4.142C6.088,3.497 6.794,3.063 7.378,2.766C7.939,2.481 8.295,2.373 8.612,2.338C8.87,2.309 9.13,2.309 9.388,2.338C9.705,2.373 10.061,2.481 10.622,2.766C11.205,3.063 11.912,3.497 12.956,4.142L13.137,4.253C14.903,5.343 15.438,5.701 15.791,6.164C15.989,6.423 16.149,6.709 16.267,7.013C16.476,7.555 16.5,8.196 16.5,10.262C16.5,11.974 16.498,13.15 16.409,14.054C16.322,14.935 16.163,15.398 15.95,15.73C15.676,16.155 15.312,16.517 14.884,16.789C14.55,17.001 14.084,17.159 13.198,17.245C12.982,17.266 12.75,17.282 12.499,17.295Z" | |
| android:fillColor="#FFB0B0" | |
| android:fillType="evenOdd"/> | |
| </vector> | |
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | |
| android:width="24dp" | |
| android:height="24dp" | |
| android:viewportWidth="24" | |
| android:viewportHeight="24"> | |
| <path | |
| android:pathData="M0,10.262C0,8.314 -0,7.339 0.334,6.478C0.502,6.044 0.73,5.635 1.013,5.264C1.573,4.528 2.406,4.014 4.072,2.987L4.252,2.875C6.299,1.613 7.322,0.981 8.445,0.857C8.814,0.816 9.186,0.816 9.554,0.857C10.677,0.981 11.701,1.613 13.748,2.875L13.928,2.987C15.594,4.014 16.427,4.528 16.987,5.264C17.27,5.635 17.498,6.044 17.667,6.478C18,7.339 18,8.314 18,10.262C18,13.627 18,15.309 17.214,16.532C16.823,17.14 16.303,17.656 15.691,18.045C14.46,18.826 12.767,18.826 9.382,18.826H8.618C5.232,18.826 3.54,18.826 2.309,18.045C1.697,17.656 1.177,17.14 0.786,16.532C-0,15.309 0,13.627 0,10.262ZM10.999,17.331C10.518,17.335 9.983,17.336 9.382,17.336H8.618C8.017,17.336 7.482,17.335 7.001,17.331V13.699C7.001,12.595 7.896,11.7 9,11.7C10.104,11.7 10.999,12.595 10.999,13.699V17.331ZM12.499,17.295V13.699C12.499,11.767 10.932,10.2 9,10.2C7.067,10.2 5.501,11.767 5.501,13.699V17.295C5.25,17.282 5.018,17.266 4.802,17.245C3.916,17.159 3.45,17.001 3.116,16.789C2.688,16.517 2.324,16.155 2.05,15.73C1.837,15.398 1.678,14.935 1.591,14.054C1.502,13.15 1.5,11.974 1.5,10.262C1.5,8.196 1.524,7.555 1.733,7.013C1.851,6.709 2.011,6.423 2.209,6.164C2.562,5.701 3.097,5.343 4.863,4.253L5.044,4.142C6.088,3.497 6.794,3.063 7.378,2.766C7.939,2.481 8.295,2.373 8.612,2.338C8.87,2.309 9.13,2.309 9.388,2.338C9.705,2.373 10.061,2.481 10.622,2.766C11.205,3.063 11.912,3.497 12.956,4.142L13.137,4.253C14.903,5.343 15.438,5.701 15.791,6.164C15.989,6.423 16.149,6.709 16.267,7.013C16.476,7.555 16.5,8.196 16.5,10.262C16.5,11.974 16.498,13.15 16.409,14.054C16.322,14.935 16.163,15.398 15.95,15.73C15.676,16.155 15.312,16.517 14.884,16.789C14.55,17.001 14.084,17.159 13.198,17.245C12.982,17.266 12.75,17.282 12.499,17.295Z" | |
| android:fillColor="?attr/colorOnPrimary" | |
| android:fillType="evenOdd"/> | |
| </vector> |
🤖 Prompt for AI Agents
In app/src/main/res/drawable/ic_home.xml lines 1 to 10, the vector drawable uses
a non-square size of 18x19dp and hardcoded fill color #FFB0B0, which reduces
consistency and theming flexibility. Update the android:width and android:height
attributes to a standard square size like 24x24dp, and replace the hardcoded
android:fillColor with a theme attribute reference (e.g.,
?attr/colorControlNormal) to support dynamic theming.
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| android:width="20dp" | ||
| android:height="20dp" | ||
| android:viewportWidth="20" | ||
| android:viewportHeight="20"> | ||
| <path | ||
| android:pathData="M5.291,4.304C5.291,1.835 7.496,0 10,0C12.504,0 14.709,1.835 14.709,4.304C14.709,6.773 12.504,8.608 10,8.608C7.496,8.608 5.291,6.773 5.291,4.304ZM10,1.519C8.124,1.519 6.778,2.858 6.778,4.304C6.778,5.75 8.124,7.089 10,7.089C11.876,7.089 13.222,5.75 13.222,4.304C13.222,2.858 11.876,1.519 10,1.519Z" | ||
| android:fillColor="#FE9191" | ||
| android:fillAlpha="0.7" | ||
| android:fillType="evenOdd"/> | ||
| <path | ||
| android:pathData="M4.933,11.208C8.043,9.242 11.957,9.242 15.067,11.208C16.889,12.361 18,14.41 18,16.618V17.132C18,17.334 18,17.495 17.985,17.64C17.854,18.873 16.913,19.849 15.718,19.984C15.577,20 15.422,20 15.226,20H4.774C4.579,20 4.423,20 4.282,19.984C3.087,19.849 2.146,18.873 2.015,17.64C2,17.495 2,17.334 2,17.132V16.618C2,14.41 3.111,12.361 4.933,11.208ZM14.285,12.527C11.654,10.864 8.346,10.864 5.715,12.527C4.339,13.398 3.498,14.947 3.498,16.618V17.09C3.498,17.353 3.499,17.422 3.505,17.472C3.559,17.986 3.952,18.391 4.446,18.447C4.494,18.452 4.56,18.453 4.814,18.453H15.186C15.44,18.453 15.507,18.452 15.554,18.447C16.048,18.391 16.441,17.986 16.495,17.472C16.5,17.422 16.502,17.353 16.502,17.09V16.618C16.502,14.947 15.661,13.398 14.285,12.527Z" | ||
| android:fillColor="#FE9191" | ||
| android:fillAlpha="0.7" | ||
| android:fillType="evenOdd"/> | ||
| </vector> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
아이콘 일관성과 접근성 개선 필요
사용자 아이콘의 구현에서 몇 가지 개선점이 있습니다:
- 색상이 하드코딩되어 테마 대응이 어려움
fillAlpha="0.7"로 투명도를 적용했는데, 이는 접근성에 영향을 줄 수 있음- 다른 아이콘들과 크기 일관성 부족
<path
android:pathData="M5.291,4.304C..."
- android:fillColor="#FE9191"
- android:fillAlpha="0.7"
+ android:fillColor="?attr/colorOnSurface"
android:fillType="evenOdd"/>
<path
android:pathData="M4.933,11.208C..."
- android:fillColor="#FE9191"
- android:fillAlpha="0.7"
+ android:fillColor="?attr/colorOnSurface"
android:fillType="evenOdd"/>투명도가 필요하다면 테마에서 알파값이 포함된 색상을 정의하는 것이 좋습니다.
🤖 Prompt for AI Agents
In app/src/main/res/drawable/ic_user.xml lines 1 to 16, the user icon has
hardcoded fill colors and uses fillAlpha for transparency, which hinders theme
adaptability and accessibility. Replace the hardcoded color values with theme
attribute references to support dynamic theming, and remove the fillAlpha
attribute by defining colors with the desired alpha directly in the theme. Also,
verify and adjust the icon size to maintain consistency with other icons in the
app.
| @Composable | ||
| fun QuestScreen() { | ||
| Column( | ||
| modifier = Modifier | ||
| .fillMaxSize() | ||
| .background(Color.White), | ||
| horizontalAlignment = Alignment.CenterHorizontally, | ||
| verticalArrangement = Arrangement.Center | ||
| ) { | ||
| Text( | ||
| text = "quest Screen", | ||
| color = Color.Black | ||
| ) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Compose 테마 사용 및 일관성 개선 필요
현재 구현은 기본적으로 작동하지만 몇 가지 개선이 필요합니다:
- 하드코딩된 색상 사용으로 테마 적용이 어려움
- 텍스트 대소문자 일관성 부족 ("quest Screen" → "Quest Screen")
- Material Design 테마 활용 부족
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
@Composable
fun QuestScreen() {
- Column(
- modifier = Modifier
- .fillMaxSize()
- .background(Color.White),
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center
- ) {
- Text(
- text = "quest Screen",
- color = Color.Black
- )
- }
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colorScheme.background
+ ) {
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.Center
+ ) {
+ Text(
+ text = "Quest Screen",
+ style = MaterialTheme.typography.headlineMedium,
+ color = MaterialTheme.colorScheme.onBackground
+ )
+ }
+ }
}📝 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.
| @Composable | |
| fun QuestScreen() { | |
| Column( | |
| modifier = Modifier | |
| .fillMaxSize() | |
| .background(Color.White), | |
| horizontalAlignment = Alignment.CenterHorizontally, | |
| verticalArrangement = Arrangement.Center | |
| ) { | |
| Text( | |
| text = "quest Screen", | |
| color = Color.Black | |
| ) | |
| } | |
| } | |
| +import androidx.compose.material3.MaterialTheme | |
| +import androidx.compose.material3.Surface | |
| @Composable | |
| fun QuestScreen() { | |
| - Column( | |
| - modifier = Modifier | |
| - .fillMaxSize() | |
| - .background(Color.White), | |
| - horizontalAlignment = Alignment.CenterHorizontally, | |
| - verticalArrangement = Arrangement.Center | |
| - ) { | |
| - Text( | |
| - text = "quest Screen", | |
| - color = Color.Black | |
| - ) | |
| - } | |
| + Surface( | |
| + modifier = Modifier.fillMaxSize(), | |
| + color = MaterialTheme.colorScheme.background | |
| + ) { | |
| + Column( | |
| + modifier = Modifier.fillMaxSize(), | |
| + horizontalAlignment = Alignment.CenterHorizontally, | |
| + verticalArrangement = Arrangement.Center | |
| + ) { | |
| + Text( | |
| + text = "Quest Screen", | |
| + style = MaterialTheme.typography.headlineMedium, | |
| + color = MaterialTheme.colorScheme.onBackground | |
| + ) | |
| + } | |
| + } | |
| } |
🤖 Prompt for AI Agents
In app/src/main/java/com/heartz/app/presentation/quest/QuestScreen.kt around
lines 13 to 27, the code uses hardcoded colors and inconsistent text casing
which reduces theme consistency and Material Design compliance. Replace
hardcoded Color.White and Color.Black with colors from the MaterialTheme color
palette, and update the text to "Quest Screen" with proper capitalization. Also,
ensure the composable uses MaterialTheme styling conventions for background and
text colors to improve theme integration and visual consistency.
| Column( | ||
| modifier = | ||
| Modifier | ||
| .background(Color.White) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
하드코딩된 색상을 테마 색상으로 변경하세요.
Color.White가 하드코딩되어 있어 다크 테마 지원이나 디자인 시스템과의 일관성에 문제가 있을 수 있습니다.
modifier =
Modifier
- .background(Color.White)
+ .background(MaterialTheme.colorScheme.surface)📝 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.
| .background(Color.White) | |
| modifier = | |
| Modifier | |
| .background(MaterialTheme.colorScheme.surface) |
🤖 Prompt for AI Agents
In app/src/main/java/com/heartz/app/presentation/main/component/MainBottomBar.kt
at line 52, replace the hardcoded Color.White with a color from the app's theme
to support dark mode and maintain design consistency. Use the appropriate theme
color reference instead of the fixed white color.
| companion object { | ||
| @Composable | ||
| fun find(predicate: @Composable (MainTabRoute) -> Boolean): MainNavTab? { | ||
| return entries.find { predicate(it.route) } | ||
| } | ||
|
|
||
| @Composable | ||
| fun contains(predicate: @Composable (Route) -> Boolean): Boolean { | ||
| return entries.map { it.route }.any { predicate(it) } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
불필요한 @composable 어노테이션을 제거하세요.
Companion object의 find와 contains 함수들이 @composable로 표시되어 있지만, 실제로는 Composition에 의존하지 않는 순수 함수들입니다. 이는 불필요한 recomposition을 유발할 수 있습니다.
companion object {
- @Composable
fun find(predicate: (MainTabRoute) -> Boolean): MainNavTab? {
return entries.find { predicate(it.route) }
}
- @Composable
fun contains(predicate: (Route) -> Boolean): Boolean {
return entries.map { it.route }.any { predicate(it) }
}
}또한, 호출하는 곳에서도 @composable 어노테이션을 제거해야 합니다:
MainNavigator.kt의 사용 부분:
val currentTab: MainNavTab?
@Composable get() =
MainNavTab.find { tab ->
currentDestination?.hasRoute(tab::class) == true
}📝 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.
| companion object { | |
| @Composable | |
| fun find(predicate: @Composable (MainTabRoute) -> Boolean): MainNavTab? { | |
| return entries.find { predicate(it.route) } | |
| } | |
| @Composable | |
| fun contains(predicate: @Composable (Route) -> Boolean): Boolean { | |
| return entries.map { it.route }.any { predicate(it) } | |
| } | |
| } | |
| companion object { | |
| fun find(predicate: (MainTabRoute) -> Boolean): MainNavTab? { | |
| return entries.find { predicate(it.route) } | |
| } | |
| fun contains(predicate: (Route) -> Boolean): Boolean { | |
| return entries.map { it.route }.any { predicate(it) } | |
| } | |
| } |
🤖 Prompt for AI Agents
In app/src/main/java/com/heartz/app/presentation/main/MainNavTab.kt between
lines 47 and 57, remove the unnecessary @Composable annotations from the
companion object's find and contains functions because they are pure functions
that do not depend on Composition. Also, update all call sites, such as in
MainNavigator.kt, to remove the @Composable annotation when invoking these
functions to prevent unnecessary recompositions.
| val properties = | ||
| Properties().apply { | ||
| load(project.rootProject.file("local.properties").inputStream()) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
local.properties 파일 누락 시 에러 처리를 추가하세요.
현재 local.properties 파일이 존재하지 않을 경우 빌드가 실패할 수 있습니다.
val properties =
Properties().apply {
- load(project.rootProject.file("local.properties").inputStream())
+ val localPropertiesFile = project.rootProject.file("local.properties")
+ if (localPropertiesFile.exists()) {
+ load(localPropertiesFile.inputStream())
+ }
}🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 13 to 16, the code loads local.properties
without checking if the file exists, which can cause a build failure if the file
is missing. Add a check to verify the existence of local.properties before
loading it, and handle the case where the file is absent by either skipping the
load or providing a clear error message to prevent the build from failing
unexpectedly.
| buildConfigField("String", "BASE_URL", properties["base.url"].toString()) | ||
| buildConfigField( | ||
| "String", | ||
| "KAKAO_NATIVE_APP_KEY", | ||
| properties["kakao.native.app.key"].toString() | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BuildConfig에서 민감한 정보 노출을 방지하세요.
buildConfigField를 통해 API 키와 URL이 APK에 평문으로 노출될 수 있습니다. 이는 보안상 위험할 수 있습니다.
더 안전한 방법들을 고려해보세요:
- Gradle 속성 사용: 런타임에 리소스에서 읽기
- 암호화: 키를 암호화하여 저장
- 서버 프록시: 민감한 API 호출을 서버를 통해 프록시
- buildConfigField("String", "BASE_URL", properties["base.url"].toString())
- buildConfigField(
- "String",
- "KAKAO_NATIVE_APP_KEY",
- properties["kakao.native.app.key"].toString()
- )
+ // 리소스 파일을 통한 방법 고려
+ resValue("string", "base_url", properties["base.url"]?.toString() ?: "\"\"")
+ manifestPlaceholders["kakaoAppKey"] = properties["kakao.native.app.key"]?.toString() ?: ""📝 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.
| buildConfigField("String", "BASE_URL", properties["base.url"].toString()) | |
| buildConfigField( | |
| "String", | |
| "KAKAO_NATIVE_APP_KEY", | |
| properties["kakao.native.app.key"].toString() | |
| ) | |
| // 리소스 파일을 통한 방법 고려 | |
| resValue("string", "base_url", properties["base.url"]?.toString() ?: "\"\"") | |
| manifestPlaceholders["kakaoAppKey"] = properties["kakao.native.app.key"]?.toString() ?: "" |
🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 31 to 36, sensitive information like API
keys and URLs are exposed in plain text via buildConfigField, which poses a
security risk. To fix this, remove these sensitive values from buildConfigField
and instead load them securely at runtime from encrypted resources or
environment variables. Alternatively, consider using a server proxy for API
calls to avoid embedding keys in the APK altogether.
| fun navigate(tab: MainNavTab) { | ||
| val navOptions = | ||
| navOptions { | ||
| navController.currentDestination?.route?.let { | ||
| popUpTo(it) { | ||
| inclusive = true | ||
| saveState = true | ||
| } | ||
| } | ||
| launchSingleTop = true | ||
| restoreState = true | ||
| } | ||
| when (tab) { | ||
| MainNavTab.QUEST -> navController.navigateToQuest(navOptions) | ||
| MainNavTab.HOME -> navController.navigateToHome(navOptions) | ||
| MainNavTab.FIGURE -> navController.navigateToFigure(navOptions) | ||
| MainNavTab.MYPAGE -> navController.navigateToMypage(navOptions) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
네비게이션 로직의 복잡성을 개선하세요.
현재 navigate 함수의 popUpTo 로직이 복잡하고 예상치 못한 동작을 일으킬 수 있습니다. 특히 inclusive = true와 saveState = true를 함께 사용하는 것은 상태 관리에 문제를 일으킬 수 있습니다.
fun navigate(tab: MainNavTab) {
val navOptions =
navOptions {
- navController.currentDestination?.route?.let {
- popUpTo(it) {
- inclusive = true
- saveState = true
- }
- }
+ popUpTo(startDestination) {
+ saveState = true
+ }
launchSingleTop = true
restoreState = true
}
when (tab) {
MainNavTab.QUEST -> navController.navigateToQuest(navOptions)
MainNavTab.HOME -> navController.navigateToHome(navOptions)
MainNavTab.FIGURE -> navController.navigateToFigure(navOptions)
MainNavTab.MYPAGE -> navController.navigateToMypage(navOptions)
}
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In app/src/main/java/com/heartz/app/presentation/main/MainNavigator.kt around
lines 33 to 51, the navigate function's popUpTo logic is overly complex and may
cause unexpected behavior due to using inclusive = true and saveState = true
together. Simplify the popUpTo block by removing inclusive = true or adjusting
the logic to avoid conflicting state management, ensuring consistent navigation
state restoration without unintended side effects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
app/src/main/java/com/heartz/app/data/datasource/local/DummyLocalDataSource.kt (1)
5-5: TODO 주석을 추후 제거해주세요.임시 구현임을 나타내는 TODO 주석이 있습니다. 실제 구현이 완료되면 이 주석을 제거하고 적절한 문서화 주석으로 대체하는 것을 권장합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/src/main/java/com/heartz/app/data/datasource/local/DummyLocalDataSource.kt(1 hunks)app/src/main/java/com/heartz/app/data/datasourceimpl/local/DummyLocalDataSourceImpl.kt(1 hunks)app/src/main/java/com/heartz/app/data/di/DataSourceModule.kt(1 hunks)app/src/main/java/com/heartz/app/data/service/DummyService.kt(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- app/src/main/java/com/heartz/app/data/service/DummyService.kt
- app/src/main/java/com/heartz/app/data/di/DataSourceModule.kt
- app/src/main/java/com/heartz/app/data/datasourceimpl/local/DummyLocalDataSourceImpl.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (1)
app/src/main/java/com/heartz/app/data/datasource/local/DummyLocalDataSource.kt (1)
6-12: 인터페이스 구조가 잘 설계되었습니다.로컬 데이터 소스의 계약을 명확히 정의하고 있습니다:
Flow<Boolean>타입의isLogin속성으로 반응형 상태 관찰suspend fun setIsLogin()으로 비동기 상태 설정suspend fun clear()로 데이터 정리초기 프로젝트 세팅 단계에서 "Dummy" 명명은 적절하며, 추후 실제 구현 시 적절한 이름으로 변경하면 됩니다.

Related issue 🛠
Work Description 📝
Screenshot 📸
PR Point 📌
컴포즈 세팅은 처음 해봐서 빠진 부분도 많을테고, 코드적으로도 수정할 부분도 많아보입니다..
네비게이션은 정말 기본적인 세팅만 했습니다!
제발 저에게 많은 피드백을 부탁드립니다.
다른 SOPT 기초세팅 많이 살펴봤습니다,,
트러블 슈팅 💥
린트 문제 해결, 코드래빗 오류 해결
Summary by CodeRabbit
새로운 기능
버그 수정
문서화
환경/설정