Skip to content

Conversation

@easyhooon
Copy link
Contributor

@easyhooon easyhooon commented Jan 3, 2026

🔗 관련 이슈

📙 작업 설명

  • 추가된 색상 변수 추가
  • 독서 기록 상세 화면 UI 반영 사항 반영
  • 다크 모드 프리뷰 제거(다크 모드 현재 지원 X, 프리뷰 볼때 걸리적 거림)
  • 독서 기록 상세 화면 상황별 프리뷰 추가
  • record 모듈 stability check stable 로 개선(map -> persistentMap)
  • detail 모듈 stability check stable 로 개선(ReadingRecordModel @Stable ->@Immutable)

🧪 테스트 내역 (선택)

  • 주요 기능 정상 동작 확인
  • 브라우저/기기에서 동작 확인
  • 엣지 케이스 테스트 완료
  • 기존 기능 영향 없음

📸 스크린샷 또는 시연 영상 (선택)

image

💬 추가 설명 or 리뷰 포인트 (선택)

  • 최다 감정 선출에 있어 기획 결정에 따라 서버 API 변경이 필요할 것으로 보여 API 변경 사항 반영시 추가 PR 올려서 대응하도록 하겠습니다
  • 삭제된 코드가 많은데 보니까 stability-compose-analyzer가 버전 업데이트됨에 따라 preview composable의 stability가 dump되는 것을 제외시켰다는군요 참고바랍니다.
    https://github.com/skydoves/compose-stability-analyzer/releases/tag/0.5.2

Summary by CodeRabbit

  • New Features
    • "기타(ETC)" 감정 카테고리 추가
    • 책 상세에서 통계 토글(확장/축소) 기능 및 관련 UI(비율 차트·통계 카드) 추가
  • Design System
    • 오렌지·바이올렛 컬러 팔레트 및 ETC 색상 토큰 추가
    • 버튼 컴포넌트 API 개선(일관된 스타일명 도입)
  • Bug Fixes
    • 감정 이미지 렌더링 널 안전성 개선
    • 데이터 모델 불변성 강화(@immutable 적용)
  • API Updates
    • 독서 기록 조회 엔드포인트 v2로 전환

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 3, 2026

Walkthrough

ETC 감정 유형과 대응 색상/이미지/문구가 추가되고 디자인 시스템 API(버튼/칩/테마 접근자)가 리팩토링되었습니다. BookDetail에 isStatsExpanded 토글이 도입되고 CollectedSeeds와 RecordItem UI가 확장/수정되었으며, 레코드 등록 상태 타입이 PersistentMap으로 교체되었습니다. 그 외 프리뷰 삭제와 안정성/의존성 메타데이터 업데이트가 포함됩니다.

Changes

