feat: Compose Stability Analyzer Plugin 적용 #200
Conversation
정적인 컴포저블 외에 동적인(리컴포지션이 런타임에 발생할 수 있는) 컴포저블에 @TraceRecomposition 어노테이션 추가
Kotlin: @TraceRecomposition 어노테이션이 정상 동작하기 위함 KSP: 2.3.0 버전 부터 Kotlin 버전과 독립적
Walkthrough다수의 Composable 함수에 Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Dev as 개발자
participant Repo as 저장소
participant Analyzer as StabilityAnalyzer
participant CI as GitHub Actions
Dev->>Repo: @TraceRecomposition 주석 및 설정 커밋
Repo->>Analyzer: Gradle :stabilityCheck 실행
Analyzer-->>Repo: `.stability` 메타데이터 생성/업데이트
CI->>Repo: stability_check job (JDK21) 트리거
CI->>Analyzer: ./gradlew :stabilityCheck
Analyzer-->>CI: 분석 결과/로그 반환
note right of Analyzer: 어노테이션은 리컴포지션 추적용 관찰 도구입니다
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/component/BookItem.kt (1)
34-34: Import 문의 순서를 정리하면 좋습니다 (선택사항).현재
com.skydoves외부 임포트가 내부com.ninecraft임포트들 사이에 위치하고 있습니다. 프로젝트 컨벤션에 따라 외부 라이브러리 임포트를 먼저 그룹화한 후 내부 임포트를 배치하면 더 명확한 구조가 될 수 있습니다.- import com.ninecraft.booket.feature.search.R - import com.skydoves.compose.stability.runtime.TraceRecomposition - import com.ninecraft.booket.core.designsystem.R as designR + import com.ninecraft.booket.core.designsystem.component.NetworkImage + import com.ninecraft.booket.core.designsystem.theme.ReedTheme + import com.ninecraft.booket.core.designsystem.theme.White + import com.ninecraft.booket.core.model.BookSummaryModel + import com.ninecraft.booket.feature.search.R + import com.skydoves.compose.stability.runtime.TraceRecomposition + import com.ninecraft.booket.core.designsystem.R as designRfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/EmotionStep.kt (1)
41-120: 리컴포지션 추적 어노테이션이 올바르게 적용되었습니다.
EmotionStep컴포저블에@TraceRecomposition어노테이션이 정확하게 추가되었습니다. 로직 변경 없이 모니터링 기능만 추가되어 기존 기능에 영향이 없습니다.선택적 개선 사항: 더 세밀한 리컴포지션 추적을 원하신다면, 123-157번째 줄의 private
EmotionItem컴포저블에도@TraceRecomposition어노테이션을 추가하는 것을 고려해보실 수 있습니다. 이는 개별 감정 아이템의 리컴포지션 패턴을 분석하는 데 도움이 될 수 있습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/QuoteStep.kt (1)
56-61: 변경사항이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션이QuoteStepComposable에 정확히 적용되어 리컴포지션 추적이 가능합니다. PR 목표에 부합하는 변경입니다.다만, 프로덕션 빌드에서의 성능 영향을 고려하여 디버그 빌드에서만 어노테이션이 활성화되도록 하는 것을 검토해볼 수 있습니다. 이는 프로젝트 전체에 걸친 아키텍처 결정이므로 선택 사항입니다.
feature/onboarding/src/main/kotlin/com/ninecraft/booket/feature/onboarding/component/PagerIndicator.kt (1)
21-23: 변경 사항이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션이PagerIndicatorComposable에 정상적으로 적용되었습니다.PagerState는 불안정(unstable)한 타입이므로 리컴포지션 추적 대상으로 적절합니다.권장사항: 프로덕션 빌드에서의 성능 영향 검토
@TraceRecomposition어노테이션이 디버그 빌드에서만 활성화되도록 설정되어 있는지 확인하는 것을 권장합니다. 런타임 추적은 프로덕션 환경에서 성능 오버헤드를 발생시킬 수 있습니다.다음 스크립트로 플러그인 설정을 확인할 수 있습니다:
#!/bin/bash # Description: Verify Compose Stability Analyzer plugin configuration to ensure it's debug-only # Check plugin configuration in build files fd -e gradle.kts -e gradle . | xargs rg -n "compose-stability-runtime" -A 3 -B 3 # Check for debug/release build variant configurations fd -e gradle.kts . | xargs rg -n "debugImplementation|releaseImplementation" | rg "compose-stability"
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (37)
core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/InfinityLazyColumn.kt(1 hunks)feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt(2 hunks)feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/BookUpdateBottomSheet.kt(1 hunks)feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.kt(2 hunks)feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/card/RecordCardUi.kt(1 hunks)feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/record/RecordDetailUi.kt(2 hunks)feature/edit/src/main/kotlin/com/ninecraft/booket/feature/edit/emotion/EmotionEditUi.kt(2 hunks)feature/edit/src/main/kotlin/com/ninecraft/booket/feature/edit/record/RecordEditUi.kt(4 hunks)feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.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/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryUi.kt(3 hunks)feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/component/FilterChip.kt(1 hunks)feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/component/FilterChipGroup.kt(1 hunks)feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt(1 hunks)feature/login/src/main/kotlin/com/ninecraft/booket/feature/termsagreement/TermsAgreementUi.kt(1 hunks)feature/login/src/main/kotlin/com/ninecraft/booket/feature/termsagreement/component/TermsItem.kt(1 hunks)feature/onboarding/src/main/kotlin/com/ninecraft/booket/feature/onboarding/OnboardingUi.kt(1 hunks)feature/onboarding/src/main/kotlin/com/ninecraft/booket/feature/onboarding/component/PagerIndicator.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/ImpressionGuideBottomSheet.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/ImpressionGuideBox.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt(3 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/SentenceBox.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUi.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/EmotionStep.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/ImpressionStep.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/QuoteStep.kt(1 hunks)feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchUi.kt(2 hunks)feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/component/BookItem.kt(1 hunks)feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/library/LibrarySearchUi.kt(2 hunks)feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/SettingsUi.kt(1 hunks)feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/component/ReedSwitch.kt(1 hunks)feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/component/ToggleItem.kt(1 hunks)feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/notification/NotificationUi.kt(1 hunks)feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/osslicenses/OssLicensesUi.kt(1 hunks)feature/splash/src/main/kotlin/com/ninecraft/booket/splash/SplashUi.kt(1 hunks)gradle/libs.versions.toml(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.
Applied to files:
feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchUi.kt
🧬 Code graph analysis (1)
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.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 (46)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeHeader.kt (1)
22-23: 임포트 순서 정리 - 문제 없음.designsystem R 알리아스 임포트가 피처 관련 R 임포트 뒤에 정리되었습니다. 코드 기능에는 영향이 없으며, PR의 전반적인 임포트 구조 정렬 패턴과 일치합니다. 라인 52에서
designR.drawable.ic_settings를 통한 사용도 정상 작동합니다.feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/component/BookItem.kt (1)
34-34:@TraceRecomposition어노테이션 적용이 정상적으로 이루어졌습니다.어노테이션이 올바르게
@Composable이전에 적용되었으며, 함수의 서명이나 동작을 변경하지 않습니다. PR 전체의 일관된 패턴을 따르고 있으며, 리컴포지션 추적 기능이 예상대로 작동할 것으로 보입니다.Also applies to: 37-38
feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/SettingsUi.kt (1)
38-38: LGTM! 리컴포지션 추적 기능이 올바르게 추가되었습니다.import와
@TraceRecomposition어노테이션이 적절하게 추가되었습니다.SettingsUi는 최상위 UI 컴포저블이므로 리컴포지션 추적을 위한 좋은 대상입니다. PR 목표에 부합하는 깔끔한 구현입니다.Also applies to: 44-44
feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/component/ReedSwitch.kt (2)
29-29: LGTM! 리컴포지션 추적을 위한 임포트 추가.Compose Stability Analyzer Plugin 적용을 위해 필요한 임포트가 정상적으로 추가되었습니다.
31-31: LGTM! 리컴포지션 추적 어노테이션 정상 적용.
@TraceRecomposition어노테이션이ReedSwitchComposable에 정상적으로 추가되어 리컴포지션 발생 횟수 및 원인을 로그로 확인할 수 있게 되었습니다. 기존 로직에는 영향이 없는 계측(instrumentation) 전용 변경사항입니다.feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/osslicenses/OssLicensesUi.kt (1)
40-48: 리컴포지션 추적 계측이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션과 임포트가 정확하게 추가되었으며, 로직 변경 없이 순수하게 계측 기능만 추가되었습니다.feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/notification/NotificationUi.kt (1)
44-49: 리컴포지션 추적 계측이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션과 임포트가 정확하게 추가되었으며, 기존 동작에 영향을 주지 않습니다.feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/component/ToggleItem.kt (1)
14-16: 리컴포지션 추적 계측이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션과 임포트가 정확하게 추가되었으며, 함수 시그니처나 동작의 변경 없이 순수하게 계측 기능만 추가되었습니다.feature/onboarding/src/main/kotlin/com/ninecraft/booket/feature/onboarding/OnboardingUi.kt (2)
26-26: LGTM! 리컴포지션 추적을 위한 import 추가PR 목표에 맞게
@TraceRecomposition어노테이션 사용을 위한 import가 올바르게 추가되었습니다.
30-30: LGTM! 리컴포지션 추적 어노테이션 적용
OnboardingUi컴포저블에@TraceRecomposition어노테이션이 올바르게 적용되었습니다. 이 화면은 페이저 상태와 사용자 상호작용을 포함하고 있어 리컴포지션 추적에 적합한 대상입니다. PR 목표와 일치하며, 로직 변경 없이 계측 기능만 추가되었습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/ImpressionGuideBox.kt (1)
23-25: 리컴포지션 추적을 위한 어노테이션 적용이 올바릅니다.
ImpressionGuideBox는isSelected파라미터에 따라 배경색과 테두리 색상이 동적으로 변경되는 컴포저블이므로,@TraceRecomposition어노테이션을 적용하여 리컴포지션 발생을 추적하는 것이 적절합니다. 임포트도 올바르게 추가되었으며, 기존 로직에는 영향을 주지 않습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/ImpressionStep.kt (2)
58-58: Import 추가가 적절합니다.리컴포지션 추적을 위한
TraceRecomposition어노테이션 사용에 필요한 import가 올바르게 추가되었습니다.
64-64: 리컴포지션 추적 어노테이션이 적절하게 적용되었습니다.
ImpressionStep은 키보드 상태, 포커스 관리, bottom sheet 표시 등 여러 상태를 관리하는 동적 Composable이므로@TraceRecomposition어노테이션을 적용하여 리컴포지션을 추적하기에 적합한 대상입니다. PR 목표와 일치하며 로직 변경 없이 올바르게 적용되었습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/EmotionStep.kt (1)
38-38: 변경 사항이 적절합니다.리컴포지션 추적을 위한
@TraceRecomposition어노테이션 사용에 필요한 임포트가 올바르게 추가되었습니다.feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/QuoteStep.kt (1)
51-51: LGTM! 임포트가 올바르게 추가되었습니다.리컴포지션 추적을 위한
TraceRecomposition어노테이션 임포트가 정확합니다.feature/login/src/main/kotlin/com/ninecraft/booket/feature/termsagreement/component/TermsItem.kt (2)
20-20: 임포트 추가가 올바르게 적용되었습니다.
TraceRecomposition어노테이션 사용을 위한 임포트가 정확하게 추가되었습니다.
23-23: 리컴포지션 추적 어노테이션이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션이 정확한 위치에 추가되어 런타임에 이 Composable의 리컴포지션 발생을 추적할 수 있게 되었습니다. 이는 성능 모니터링 및 디버깅에 유용하며, 로직 변경 없이 계측만 추가되어 기존 기능에 영향을 주지 않습니다.feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.kt (3)
17-17: 필요한 임포트가 올바르게 추가되었습니다.리컴포지션 추적과 프리뷰 기능을 위한 임포트가 적절하게 추가되었습니다.
Also applies to: 21-21
24-24: @TraceRecomposition 어노테이션이 적절하게 적용되었습니다.이 Composable은 런타임에 변경 가능한 동적 파라미터(
totalCount,currentRecordSort)를 가지고 있어 리컴포지션 추적 대상으로 적합합니다.
69-79: 프리뷰 함수가 잘 구현되었습니다.디자인 타임 프리뷰를 위한 함수가 Compose 모범 사례를 따라 잘 구현되었습니다:
private가시성으로 캡슐화- 테마로 적절히 감싸져 있음
- 대표적인 샘플 데이터 제공
feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/library/LibrarySearchUi.kt (1)
36-36: 리컴포지션 추적 기능이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션이 주요 진입점 Composable 함수들에 적절히 적용되었으며, 임포트도 정확합니다. PR 목표에 부합하는 변경사항입니다.Also applies to: 40-40, 60-60
feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchUi.kt (1)
43-43: 리컴포지션 추적 어노테이션이 정상적으로 적용되었습니다.
BookSearchUi와BookSearchContent에@TraceRecomposition어노테이션이 올바르게 추가되었으며, 기존 로직에는 영향을 주지 않습니다.Also applies to: 50-50, 85-85
feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryUi.kt (1)
37-37: 리컴포지션 추적 기능이 적절하게 적용되었습니다.
LibraryUi,LibraryContent,EmptyResult모든 컴포저블에@TraceRecomposition어노테이션이 올바르게 적용되었습니다. Private 함수인EmptyResult에도 어노테이션을 추가한 것은 리컴포지션 추적 관점에서 적절한 선택입니다.Also applies to: 43-43, 89-89, 193-193
feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/component/FilterChipGroup.kt (1)
16-16: 리컴포지션 추적 어노테이션이 정상적으로 추가되었습니다.
FilterChipGroup에@TraceRecomposition어노테이션이 올바르게 적용되었으며, 프로젝트 전반의 추적 패턴과 일관성을 유지하고 있습니다.Also applies to: 20-20
feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/component/FilterChip.kt (1)
23-23: 리컴포지션 추적 및 API 확장이 잘 구현되었습니다.
@TraceRecomposition어노테이션이 올바르게 추가되었으며, 새로운 파라미터들(count,isSelected,onChipClick)을 통한 API 확장이 적절하게 구현되었습니다. 선택 상태에 따른 색상 및 스타일 변경 로직이 명확하고, 클릭 핸들러도 정상적으로 연결되어 있습니다.Also applies to: 25-77
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/ImpressionGuideBottomSheet.kt (1)
31-31: 리컴포지션 추적 기능이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션이 적절히 추가되어 런타임에 리컴포지션 발생을 추적할 수 있습니다.Also applies to: 36-36
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUi.kt (1)
34-34: 리컴포지션 추적 어노테이션이 정상적으로 추가되었습니다.Circuit UI 진입점에
@TraceRecomposition이 올바르게 적용되어 있습니다.Also applies to: 38-38
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/OcrUi.kt (1)
71-71: OCR UI의 주요 컴포저블에 추적 기능이 적절히 추가되었습니다.진입점인
OcrUi와 주요 하위 컴포저블인CameraPreview,TextScanResult에@TraceRecomposition이 추가되어 세밀한 리컴포지션 추적이 가능합니다.Also applies to: 78-78, 93-93, 318-318
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/SentenceBox.kt (1)
18-18: 재사용 가능한 컴포넌트에 추적 기능이 추가되었습니다.리스트 아이템으로 사용되는
SentenceBox에@TraceRecomposition이 추가되어 불필요한 리컴포지션을 식별할 수 있습니다.Also applies to: 20-20
core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/InfinityLazyColumn.kt (1)
38-38: 공통 UI 컴포넌트에 리컴포지션 추적이 적용되었습니다.프로젝트 전반에서 사용되는
InfinityLazyColumn에@TraceRecomposition이 추가되어 무한 스크롤 관련 성능 이슈를 모니터링할 수 있습니다.Also applies to: 43-43
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/record/RecordDetailUi.kt (1)
34-34: Detail UI의 진입점과 컨텐츠 컴포저블에 추적 기능이 추가되었습니다.
RecordDetailUi와RecordDetailContent에 각각@TraceRecomposition이 적용되어 Scaffold와 컨텐츠의 리컴포지션을 개별적으로 추적할 수 있습니다.Also applies to: 40-40, 121-121
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/BookUpdateBottomSheet.kt (1)
40-40: 바텀 시트 컴포넌트에 리컴포지션 추적이 적용되었습니다.
BookUpdateBottomSheet에@TraceRecomposition이 추가되어 모달 시트의 상태 변경에 따른 리컴포지션을 모니터링할 수 있습니다.Also applies to: 45-45
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt (1)
57-57: 복잡한 Detail UI에 리컴포지션 추적이 체계적으로 추가되었습니다.여러 바텀 시트와 다이얼로그를 포함한
BookDetailUi와BookDetailContent에@TraceRecomposition이 적용되어 복잡한 UI 계층에서 리컴포지션 원인을 파악할 수 있습니다.Also applies to: 64-64, 200-200
feature/edit/src/main/kotlin/com/ninecraft/booket/feature/edit/record/RecordEditUi.kt (3)
48-48: LGTM: 리컴포지션 추적을 위한 임포트 추가
@TraceRecomposition어노테이션 사용을 위한 필수 임포트가 올바르게 추가되었습니다.
53-53: LGTM: 리컴포지션 추적 어노테이션 적용
RecordEditUi와RecordEditContentComposable에@TraceRecomposition어노테이션이 올바르게 적용되었습니다. 이를 통해 런타임에 리컴포지션 발생 횟수와 원인을 로그로 확인할 수 있습니다.Also applies to: 88-88
8-9: IME 인셋 처리는 의도된 설계 패턴으로 문제 없음검증 결과, 라인 67의
contentWindowInsets = ScaffoldDefaults.contentWindowInsets.exclude(WindowInsets.ime)변경은 의도된 아키텍처 설계이며, 라인 73의.imePadding()과 함께 작동합니다. 이 패턴은 RecordRegisterUi.kt(라인 56)에서도 동일하게 적용되어 있어 일관된 IME 처리 전략을 나타냅니다.Scaffold의 자동 인셋 조정을 제외하고 콘텐츠 요소에서 수동으로
.imePadding()을 적용하는 방식은 키보드 패딩에 대한 세밀한 제어를 가능하게 하는 유효한 패턴입니다. 동작 검증 결과 정상적으로 작동하므로 변경사항 승인 가능합니다.feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/component/HomeBanner.kt (1)
32-32: 리컴포지션 추적 어노테이션이 올바르게 적용되었습니다.
@TraceRecomposition어노테이션과 import가 정확하게 추가되었습니다. 함수 시그니처나 로직 변경 없이 깔끔하게 적용되었으며, PR 목표에 완벽히 부합합니다.Also applies to: 35-35
gradle/libs.versions.toml (1)
30-30: Kotlin 2.2.21과 KSP 2.3.0의 호환성 확인됨KSP 2.3.0은 Kotlin 2.2.x와 호환되며, KSP 2.3.0은 Kotlin 2.3.0과 직접 연결되지 않습니다. 선택한 버전들은 모두 최신 안정 버전이고 호환됩니다.
다음 사항들을 추가로 확인해주세요:
- KSP2를 사용 중인지 확인하세요 (KSP1은 더 이상 사용되지 않으며 호환되지 않습니다)
- Room, Hilt 등 타사 프로세서들이 KSP2 호환 버전으로 업데이트되었는지 확인하세요
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt (1)
36-36: 리컴포지션 추적 어노테이션이 올바르게 적용되었습니다.변경사항이 TermsAgreementUi.kt와 일관되게 적용되었으며, 구현이 정확합니다. 릴리스 빌드 설정에 대한 검증은 이전 파일의 검증 스크립트로 함께 확인할 수 있습니다.
Also applies to: 40-40
feature/login/src/main/kotlin/com/ninecraft/booket/feature/termsagreement/TermsAgreementUi.kt (1)
32-32: convention plugin 설정을 확인하겠습니다.더 구체적인 정보가 필요합니다.
더 정확한 정보를 찾겠습니다.
빌드 설정에서 성능 최적화 관련 명확한 증거를 찾을 수 없습니다.
코드베이스와 공개 문서를 검토한 결과 다음을 확인했습니다:
- root build.gradle.kts에서 compose.stability.analyzer 플러그인이 "apply false"로 선언되어 있습니다
- feature/login 모듈은 convention plugin을 사용하며 명시적인 stability analyzer 설정이 없습니다
- @TraceRecomposition 어노테이션의 공개 문서를 찾을 수 없어 릴리스 빌드에서의 동작을 확인할 수 없습니다
@TraceRecomposition 어노테이션의 런타임 성능 영향에 대해 직접 검증이 필요합니다.
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (1)
47-52: 코드 변경 자체는 문법적으로 올바릅니다.임포트와 어노테이션 적용이 정확하게 이루어졌으나, 다음 사항들의 검증이 여전히 필요합니다:
프로덕션 빌드에서의 TraceRecomposition 활성화 상태: 빌드 스크립트에서
compose-stability-analyzer플러그인은 확인되었으나,@TraceRecomposition어노테이션이 프로덕션 빌드에서 조건부로 비활성화되는지 명시적인 설정이 보이지 않습니다. Skydovescompose-stability-runtime라이브러리의 동작 방식을 확인하세요.선택적 적용 전략의 의도:
HomeUi만 추적하고HomeContent등 내부 컴포저블은 제외한 이유를 문서화하거나 팀 내 합의를 확인하세요.라이브러리 버전과 문서를 확인하여 다음을 명확히 해 주세요:
- 런타임 오버헤드가 프로덕션 성능에 미치는 영향
- 프로덕션 빌드에서 추적이 자동으로 비활성화되는지 여부
feature/edit/src/main/kotlin/com/ninecraft/booket/feature/edit/emotion/EmotionEditUi.kt (3)
39-39: 변경 사항 확인 완료리컴포지션 추적을 위한 import가 정상적으로 추가되었습니다.
70-75: 내부 Composable에 대한 추적 설정 완료
EmotionEditContent에@TraceRecomposition어노테이션이 정상적으로 적용되었습니다.EmotionItem(line 130)에는 어노테이션이 적용되지 않았는데, 이는 리프 컴포넌트로서 추적 노이즈를 줄이기 위한 의도적인 선택으로 보입니다.
44-50: <!-- [scratchpad_start]
[task review_file_1/1 review_segment_2/3]
Verify @TraceRecomposition annotation source and behavior[observations]
- Web search for "TraceRecomposition skydoves compose-stability" returned no results
- Import path in codebase: com.skydoves.compose.stability.runtime.TraceRecomposition
- Web search result suggests TraceRecomposition may not be from official skydoves library
- Could be custom annotation or from different library
[analysis]
- Web search couldn't locate TraceRecomposition in skydoves projects
- Need to verify actual dependency definition in build files
- compose-stable-marker is a known skydoves project but not the same as TraceRecomposition
- Original review comment's assumption about "production build behavior" may be based on unknown library
[pending]
- Find actual dependency providing TraceRecomposition
- Check build.gradle/libs.versions.toml for compose-stability or related dependency
- Determine if TraceRecomposition is custom annotation or from third-party lib
[actions]
- Search build files for compose.stability dependencies
- Find where TraceRecomposition annotation is defined in codebase
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/card/RecordCardUi.kt (2)
39-39: LGTM: import 문이 올바르게 추가되었습니다.
@TraceRecomposition어노테이션 사용을 위한 import 문이 정확하게 추가되었습니다.
44-50: 주석 작성이 정확합니다:@TraceRecomposition어노테이션이 올바르게 적용되었습니다.검증 결과:
- @TraceRecomposition은 com.skydoves.compose.stability.runtime 라이브러리(v0.3.0)에서 제공하는 유효한 어노테이션입니다
- RecordCardUi의 annotation 배치가 정확합니다 (다른 어노테이션 위에 위치)
- 프로젝트 전역에 40개 이상의 UI 컴포넌트에서 일관되게 사용 중입니다
다만, 초기 리뷰의 우려사항을 확인한 결과:
- compose.stability.analyzer 플러그인은 feature 모듈에 적용되지 않음
- feature/detail 모듈에 명시적 buildTypes 설정 없음
- 라이브러리의 release 빌드 동작 방식이 코드베이스에서 확인 불가
프로덕션 성능 영향 확인 필요: skydoves compose-stability 라이브러리 문서를 검토하여 release 빌드에서 @TraceRecomposition이 자동으로 비활성화되는지 또는 수동 설정이 필요한지 확인하시기 바랍니다.
| import com.ninecraft.booket.core.ui.component.ReedDialog | ||
| import com.ninecraft.booket.feature.screens.SplashScreen | ||
| import com.ninecraft.booket.feature.splash.R | ||
| import com.skydoves.compose.stability.runtime.TraceRecomposition |
There was a problem hiding this comment.
🧩 Analysis chain
LGTM! 리컴포지션 추적 어노테이션 정상 적용됨
@TraceRecomposition 어노테이션과 관련 임포트가 올바르게 추가되었습니다. Splash 화면은 앱의 진입점이므로 리컴포지션 추적 대상으로 적합합니다.
다만, 이 어노테이션이 프로덕션 빌드에서도 활성화되는지 확인하시는 것을 권장합니다. 디버그 빌드에서만 활성화되도록 설정하면 프로덕션 오버헤드를 방지할 수 있습니다.
다음 스크립트로 플러그인 설정을 확인할 수 있습니다:
Also applies to: 32-32
🏁 Script executed:
#!/bin/bash
# Description: Compose Stability Analyzer 플러그인 설정 확인
# Gradle 설정 파일에서 플러그인 적용 및 buildType별 설정 확인
fd -e gradle -e kts | xargs rg -C3 'compose.*stability|TraceRecomposition'Length of output: 473
플러그인 설정을 추가 확인하겠습니다.
스크립트 실행 결과를 기다리는 중입니다...
---
🏁 Script executed:
```shell
#!/bin/bash
# Search for splash module build file and plugin application
# Find the splash module build file
fd -name "build.gradle.kts" | xargs rg -l "feature.*splash|splash" | head -5
# Look for splash module specifically
find . -path "*feature/splash/build*" -name "*.kts" -o -path "*feature/splash/build*" -name "*.gradle" 2>/dev/null | head -10
# Search for plugin application in splash module
fd -e kts | xargs rg -C5 "compose.*stability|TraceRecomposition" 2>/dev/null | head -30
Length of output: 1107
---
🏁 Script executed:
```shell
#!/bin/bash
# Read the splash module's build.gradle.kts to check for plugin application
cat ./feature/splash/build.gradle.kts
# Also search for any buildTypes configurations in the splash module
rg -A10 "buildTypes|release|debug" ./feature/splash/build.gradle.kts
Length of output: 330
---
🏁 Script executed:
```shell
#!/bin/bash
# Find and examine the convention plugin
# Search for booket.android.feature plugin definition
fd -e kt | xargs rg -C10 "booket.android.feature|AndroidFeature" | head -50
# Look for gradle convention plugins directory
find . -path "*/gradle/plugins/*" -o -path "*/gradle/src/*" -type d 2>/dev/null | head -10
# Search for any buildTypes or variantFilter configuration at root level
rg -C5 "buildTypes|variantFilter|debuggable" build.gradle.kts
Length of output: 2079
---
🏁 Script executed:
```shell
#!/bin/bash
# Search for where compose.stability.analyzer is APPLIED (not just declared)
rg "apply.*compose.*stability|compose.*stability.*apply" --type=kt --type=kts
# Search for plugin application in all build files
rg '"compose\.stability\.analyzer"|"compose-stability-analyzer"' --type=kt --type=kts
# Check parent convention plugins
cat build-logic/src/main/kotlin/AndroidLibraryConventionPlugin.kt 2>/dev/null | head -40
# Search for any plugin application in convention plugins
fd "ConventionPlugin.kt" -x cat {} \; 2>/dev/null | grep -A5 "applyPlugins\|id\(" | head -60
Length of output: 928
🏁 Script executed:
#!/bin/bash
# Search for modules that explicitly apply compose.stability.analyzer
fd -e kts -e gradle | xargs grep -l "compose.stability.analyzer" 2>/dev/null | grep -v "build\.gradle\.kts:build"
# More direct search - look for plugin application in any build file
rg "id\(.*compose.*stability" --type kts
# Check if compose.stability.analyzer is applied anywhere
rg "compose\.stability\.analyzer" --type kts -B2 -A2Length of output: 72
🌐 Web query:
com.skydoves.compose.stability @TraceRecomposition annotation behavior without plugin
💡 Result:
Short answer: If you put com.skydoves.compose.stability.@TraceRecomposition on code but don’t run the Compose compiler/plugin that knows how to act on it, the annotation is just metadata — it does nothing to change recomposition behavior or produce trace output. The Compose compiler/plugin (or library tooling that reads those annotations) is what interprets/acts on stability/tracing annotations; without that compile-time/plugin support you get no tracing instrumentation. [1][2][3]
Sources
- skydoves/compose-stable-marker (usage as compileOnly markers for Compose tooling). [1]
- Jetpack Compose stability docs — stability annotations are contracts the compiler/tooling uses. [2]
- Compose release notes / runtime-annotation info — annotations are meaningful to the compiler/tooling (moved to runtime-annotation to allow non-Compose modules to declare them). [3]
compose.stability.analyzer 플러그인 미적용 — @TraceRecomposition 어노테이션이 작동하지 않음
@TraceRecomposition 어노테이션은 compile-time 도구나 플러그인이 이를 처리할 때만 실제 리컴포지션 추적이 작동합니다. 현재 feature/splash 모듈에는 compose.stability.analyzer 플러그인이 적용되지 않아, 어노테이션이 추가되어도 메타데이터로만 남고 실제 추적 기능이 작동하지 않습니다.
다음 중 하나를 수행해야 합니다:
- feature/splash/build.gradle.kts에
alias(libs.plugins.compose.stability.analyzer)플러그인을 추가하거나 - 해당 플러그인 설정이 convention 플러그인(
booket.android.feature)에 포함되도록 build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt을 수정
🤖 Prompt for AI Agents
In feature/splash/src/main/kotlin/com/ninecraft/booket/splash/SplashUi.kt around
line 27, the @TraceRecomposition import is ineffective because the
compose.stability.analyzer Gradle plugin is not applied in the feature/splash
module; add the plugin to feature/splash/build.gradle.kts (e.g.,
alias(libs.plugins.compose.stability.analyzer)) so the annotation is processed
at compile time, or alternatively update
build-logic/src/main/kotlin/AndroidFeatureConventionPlugin.kt to include the
compose.stability.analyzer plugin so all feature modules (including
feature/splash) get the plugin automatically.
There was a problem hiding this comment.
import com.android.build.gradle.LibraryExtension
import com.ninecraft.booket.convention.Plugins
import com.ninecraft.booket.convention.applyPlugins
import com.ninecraft.booket.convention.configureCompose
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
class AndroidLibraryComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
applyPlugins(
Plugins.ANDROID_LIBRARY,
Plugins.KOTLIN_COMPOSE,
Plugins.COMPOSE_STABILITY_ANALYZER,
)
extensions.configure<LibraryExtension> {
configureCompose(this)
}
}
}
}AndroidLibraryComposeConventionPlugin에 적용해뒀고 이를 모든 compose 를 사용하는 library 모듈에 주입하고 있어.
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
|
CI 적용 예시 |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-ci.yml(1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.8)
.github/workflows/android-ci.yml
54-54: job "stability_check" needs job "build" which does not exist in this workflow
(job-needs)
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
.github/workflows/android-ci.yml (1)
62-63: 선택사항: 중복된 keystore.properties 생성 단계 통합
keystore.properties생성 단계가ci-build작업(Line 41-42)과stability_check작업(Line 62-63)에서 중복되고 있습니다. 향후 유지보수성을 위해 이 단계를 재사용 가능한 워크플로우 또는 composite action으로 추출하는 것을 고려하세요.Also applies to: 41-42
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-ci.yml(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android 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)만 별도로 선언하면 된다.
⏰ 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 (3)
.github/workflows/android-ci.yml (3)
54-72: 이전 리뷰 지적 사항 해결 확인이전 리뷰에서 지적한
needs: build문제가 Line 57에서needs: ci-build로 올바르게 수정되었습니다. GitHub Actions 버전도v5.0.0에서v5단축 형태로 개선되었습니다.
66-69: Java 버전 선택 사유 검증 필요
ci-build작업은 Java 17을 사용하지만, 새로운stability_check작업은 Java 21을 사용합니다. Compose Stability Analyzer 플러그인이 Java 21을 반드시 요구하는지, 또는 Java 17로도 정상 작동하는지 확인이 필요합니다. Java 21이 필수가 아니라면 ci-build와 동일한 버전으로 통일하는 것이 버전 관리 일관성을 개선합니다.
56-56: macOS 러너 사용 사유 검증 필요
stability_check작업이macos-latest에서 실행되고 있습니다. macOS 러너는 ubuntu-latest보다 비용이 높으므로, stabilityCheck 태스크가 macOS 환경을 반드시 요구하는지 검증이 필요합니다. 만약 ubuntu-latest에서도 정상 작동한다면 비용 효율을 위해 러너 변경을 고려하세요.Also applies to: 56-56
…ties, Generate google-services.json step 추가
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
.github/workflows/android-ci.yml (2)
62-69: 중복 코드: 시크릿 생성 로직 추상화 권장라인 62-69의 시크릿 생성 단계들이
ci-build작업의 라인 38-45와 정확히 동일합니다. DRY 원칙에 따라 GitHub Actions의reusable workflow또는composite action으로 추상화하는 것을 권장합니다.
55-55: 작업 이름 케이싱 통일 필요라인 55의
name필드는 "Compose Stability Check" (파스칼 케이스)이고, 라인 77의run명령 설명은 "compose stability check" (스네이크 케이스)입니다. 일관성을 위해 둘 다 같은 케이싱으로 통일하기를 권장합니다.- - name: compose stability check + - name: Compose Stability CheckAlso applies to: 77-77
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-ci.yml(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android 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)만 별도로 선언하면 된다.
⏰ 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 (2)
.github/workflows/android-ci.yml (2)
54-78: ✅ 이전 리뷰 피드백 적용됨: 작업 의존성 수정이전 리뷰에서 지적한
needs: build→needs: ci-build변경이 올바르게 적용되었습니다.
60-60: 워크플로우 내 버전 및 환경 일관성 확인 필요
ci-build작업과stability_check작업 간 다음 사항들이 상이합니다:
- Java 버전:
ci-build는 JDK 17 (corretto),stability_check는 JDK 21 (zulu)- Actions 버전:
ci-build는 v4,stability_check는 v5이러한 차이가 의도적인지(예: 안정성 검사용 최신 Java 요구), 아니면 일관성 유지가 필요한지 확인해 주시기 바랍니다. 특히 macOS 환경에서 JDK 21이 필요한 구체적인 이유가 있다면 문서화를 권장합니다.
Also applies to: 72-72, 74-75
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
.github/workflows/android-ci.yml (1)
54-78: stabilityCheck 작업 설정 검증 결과검증을 통해 확인된 사항:
구성 불일치 확인됨: ci-build는
ubuntu-latest+ JDK 17 Corretto +gradle/gradle-build-action@v2를 사용하지만, stability_check는macos-latest+ JDK 21 Zulu + gradle 액션 없음 (검증됨)플랫폼/JDK 버전 요구사항 미발견: Compose Compiler 플러그인은 호환되는 Kotlin/Compose 컴파일러 버전만 필요하며, macOS 또는 특정 JDK 버전이 필수가 아님
gradle-build-action 누락 확인됨: ci-build에만 포함되어 있고 stability_check에는 없음
따라서 검토 의견의 제안이 타당합니다. 다음 사항을 권장합니다:
runs-on: ubuntu-latest로 변경 (비용 효율성, 일관성)- JDK를 17 Corretto로 맞춤
gradle/gradle-build-action@v2추가단, stabilityCheck 작업이 제안된 구성에서 실제로 작동하는지 검증하여 변경하시기 바랍니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
.github/workflows/android-ci.yml(1 hunks)app/build.gradle.kts(1 hunks)build-logic/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt(1 hunks)core/common/stability/common.stability(1 hunks)core/designsystem/stability/designsystem.stability(1 hunks)core/ui/stability/ui.stability(1 hunks)feature/detail/stability/detail.stability(1 hunks)feature/edit/stability/edit.stability(1 hunks)feature/home/stability/home.stability(1 hunks)feature/library/stability/library.stability(1 hunks)feature/login/stability/login.stability(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- feature/library/stability/library.stability
- core/ui/stability/ui.stability
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android 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)만 별도로 선언하면 된다.
📚 Learning: 2025-07-31T23:17:40.054Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Applied to files:
feature/edit/stability/edit.stability
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.
Applied to files:
feature/edit/stability/edit.stabilityfeature/home/stability/home.stabilityfeature/detail/stability/detail.stabilityfeature/login/stability/login.stability
⏰ 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 (4)
core/designsystem/stability/designsystem.stability (1)
7-316: 자동 생성된 안정성 베이스라인 확인 완료
designsystem모듈의 공개 컴포저블 시그니처와 Analyzer 출력이 일치하고, 표기된 STABLE/RUNTIME 분류도 Compose Stability Analyzer 결과와 모순이 없어 보입니다. 추가 조치 없이 그대로 반영하셔도 될 것 같습니다.build-logic/src/main/kotlin/AndroidApplicationComposeConventionPlugin.kt (1)
15-15: LGTM! 플러그인 추가가 올바르게 적용되었습니다.Compose Stability Analyzer 플러그인이 Android Application Compose 설정에 올바르게 추가되었습니다. 이는 PR의 목표와 일치하며 app/build.gradle.kts의 설정과 함께 작동합니다.
app/build.gradle.kts (1)
62-64: LGTM! Compose Stability Analyzer 활성화가 올바르게 설정되었습니다.설정이 올바르게 적용되었으며, convention plugin의 플러그인 추가와 함께 작동하여 앱 모듈에서 안정성 분석을 활성화합니다.
core/common/stability/common.stability (1)
1-33: LGTM! 자동 생성된 안정성 메타데이터입니다.이 파일은 Compose Stability Analyzer에 의해 자동으로 생성된 파일입니다. 파일 헤더에 명시된 대로 직접 편집하지 말고
./gradlew :common:stabilityDump명령어를 통해 업데이트해야 합니다. 생성된 안정성 정보는 올바르게 보이며, 모든 composable이 skippable 및 restartable로 적절하게 표시되어 있습니다.
seoyoon513
left a comment
There was a problem hiding this comment.
믿음의 approve! 덕분에 안정성 검증 과정을 훨씬 수월하게 진행할 수 있을 것 같슴다 👍👍 요런 세심한 작업 해주시는 모습에 많은 걸 배워갑니다🙇
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (1)
55-55: LGTM! 리컴포지션 추적이 올바르게 적용되었습니다.@TraceRecomposition 어노테이션이 HomeUi 엔트리 포인트에 올바르게 적용되었습니다. 이는 PR 목표와 일치하며, 다른 feature 모듈들과 일관된 패턴을 따르고 있습니다.
참고: 추후 성능 모니터링 결과에 따라 프로덕션 빌드에서의 오버헤드가 우려된다면, debug 빌드에서만 조건적으로 적용하는 것을 고려할 수 있습니다. 하지만 현재 구현은 런타임 추적이라는 의도된 목적에 적합합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/EmotionStep.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/ImpressionStep.kt(1 hunks)feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/QuoteStep.kt(1 hunks)feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/component/ToggleItem.kt(1 hunks)feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/notification/NotificationUi.kt(1 hunks)gradle/libs.versions.toml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/component/ToggleItem.kt
- feature/settings/src/main/kotlin/com/ninecraft/booket/feature/settings/notification/NotificationUi.kt
- feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/QuoteStep.kt
- feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/ImpressionStep.kt
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android 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)만 별도로 선언하면 된다.
📚 Learning: 2025-07-31T23:17:40.054Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Applied to files:
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/EmotionStep.kt
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.
Applied to files:
feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt
📚 Learning: 2025-07-14T00:51:38.952Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 46
File: core/network/src/main/kotlin/com/ninecraft/booket/core/network/response/BookSearchResponse.kt:33-44
Timestamp: 2025-07-14T00:51:38.952Z
Learning: The project uses Kotlinx Serialization with JSON configuration that includes `ignoreUnknownKeys = true`, `encodeDefaults = true`, `isLenient = true`, and `prettyPrint = true` to handle API response parsing robustly, making additional null safety measures less critical if the API consistently provides all expected fields.
Applied to files:
gradle/libs.versions.toml
⏰ 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 (6)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/EmotionStep.kt (2)
38-38: 리컴포지션 추적을 위한 import가 올바르게 추가되었습니다.
TraceRecompositionimport가 정확하게 추가되어 아래 어노테이션 사용을 지원합니다.
41-46: 리컴포지션 추적 어노테이션이 적절하게 적용되었습니다.
EmotionStep컴포저블에@TraceRecomposition어노테이션이 올바르게 추가되었습니다. 이 컴포저블은state.emotionTags및state.selectedEmotion과 같은 상태에 의존하므로 리컴포지션 추적의 좋은 후보입니다. 로직 변경 없이 순수 계측 목적으로만 사용되어 적합합니다.feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomeUi.kt (1)
50-50: LGTM!TraceRecomposition 임포트가 올바르게 추가되었습니다.
gradle/libs.versions.toml (3)
30-30: KSP 2.3.0과 Kotlin 2.2.21 호환성 확인 완료웹 검색 결과에 따르면 KSP 2.3.0은 Kotlin 2.2.21과 완전히 호환됩니다. KSP 2.3.0 릴리스 노트에서 KSP가 이제 Kotlin 버전과 독립적으로 작동하며, KSP 팀도 "KSP 2.3.0이 Kotlin 2.2.* 이상에서 작동해야 한다"고 명확히 했습니다. 따라서 버전 조합에는 호환성 문제가 없습니다.
30-30: KSP 2.3.0과 Kotlin 2.2.21은 현재 기준 정확한 최신 안정 버전입니다.KSP 2.3.0은 이전 버전 KSP 2.2.20-2.0.4보다 최신이며, KSP 2.3.0부터는 Kotlin 컴파일러 버전과의 연계가 제거되어 Kotlin 2.2.21과의 호환성 문제가 없습니다. Kotlin 2.2.21은 2.2 시리즈의 최신 패치 버전입니다. 별도의 더 최신 패치 버전은 현재 존재하지 않습니다.
27-27: Compose Stability Analyzer 플러그인 적용 확인 완료플러그인은 정상적으로 구성 및 적용되었습니다. 검증 결과:
libs.versions.tomlLine 27에서 버전(0.3.0) 정의, Line 177에서 플러그인 alias 정의 완료Plugins.kt에 상수로 정의:COMPOSE_STABILITY_ANALYZER = "com.github.skydoves.compose.stability.analyzer"AndroidLibraryComposeConventionPlugin.kt와AndroidApplicationComposeConventionPlugin.kt에서applyPlugins()를 통해 자동 적용- 해당 convention plugin을 사용하는 모듈(app, core/common, core/designsystem, core/ui, feature/screens 등)에서 플러그인 자동 적용됨
- Root
build.gradle.kts에서apply false로 선언 - 모듈별 조건부 적용을 위한 올바른 설정프로젝트의 convention plugin 시스템이 이 플러그인을 포함하여 공통 의존성을 효과적으로 관리하고 있습니다.
.stability 파일은 ./gradlew stabilityDump 명령어로 생성할 수 있다.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
feature/splash/stability/splash.stability (1)
1-34: 자동 생성된 안정성 메타데이터가 올바르게 생성되었습니다.모든 Composable 함수가 skippable 및 restartable로 표시되고 모든 파라미터가 STABLE로 분석되어 최적의 재구성 성능을 보장합니다. Compose Stability Analyzer 플러그인의 의도대로 CI 검증 및 문서화를 위해 이 파일을 커밋하는 것이 적절합니다.
선택 사항으로,
.gitattributes에*.stability linguist-generated=true를 추가하여 자동 생성 파일임을 명시적으로 표시할 수 있습니다.app/stability/app.stability (1)
7-13:Decoration함수가 skippable하지 않아 성능에 영향을 줄 수 있습니다.
Decoration함수가skippable: false로 표시되어 있으며,targetState파라미터가 런타임 체크가 필요한 것으로 분류되었습니다. 이는 입력이 변경되지 않았더라도 이 Composable이 recomposition을 건너뛸 수 없음을 의미합니다.
CrossFadeNavDecorator는 네비게이션 전환 시 호출되므로, 이러한 비효율성이 사용자 경험에 영향을 줄 수 있습니다.DefaultAnimatedState<T>의 안정성을 개선하거나@Stable/@Immutable어노테이션 적용을 고려해보세요.다음 스크립트로
CrossFadeNavDecorator의 실제 구현을 확인하여 안정성 개선 방법을 검토하세요:#!/bin/bash # Description: Find and examine the CrossFadeNavDecorator implementation # Locate the CrossFadeNavDecorator class ast-grep --pattern 'class CrossFadeNavDecorator' # Find the Decoration composable function rg -nP -A 10 'fun.*Decoration\s*\(' --type kotlin # Check if DefaultAnimatedState is marked as Stable rg -nP '@(Stable|Immutable).*class.*DefaultAnimatedState' --type kotlin
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
app/stability/app.stability(1 hunks)feature/onboarding/stability/onboarding.stability(1 hunks)feature/record/stability/record.stability(1 hunks)feature/screens/stability/screens.stability(1 hunks)feature/search/stability/search.stability(1 hunks)feature/settings/stability/settings.stability(1 hunks)feature/splash/stability/splash.stability(1 hunks)feature/webview/stability/webview.stability(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android 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)만 별도로 선언하면 된다.
📚 Learning: 2025-07-29T07:02:18.885Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android 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 상수를 공유할 수 있습니다.
Applied to files:
feature/onboarding/stability/onboarding.stability
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.
Applied to files:
feature/onboarding/stability/onboarding.stabilityfeature/search/stability/search.stability
⏰ 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 (8)
feature/webview/stability/webview.stability (1)
1-35: 자동 생성된 안정성 메타데이터 파일이 올바르게 추가되었습니다.이 파일은 Compose Stability Analyzer 플러그인에 의해 자동 생성된 메타데이터 파일로, 모든 Composable 함수들이
skippable: true,restartable: true로 표시되어 있고 모든 파라미터가STABLE로 분석되어 최적의 리컴포지션 동작을 보여주고 있습니다. PR 코멘트에서 언급된 CI 통합을 위해 이러한 안정성 파일들을 버전 관리에 포함하는 것은 적절한 접근입니다.feature/screens/stability/screens.stability (1)
1-30: 자동 생성된 안정성 분석 결과가 정상적으로 추가되었습니다.모든 Composable이
skippable: true,restartable: true로 표시되었고, 파라미터들이 모두 STABLE로 분류되어 리컴포지션 최적화가 잘 적용될 것으로 보입니다. 이 파일을 커밋하여 안정성 변경 사항을 추적하고 CI에서 검증하는 것은 좋은 접근입니다.feature/record/stability/record.stability (1)
1-213: 자동 생성된 안정성 분석 결과가 우수합니다.모든 Composable 함수가
skippable: true와restartable: true로 분석되었고, 모든 파라미터가 STABLE로 표시되어 있습니다. 이는 Compose의 스마트 리컴포지션이 최적으로 작동할 수 있는 이상적인 상태입니다.자동 생성 파일을 버전 관리에 포함하는 것은 다음과 같은 장점이 있습니다:
- PR 리뷰 시 안정성 변화를 쉽게 추적 가능
- CI에서 안정성 검증 가능 (PR 설명에 언급된 향후 작업과 일치)
참고로
.stability파일들을.gitignore에 추가하고 CI에서 생성하는 방식도 고려할 수 있지만, 현재 접근 방식도 타당합니다.feature/onboarding/stability/onboarding.stability (2)
1-6: 자동 생성 파일 커밋 확인.이 파일은 Compose Stability Analyzer 플러그인에 의해 자동 생성됩니다. PR 코멘트에서 CI 통합 예시를 공유하신 것으로 보아, 향후 CI에서 stability 변경 사항을 추적하기 위해 의도적으로 커밋하신 것으로 보입니다. 이는 좋은 접근 방식입니다.
7-58: 모든 Composable이 최적의 안정성 특성을 보여줍니다.분석 결과가 매우 우수합니다:
- 모든 Composable이
skippable: true,restartable: true로 표시되어 스마트 리컴포지션이 가능합니다.- 모든 파라미터가
STABLE로 표시되어 불필요한 리컴포지션이 발생하지 않습니다.OnboardingUiState가 STABLE로 인식된 것은 불변 데이터 모델링이 올바르게 구현되었음을 의미합니다.이는 Compose 성능 최적화 관점에서 이상적인 상태입니다.
feature/search/stability/search.stability (1)
1-198: 자동 생성된 파일의 버전 관리 전략을 확인하세요.이 파일은 Compose Stability Analyzer 플러그인에 의해 자동 생성된 안정성 덤프 파일입니다. 모든 Composable의 파라미터가 STABLE로 분석되어 재구성 성능 측면에서는 매우 좋은 상태입니다.
다만, 일반적으로 자동 생성 파일은 버전 관리에서 제외하는 것이 일반적이지만, PR 코멘트에서 언급하신 CI 통합 사례를 고려하면 의도적으로 커밋하시는 것으로 보입니다.
다음 사항을 확인해주세요:
- 이 파일들을 CI에서 안정성 검증에 사용할 계획인가요? (예: PR에서 안정성 퇴행 검사)
- 그렇지 않다면
.gitignore에**/*.stability패턴을 추가하는 것을 고려해보세요.참고로, 제공하신 CI 통합 예시를 보면 stability 파일들을 커밋하여 변경사항을 추적하고 있습니다. 동일한 전략을 사용하신다면 현재 접근 방식이 적절합니다.
feature/settings/stability/settings.stability (1)
1-168: 설정 모듈의 안정성 메타데이터가 올바르게 생성되었습니다.설정, 알림, OSS 라이선스 관련 20개의 Composable 함수에 대한 안정성 분석이 완료되었으며, 모두 최적의 재구성 특성(skippable, restartable, STABLE 파라미터)을 가지고 있습니다. 이는 런타임 재구성 추적을 위한 견고한 기반을 제공합니다.
app/stability/app.stability (1)
1-21: 프로젝트의.stability파일 커밋 정책이 이미 확립되어 있습니다.현재 프로젝트 전체에서 16개의
.stability파일이 버전 관리되고 있으며, 이들은.gitignore에 포함되어 있지 않습니다.app/stability/app.stability는 다른 모든 모듈(core/, feature/)의 안정성 파일과 동일한 패턴을 따르고 있으므로, 별도의 버전 관리 조정이 필요하지 않습니다.파일 헤더의 주석(
./gradlew :app:stabilityDump)에서 확인할 수 있듯이, 이는 의도적으로 생성되고 커밋되는 빌드 산출물입니다. 이 파일이 CI 기반 안정성 검증에 활용될 수 있으므로, 현재 접근 방식은 적절합니다.
병렬 실행, OS 통일, JDK 버전 통일, 설정 일관
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
.github/workflows/android-ci.yml (1)
54-59:stability_check작업에needs: ci-build의존성 추가 필수현재 코드에서
stability_check작업에needs: ci-build절이 누락되어 있습니다. 이전 리뷰에서 지적했던 문제가 여전히 해결되지 않았습니다. 의존성이 없으면 두 작업이 병렬로 실행되어, 빌드가 실패해도 안정성 검사는 진행될 수 있습니다.라인 55(현재
runs-on:)에 다음을 추가하세요:stability_check: name: Compose Stability Check + needs: ci-build runs-on: ubuntu-latest
🧹 Nitpick comments (1)
.github/workflows/android-ci.yml (1)
60-85: 선택사항: 반복되는 설정 단계를 합성 액션으로 리팩토링 고려
ci-build와stability_check작업 간에 checkout, JDK 설정, Android SDK 설정, Gradle 설정, 프로퍼티 파일 생성 단계가 동일하게 반복됩니다. 이를 재사용 가능한 composite action으로 추상화하면 유지보수성을 개선할 수 있습니다.# .github/actions/setup-gradle-environment/action.yml 예시 name: Setup Gradle Environment runs: using: composite steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: distribution: 'corretto' java-version: 21 # ... 나머지 단계그러나 현재 워크플로우도 명확하고 유지보수 가능하므로, 이는 향후 최적화 과제로 미뤄도 무방합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/android-ci.yml(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android 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)만 별도로 선언하면 된다.
⏰ 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). (2)
- GitHub Check: Compose Stability Check
- GitHub Check: ci-build
🔇 Additional comments (1)
.github/workflows/android-ci.yml (1)
64-68: JDK 21 버전 업그레이드 적절함
ci-build와stability_check모두 JDK 21로 일관성 있게 설정되어 있습니다. Compose Stability Analyzer 플러그인과 최신 Kotlin/KSP 버전을 지원하기에 충분합니다.
|
@seoyoon513 compose stability check job이 생각보다 오래 걸려 CI 진행 시간이 20분이 넘는 문제가 발생하여, 이를 로컬에서만 실행하고 CI에선 제거하려다가, 기존 job과 병렬로 실행할 수 있는 방법을 발견하여 적용 후 CI 시간을 8분 정도로 줄일 수 있었습니다~ |
|
@easyhooon 동시에 같이 잘 돌고 있네요 |

🔗 관련 이슈
📙 작업 설명
🧪 테스트 내역 (선택)
📸 스크린샷 또는 시연 영상 (선택)
💬 추가 설명 or 리뷰 포인트 (선택)
Summary by CodeRabbit
새로운 기능
업데이트
기타