Conversation
- 스플래시 화면에 Lottie 애니메이션을 추가하고, 애니메이션 완료 후 화면 이동 - 토큰 확인 로직을 추가하여 토큰 유무에 따라 다음 화면으로 분기
Walkthrough이 변경사항은 앱의 런처 아이콘을 새로운 디자인으로 교체하고, 스플래시-인트로-약관동의 화면의 UI와 전환 흐름을 개선하며, Lottie 애니메이션을 활용한 스플래시 화면과 관련된 상태 관리 및 네비게이션 로직을 리팩토링합니다. 여러 화면에 status bar 패딩이 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant App
participant SplashViewModel
participant Navigation
User->>App: 앱 실행
App->>SplashViewModel: Splash 화면 표시, 토큰 체크 시작
App->>App: Lottie 애니메이션 재생
App->>SplashViewModel: 애니메이션 완료 시 onAnimationCompleted 호출
SplashViewModel->>SplashViewModel: 토큰 체크 완료 여부 확인
alt 토큰 있음
SplashViewModel->>Navigation: 홈 화면으로 이동
else 토큰 없음
SplashViewModel->>Navigation: 인트로 화면으로 이동 (Splash 스택 제거)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changesNo out-of-scope changes detected. Possibly related PRs
Suggested labels
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 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.
Actionable comments posted: 6
🧹 Nitpick comments (5)
presentation/src/main/java/com/threegap/bitnagil/presentation/splash/component/template/BitnagilLottieAnimation.kt (2)
41-53: 애니메이션 로딩 실패에 대한 에러 처리를 고려해보세요.Lottie 컴포지션 로딩이 실패할 경우에 대한 처리가 없습니다. 사용자 경험을 위해 fallback 처리를 추가하는 것을 권장합니다.
LaunchedEffect(lottieComposition) { - lottieComposition?.let { + lottieComposition?.let { composition -> onStart?.invoke() - lottieAnimatable.animate( - composition = it, - clipSpec = LottieClipSpec.Frame(0, maxFrame), - iterations = 1, - ignoreSystemAnimationsDisabled = true, - useCompositionFrameRate = true, - ) - onComplete() + try { + lottieAnimatable.animate( + composition = composition, + clipSpec = LottieClipSpec.Frame(0, maxFrame), + iterations = 1, + ignoreSystemAnimationsDisabled = true, + useCompositionFrameRate = true, + ) + onComplete() + } catch (e: Exception) { + // 애니메이션 실패 시에도 완료 콜백 호출 + onComplete() + } + } ?: run { + // 컴포지션 로딩 실패 시 즉시 완료 처리 + onComplete() } }
48-48: 접근성을 위한 시스템 애니메이션 설정 고려사항
ignoreSystemAnimationsDisabled = true설정이 접근성을 위해 애니메이션을 비활성화한 사용자의 설정을 무시합니다. 스플래시 화면의 중요성을 고려하여 이 설정이 적절한지 검토해보세요.presentation/src/main/java/com/threegap/bitnagil/presentation/splash/SplashScreen.kt (1)
54-85: UI 구현이 잘 되어 있습니다. 일부 개선사항을 고려해보세요.Lottie 애니메이션과 아이콘의 조합이 좋은 사용자 경험을 제공합니다. 몇 가지 개선사항을 제안합니다:
- 매직 넘버들을 상수로 분리
- 다양한 화면 크기에 대한 대응
+private object SplashConstants { + val LOTTIE_SIZE = 204.dp + val LOTTIE_BOTTOM_PADDING = 36.dp + const val MAX_FRAME = 120 + const val FADE_DURATION = 500 +} + @Composable private fun SplashScreen( onCompleted: () -> Unit, modifier: Modifier = Modifier, ) { var showIcon by remember { mutableStateOf(false) } Column( modifier = modifier .fillMaxSize() .background(BitnagilTheme.colors.white), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { Box( contentAlignment = Alignment.Center, ) { BitnagilLottieAnimation( lottieJson = R.raw.splash_lottie, onComplete = onCompleted, onStart = { showIcon = true }, - maxFrame = 120, + maxFrame = SplashConstants.MAX_FRAME, modifier = Modifier - .padding(bottom = 36.dp) - .size(204.dp) + .padding(bottom = SplashConstants.LOTTIE_BOTTOM_PADDING) + .size(SplashConstants.LOTTIE_SIZE) .align(Alignment.BottomCenter), ) androidx.compose.animation.AnimatedVisibility( visible = showIcon, - enter = fadeIn(animationSpec = tween(500)), + enter = fadeIn(animationSpec = tween(SplashConstants.FADE_DURATION)), modifier = Modifier.align(Alignment.BottomCenter), ) { BitnagilIcon(id = R.drawable.img_app_name) } } } }app/src/main/res/values/ic_bitnagil_launcher_background.xml (1)
1-4: 배경색 리소스를 기존 colors.xml로 통합하는 방안을 고려해 주세요
런처 아이콘 배경 한 가지를 위해 별도 values-파일을 만들면 리소스 파일이 불필요하게 늘어납니다. 기존colors.xml(또는 theme-palette)로 이동하면 유지보수가 쉬워집니다.core/designsystem/src/main/res/drawable/img_app_name.xml (1)
1-5: 벡터 루트에 android:autoMirrored="true" 옵션을 추가해 RTL 레이아웃 지원
앱이 아랍어나 히브리어처럼 RTL 언어를 지원할 경우 아이콘이 자동으로 뒤집히도록android:autoMirrored="true"속성을 권장합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
app/src/main/ic_bitnagil_launcher-playstore.pngis excluded by!**/*.png
📒 Files selected for processing (17)
app/src/main/AndroidManifest.xml(1 hunks)app/src/main/java/com/threegap/bitnagil/MainNavHost.kt(1 hunks)app/src/main/res/drawable/ic_bitnagil_launcher_foreground.xml(1 hunks)app/src/main/res/mipmap-anydpi-v26/ic_bitnagil_launcher.xml(1 hunks)app/src/main/res/mipmap-anydpi-v26/ic_bitnagil_launcher_round.xml(1 hunks)app/src/main/res/values/ic_bitnagil_launcher_background.xml(1 hunks)app/src/main/res/values/themes.xml(1 hunks)core/designsystem/src/main/res/drawable/img_app_name.xml(1 hunks)gradle/libs.versions.toml(2 hunks)presentation/build.gradle.kts(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/intro/IntroScreen.kt(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/splash/SplashScreen.kt(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/splash/SplashViewModel.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/splash/component/template/BitnagilLottieAnimation.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/splash/model/SplashIntent.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/splash/model/SplashState.kt(1 hunks)
🧰 Additional context used
🧠 Learnings (4)
app/src/main/java/com/threegap/bitnagil/MainNavHost.kt (1)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.
presentation/src/main/java/com/threegap/bitnagil/presentation/splash/model/SplashState.kt (2)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
presentation/src/main/java/com/threegap/bitnagil/presentation/splash/model/SplashIntent.kt (3)
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like LoadMyPageSuccess are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
Learnt from: l5x5l
PR: #41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageState.kt:6-14
Timestamp: 2025-07-23T13:31:46.809Z
Learning: In the Bitnagil Android project, MviState interface extends Parcelable, so any class implementing MviState automatically implements Parcelable. Therefore, @parcelize annotation works correctly without explicitly adding Parcelable implementation.
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt (1)
Learnt from: l5x5l
PR: #38
File: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt:30-35
Timestamp: 2025-07-21T10:38:49.104Z
Learning: presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt의 TextButton 컴포넌트는 임시로 구현된 컴포넌트로, 디자인 시스템 구현시 대체 예정입니다.
🧬 Code Graph Analysis (3)
presentation/src/main/java/com/threegap/bitnagil/presentation/splash/SplashViewModel.kt (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (2)
sendSideEffect(23-23)sendIntent(30-37)
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt (1)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilIcon.kt (1)
BitnagilIcon(21-33)
presentation/src/main/java/com/threegap/bitnagil/presentation/splash/SplashScreen.kt (2)
presentation/src/main/java/com/threegap/bitnagil/presentation/splash/component/template/BitnagilLottieAnimation.kt (1)
BitnagilLottieAnimation(21-61)core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilIcon.kt (1)
BitnagilIcon(21-33)
🪛 detekt (1.23.8)
presentation/src/main/java/com/threegap/bitnagil/presentation/splash/SplashViewModel.kt
[warning] 56-56: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (15)
presentation/build.gradle.kts (1)
21-21: LGTM!Lottie Compose 라이브러리 의존성이 올바르게 추가되었습니다. 버전 카탈로그를 통한 참조 방식이 적절합니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/intro/IntroScreen.kt (1)
4-4: LGTM!테마 색상을 사용한 배경 설정이 적절합니다. 스플래시 화면과의 시각적 일관성을 위한 좋은 개선사항입니다.
Also applies to: 61-63
presentation/src/main/java/com/threegap/bitnagil/presentation/splash/model/SplashState.kt (1)
8-8: LGTM!
isLoading에서isTokenChecked로의 변경이 상태의 목적을 더 명확하게 표현합니다. 토큰 확인 상태를 나타내는 더 구체적인 네이밍입니다.app/src/main/java/com/threegap/bitnagil/MainNavHost.kt (1)
31-35: LGTM!스플래시 화면에서 인트로 화면으로의 네비게이션 로직이 개선되었습니다.
popUpTo를 통해 스플래시 화면을 백스택에서 제거하여 사용자가 뒤로 가기로 스플래시 화면에 돌아갈 수 없도록 하는 것이 적절합니다.presentation/src/main/java/com/threegap/bitnagil/presentation/splash/model/SplashIntent.kt (1)
6-6: MVI 아키텍처에 맞는 적절한 Intent 변경입니다.로딩 상태에서 토큰 체크 상태로의 변경이 기능 요구사항과 잘 부합하며, nullable Boolean 사용으로 체크 진행 상태와 결과를 명확히 구분할 수 있습니다.
core/designsystem/src/main/res/drawable/img_app_name.xml (1)
30-50: SVG → Vector 변환으로 path 수가 많아 용량이 큰 편입니다
런타임 메모리·빌드 속도를 고려해OPTIMIZE플래그로 단순화하거나 PNG 정적 리소스로 교체하는 것이 좋습니다(특히 저사양 기기 대상으로).app/src/main/AndroidManifest.xml (1)
12-15: 하위 API 리소스 누락 이슈 없음 확인
모든 density 별 레거시 mipmap 아이콘과 adaptive 아이콘이 제공되고 있어 API 25 이하 기기에서도 리소스 미존재 오류가 발생하지 않습니다.
- app/src/main/res/mipmap-mdpi/ic_bitnagil_launcher.webp, ic_bitnagil_launcher_round.webp
- app/src/main/res/mipmap-hdpi/ic_bitnagil_launcher.webp, ic_bitnagil_launcher_round.webp
- app/src/main/res/mipmap-xhdpi/ic_bitnagil_launcher.webp, ic_bitnagil_launcher_round.webp
- app/src/main/res/mipmap-xxhdpi/ic_bitnagil_launcher.webp, ic_bitnagil_launcher_round.webp
- app/src/main/res/mipmap-xxxhdpi/ic_bitnagil_launcher.webp, ic_bitnagil_launcher_round.webp
- app/src/main/res/mipmap-anydpi-v26/ic_bitnagil_launcher.xml, ic_bitnagil_launcher_round.xml
- app/src/main/res/drawable/ic_bitnagil_launcher_foreground.xml
- app/src/main/res/values/ic_bitnagil_launcher_background.xml
app/src/main/res/mipmap-anydpi-v26/ic_bitnagil_launcher_round.xml (1)
1-5: Adaptive 아이콘 구성 적절 – 별도 이슈 없음
배경과 전경이 리소스로 잘 분리되어 있습니다.app/src/main/res/mipmap-anydpi-v26/ic_bitnagil_launcher.xml (1)
1-5: Adaptive 아이콘 구성 적절 – 별도 이슈 없음
배경과 전경이 리소스로 잘 분리되어 있습니다.app/src/main/res/drawable/ic_bitnagil_launcher_foreground.xml (1)
1-42: 런처 아이콘 벡터 드로어블 구현이 적절합니다.복잡한 벡터 패스와 적절한 변환을 사용하여 앱 브랜딩을 구현했습니다. 108dp x 108dp 크기와 적절한 뷰포트 설정으로 어댑티브 아이콘 표준을 준수하고 있습니다.
app/src/main/res/values/themes.xml (1)
4-8: 테마 리팩토링이 잘 구현되었습니다.베이스 스타일을 도입하여 계층 구조를 개선했고,
windowIsTranslucent속성 추가로 스플래시 화면 등의 시각적 효과를 지원할 수 있습니다.presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt (4)
77-80: 화면 높이 기반 반응형 디자인 구현
LocalWindowInfo와LocalDensity를 사용한 동적 레이아웃 계산이 적절합니다. 다양한 화면 크기에서의 일관성을 보장합니다.
82-96: 레이아웃 구조 개선 및 테마 적용
Box에서Column으로 변경하여 더 명확한 레이아웃 구조를 구현했습니다. 테마 색상과 타이포그래피를 적절히 활용하고 있습니다.
100-107: 이미지 컴포넌트 구현 적절
aspectRatio와ContentScale.Fit사용으로 이미지 비율을 올바르게 유지하고 있습니다. 50dp 패딩 설정도 적절합니다.
128-136: 디자인 시스템 컴포넌트 활용 우수
BitnagilIcon과 테마 색상, 타이포그래피를 일관되게 사용하여 디자인 시스템을 잘 활용하고 있습니다.
|
[7/31] 기준
Screen_recording_20250731_094122.mp4 |
l5x5l
left a comment
There was a problem hiding this comment.
새로 구현해주신 edge-to-edge 대응 관련해서 아래 상황 테스트 요청드립니다!
- 루틴 작성 화면에서 softKeyboard가 올라올 때 적절하게 처리되는지
- android 15 미만과 android 15 이상이 동일하게 보여지는지
- 다크모드/라이트모드에서 상단 statusBar, 하단 NavigationBar의 아이콘들이 제대로 표시되는지
- enableEdgeToEdge의 navigationBarStyle을 투명하게 설정 - Android Q 이상 버전에서 isNavigationBarContrastEnforced를 false로 설정하여 navigation bar의 contrast를 비활성화
반영완료! -> 0144038 default.mp4 |
[ PR Content ]
앱 진입 시 스플래시 -> 인트로 -> 로그인까지의 flow를 구현했습니다.
Related issue
Screenshot 📸
default.mp4
Work Description
To Reviewers 📢
Summary by CodeRabbit
신규 기능
UI/스타일 개선
버그 수정 및 개선
기타