응집군 / 파일(s) 변경 요약
색상 팔레트 추가
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt
Orange50–Orange900, Violet50–Violet900, EtcTextColor, EtcBgColor 새 색상 토큰 추가
감정(Emotion) 리소스 확장
core/model/src/main/kotlin/com/ninecraft/booket/core/model/SeedModel.kt,
core/designsystem/src/main/kotlin/.../Emotion.kt,
core/designsystem/src/main/res/values/strings.xml
Emotion.ETC("기타") 추가; Emotion 매핑에 ETC 색상/이미지/description(emotion_etc_description) 포함
디자인 시스템 API 리팩토링(버튼/칩/테마)
core/designsystem/stability/designsystem.stability
ReedButton/ReedTextButton 시그니처 재정의 및 스타일 접근자(get-* → 메서드), ReedTheme 접근자명 변경 등 공용 API 표면 재구성(네이밍·파라미터 변경, 안정성 어노테이션 추가)
프리뷰(다크/개별) 제거
core/designsystem/src/main/kotlin/.../ComponentPreview.kt,
core/designsystem/src/main/kotlin/.../DevicePreview.kt,
core/ui/stability/ui.stability,
feature/*/stability/*.stability
다크 프리뷰 블록 및 다수의 private @Preview 함수 제거(안정성 덤프에서 프리뷰 항목 축소)
Book Detail 상태·이벤트 확장
feature/detail/src/main/kotlin/.../BookDetailPresenter.kt,
feature/detail/src/main/kotlin/.../BookDetailUiState.kt
isStatsExpanded: Boolean 필드 추가 및 OnStatsToggleClick 이벤트 도입, Presenter에서 상태 보존 및 반영
CollectedSeeds UI 확장
feature/detail/src/main/kotlin/.../CollectedSeeds.kt
접힘/펼침(AnimatedVisibility) 도입, 헤더·비율바·EmotionStatCard 추가, isStatsExpanded·onToggleClick 파라미터 수용 및 감정 분석 통합
RecordItem 및 BookDetail UI 변경
feature/detail/src/main/kotlin/.../RecordItem.kt,
feature/detail/src/main/kotlin/.../BookDetailUi.kt
onRecordClick 콜백 추가(클릭 처리 노출), 감정 이미지 제거→텍스트/페이지/날짜로 대체, ETC 이미지 매핑 추가, 프리뷰 갱신
SeedItem 감정 매핑 추가
feature/detail/src/main/kotlin/.../SeedItem.kt
Emotion.ETC 케이스에 R.drawable.img_etc 매핑 추가
레코드 등록 상태 컬렉션 변경
feature/record/src/main/kotlin/.../RecordRegisterPresenter.kt,
feature/record/src/main/kotlin/.../RecordRegisterUiState.kt
selectedEmotionDetails/committedEmotionDetails: Map<Emotion,ImmutableList<String>>PersistentMap<Emotion,ImmutableList<String>> 및 초기화 persistentMapOf()로 변경; 관련 업데이트 로직 교체
Emotion 이미지 안전성 강화
feature/record/src/main/kotlin/.../EmotionItem.kt
emotion.graphicResV2 null 체크 추가, 조건부 Image 렌더링으로 NPE 방지
안정성 어노테이션 변경
core/model/src/main/kotlin/.../ReadingRecordsModel.kt
@Stable@Immutable로 어노테이션 변경
네트워크 엔드포인트 버전 업그레이드
core/network/src/main/kotlin/.../ReedService.kt
GET api/v1/reading-records/detail/{...}api/v2/reading-records/detail/{...} 로 변경(경로 주석/어노테이션만 변경)
빌드/도구 버전 업데이트
gradle/libs.versions.toml
compose-stability-analyzer 버전 0.5.20.6.6 업그레이드

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45분

Possibly related PRs

Suggested reviewers

  • seoyoon513

Poem

🐰 ETC가 훌쩍 와서 팔레트를 물들이네,
주황빛·보라빛 한숨에 반짝이고,
버튼과 칩은 이름을 고치고,
통계는 접혔다 펴졌다 춤을 추며,
리뷰어여, 당근 한 개는 준비됐나? ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 '독서 기록 상세 화면 UI 반영 사항 반영'으로 독서 기록 상세 화면 UI 업데이트라는 주요 변경사항을 명확하게 설명합니다.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a650da and 5014318.

📒 Files selected for processing (2)
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
  • feature/detail/stability/detail.stability
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
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" }`로 적용될 예정이다.
📚 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/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
📚 Learning: 2025-07-28T18:08:47.298Z
Learnt from: seoyoon513
Repo: YAPP-Github/Reed-Android PR: 72
File: feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/CameraFrame.kt:21-82
Timestamp: 2025-07-28T18:08:47.298Z
Learning: Jetpack Compose에서 scale() 변환은 시각적 변환만 적용하며 레이아웃 좌표계는 변경하지 않는다. 따라서 scale(scaleX = -1f, scaleY = -1f)로 반전된 아이콘에서 padding()은 원래 레이아웃 기준으로 동작하므로, 시각적으로 올바른 위치를 위해서는 변환 전 좌표계 기준으로 padding을 설정해야 한다.

Applied to files:

  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.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/detail/stability/detail.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). (2)
  • GitHub Check: Compose Stability Check
  • GitHub Check: ci-build
🔇 Additional comments (6)
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt (5)

35-43: onRecordClick 콜백 추가가 잘 구현되었습니다.

새로운 onRecordClick 파라미터가 추가되고 clickable 모디파이어와 올바르게 연결되어 있습니다. 이를 통해 레코드 아이템 전체가 클릭 가능해졌습니다.


57-62: 페이지 번호 표시 로직이 개선되었습니다.

페이지 번호가 0일 때 "-p"를 표시하고 Italic 스타일을 적용한 것은 UX 관점에서 적절한 처리입니다.


95-97: 날짜 포맷팅이 적절하게 적용되었습니다.

toFormattedDate() 확장 함수를 사용하여 날짜를 표시하는 것은 일관된 날짜 형식을 유지하는 좋은 방법입니다.


109-109: "기타" 감정 타입 지원이 추가되었습니다.

새로운 감정 타입 "기타"에 대한 이미지 리소스 매핑이 적절하게 추가되었습니다.


121-126: 프리뷰에 immutable 컬렉션 사용이 적절합니다.

persistentListOf를 사용하여 프리뷰 데이터를 구성한 것은 안정성 측면에서 좋은 선택이며, 새로운 콜백 파라미터들도 올바르게 전달되고 있습니다.

feature/detail/stability/detail.stability (1)

8-15: 자동 생성된 안정성 메타데이터가 올바릅니다.

RecordItem의 업데이트된 시그니처가 안정성 파일에 정확하게 반영되었습니다. 새로 추가된 onRecordClick 파라미터가 STABLE로 올바르게 표시되어 있으며, 모든 파라미터의 안정성 마킹이 적절합니다.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot requested a review from seoyoon513 January 3, 2026 14:51
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/SeedItem.kt (1)

67-75: img_etc drawable 리소스 존재 확인 및 승인

Emotion.ETC 케이스가 적절하게 추가되어 when 표현식이 완전해졌으며, img_etc.webp drawable 리소스도 존재합니다. 변경 사항은 정상입니다.

다만, 유사한 패턴을 사용하는 RecordItem.ktgetEmotionImageResourceByDisplayName() 함수도 함께 업데이트하여 일관성을 맞춰주세요:

  • 현재: "기타" -> R.drawable.img_warm // TODO: ETC 이미지 리소스 추가 필요
  • 변경 필요: "기타" -> R.drawable.img_etc
🧹 Nitpick comments (5)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt (1)

238-248: 일관성을 위한 선택적 개선 제안

Line 240에서 selectedEmotionDetails[selectedEmotion]을 사용하고 있는데, emotionKey를 사용하면 일관성이 높아집니다.

🔎 제안된 변경사항
 is RecordRegisterUiEvent.OnEmotionDetailToggled -> {
     val emotionKey = selectedEmotion ?: return
-    val currentDetails = selectedEmotionDetails[selectedEmotion].orEmpty()
+    val currentDetails = selectedEmotionDetails[emotionKey].orEmpty()
     val updatedDetails = if (event.detail in currentDetails) {
         currentDetails - event.detail
     } else {
         currentDetails + event.detail
     }

     selectedEmotionDetails = selectedEmotionDetails.put(emotionKey, updatedDetails.toPersistentList())
 }
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt (1)

76-85: null 체크 후 !! 사용 대신 let 또는 스마트 캐스트 사용을 권장합니다.

null 체크 후 !!를 사용하는 것보다 let을 사용하면 더 안전하고 관용적인 Kotlin 코드가 됩니다. 또한 이미지가 없을 때 Spacer가 항상 렌더링되어 불필요한 여백이 생길 수 있습니다.

🔎 제안된 수정
-            if (emotion.graphicResV2 != null) {
-                Image(
-                    painter = painterResource(emotion.graphicResV2!!),
-                    contentDescription = "Emotion Image",
-                    modifier = Modifier
-                        .size(60.dp)
-                        .clip(CircleShape),
-                )
-            }
-            Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing4))
+            emotion.graphicResV2?.let { graphicRes ->
+                Image(
+                    painter = painterResource(graphicRes),
+                    contentDescription = "Emotion Image",
+                    modifier = Modifier
+                        .size(60.dp)
+                        .clip(CircleShape),
+                )
+                Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing4))
+            }
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt (1)

101-102: 기존 Neutral 색상을 재사용하는 것을 고려해보세요.

EtcTextColorEtcBgColor는 각각 Neutral500, Neutral100과 동일한 색상 값을 하드코딩하고 있습니다. 기존 색상 상수를 참조하면 유지보수성이 향상됩니다.

🔎 제안하는 리팩토링
 // Emotion Color
 val WarmthTextColor = Color(0xFFE3931B)
 val WarmthBgColor = Color(0xFFFFF5D3)
 val JoyTextColor = Color(0xFFEE6B33)
 val JoyBgColor = Color(0xFFFFEBE3)
 val InsightTextColor = Color(0xFF9A55E4)
 val InsightBgColor = Color(0xFFF3E8FF)
 val SadnessTextColor = Color(0xFF2872E9)
 val SadnessBgColor = Color(0xFFE1ECFF)
-val EtcTextColor = Color(0xFF737373)
-val EtcBgColor = Color(0xFFF5F5F5)
+val EtcTextColor = Neutral500
+val EtcBgColor = Neutral100
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt (1)

109-109: TODO 주석을 추적하여 완료하세요.

"기타" 감정에 대한 적절한 이미지 리소스가 아직 추가되지 않았습니다. 이 작업이 추적되고 있는지 확인하세요.

이 TODO 항목을 추적하기 위한 별도 이슈를 생성하시겠습니까?

feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt (1)

139-148: topEmotion이 null일 때 UX 개선 필요

topEmotion이 null인 경우 "''" (빈 따옴표)가 표시됩니다. 감정 통계가 없는 경우 더 나은 대체 메시지를 표시하거나 해당 섹션을 숨기는 것을 고려하세요.

🔎 개선 제안
-            Row {
-                Text(
-                    text = "'${topEmotion?.name?.displayName ?: ""}'",
-                    color = Yellow700,
-                    style = ReedTheme.typography.label1SemiBold,
-                )
-                Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing1))
-                Text(
-                    text = "감정을 많이 느꼈어요",
-                    color = ReedTheme.colors.contentSecondary,
-                    style = ReedTheme.typography.label1Medium,
-                )
-            }
+            if (topEmotion != null) {
+                Row {
+                    Text(
+                        text = "'${topEmotion.name.displayName}'",
+                        color = Yellow700,
+                        style = ReedTheme.typography.label1SemiBold,
+                    )
+                    Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing1))
+                    Text(
+                        text = "감정을 많이 느꼈어요",
+                        color = ReedTheme.colors.contentSecondary,
+                        style = ReedTheme.typography.label1Medium,
+                    )
+                }
+            } else {
+                Text(
+                    text = "아직 수집된 감정이 없어요",
+                    color = ReedTheme.colors.contentSecondary,
+                    style = ReedTheme.typography.label1Medium,
+                )
+            }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21c99a4 and 7a650da.

📒 Files selected for processing (39)
  • app/stability/app.stability
  • core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/ComponentPreview.kt
  • core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/DevicePreview.kt
  • core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/Emotion.kt
  • core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt
  • core/designsystem/src/main/res/values/strings.xml
  • core/designsystem/stability/designsystem.stability
  • core/model/src/main/kotlin/com/ninecraft/booket/core/model/ReadingRecordsModel.kt
  • core/model/src/main/kotlin/com/ninecraft/booket/core/model/SeedModel.kt
  • core/network/src/main/kotlin/com/ninecraft/booket/core/network/service/ReedService.kt
  • core/ui/stability/ui.stability
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailPresenter.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUiState.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/SeedItem.kt
  • feature/detail/src/main/res/drawable/img_etc.webp
  • feature/detail/src/main/res/drawable/img_insight.webp
  • feature/detail/src/main/res/drawable/img_joy.webp
  • feature/detail/src/main/res/drawable/img_sad.webp
  • feature/detail/src/main/res/drawable/img_warm.webp
  • feature/detail/stability/detail.stability
  • feature/edit/stability/edit.stability
  • feature/home/stability/home.stability
  • feature/library/stability/library.stability
  • feature/login/stability/login.stability
  • feature/onboarding/stability/onboarding.stability
  • feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
  • feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.kt
  • feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt
  • feature/record/stability/record.stability
  • feature/screens/stability/screens.stability
  • feature/search/stability/search.stability
  • feature/settings/stability/settings.stability
  • feature/splash/stability/splash.stability
  • feature/webview/stability/webview.stability
  • gradle/libs.versions.toml
💤 Files with no reviewable changes (13)
  • feature/screens/stability/screens.stability
  • core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/DevicePreview.kt
  • feature/splash/stability/splash.stability
  • core/ui/stability/ui.stability
  • feature/webview/stability/webview.stability
  • feature/login/stability/login.stability
  • core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/ComponentPreview.kt
  • feature/settings/stability/settings.stability
  • feature/onboarding/stability/onboarding.stability
  • feature/home/stability/home.stability
  • feature/library/stability/library.stability
  • feature/edit/stability/edit.stability
  • feature/search/stability/search.stability
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
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" }`로 적용될 예정이다.
📚 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:

  • core/model/src/main/kotlin/com/ninecraft/booket/core/model/SeedModel.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/SeedItem.kt
  • core/designsystem/src/main/res/values/strings.xml
  • feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step_v2/EmotionItem.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.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/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailPresenter.kt
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUiState.kt
  • feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
  • core/model/src/main/kotlin/com/ninecraft/booket/core/model/ReadingRecordsModel.kt
  • feature/detail/stability/detail.stability
  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt
📚 Learning: 2025-07-28T18:08:47.298Z
Learnt from: seoyoon513
Repo: YAPP-Github/Reed-Android PR: 72
File: feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/CameraFrame.kt:21-82
Timestamp: 2025-07-28T18:08:47.298Z
Learning: Jetpack Compose에서 scale() 변환은 시각적 변환만 적용하며 레이아웃 좌표계는 변경하지 않는다. 따라서 scale(scaleX = -1f, scaleY = -1f)로 반전된 아이콘에서 padding()은 원래 레이아웃 기준으로 동작하므로, 시각적으로 올바른 위치를 위해서는 변환 전 좌표계 기준으로 padding을 설정해야 한다.

Applied to files:

  • feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
🧬 Code graph analysis (2)
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt (2)
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt (1)
  • CollectedSeeds (44-106)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
  • ReedTheme (14-21)
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt (2)
core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/EmotionAnalyzer.kt (1)
  • analyzeEmotions (17-34)
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt (1)
  • getEmotionImageResourceByDisplayName (103-112)
⏰ 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: ci-build
  • GitHub Check: Compose Stability Check
🔇 Additional comments (33)
feature/record/stability/record.stability (1)

1-77: LGTM! Stability 개선이 올바르게 반영되었습니다.

MapPersistentMap 변경으로 인해 모든 RecordRegisterUiState 파라미터가 STABLE로 인식되고, 모든 Composable이 skippable: true가 되었습니다. 이는 불필요한 recomposition을 방지하여 성능 향상에 기여합니다.

참고: 이 파일은 ./gradlew :record:stabilityDump 명령으로 자동 생성되므로, 직접 수정하지 않도록 주의해 주세요.

feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterUiState.kt (1)

25-27: LGTM! Compose 안정성 향상을 위한 PersistentMap 적용

Map에서 PersistentMap으로 변경하여 Compose의 안정성 추론이 개선됩니다. PersistentMap은 구조적 공유와 불변성을 보장하므로 불필요한 리컴포지션을 방지하는 데 도움이 됩니다.

feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt (3)

100-102: LGTM! PersistentMap을 사용한 상태 선언

PersistentMap을 사용하여 Compose 안정성이 개선됩니다. rememberRetained와 함께 사용하여 구성 변경 시에도 상태가 유지됩니다.


267-275: LGTM! 감정 세부사항 커밋 로직

OnEmotionDetailCommitted 핸들러가 현재 선택된 감정의 세부사항만 유지하도록 새로운 persistentMapOf를 생성합니다. 단일 감정 선택 플로우에 맞는 올바른 설계입니다.


336-344: 감정 세부사항 API 연동 확인

현재 emotionTags에는 감정 이름만 전송되고 세부 감정 태그(committedEmotionDetails)는 포함되지 않습니다. PR 설명에 따르면 API 변경이 후속 PR에서 처리될 예정이므로, 해당 시점에 세부 감정 데이터도 함께 전송되도록 업데이트가 필요합니다.

Based on learnings, 이 프로젝트는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고 API 연동 시점에 데이터를 교체하는 개발 방식을 사용합니다.

core/model/src/main/kotlin/com/ninecraft/booket/core/model/ReadingRecordsModel.kt (2)

3-3: 올바른 import 변경입니다.

@Immutable 어노테이션 변경에 맞춰 import가 올바르게 업데이트되었습니다.


13-27: @Immutable 어노테이션 변경이 적절합니다.

불변 데이터 클래스에 @Immutable 어노테이션을 적용하여 Compose의 재구성 최적화를 개선한 좋은 변경입니다. 모든 프로퍼티가 val로 선언되어 있고, emotionTags 등의 List 프로퍼티는 코드베이스 전체에서 변경되지 않습니다. 모든 조작이 .copy() 등의 불변 패턴으로 처리되고 있어 @Immutable 계약을 충분히 만족합니다.

향후 리팩토링 시, kotlinx.collections.immutable의 ImmutableList를 사용하면 컴파일 타임에 불변성을 강제할 수 있습니다:

선택사항: 더 강력한 불변성 보장
import kotlinx.collections.immutable.ImmutableList

@Immutable
data class ReadingRecordModel(
    // ...
    val emotionTags: ImmutableList<String> = persistentListOf(),
    // ...
)
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.kt (1)

44-48: LGTM!

총 개수 텍스트 색상을 contentTertiary로 변경한 것은 UI 요구사항에 맞는 적절한 수정입니다.

core/designsystem/src/main/res/values/strings.xml (1)

11-11: LGTM!

ETC 감정에 대한 설명 문자열 리소스가 기존 네이밍 컨벤션(emotion_*_description)을 따르고 있으며, 적절한 설명 텍스트입니다.

core/model/src/main/kotlin/com/ninecraft/booket/core/model/SeedModel.kt (1)

16-30: LGTM!

ETC("기타") enum 상수가 적절하게 추가되었습니다. fromDisplayName 함수는 entries.find를 사용하므로 새로운 ETC 값도 자동으로 처리됩니다.

core/designsystem/stability/designsystem.stability (1)

1-270: LGTM!

Compose Stability Analyzer에 의해 자동 생성된 파일입니다. 모든 컴포저블 함수가 skippable: true로 표시되어 있어 리컴포지션 성능이 최적화되어 있습니다.

core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/Emotion.kt (3)

39-46: graphicRes에서 ETC가 placeholder 이미지를 사용 중입니다.

Emotion.ETCR.drawable.img_emotion_warmth를 재사용하고 있습니다. 의도적인 placeholder인지, 아니면 별도의 ETC 이미지가 필요한지 확인해 주세요.

PR 설명에서 API 변경이 후속 PR에서 처리될 예정이라고 언급되어 있으므로, 이것도 추후 반영될 수 있습니다. 기존 learnings에 따르면 API 준비 전 UI를 먼저 구현하는 방식을 사용하고 있습니다.


48-55: LGTM!

새로운 ratioBarColor 속성이 각 감정 타입에 맞는 색상을 깔끔하게 매핑하고 있습니다.


57-64: LGTM!

graphicResV2가 nullable(Int?)로 선언되어 ETC 감정에 대해 null을 반환하는 것은 적절합니다. EmotionItem.kt에서 이 값에 대한 null 체크가 올바르게 처리되고 있습니다.

core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt (2)

66-75: Orange 팔레트가 올바르게 추가되었습니다.

Orange 색상 팔레트가 기존 색상 정의 패턴(50-900 스케일)을 일관되게 따르고 있으며, 구문 오류가 없습니다.


77-86: Violet 팔레트가 올바르게 추가되었습니다.

Violet 색상 팔레트가 기존 색상 정의 패턴을 일관되게 따르고 있으며, 구문 오류가 없습니다.

core/network/src/main/kotlin/com/ninecraft/booket/core/network/service/ReedService.kt (1)

130-133: v2 엔드포인트 배포 상태와 응답 형식 검증 필요

코드 구현 수준에서는 다음이 확인되었습니다:

  • RecordDetailResponse 매퍼가 완전하게 구현되어 있음 (12개 필드 모두 매핑)
  • 에러 처리가 runSuspendCatching으로 적절히 처리됨
  • 모든 호출 지점에서 응답을 올바르게 처리함

다음 항목의 외부 검증이 필요합니다:

  1. 백엔드 v2 엔드포인트 배포 상태: 프로덕션 환경에 /api/v2/reading-records/detail/{readingRecordId} 엔드포인트가 배포되어 있는지 확인
  2. v1과 v2의 응답 형식 차이: API 문서를 통해 v2 응답이 RecordDetailResponse의 필드 구조(id, userBookId, pageNumber, quote, review, emotionTags, createdAt, updatedAt, bookTitle, bookPublisher, bookCoverImageUrl, author)와 일치하는지 확인
  3. 부분 마이ग레이션 계획: 다른 모든 엔드포인트는 여전히 v1을 사용하고 있으므로, 이 단계적 마이그레이션이 의도된 것인지 확인
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt (3)

286-292: LGTM! 통계 확장 기능이 잘 통합되었습니다.

CollectedSeeds 컴포넌트에 isStatsExpandedonToggleClick 파라미터가 적절히 전달되어 통계 확장/축소 기능이 올바르게 구현되었습니다.


341-343: LGTM! 레코드 아이템 클릭 처리가 명확해졌습니다.

RecordItemonRecordClick 콜백을 추가하여 클릭 이벤트 처리가 더 명시적이고 추적하기 쉬워졌습니다.


377-500: LGTM! 포괄적인 프리뷰로 다양한 UI 상태를 확인할 수 있습니다.

Empty, SeedStats, SeedsStatsExpanded 세 가지 시나리오에 대한 프리뷰를 제공하여 UI 개발과 검증이 용이합니다. 샘플 데이터도 현실적이고 적절합니다.

feature/detail/stability/detail.stability (1)

32-39: LGTM! RecordItem 시그니처 업데이트가 안정성 설정에 올바르게 반영되었습니다.

onRecordClick 파라미터 추가가 stability 설정에 정확하게 반영되었으며, 모든 파라미터가 STABLE로 올바르게 표시되어 있습니다.

feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUiState.kt (2)

30-30: LGTM! 통계 확장 상태 필드가 적절히 추가되었습니다.

isStatsExpanded 필드가 기본값 false로 올바르게 초기화되어 있으며, 통계 섹션의 확장/축소 상태를 추적하는 명확한 목적을 가지고 있습니다.


88-88: LGTM! 통계 토글 이벤트가 명확하게 정의되었습니다.

OnStatsToggleClick 이벤트가 flag 파라미터를 통해 명시적으로 상태를 전달하여 의도가 분명합니다.

feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailPresenter.kt (3)

82-82: LGTM! 상태가 올바르게 보존됩니다.

rememberRetained를 사용하여 isStatsExpanded 상태가 재구성 간에도 보존되므로 사용자가 화면을 벗어났다가 돌아와도 확장 상태가 유지됩니다.


403-405: LGTM! 이벤트 처리가 간단하고 명확합니다.

토글 이벤트 처리가 직접적이며 부작용이 없어 예측 가능한 동작을 보장합니다.


418-418: LGTM! 상태가 UI에 올바르게 전달됩니다.

isStatsExpandedBookDetailUiState에 포함되어 UI 레이어에서 올바르게 사용될 수 있습니다.

feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt (2)

35-43: LGTM! 명시적인 클릭 콜백으로 이벤트 처리가 개선되었습니다.

onRecordClick 파라미터를 추가하고 clickable modifier를 통해 연결하여 레코드 아이템 클릭 이벤트를 명확하게 처리할 수 있게 되었습니다.


57-62: LGTM! 페이지 번호 표시가 간결해졌습니다.

페이지 번호 표시 방식이 명확하며, italic 스타일이 적용되어 시각적으로 구별됩니다.

feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt (4)

44-106: 상태 관리와 애니메이션 구현이 적절합니다.

remember를 통한 분석 결과 메모이제이션과 AnimatedVisibility를 사용한 확장/축소 애니메이션이 잘 구현되었습니다. Emotion.entries를 순회하며 누락된 감정에 대해 count 0인 기본값을 생성하는 로직도 올바릅니다.


163-190: 비율 막대 구현이 올바릅니다.

coerceAtLeast(1)을 통한 0으로 나누기 방지와 count가 0보다 큰 감정만 렌더링하는 최적화가 잘 구현되었습니다.


192-228: LGTM!

감정 통계 카드 구현이 명확하고 올바릅니다.


230-282: 프리뷰 구현이 적절합니다.

축소/확장 상태와 최다 감정 중복 시나리오를 포함하여 다양한 UI 상태를 잘 커버하고 있습니다.

app/stability/app.stability (1)

1-13: 자동 생성된 파일의 예상된 변경사항입니다.

이 파일은 Compose Stability Analyzer에 의해 자동 생성되며, targetState 매개변수의 안정성 분류가 업데이트된 버전의 분석기에 의해 더 정확하게 감지되었습니다. 이는 gradle/libs.versions.toml의 도구 업그레이드에 따른 자연스러운 결과입니다.

Comment on lines +125 to +135
topEmotion?.let { emotion ->
Image(
painter = painterResource(id = getEmotionImageResourceByDisplayName(emotion.name.displayName)),
contentDescription = "Seed Image",
modifier = Modifier
.size(36.dp)
.clip(CircleShape)
.background(ReedTheme.colors.basePrimary),
)
Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing2))
}
Copy link

@coderabbitai coderabbitai bot Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for getEmotionImageResourceByDisplayName function
rg "getEmotionImageResourceByDisplayName" -A 10

Repository: YAPP-Github/Reed-Android

Length of output: 6085


🏁 Script executed:

#!/bin/bash
# Look for ETC image resource files
fd -type f \( -name "*etc*" -o -name "*ETC*" \) core/designsystem/src/main/res/drawable*/

