feat: 홈 화면 UI 구현#75
Conversation
Walkthrough홈 화면 UI가 전면적으로 구현되었습니다. 기존의 임시 UI와 버튼들은 제거되고, 실제 도서 목록, 배너, 헤더, 북 카드 등 다양한 컴포저블과 테마 색상, 문자열 리소스가 추가되었습니다. 이벤트 처리 및 내비게이션 로직도 세분화되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant HomeUi
participant HomePresenter
participant Navigator
User->>HomeUi: 버튼(설정/등록/레코드/상세) 클릭
HomeUi->>HomePresenter: HomeUiEvent 전달
HomePresenter->>Navigator: 해당 화면으로 이동 (Settings, Search, Record, BookDetail)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Assessment against linked issues
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ 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: 5
🧹 Nitpick comments (5)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeHeader.kt (1)
51-51: contentDescription 현지화 제안설정 아이콘의 contentDescription이 영어로 하드코딩되어 있습니다. 프로젝트에서 한국어를 선호하므로 문자열 리소스로 분리하거나 한국어로 변경하는 것을 고려해보세요.
- contentDescription = "Settings Icon", + contentDescription = "설정",또는 문자열 리소스로 분리:
- contentDescription = "Settings Icon", + contentDescription = stringResource(R.string.settings_icon_description),feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUiState.kt (1)
14-14: 코드 스타일 일관성 개선 필요다른 이벤트 클래스들과의 일관성을 위해 콜론 앞에 공백을 추가해주세요.
- data object OnBookDetailClick: HomeUiEvent + data object OnBookDetailClick : HomeUiEventfeature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (1)
122-136: 페이지 인디케이터 재사용성 개선페이지 인디케이터 로직을 별도의 Composable로 추출하면 재사용성이 향상됩니다.
@Composable fun HorizontalPagerIndicator( pageCount: Int, currentPage: Int, modifier: Modifier = Modifier, ) { Row( modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center, ) { repeat(pageCount) { iteration -> val color = if (currentPage == iteration) ReedTheme.colors.bgPrimary else ReedTheme.colors.bgSecondaryPressed Box( modifier = Modifier .size(12.dp) .padding(3.dp) .clip(CircleShape) .background(color) ) } } }feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/BookCard.kt (2)
57-61: 그림자 색상 값 추출 필요하드코딩된 그림자 색상 값을 디자인 시스템으로 추출하면 일관성과 유지보수성이 향상됩니다.
// 디자인 시스템에 추가 val shadowColor = Color(0xFFBCC4BE).copy(alpha = 0.2f) // 사용 shadow( elevation = 6.dp, shape = RoundedCornerShape(ReedTheme.radius.sm), ambientColor = ReedTheme.colors.shadowColor, spotColor = ReedTheme.colors.shadowColor, )Also applies to: 198-202
152-156: 빈 Box 컴포넌트흰색 배경의 Box가 내용 없이 비어있습니다. 이미지나 아이콘을 추가할 예정인가요?
리뷰 아이콘이나 이미지를 추가하는 구현이 필요하다면 도움을 드릴 수 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt(2 hunks)feature/home/build.gradle.kts(1 hunks)feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt(2 hunks)feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt(2 hunks)feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUiState.kt(1 hunks)feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/BookCard.kt(1 hunks)feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeBanner.kt(1 hunks)feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeHeader.kt(1 hunks)feature/home/src/main/res/values/strings.xml(1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
feature/home/build.gradle.kts (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt (3)
Learnt from: seoyoon513
PR: #32
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ButtonColorStyle.kt:10-16
Timestamp: 2025-07-08T12:33:01.863Z
Learning: Reed Android 프로젝트에서 KAKAO 버튼 스타일은 디자이너가 pressed 상태 색상을 별도로 정의하지 않았기 때문에 pressed 상태에서도 동일한 Kakao 색상을 사용한다.
Learnt from: seoyoon513
PR: #32
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt:15-21
Timestamp: 2025-07-08T03:21:24.693Z
Learning: Reed Android 프로젝트에서는 다크모드/라이트모드 대응 계획이 없고 기본 테마 값만 사용할 예정이다.
Learnt from: easyhooon
PR: #55
File: core/designsystem/src/main/res/drawable/ic_x_circle.xml:6-11
Timestamp: 2025-07-17T23:41:33.929Z
Learning: Reed Android 프로젝트에서는 SVG에서 vector drawable로 변환시 색상 매핑 대신 모드별 별도 아이콘 파일을 사용하는 방식을 선호한다. Figma에서 SVG export한 형태를 그대로 사용하며, 다크모드 대응이 필요할 경우 drawable-night 폴더에 별도 아이콘을 배치하는 방식을 사용한다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt (3)
Learnt from: seoyoon513
PR: #35
File: feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/TermsAgreementScreen.kt:127-127
Timestamp: 2025-07-09T01:14:29.836Z
Learning: In the Reed-Android project's TermsAgreementScreen.kt, the OnTermDetailClick event is intentionally passed an empty string for the URL parameter because the actual URLs for terms detail pages haven't been decided yet. This is a temporary implementation that will be updated once the URLs are finalized.
Learnt from: easyhooon
PR: #52
File: feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/screens/DelegatingNavigator.kt:0-0
Timestamp: 2025-07-16T15:54:19.322Z
Learning: In the Reed-Android project using Circuit architecture, DelegatingNavigator was restored because NavigableCircuitContent can only inject a single navigator, but the dual-navigator architecture (childNavigator for bottom navigation screens, rootNavigator for full-screen screens) requires a delegating component to work within Circuit's constraint.
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
feature/home/src/main/res/values/strings.xml (2)
Learnt from: seoyoon513
PR: #45
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/appbar/ReedTopAppBar.kt:65-65
Timestamp: 2025-07-12T01:33:57.101Z
Learning: Reed Android 프로젝트에서 타이포그래피 사용 규칙: 톱 앱바(Top App Bar)에서는 headline2SemiBold를 사용하고, 바텀시트(Bottom Sheet)에서는 heading2SemiBold를 사용한다. 이는 의도적인 디자인 시스템 차별화이다.
Learnt from: seoyoon513
PR: #32
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt:15-21
Timestamp: 2025-07-08T03:21:24.693Z
Learning: Reed Android 프로젝트에서는 다크모드/라이트모드 대응 계획이 없고 기본 테마 값만 사용할 예정이다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/BookCard.kt (1)
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
🧬 Code Graph Analysis (2)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeHeader.kt (1)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeBanner.kt (1)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
⏰ 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: ci-build
🔇 Additional comments (10)
feature/home/build.gradle.kts (1)
21-21: 시스템 UI 컨트롤러 의존성 추가 승인홈 화면에서 상태바 색상 제어를 위해 필요한 의존성입니다. HomeUi.kt에서 HomeBg 색상으로 상태바를 설정하는 기능과 연관되어 있습니다.
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt (2)
67-67: 홈 배경색 추가 승인홈 화면 전용 배경색이 적절히 추가되었습니다. 연한 녹색 계열 색상(#F0F9E8)으로 앱의 전체적인 녹색 테마와 잘 어울립니다.
98-98: 보더 보조 색상 추가 승인ReedColorScheme에 borderSecondary 속성이 추가되어 디자인 시스템이 확장되었습니다. Neutral100 기본값이 적절합니다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt (1)
29-43: 이벤트 처리 로직 개선 승인단일 OnButtonClick 이벤트를 의미론적으로 명확한 4개의 개별 이벤트로 분리한 것이 좋습니다. 각 이벤트가 적절한 화면으로 네비게이션되고 있습니다.
feature/home/src/main/res/values/strings.xml (1)
1-11: 홈 화면 문자열 리소스 추가 승인홈 화면 UI 구성요소들을 위한 한국어 문자열 리소스가 잘 정의되었습니다. 문자열 키 명명이 명확하고 의미론적으로 적절합니다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeHeader.kt (2)
25-56: HomeHeader 컴포넌트 구현 승인홈 화면 헤더 컴포넌트가 잘 구현되었습니다. 적절한 레이아웃 구조, 테마 색상 사용, 그리고 간격 처리가 되어 있습니다.
58-66: 미리보기 컴포넌트 구현 승인ComponentPreview 어노테이션을 사용한 미리보기 컴포넌트가 적절히 구현되어 있어 디자인 타임 테스트가 가능합니다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeBanner.kt (1)
38-48: ReedTheme의 CompositionLocal 제공 확인됨
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt의object ReedTheme내에서
colors는@Composable @ReadOnlyComposable get() = LocalColorScheme.currenttypography는@Composable @ReadOnlyComposable get() = LocalTypography.current- (spacing도 동일한 패턴으로
LocalSpacing.current를 반환하도록 구성되어 있음)위 구현을 통해
ReedTheme.spacing과ReedTheme.colors는 CompositionLocal에서 안전하게 가져오므로, HomeBanner.kt에서 직접 참조해도 런타임 오류가 발생하지 않습니다.feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (1)
71-75: 알려진 이슈 확인PR 설명에서 언급하신 대로 onDispose에서 statusBarColor 리셋 시 딜레이 이슈가 있다는 것을 확인했습니다. 다음 PR에서 수정 예정이라고 하셨으니 현재는 문제없습니다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/BookCard.kt (1)
67-69: 중복된 클릭 핸들러BookCard의 전체 영역(line 67-69)과 리뷰 카운트 영역(line 143-145) 모두 동일한
onBookDetailClick()을 호출합니다. 의도적인 것인지 확인이 필요합니다.만약 의도적이지 않다면, 리뷰 카운트 영역의 클릭 핸들러를 제거하거나 다른 동작으로 변경하는 것을 고려해보세요.
Also applies to: 143-145
| } | ||
|
|
||
| is HomeUiEvent.OnBookDetailClick -> { | ||
| navigator.goTo(BookDetailScreen("")) |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
BookDetailScreen 파라미터 확인 필요
BookDetailScreen에 빈 문자열이 전달되고 있습니다. 실제 책 ID나 데이터가 전달되어야 하는지 확인이 필요합니다.
다음 스크립트로 BookDetailScreen의 파라미터 요구사항을 확인해보세요:
🏁 Script executed:
#!/bin/bash
# BookDetailScreen의 파라미터 정의 확인
ast-grep --pattern 'data object BookDetailScreen'
ast-grep --pattern 'data class BookDetailScreen'Length of output: 102
BookDetailScreen 선언 위치 확인을 위해 전체 코드베이스에서 해당 이름을 검색해 주세요:
🏁 Script executed:
#!/bin/bash
# 전체 코드베이스에서 BookDetailScreen 검색
rg --color=never -n "BookDetailScreen" .Length of output: 1736
BookDetailScreen에 ISBN 파라미터 전달 필요
BookDetailScreen은 data class BookDetailScreen(val isbn: String)로 선언되어 있어, 빈 문자열이 아닌 실제 ISBN을 전달하셔야 합니다.
-
파일:
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt
라인: 42 -
수정 제안:
- navigator.goTo(BookDetailScreen("")) + navigator.goTo(BookDetailScreen(isbn = /* 선택된 책의 ISBN 변수 */))
예를 들어, 이벤트에 ISBN이 담겨 있다면:
- navigator.goTo(BookDetailScreen("")) + navigator.goTo(BookDetailScreen(isbn = event.isbn))
📝 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.
| navigator.goTo(BookDetailScreen("")) | |
| - navigator.goTo(BookDetailScreen("")) | |
| + navigator.goTo(BookDetailScreen(isbn = event.isbn)) |
🤖 Prompt for AI Agents
In
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt
at line 42, the call to navigator.goTo(BookDetailScreen("")) incorrectly passes
an empty string as the ISBN parameter. Since BookDetailScreen requires a valid
ISBN string, update this call to pass the actual ISBN value from the relevant
event or data source instead of an empty string.
There was a problem hiding this comment.
여기도 서버 연동할 때 변경사항이 생길 예정이라 그때 바꿀게
There was a problem hiding this comment.
@seoyoon513 알겠습니다! 팀에서 UI 구현 단계에서 더미 데이터를 사용하고 서버 연동 시점에 실제 데이터로 교체하는 방식을 사용하신다는 점을 고려하면, 서버 연동할 때 함께 수정하시는 것이 합리적이네요.
그때 실제 책 데이터와 함께 올바른 ISBN 파라미터를 전달하도록 수정해주시면 됩니다! 🐰
(\ /)
( ._. )
o_(")(")
🧠 Learnings used
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#35
File: feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/TermsAgreementScreen.kt:127-127
Timestamp: 2025-07-09T01:14:29.836Z
Learning: In the Reed-Android project's TermsAgreementScreen.kt, the OnTermDetailClick event is intentionally passed an empty string for the URL parameter because the actual URLs for terms detail pages haven't been decided yet. This is a temporary implementation that will be updated once the URLs are finalized.
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#75
File: feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt:0-0
Timestamp: 2025-07-29T06:07:11.709Z
Learning: seoyoon513 팀에서는 UI 구현 단계에서 더미 데이터를 하드코딩하여 화면을 먼저 구현하고, 이후 서버 연동 시점에 실제 데이터로 교체하는 개발 방식을 사용합니다.
| val dummyBooks = listOf( | ||
| Book("여름은 오래 그곳에 남아", "마쓰이에 마사시", "비채", "https://image.aladin.co.kr/product/7492/9/cover200/8934972203_1.jpg", 3), | ||
| Book("여름은 오래 그곳에 남아", "마쓰이에 마사시", "비채", "https://image.aladin.co.kr/product/7492/9/cover200/8934972203_1.jpg", 3), | ||
| Book("여름은 오래 그곳에 남아", "마쓰이에 마사시", "비채", "https://image.aladin.co.kr/product/7492/9/cover200/8934972203_1.jpg", 3) | ||
| ) |
There was a problem hiding this comment.
🛠️ Refactor suggestion
더미 데이터 위치 개선 필요
더미 데이터가 UI 레이어에 하드코딩되어 있습니다. 이는 Presenter나 State에서 관리하는 것이 더 적절합니다.
HomeUiState에 books 필드를 추가하고 Presenter에서 더미 데이터를 제공하는 방식으로 변경을 고려해보세요.
🤖 Prompt for AI Agents
In feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt
around lines 58 to 62, the dummy book data is hardcoded directly in the UI
layer, which is not ideal. Move this dummy data out of the UI composable and
instead add a books field to the HomeUiState data class. Then, provide the dummy
book list from the Presenter or ViewModel layer by populating the books field in
HomeUiState, so the UI only consumes state data without managing the dummy data
itself.
There was a problem hiding this comment.
UI 보여주기 위해 하드코딩한거고 서버 연동할 때 바꿀거야
There was a problem hiding this comment.
@seoyoon513 네, 이해했습니다! UI 구현을 위한 임시 더미 데이터군요. 서버 연동 시점에 적절히 리팩토링하시면 됩니다.
✏️ Learnings added
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#75
File: feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt:0-0
Timestamp: 2025-07-29T06:07:11.709Z
Learning: seoyoon513 팀에서는 UI 구현 단계에서 더미 데이터를 하드코딩하여 화면을 먼저 구현하고, 이후 서버 연동 시점에 실제 데이터로 교체하는 개발 방식을 사용합니다.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#63
File: feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt:28-53
Timestamp: 2025-07-22T05:19:10.071Z
Learning: feature/library의 LibraryPresenter에서 현재 FilterChipState의 카운트 값들은 UI 확인용 더미 데이터이며, API가 준비되면 실제 데이터로 교체될 예정입니다.
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
|
와 짱 빠르다 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (1)
126-135: 페이지 인디케이터 접근성 개선페이지 인디케이터에 스크린 리더를 위한 설명이 없습니다.
Box( modifier = Modifier .size(12.dp) .padding(3.dp) .clip(CircleShape) - .background(color), + .background(color) + .semantics { + contentDescription = "${iteration + 1}/${pagerState.pageCount} 페이지" + }, )필요한 import 추가:
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#75
File: feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt:0-0
Timestamp: 2025-07-29T06:07:11.727Z
Learning: seoyoon513 팀에서는 UI 구현 단계에서 더미 데이터를 하드코딩하여 화면을 먼저 구현하고, 이후 서버 연동 시점에 실제 데이터로 교체하는 개발 방식을 사용합니다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (5)
Learnt from: seoyoon513
PR: #63
File: feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt:28-53
Timestamp: 2025-07-22T05:19:10.071Z
Learning: feature/library의 LibraryPresenter에서 현재 FilterChipState의 카운트 값들은 UI 확인용 더미 데이터이며, API가 준비되면 실제 데이터로 교체될 예정입니다.
Learnt from: seoyoon513
PR: #75
File: feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt:0-0
Timestamp: 2025-07-29T06:07:11.727Z
Learning: seoyoon513 팀에서는 UI 구현 단계에서 더미 데이터를 하드코딩하여 화면을 먼저 구현하고, 이후 서버 연동 시점에 실제 데이터로 교체하는 개발 방식을 사용합니다.
Learnt from: seoyoon513
PR: #35
File: feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/TermsAgreementScreen.kt:127-127
Timestamp: 2025-07-09T01:14:29.836Z
Learning: In the Reed-Android project's TermsAgreementScreen.kt, the OnTermDetailClick event is intentionally passed an empty string for the URL parameter because the actual URLs for terms detail pages haven't been decided yet. This is a temporary implementation that will be updated once the URLs are finalized.
Learnt from: easyhooon
PR: #61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 booket.android.feature convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
Learnt from: easyhooon
PR: #77
File: feature/onboarding/src/main/kotlin/com/ninecraft/booket/feature/onboarding/OnboardingUi.kt:73-73
Timestamp: 2025-07-29T07:02:18.885Z
Learning: Kotlin에서 같은 패키지 내의 파일들은 패키지 레벨에 정의된 const val 상수를 import 없이 직접 접근할 수 있습니다. OnboardingPresenter.kt와 OnboardingUi.kt 모두 com.ninecraft.booket.feature.onboarding 패키지에 속해 있어서 ONBOARDING_STEPS_COUNT 상수를 공유할 수 있습니다.
⏰ 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: ci-build
| val systemUiController = rememberSystemUiController() | ||
|
|
||
| DisposableEffect(systemUiController) { | ||
| systemUiController.setStatusBarColor( | ||
| color = HomeBg, | ||
| darkIcons = true, | ||
| ) | ||
| onDispose { | ||
| systemUiController.setStatusBarColor( | ||
| color = White, | ||
| darkIcons = true, | ||
| ) | ||
| } | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
SystemUiController는 deprecated 예정입니다
SystemUiController는 향후 deprecated될 예정입니다. Android 15 이상에서의 호환성을 위해 WindowCompat.setDecorFitsSystemWindows()와 WindowInsetsControllerCompat를 사용하는 것을 고려해보세요.
Android 15에서의 statusBar 색상 문제도 이와 관련이 있을 수 있습니다. 다음 웹 검색을 통해 최신 권장사항을 확인해보세요:
🌐 Web query:
Android 15 SystemUiController deprecated replacement WindowInsetsControllerCompat
💡 Result:
In Android 15 (API level 35), multiple APIs in the system UI domain—most notably setStatusBarColor, setNavigationBarColor, and related attributes—have been deprecated or made non-functional for apps targeting Android 15, especially when using gesture navigation or trying to draw content edge-to-edge[1]. Developers who previously used tools like Accompanist's SystemUiController (now deprecated and unsupported[3]) are advised to migrate to the official WindowInsetsControllerCompat API for controlling system bars and applying insets.
Key Changes in Android 15
- setStatusBarColor and setNavigationBarColor are deprecated and have no effect under gesture navigation, and only a limited effect under 3-button navigation[1].
- Edge-to-edge mode is now enforced by default for all apps targeting Android 15, requiring you to explicitly manage how your app's content draws around system bars and navigation areas[1][5].
- Accompanist’s SystemUiController is deprecated. Official support and updates have stopped, so it should no longer be used[3].
Modern Replacement: WindowInsetsControllerCompat
WindowInsetsControllerCompat (from AndroidX) is now the recommended API:
- It provides unified control over status bars, navigation bars, and system gestures.
- It can be used for immersive mode, light/dark icon settings, and runtime control of system bar visibility[2][5].
- It automatically wraps the framework's WindowInsetsController where available (API 30+), offering fallback implementations for older SDKs[2].
Example Use (Java/Kotlin)
// Standard usage in an Activity or Fragment
val controller = WindowCompat.getInsetsController(window, window.decorView)
controller?.hide(WindowInsetsCompat.Type.systemBars()) // Hide status/navigation bars
controller?.show(WindowInsetsCompat.Type.systemBars()) // Show them again
controller?.isAppearanceLightStatusBars = true // Set light status bar iconsOr in Java:
Window window = getWindow();
WindowInsetsControllerCompat controller = WindowCompat.getInsetsController(window, window.getDecorView());
if (controller != null) {
controller.hide(WindowInsetsCompat.Type.systemBars());
controller.setAppearanceLightStatusBars(true);
}[5]
Handling Insets with Edge-to-Edge
Since content is now drawn behind the system bars by default:
- Use ViewCompat.setOnApplyWindowInsetsListener to adjust your view paddings or margins based on system bar insets.
- Use WindowInsetsCompat.Type.systemBars() or Type.systemGestures() to query insets[5][8].
Updating System Bar Icons for Edge-to-Edge
WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = false[5]
Compose Applications
- Jetpack Compose now recommends using its own WindowInsets support for edge-to-edge and system UI configuration, relying internally on similar platform APIs[6].
- If you need imperative control (hide/show bars, set icon color), use WindowInsetsControllerCompat via interop.
Summary Table: Deprecated vs. Recommended APIs
| Deprecated (Accompanist/SystemUiController) | Replacement (AndroidX/Platform) |
|---|---|
| SystemUiController.setStatusBarColor(), .setNavigationBarColor() | WindowInsetsControllerCompat + insets |
| Accompanist edge-to-edge APIs | View/window insets, WindowInsetsCompat |
| SystemUiController immersive mode methods | WindowInsetsControllerCompat.hide/show() |
Caveats and Migration Notes
- Many previous "color setting" APIs now have no effect with gesture navigation or are fully deprecated[1].
- Always apply padding or margin based on WindowInsets or WindowInsetsCompat to prevent UI overlap.
- WindowInsetsControllerCompat offers concise, cross-version support for all major system bar behaviors and should be your default choice for managing system bars going forward[2][5].
If you are migrating from Accompanist’s SystemUiController or working on a new app for Android 15+, WindowInsetsControllerCompat is the authoritative and future-proof solution to control system UI visibility and behavior.
Citations:
- 1: https://developer.android.com/about/versions/15/behavior-changes-15
- 2: https://developer.android.com/reference/androidx/core/view/WindowInsetsControllerCompat
- 3: [System UI Controller] Provide way to set layoutInDisplayCutoutMode google/accompanist#964
- 4: https://developer.android.com/about/versions/15/summary
- 5: https://developer.android.com/develop/ui/views/layout/edge-to-edge
- 6: https://developer.android.com/develop/ui/compose/system/insets
- 7: https://source.android.com/docs/whatsnew/android-15-release
- 8: https://gist.github.com/oguzhanaslann/4becf9c6f2fc914f72d1ab2a0c4eb59b
- 9: https://github.com/google/accompanist/releases
- 10: https://slack-chats.kotlinlang.org/t/15881206/now-that-systemuicontroller-is-deprecated-and-enableedgetoed
SystemUiController 대신 WindowInsetsControllerCompat 사용 검토
Android 15(API 35)부터는 setStatusBarColor 등 SystemUiController 기반 API가 deprecated 또는 무효화되며, Edge-to-Edge가 기본 적용됩니다. Accompanist의 SystemUiController는 더 이상 지원되지 않으므로 다음과 같이 마이그레이션을 권장합니다.
• 대상 파일
- feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (47–60번 라인)
• 변경 요점
rememberSystemUiController()및DisposableEffect내setStatusBarColor호출 제거WindowCompat.getInsetsController(window, decorView)로WindowInsetsControllerCompat인스턴스 생성window.statusBarColor = …과insetsController.isAppearanceLightStatusBars = …로 상태 표시줄 색상 및 아이콘 모드 설정
• 예시 코드
@Composable
fun HomeUi(/*…*/) {
val activity = LocalContext.current as Activity
val window = activity.window
val decorView = window.decorView
val insetsController = WindowCompat.getInsetsController(window, decorView)
DisposableEffect(insetsController) {
// 상태 표시줄 배경색 설정
window.statusBarColor = HomeBg.toArgb()
// 라이트 아이콘 모드 설정
insetsController.isAppearanceLightStatusBars = true
onDispose {
window.statusBarColor = Color.White.toArgb()
insetsController.isAppearanceLightStatusBars = true
}
}
// …나머지 UI 구성
}위 방식으로 마이그레이션하면 Android 15 이상의 환경에서도 정상 동작하며, 향후 지원 중단에 대비할 수 있습니다.
🤖 Prompt for AI Agents
In feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt
around lines 47 to 60, replace the usage of rememberSystemUiController and its
setStatusBarColor calls inside DisposableEffect with
WindowInsetsControllerCompat. Obtain the WindowInsetsControllerCompat instance
via WindowCompat.getInsetsController using the current activity's window and
decorView, then set the status bar color by assigning window.statusBarColor and
control icon appearance with insetsController.isAppearanceLightStatusBars. Also
update the onDispose block to reset these properties accordingly. This migration
ensures compatibility with Android 15+ where SystemUiController is deprecated.
There was a problem hiding this comment.
거기만 고친다고 해서 적용이 되는 문제는 아니라 MainActivity쪽도 같이 수정 들어가야 할 듯. 좀 전체적으로 파악해보고 나중에 고쳐볼게
There was a problem hiding this comment.
@seoyoon513 맞습니다! 상태바 색상 관리는 Activity 레벨에서의 설정과 개별 화면 컴포넌트가 함께 조화롭게 동작해야 하는 부분이라 HomeUi.kt만 수정해서는 완전한 해결이 어려울 수 있습니다.
전체적인 아키텍처를 파악하고 MainActivity와 함께 종합적으로 접근하시는 것이 좋은 판단인 것 같습니다. Android 15 호환성 문제는 이미 알고 계신 이슈이고, 나중에 전체적으로 정리해서 해결하시는 방향이 더 안정적일 것 같네요.
현재 PR에서는 UI 구현에 집중하시고, 시스템 UI 관련 이슈는 별도 PR에서 체계적으로 다루시는 것이 합리적인 것 같습니다! 👍
🧠 Learnings used
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#77
File: feature/onboarding/src/main/kotlin/com/ninecraft/booket/feature/onboarding/OnboardingUi.kt:73-73
Timestamp: 2025-07-29T07:02:18.885Z
Learning: Kotlin에서 같은 패키지 내의 파일들은 패키지 레벨에 정의된 const val 상수를 import 없이 직접 접근할 수 있습니다. OnboardingPresenter.kt와 OnboardingUi.kt 모두 com.ninecraft.booket.feature.onboarding 패키지에 속해 있어서 ONBOARDING_STEPS_COUNT 상수를 공유할 수 있습니다.
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#55
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/ReedTextField.kt:0-0
Timestamp: 2025-07-17T23:43:38.687Z
Learning: Reed Android 프로젝트에서 아이콘의 tint 속성을 Color.Unspecified로 설정하는 이유는 theme 색상이 아이콘에 적용되어 아이콘 고유의 색상이 변경되는 것을 방지하기 위함이다. 이는 아이콘의 원본 색상을 보존하려는 디자인 시스템 정책과 일치한다.
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#75
File: feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt:0-0
Timestamp: 2025-07-29T06:07:11.727Z
Learning: seoyoon513 팀에서는 UI 구현 단계에서 더미 데이터를 하드코딩하여 화면을 먼저 구현하고, 이후 서버 연동 시점에 실제 데이터로 교체하는 개발 방식을 사용합니다.
| val pagerState = rememberPagerState(pageCount = { dummyBooks.size }) | ||
| HorizontalPager( | ||
| state = pagerState, | ||
| modifier = Modifier.fillMaxWidth(), | ||
| contentPadding = PaddingValues(horizontal = ReedTheme.spacing.spacing5), | ||
| pageSpacing = ReedTheme.spacing.spacing5, | ||
| ) { page -> | ||
| BookCard( | ||
| bookInfo = dummyBooks[page], | ||
| onBookDetailClick = { | ||
| state.eventSink(HomeUiEvent.OnBookDetailClick) | ||
| }, | ||
| onRecordButtonClick = { | ||
| state.eventSink(HomeUiEvent.OnRecordButtonClick) | ||
| }, | ||
| ) | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
빈 리스트 처리 추가 필요
dummyBooks가 비어있을 경우를 처리해야 합니다. 현재 코드에서는 빈 리스트일 때 HorizontalPager가 아무것도 표시하지 않습니다.
val pagerState = rememberPagerState(pageCount = { dummyBooks.size })
+if (dummyBooks.isEmpty()) {
+ // EmptyBookCard 표시 또는 다른 빈 상태 UI
+ return
+}
HorizontalPager(또는 BookCard.kt에 있는 EmptyBookCard 컴포넌트를 활용하는 방안도 고려해보세요.
📝 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.
| val pagerState = rememberPagerState(pageCount = { dummyBooks.size }) | |
| HorizontalPager( | |
| state = pagerState, | |
| modifier = Modifier.fillMaxWidth(), | |
| contentPadding = PaddingValues(horizontal = ReedTheme.spacing.spacing5), | |
| pageSpacing = ReedTheme.spacing.spacing5, | |
| ) { page -> | |
| BookCard( | |
| bookInfo = dummyBooks[page], | |
| onBookDetailClick = { | |
| state.eventSink(HomeUiEvent.OnBookDetailClick) | |
| }, | |
| onRecordButtonClick = { | |
| state.eventSink(HomeUiEvent.OnRecordButtonClick) | |
| }, | |
| ) | |
| } | |
| val pagerState = rememberPagerState(pageCount = { dummyBooks.size }) | |
| if (dummyBooks.isEmpty()) { | |
| // EmptyBookCard 표시 또는 다른 빈 상태 UI | |
| return | |
| } | |
| HorizontalPager( | |
| state = pagerState, | |
| modifier = Modifier.fillMaxWidth(), | |
| contentPadding = PaddingValues(horizontal = ReedTheme.spacing.spacing5), | |
| pageSpacing = ReedTheme.spacing.spacing5, | |
| ) { page -> | |
| BookCard( | |
| bookInfo = dummyBooks[page], | |
| onBookDetailClick = { | |
| state.eventSink(HomeUiEvent.OnBookDetailClick) | |
| }, | |
| onRecordButtonClick = { | |
| state.eventSink(HomeUiEvent.OnRecordButtonClick) | |
| }, | |
| ) | |
| } |
🤖 Prompt for AI Agents
In feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt
around lines 104 to 120, the code does not handle the case when dummyBooks is
empty, causing HorizontalPager to show nothing. Add a conditional check before
rendering HorizontalPager to detect if dummyBooks is empty, and if so, display
the EmptyBookCard component from BookCard.kt instead. This ensures the UI
gracefully handles empty lists by showing a placeholder card.
There was a problem hiding this comment.
어차피 dummy 데이터로 하는거라 EmtyBookCard 적용은 API 연결 때 할 예정!
There was a problem hiding this comment.
@seoyoon513 네, 이해했습니다! 더미 데이터 단계에서는 현재 구현으로 충분하고, API 연동 시점에 실제 데이터와 함께 빈 상태 처리를 구현하는 것이 합리적인 접근 방식이네요. 👍
🧠 Learnings used
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#77
File: feature/onboarding/src/main/kotlin/com/ninecraft/booket/feature/onboarding/OnboardingUi.kt:73-73
Timestamp: 2025-07-29T07:02:18.885Z
Learning: Kotlin에서 같은 패키지 내의 파일들은 패키지 레벨에 정의된 const val 상수를 import 없이 직접 접근할 수 있습니다. OnboardingPresenter.kt와 OnboardingUi.kt 모두 com.ninecraft.booket.feature.onboarding 패키지에 속해 있어서 ONBOARDING_STEPS_COUNT 상수를 공유할 수 있습니다.
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#63
File: feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt:28-53
Timestamp: 2025-07-22T05:19:10.071Z
Learning: feature/library의 LibraryPresenter에서 현재 FilterChipState의 카운트 값들은 UI 확인용 더미 데이터이며, API가 준비되면 실제 데이터로 교체될 예정입니다.
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#46
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/component/InfiniteLazyColumn.kt:83-95
Timestamp: 2025-07-14T00:46:03.843Z
Learning: seoyoon513과 팀은 한국어 주석을 선호하며, 한국어 주석을 영어로 번역하라는 제안을 하지 않아야 함
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#75
File: feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt:0-0
Timestamp: 2025-07-29T06:07:11.727Z
Learning: seoyoon513 팀에서는 UI 구현 단계에서 더미 데이터를 하드코딩하여 화면을 먼저 구현하고, 이후 서버 연동 시점에 실제 데이터로 교체하는 개발 방식을 사용합니다.
|
이거 일단 merge 하고(issue에 버그 사항 남겨두고) 다음 작업 진행해도 될것같습니다 |


🔗 관련 이슈
📙 작업 설명
📸 스크린샷 또는 시연 영상
Reed_Home.mp4
💬 추가 설명 or 리뷰 포인트
Summary by CodeRabbit
신규 기능
스타일
문서화
리팩터링