Repository: YAPP-Github/Reed-Android

Length of output: 238


🏁 Script executed:

#!/bin/bash
# Search for TODO comments related to ETC or image resource
rg "TODO.*[Ee][Tt][Cc]|TODO.*image.*resource" -A 2 -B 2

Repository: YAPP-Github/Reed-Android

Length of output: 50382


🏁 Script executed:

#!/bin/bash
# Check if EmotionUtils or similar utility already exists
fd -type f -path "*/utils/*" -name "*motion*" -o -path "*/utils/*" -name "*Emotion*"

Repository: YAPP-Github/Reed-Android

Length of output: 238


🏁 Script executed:

#!/bin/bash
# Check imports at top of CollectedSeeds.kt
head -50 feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt | grep -i "import.*[Ee]motion"

Repository: YAPP-Github/Reed-Android

Length of output: 228


🏁 Script executed:

#!/bin/bash
# Check full function definitions in CollectedSeeds.kt to see if it defines its own version
grep -n "fun getEmotionImageResourceByDisplayName" feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt

Repository: YAPP-Github/Reed-Android

Length of output: 50


🏁 Script executed:

#!/bin/bash
# Search for all function definitions in CollectedSeeds.kt
grep -n "^fun " feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt | head -20

Repository: YAPP-Github/Reed-Android

Length of output: 50


🏁 Script executed:

#!/bin/bash
# Get all imports from CollectedSeeds.kt
grep "^import" feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt

Repository: YAPP-Github/Reed-Android

Length of output: 2039


🏁 Script executed:

#!/bin/bash
# Check file size and get full content or key sections
wc -l feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt

Repository: YAPP-Github/Reed-Android

Length of output: 171


🏁 Script executed:

#!/bin/bash
# Check around line 127 where getEmotionImageResourceByDisplayName is used
sed -n '110,145p' feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt

Repository: YAPP-Github/Reed-Android

Length of output: 1422


🏁 Script executed:

#!/bin/bash
# Search for getEmotionImageResourceByDisplayName definition anywhere in the file
grep -B5 -A5 "getEmotionImageResourceByDisplayName" feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt

Repository: YAPP-Github/Reed-Android

Length of output: 574


🏁 Script executed:

#!/bin/bash
# Search for img_etc resource in drawable directories
find core/designsystem/src/main/res -type f \( -name "*etc*" -o -name "*img_etc*" \)

Repository: YAPP-Github/Reed-Android

Length of output: 50


🏁 Script executed:

#!/bin/bash
# Check what drawable resources exist
ls -la core/designsystem/src/main/res/drawable*/img_* 2>/dev/null | head -20

Repository: YAPP-Github/Reed-Android

Length of output: 983


🏁 Script executed:

#!/bin/bash
# Get all drawable files to see full list
ls -1 core/designsystem/src/main/res/drawable/*.webp 2>/dev/null | grep -i "img_" | sort

Repository: YAPP-Github/Reed-Android

Length of output: 575


🏁 Script executed:

#!/bin/bash
# Check if the function is actually in same package without needing import
grep -n "package" feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
grep -n "package" feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt

Repository: YAPP-Github/Reed-Android

Length of output: 189


ETC 감정 이미지 리소스 추가 필요

RecordItem.ktgetEmotionImageResourceByDisplayName 함수에서 "기타" 감정에 대해 R.drawable.img_warm으로 임시 처리하고 있으며, TODO 주석으로 ETC 이미지 리소스 추가가 필요함이 표시되어 있습니다. 실제 img_etc 리소스 파일이 아직 추가되지 않았으므로 이를 먼저 추가한 후 함수를 수정해야 합니다.

🤖 Prompt for AI Agents
In
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt
around lines 125 to 135, the code relies on getEmotionImageResourceByDisplayName
which currently falls back to R.drawable.img_warm for the "기타" (ETC) emotion
while a proper img_etc resource hasn't been added; add a new drawable resource
file named img_etc (or appropriate asset) to res/drawable, then update
getEmotionImageResourceByDisplayName in RecordItem.kt to return
R.drawable.img_etc for the "기타"/ETC case (remove the TODO/fallback), and rebuild
to ensure the new resource is recognized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the commit details to see what was changed
git show 5014318f --stat --oneline

Length of output: 225


🏁 Script executed:

#!/bin/bash
# Check if img_etc resource has been added
fd -type f "img_etc" core/designsystem/src/main/res/

Length of output: 170


🏁 Script executed:

#!/bin/bash
# Verify the updated getEmotionImageResourceByDisplayName function
rg -A 15 "fun getEmotionImageResourceByDisplayName" feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt

Length of output: 428


🏁 Script executed:

#!/bin/bash
# Fix the command to search for img_etc resource files
fd "img_etc" core/designsystem/src/main/res/

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Also list all img_ drawables to confirm img_etc is among them
ls -1 core/designsystem/src/main/res/drawable*/ | grep "img_etc"

Length of output: 0


🏁 Script executed:

#!/bin/bash
# List all emotion-related drawable files to see what exists
ls -la core/designsystem/src/main/res/drawable/*.webp 2>/dev/null | grep "img_"

Length of output: 915


🏁 Script executed:

#!/bin/bash
# Search for any file containing "etc" in drawable directories
find core/designsystem/src/main/res/drawable* -name "*etc*" -o -name "*ETC*" 2>/dev/null

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check if the code will compile by looking for R.drawable references
rg "R\.drawable\.img_etc" feature/detail/

Length of output: 266


@easyhooon, 코드 업데이트는 잘 되었습니다! 👍 getEmotionImageResourceByDisplayName 함수에서 "기타"가 이제 R.drawable.img_etc를 올바르게 참조하고 있습니다.

하지만 한 가지 문제가 있습니다: 실제 img_etc.webp drawable 리소스 파일이 아직 추가되지 않았습니다.

현재 상황:

  • ✅ RecordItem.kt: "기타" -> R.drawable.img_etc (업데이트 완료)
  • ✅ SeedItem.kt: Emotion.ETC -> R.drawable.img_etc (이미 참조 중)
  • core/designsystem/src/main/res/drawable/img_etc.webp (파일 없음)

다른 감정 이미지들은 존재합니다:

  • img_emotion_warmth.webp
  • img_emotion_joy.webp
  • img_emotion_sadness.webp
  • img_emotion_insight.webp

다음 작업이 필요합니다:
core/designsystem/src/main/res/drawable/ 디렉토리에 img_etc.webp 파일을 추가해주세요. 그렇지 않으면 R.drawable.img_etc가 생성되지 않아 컴파일 에러가 발생합니다.


🧬 Code Graph Analysis Results

[feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt] (no direct snippet, see below)

[relevant_snippets]

  1. File: core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/EmotionAnalyzer.kt
    Lines: 17-34
    Content:
fun analyzeEmotions(emotions: List<EmotionModel>): EmotionAnalysisResult {
    val maxCount = emotions.maxOf { it.count }

    // 모든 감정의 count가 0인 경우
    if (maxCount == 0) {
        return EmotionAnalysisResult(emptyList(), EmotionDisplayType.NONE)
    }

    val topEmotions = emotions.filter { it.count == maxCount }

    val displayType = when (topEmotions.size) {
        1 -> EmotionDisplayType.SINGLE
        2 -> EmotionDisplayType.DUAL
        else -> EmotionDisplayType.BALANCED
    }

    return EmotionAnalysisResult(topEmotions, displayType)
}
  1. File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
    Lines: 103-112
    Content:
fun getEmotionImageResourceByDisplayName(displayName: String): Int {
    return when (displayName) {
        "따뜻함" -> R.drawable.img_warm
        "즐거움" -> R.drawable.img_joy
        "슬픔" -> R.drawable.img_sad
        "깨달음" -> R.drawable.img_insight
        "기타" -> R.drawable.img_etc
        else -> R.drawable.img_warm
    }
}

🧠 Learnings used
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" }`로 적용될 예정이다.

) {
Text(
text = recordInfo.createdAt.toFormattedDate(),
text = "#${recordInfo.emotionTags[0]}",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find and read RecordItem.kt to see the full context around line 89
find . -name "RecordItem.kt" -type f

Repository: YAPP-Github/Reed-Android

Length of output: 165


🏁 Script executed:

# Search for ReadingRecordModel to understand emotionTags definition
rg -n "class ReadingRecordModel" --type=kotlin -A 20

Repository: YAPP-Github/Reed-Android

Length of output: 1684


🏁 Script executed:

# Check for emotionTags initialization patterns
rg -n "emotionTags" --type=kotlin -B 2 -A 2

Repository: YAPP-Github/Reed-Android

Length of output: 30532


🏁 Script executed:

# Check if there are any guards or null checks for emotionTags
rg -n "emotionTags\[0\]|emotionTags\.first|emotionTags\.get" --type=kotlin -B 3 -A 3

Repository: YAPP-Github/Reed-Android

Length of output: 5941


emotionTags 배열 접근 시 안전성을 확인하세요.

emotionTags[0]에 직접 접근하면 emotionTags가 비어있을 때 IndexOutOfBoundsException이 발생할 수 있습니다. ReadingRecordModel의 기본값이 emptyList()이므로 이 문제는 실제 발생 가능합니다. 같은 프로젝트의 다른 부분(RecordDetailUi.kt, RecordEditPresenter.kt)에서는 이미 getOrNull() 또는 firstOrNull()로 안전하게 처리하고 있습니다.

🔎 안전한 접근을 위한 수정 제안
             Text(
-                text = "#${recordInfo.emotionTags[0]}",
+                text = recordInfo.emotionTags.firstOrNull()?.let { "#$it" } ?: "",
                 color = ReedTheme.colors.contentTertiary,
                 style = ReedTheme.typography.label1Medium,
             )
📝 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.

Suggested change
text = "#${recordInfo.emotionTags[0]}",
Text(
text = recordInfo.emotionTags.firstOrNull()?.let { "#$it" } ?: "",
color = ReedTheme.colors.contentTertiary,
style = ReedTheme.typography.label1Medium,
)
🤖 Prompt for AI Agents
In
feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
around line 89, the code accesses emotionTags[0] directly which can throw
IndexOutOfBoundsException when emotionTags is empty; change the access to a safe
variant such as emotionTags.firstOrNull() or emotionTags.getOrNull(0) and
provide a sensible fallback (e.g., empty string or skip rendering the tag) so
the UI handles empty lists without crashing.

compose-effects = "0.1.4"
compose-shadow = "2.0.4"
compose-stability-analyzer = "0.5.2"
compose-stability-analyzer = "0.6.6"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat gradle/libs.versions.toml | grep -A 2 -B 2 "compose-stability-analyzer"

Repository: YAPP-Github/Reed-Android

Length of output: 458


🌐 Web query:

compose-stability-analyzer gradle plugin latest version release

💡 Result:

The latest published Gradle plugin version is 0.6.0 (published to Maven Central on Nov 24, 2025). [1][2]

Notes:

  • GitHub releases/tags currently show 0.5.3 as the latest release (Nov 18, 2025). [2]

Sources:

  • Maven Central / mvnrepository entry for compose-stability-gradle 0.6.0. [1]
  • GitHub releases for skydoves/compose-stability-analyzer (latest tag 0.5.3). [2]

Compose Stability Analyzer 버전이 존재하지 않습니다.

지정된 버전 0.6.6은 Maven Central이나 GitHub의 공식 저장소에서 찾을 수 없습니다. 현재 사용 가능한 최신 버전은 Maven Central에서 0.6.0(2025년 11월 24일 배포)이고, GitHub에서는 0.5.3(2025년 11월 18일)입니다. 이 버전을 사용하면 빌드가 실패할 수 있으므로, 최신 버전(0.6.0)으로 수정해야 합니다.

🤖 Prompt for AI Agents
In gradle/libs.versions.toml around line 27, the compose-stability-analyzer
version is set to "0.6.6" which does not exist in Maven Central or GitHub;
update the version string to the confirmed latest available version "0.6.0" to
prevent build failures by replacing 0.6.6 with 0.6.0.

compose stability check success
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants