Feature/#144 curation#156
Conversation
- **큐레이션 UI 구조 리팩터링**
- `CurationDetailScreen` 및 상단 카드 컴포넌트(`HighlightCard`) 삭제 (디자인 변경 및 구조 통합 대응)
- `CurationScreen` 및 `CurationKeywordDetailScreen`에서 닉네임 정보를 최상단(MainApp)으로부터 주입받도록 수정
- `MainApp` 라이프사이클에 맞춰 홈/큐레이션 탭 전환 시 닉네임을 갱신하도록 `fetchNickname` 호출 로직 추가
- **데이터 계층 정리 (`data`, `core`)**
- `CurationRepository` 및 `CurationApi` 내 사용하지 않는 레거시 인터페이스와 DTO 매핑 로직 일괄 삭제
- `CurationRepositoryImpl` 및 `CurationRepositoryModule`에서 불필요한 의존성(`Moshi`, `ServerApi`, `AuthPreference`) 제거 및 구현체 슬림화
- **ViewModel 로직 간소화**
- `CurationViewModel` 내 검색 로직(최근 검색어, 빠른 검색) 및 큐레이션 생성/좋아요 상태 관리 로직 삭제 (사용자 인터페이스 변경에 따른 정리)
- `CurationDetailViewModel` 내 추천 링크 및 상세 정보 로드 로직 임시 제거
- **내비게이션 구조 조정**
- `curationGraph` 정의 시 `nickname` 파라미터를 추가하여 전역 상태를 하위 스크린으로 전파하도록 개선
- 사용하지 않는 상세 화면 경로(`curation_detail`) 제거 및 `CurationMonthDetailScreen` 연결 구조 유지
- **`CurationBackground` 컴포넌트 구현**
- `RadialGradientCircle`을 활용한 배경 그라데이션 효과 및 디자인 요소 배치
- `showLogo` 파라미터를 통한 큐레이션 로고 노출 여부 제어 로직 추가
- **`CurationHeader` 컴포넌트 구현**
- 사용자 닉네임을 포함한 맞춤형 타이틀 문구(`"${nickname}님을 위한 링큐레이션"`) 노출
- `curationGradient`를 적용한 텍스트 스타일링 및 상단 타이틀 이미지 배치
- **디자인 시스템 통합 및 프리뷰 추가**
- `scaler` 유틸리티를 통한 컴포넌트 크기 및 오프셋 최적화
- 개발 편의를 위한 각 컴포넌트별 `LinkuPreview` 환경 구축
- **ThemeColorScheme 구조 확장**
- `curationGradient` 속성을 추가하여 큐레이션 화면에서 사용할 디자인 시스템 컬러 정의
- `0xFF1451D5`에서 `0xFF000208`로 이어지는 수평 그라데이션(`Brush.horizontalGradient`) 적용
…Screen`) 스켈레톤 추가
- 큐레이션 카드 타입별 상세 화면 구분을 위한 신규 스크린 컴포넌트 추가
- `CurationCard1Screen` 및 `CurationCard3Screen` 기본 구조 정의
- 시스템 백 버튼 핸들링을 위한 `BackHandler` 적용
- 이후 상세 로직 구현을 위한 TODO 주석 추가
- **사용하지 않는 상세 화면 컴포넌트 제거**
- 애니메이션 오버레이 로직이 포함된 `CurationMonthDetailOverlay.kt` 삭제
- 큐레이션 상세 정보를 표시하던 `CurationMonthDetailScreen.kt` 삭제 (디자인 변경 및 구조 개편에 따른 정리)
- **UI 로직 정리**
- `BackHandler`, `animateFloatAsState` 등을 이용한 커스텀 확장/축소 애니메이션 및 상태 관리 코드 제거
- 상세 화면 내 이미지 로딩 및 콘텐츠 렌더링 관련 프레젠테이션 로직 제거
- `TOPBAR_SIMPLE_HEIGHT` 값을 기존 `77.4f`에서 `80f`로 변경하여 상단 바 높이 조정 - `TopBar` 컴포넌트 상단에 리팩터링 관련 검토 의견 주석 추가
- **SocialProfileMapper 필드 매핑 수정**
- `SocialProfileRequestDTO` 생성 시 `gender` 필드에 전달하는 값을 기존 `value`에서 `name`으로 변경하여 서버 API 명세와의 일관성 확보
- **테마 시스템 통합**
- `MaterialTheme.linkuColors`를 사용하여 하드코딩된 색상값(`0xFFEFF4FF`, `0xFF43454B` 등)을 시맨틱 컬러(`curationCalendarBoxColor`, `gray[800]`, `white`, `black`)로 대체
- 프리뷰 구조를 `LinkuPreview` 공통 컴포넌트 사용 방식으로 변경 및 불필요한 배경 설정 제거
- **CalendarIconBox 개선**
- `LocalDate` 사용에 필요했던 `@RequiresApi(Build.VERSION_CODES.O)` 어노테이션 삭제
- `Text` 컴포넌트 내 불필요한 `TextStyle` 래핑을 제거하고 파라미터 직접 주입 방식으로 간소화
- 폰트 관련 주석 추가 및 가독성 개선
- **CalendarBox 개선**
- `Paperlogy.font` 정의를 제거하고 기본 테마 폰트 설정을 따르도록 수정
- 텍스트 색상 및 배경색을 테마 정의에 맞춰 동기화
- **감정 분석 시각화 컴포넌트 구현**
- `CurationEmotionBar`: 감정 비율(progress)과 순위(rank)에 따라 너비와 색상이 가변적으로 변하는 프로그레스 바 구현
- `CurationEmotionChip`: 감정 키워드를 표시하는 테두리 스타일의 칩 컴포넌트 구현
- `CurationEmotionSection`: 상위 3개 감정 항목을 리스트 형태로 표시하는 섹션 UI 구현
- **디자인 시스템 및 데이터 바인딩**
- `rank`에 따라 1~3순위별 색상(blue 300/200/100) 자동 적용 로직 포함
- `Calendar`를 이용하여 현재 날짜 기준 직전 달의 "상황/감정 요약" 타이틀 노출
- `EmotionItem` 데이터 모델 정의를 통해 백엔드 연동 구조 마련
- **CurationMainCardPager 리팩터링 및 애니메이션 최적화**
- 카드 크기 전환 로직을 `animateDpAsState`에서 `graphicsLayer` 기반의 `animateFloatAsState` 스케일 방식으로 변경 (레이아웃 크기 고정 및 렌더링 최적화)
- 페이지 전환 애니메이션에 `spring` 스펙을 적용하여 자연스러운 움직임 구현
- 불필요한 `isDetailOpen` 파라미터 및 `snap` 애니메이션 로직 제거
- **테마 시스템 및 디자인 시스템 연동**
- 하드코딩된 색상값(`Color(0xFF...)`)을 `MaterialTheme.linkuColors` 기반의 테마 색상으로 전면 교체
- 인디케이터, 카드 배경, 텍스트 오버레이 그라데이션 등에 공통 컬러 에셋 적용
- `Paperlogy` 폰트 명시적 지정을 제거하고 시스템 기본 폰트 및 `FontWeight` 설정으로 간소화
- **카드 콘텐츠 및 로직 개선**
- `CurationCardItem` 내 카드별 고정 콘텐츠 관리 로직 최적화 (`Calendar` API 사용) 및 `padStart`를 이용한 인디케이터 텍스트 포맷팅 개선
- `imageUrl`의 Null/Blank 체크 로직을 강화하여 Fallback 이미지 노출 안정성 확보
- `CurationHeader`의 기본 닉네임 설정 및 불필요한 상단 패딩 제거
- **코드 품질 및 유지보수성 향상**
- 각 컴포넌트(`CurationMainCardPager`, `CurationCardItem` 등)에 KDoc 주석 추가
- 사용하지 않는 임포트 정리 및 프리뷰(`LinkuPreview`) 코드 보완
- 파라미터 순서 조정 및 기본값 설정을 통한 컴포넌트 사용성 개선
- **내비게이션 및 화면 전환 로직 수정**
- 레거시 상세 화면 경로(`curation_month_detail`) 및 관련 파라미터(`curationId`, `imageUrl` 등) 처리 로직 삭제
- 신규 상세 화면인 `CurationCard1Screen` 및 `CurationCard3Screen`을 위한 경로 추가
- `CurationScreen`에서 각 카드 클릭 시 상세 화면으로 이동하도록 콜백(`onCard1Click`, `onCard3Click`) 주입 및 하단바 숨김 처리 적용
- **의존성 및 설정 최적화**
- `hiltViewModel` 임포트 패키지를 최신 기준인 `androidx.hilt.navigation.compose`로 변경
- 미사용 `ExperimentalSharedTransitionApi` 옵트인 어노테이션 제거
- **기타 변경사항**
- `CurationRecommendedLinksSection`에 향후 공통 컴포넌트 병합 및 교체 예정임을 알리는 TODO 주석 추가
- **디자인 시스템 및 테마 확장**
- `ThemeColorScheme`에 큐레이션 도메인 전용 컬러 및 그라데이션 속성 추가 (`curationCalendarBoxColor`, `curationCardOverlayGradient`, `emotionTitleGradient` 등)
- `RadialGradientCircle` 컴포넌트의 기본 색상을 테마 컬러(`accentColor`)와 연동하고 내부 알파 채널 처리 로직 고도화
- **큐레이션 UI 구조 리팩터링 (`CurationScreen`)**
- 배경 로직을 `CurationBackground` 컴포넌트로 분리하고 상단 헤더 영역을 `CurationHeader`로 모듈화하여 가독성 개선
- `SharedTransitionLayout` 및 사용하지 않는 상세 페이지 오버레이(`CurationMonthDetailOverlay`) 로직 제거 (UI 단순화)
- `Scaffold`를 제거하고 `Box`와 `Column` 기반의 레이아웃으로 변경하여 배경 요소 제어 최적화
- **컴포넌트 및 내비게이션 로직 정리**
- `CurationMainCardPager` 클릭 이벤트를 명확한 콜백(`onCard1Click`, `onCard3Click`)으로 분리하여 외부 주입 구조로 변경
- 하드코딩된 스타일(FontSize, FontWeight, Color)을 테마 시스템 및 `MaterialTheme` 참조 방식으로 전환
- 미사용 임포트 및 주석 처리된 레거시 코드 일괄 삭제
- **기타 변경사항**
- 프리뷰(Preview) 환경에 `LinkuPreview` 적용 및 불필요한 레이아웃 중첩 제거
- 뷰모델 주입 방식 최적화 (`hilt-navigation-compose` 활용)
- **CalendarIconBox 컴포넌트 최적화**
- 박스 크기 단위를 `dp`에서 `scaler`로 변경하여 해상도 대응 강화
- 연도(Year) 텍스트의 `lineHeight` 추가 및 불필요한 가로 패딩 제거
- 연도와 월 사이의 `Spacer`를 제거하고 월(Month) 텍스트의 좌우 패딩을 조정하여 컴포넌트 내 요소 배치 수정
- **CurationCardItem 레이아웃 수정**
- 카드 내 콘텐츠 영역의 상단 여백 조정 (262 -> 248 scaler)을 통한 시각적 위치 최적화 (피그마 가이드 대비 임의 조정)
|
Warning Review limit reached
Next review available in: 46 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
Walkthrough큐레이션 도메인의 리포지토리/API/뷰모델 계층에서 상세·추천 관련 로직이 제거되고 Changes큐레이션 리팩터링 및 신규 UI
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant MainApp
participant CurationViewModel as viewModel
participant curationGraph
participant CurationScreen
MainApp->>MainApp: LaunchedEffect(currentRoute)
MainApp->>viewModel: fetchNickname()
viewModel-->>MainApp: nickname 상태 갱신
MainApp->>curationGraph: nickname 전달
curationGraph->>CurationScreen: nickname, onCard1Click, onCard3Click
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 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.
Code Review
This pull request refactors the curation feature by cleaning up unused repository and API code, updating the navigation graph to pass the user's nickname, and introducing several new UI components such as CurationBackground, CurationHeader, and an emotion analysis section. The review feedback is highly constructive, pointing out informal or conversational comments left in the code and recommending the use of null instead of empty strings as default values for nullable parameters to improve null safety.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| modifier: Modifier = Modifier, | ||
| imageUrl: String? = "", | ||
| @DrawableRes fallbackImage: Int = R.drawable.img_curation_example, //이건 프리뷰 확인 용이라 나중에 지워주세요:) |
There was a problem hiding this comment.
임시 확인용 주석을 제거하고, imageUrl의 기본값을 빈 문자열("") 대신 null로 설정하여 널 안전성을 명확히 하는 것이 좋습니다.
| modifier: Modifier = Modifier, | |
| imageUrl: String? = "", | |
| @DrawableRes fallbackImage: Int = R.drawable.img_curation_example, //이건 프리뷰 확인 용이라 나중에 지워주세요:) | |
| modifier: Modifier = Modifier, | |
| imageUrl: String? = null, | |
| @DrawableRes fallbackImage: Int = R.drawable.img_curation_example, |
| animationSpec = spring( // 스프링이 쫀득한 대신, 시간 조절이 안됩니다. 디자이너, pm이 원해도 애니메이션 시간 지정 불가함.... | ||
| dampingRatio = Spring.DampingRatioMediumBouncy, | ||
| stiffness = Spring.StiffnessMedium | ||
| ), |
There was a problem hiding this comment.
주석의 설명은 기술적 제약을 공유하는 데 유용하지만, "쫀득한 대신", "불가함...."과 같은 비공식적인 톤 대신 더 정제되고 전문적인 문구로 작성하는 것이 좋습니다.
| animationSpec = spring( // 스프링이 쫀득한 대신, 시간 조절이 안됩니다. 디자이너, pm이 원해도 애니메이션 시간 지정 불가함.... | |
| dampingRatio = Spring.DampingRatioMediumBouncy, | |
| stiffness = Spring.StiffnessMedium | |
| ), | |
| animationSpec = spring( // Spring 애니메이션 특성상 지속 시간(duration)을 직접 지정할 수 없음을 참고 바랍니다. | |
| dampingRatio = Spring.DampingRatioMediumBouncy, | |
| stiffness = Spring.StiffnessMedium | |
| ), |
ugmin1030
left a comment
There was a problem hiding this comment.
❤️❤️❤️채윤지님❤️❤️❤️
정말❕ 고생🤮 많으🤯셨어요
| fun CurationEmotionBar( | ||
| modifier: Modifier = Modifier, | ||
| progress: Float = 0.75f, | ||
| rank: Int = 0, //0,1,2 (혹시 마음에 안 들면 1번부터 하게 편하게 수정해주세요~!) |
There was a problem hiding this comment.
rank 따로 자료형 파는 게 낫지 않을까? rank 별로 다른 코드를 사용한다면 관리도 확장될 때도 그게 편할 거야.
There was a problem hiding this comment.
api 연동하는 사람이 하는게 더 좋지 않을까? 그래서 그냥 저렇게 놓았는데 @codebidoof 전 princehw에게 맞추겠습니다. 원하는 걸 말해봐
| fun CurationCardItem( | ||
| imageUrl: String?, | ||
| modifier: Modifier = Modifier, | ||
| imageUrl: String? = "", // null로 놓으면 지민이가 코멘트를 남기겠지... |
There was a problem hiding this comment.
❤️윤지님❤️ null😒은 왜🤔 허용😵하셨나요❔❔
| imageUrl: String?, | ||
| modifier: Modifier = Modifier | ||
| modifier: Modifier = Modifier, | ||
| imageUrl: String? = "", |
| modifier: Modifier = Modifier, | ||
| onCardClick: (index: Int, imageUrl: String?) -> Unit = { _, _ -> } // 추가 | ||
| pagerState: PagerState, | ||
| imageUrls: List<String?> = listOf("", "", ""), |
|
|
||
| //TODO : 다음 PR에서 구현할거예요.... | ||
| @Composable | ||
| fun CurationCard1Screen( |
There was a problem hiding this comment.
ㅋㅋ이름 1 3 말고 더 명확한 지칭 없나여?
There was a problem hiding this comment.
"지민님" TODO 주석 읽어봐주세요:)
나중에 구현한다 적혀 있습니당
설마 제가 저 밤티 이름을 채택할리가요
- **UI 컴포넌트 속성 정의 개선**
- `CurationMainCardPager`의 `imageUrls` 파라미터에서 불필요한 기본 빈 리스트(`listOf("", "", "")`) 설정 제거
- `CurationHeader`의 `nickname` 파라미터에서 하드코딩된 기본값("세나") 제거
- 컴포넌트 호출 시 외부로부터 명시적인 데이터 주입을 강제하도록 구조 변경 및 코드 정리(trailing comma 추가 등)
- **`imageUrl` 파라미터 타입 및 제약 변경**
- `CurationCardItem` 및 `CurationMainCard`의 `imageUrl` 타입을 `String?`에서 `String`으로 변경하여 Null 허용성 제거
- 불필요한 기본값(empty string)을 삭제하고 호출부에서 명시적으로 주입하도록 개선
- **로직 및 문서 최적화**
- `CurationMainCard` 내 배경 이미지 렌더링 조건을 `isNullOrBlank()`에서 `isBlank()`로 간소화
- KDoc(문서 주석)에서 null 처리와 관련된 설명 제거 및 프리뷰 코드 업데이트
- 코드 내 사적인 주석(작업 관련 메모) 삭제 등 코드 정리 조치 적용
- **데이터 타입 변경 및 널 안전성 강화**
- `imageUrls` 및 `onCardClick` 콜백의 이미지 URL 타입을 `String?`에서 `String`으로 변경하여 타입 안정성 확보
- **Fallback 처리 기준 수정**
- 기존 `null` 체크 기반의 fallback 로직을 빈 문자열(blank) 또는 `"null"` 문자열이 전달되는 경우로 변경하도록 주석 및 인터페이스 수정
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
feature/curation/src/main/java/com/linku/curation/ui/screen/CurationKeywordDetailScreen.kt (1)
37-49: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win시스템 뒤로가기를
onBack에 연결해 주세요.CurationScreen에서 이 화면을 오버레이로 띄우는데, 현재BackHandler가 없어 시스템 back이 상세 닫기가 아니라 상위 네비게이션으로 빠질 수 있습니다.onBack을 뒤로가기에도 연결해야 합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@feature/curation/src/main/java/com/linku/curation/ui/screen/CurationKeywordDetailScreen.kt` around lines 37 - 49, The CurationKeywordDetailScreen composable currently forwards onBack only to the content and does not handle the system back action, so add a BackHandler in CurationKeywordDetailScreen that invokes onBack when the user presses back. Keep the fix localized to CurationKeywordDetailScreen and ensure CurationKeywordDetailContent still receives the same onBack callback for UI-driven back actions.feature/curation/src/main/java/com/linku/curation/ui/main_card/CurationMainCard.kt (1)
49-63: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
"null"문자열은 아직 fallback으로 처리되지 않습니다.같은 PR의
CurationCardItem은"null"을 무효 URL로 걸러내는데, 여기만isNullOrBlank()만 검사합니다. 백엔드가 동일한 값을 보내면 이 카드만 깨진 이미지 로드를 시도하게 됩니다.수정 예시
+ val resolvedImageUrl = + imageUrl?.takeIf { it.isNotBlank() && !it.equals("null", ignoreCase = true) } + Box( modifier = modifier .size( width = 346.scaler, height = 432.scaler ) .clip(RoundedCornerShape(24.scaler)) .background(colorTheme.curationCardBackground) ) { - if (imageUrl.isNullOrBlank()) { + if (resolvedImageUrl == null) { Image( painter = painterResource(id = fallbackImage), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.matchParentSize() ) } else { // 실제 백엔드에서 받아온 이미지 SubcomposeAsyncImage( - model = imageUrl, + model = resolvedImageUrl, contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.matchParentSize() ) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@feature/curation/src/main/java/com/linku/curation/ui/main_card/CurationMainCard.kt` around lines 49 - 63, The image fallback logic in CurationMainCard still treats the literal "null" as a valid URL because it only checks imageUrl.isNullOrBlank(). Update the conditional in CurationMainCard to match the same invalid-URL handling used by CurationCardItem, so both blank values and the "null" string route to the fallback Image and only real URLs reach SubcomposeAsyncImage.feature/curation/src/main/java/com/linku/curation/ui/calendar/CalendarIconBox.kt (1)
41-46: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win달 계산을
remember로 고정하지 마세요.이 값은 첫 composition 시점에만 계산돼 화면이 살아있는 동안 월이 바뀌어도
year/monthLabel이 갱신되지 않습니다. 여기서는remember를 빼거나, 상위에서 표시할 연/월을 상태로 내려주는 편이 안전합니다. As per coding guidelines, "Focus on state management (state hoisting, remember vs rememberSaveable) in Android/Kotlin/Compose code".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@feature/curation/src/main/java/com/linku/curation/ui/calendar/CalendarIconBox.kt` around lines 41 - 46, The date calculation in CalendarIconBox is being frozen by remember, so year and monthLabel won’t update as time changes while the composable stays alive. Remove the remember around prevMonth in CalendarIconBox, or hoist the displayed year/month into state from the parent so the UI recomposes with the current month.Source: Coding guidelines
🧹 Nitpick comments (2)
design/src/main/java/com/linku/design/top/bar/TopBar.kt (1)
55-55: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value남아있는 메모성 주석 정리 필요
//아 이것도 리펙해야하나...?같은 개인 메모성 주석은 PR 병합 전 정리하는 것이 좋습니다.♻️ 제안
-//아 이것도 리펙해야하나...? `@Composable` fun TopBar(🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@design/src/main/java/com/linku/design/top/bar/TopBar.kt` at line 55, Remove the remaining personal memo comment in TopBar.kt; the stray note inside the TopBar file should be cleaned up before merge. Locate the comment near the TopBar implementation and delete it, keeping only production-ready code and any intentional documentation comments.feature/curation/src/main/java/com/linku/curation/CurationApp.kt (1)
23-25: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win컴포지션 본문에서
showNavBar를 바로 호출하지 마세요.지금처럼 각
composable본문에서showNavBar(...)를 직접 호출하면, 목적지 재구성 때마다 상위MainApp상태를 컴포지션 중에 갱신하게 됩니다. 이건 바텀바 표시를SideEffect/LaunchedEffect로 넘기거나, 아예MainApp에서currentRoute만 보고 파생시키는 쪽이 더 안전합니다. As per coding guidelines, Android/Kotlin/Compose code should focus on SideEffect / LaunchedEffect misuse.🔧 제안 코드
composable("curation_list") { backStackEntry -> - showNavBar(true) + SideEffect { showNavBar(true) } val parentEntry = remember(backStackEntry) { navigator.getBackStackEntry("curation") } val curationVm: CurationViewModel = hiltViewModel(parentEntry) CurationScreen( nickname = nickname, viewModel = curationVm, onCard1Click = { navigator.navigate("curation_card1") }, onCard3Click = { navigator.navigate("curation_card3") } ) } composable("curation_card1") { - showNavBar(false) + SideEffect { showNavBar(false) } CurationCard1Screen(onBack = { navigator.popBackStack() }) } composable("curation_card3") { - showNavBar(false) + SideEffect { showNavBar(false) } CurationCard3Screen(onBack = { navigator.popBackStack() }) }Also applies to: 39-46
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@feature/curation/src/main/java/com/linku/curation/CurationApp.kt` around lines 23 - 25, `CurationApp`의 `composable("curation_list")` 등 각 destination 본문에서 `showNavBar(...)`를 직접 호출하지 말고, 상태 갱신을 `SideEffect` 또는 `LaunchedEffect`로 옮기거나 `MainApp`에서 `currentRoute` 기반으로 파생되게 바꾸세요. `CurationApp`의 navigation setup에서 `showNavBar` 호출 위치를 찾아 컴포지션 중 상태 변경이 발생하지 않도록 정리하면 됩니다.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@feature/curation/src/main/java/com/linku/curation/CurationApp.kt`:
- Around line 31-46: `CurationApp`의 `curation_card1`/`curation_card3` 라우트는 아직 실제
상세 화면이 없어 `CurationCard1Screen`과 `CurationCard3Screen`이 빈 `Box(fillMaxSize())`만
보여줍니다. `CurationScreen`의 `onCard1Click`/`onCard3Click` 네비게이션을 잠시 비활성화하거나,
`composable("curation_card1")`과 `composable("curation_card3")`에서 안내용 UI를 표시하도록
`showNavBar(false)` 및 각 Screen 진입부를 수정하세요.
In `@feature/curation/src/main/java/com/linku/curation/CurationViewModel.kt`:
- Around line 9-12: The CurationViewModel declaration is an empty class body,
which triggers EmptyClassBlock. Update the CurationViewModel constructor/class
declaration so it is kept without an empty block, or remove the ViewModel
entirely if it is not needed; use the CurationViewModel symbol to locate and
adjust the declaration cleanly.
In `@feature/curation/src/main/java/com/linku/curation/ui/CurationScreen.kt`:
- Around line 35-38: CurationScreen currently uses hiltViewModel() as a default
parameter, which can break PreviewCurationScreen and is unnecessary because the
viewModel parameter is not used inside the composable. Remove the viewModel
parameter from CurationScreen entirely (or at minimum remove the hiltViewModel()
default) and update any call sites such as PreviewCurationScreen to call
CurationScreen without it, keeping the function focused on the nickname and
click callbacks only.
In
`@feature/curation/src/main/java/com/linku/curation/ui/emotion/CurationEmotionChip.kt`:
- Around line 35-43: In CurationEmotionChip.kt, the fixed height in the chip
modifier can clip text when system font scaling is larger. Update the modifier
on CurationEmotionChip so it no longer forces a hard 26.dp height; instead,
preserve the visual minimum while allowing the chip to grow vertically with the
content, keeping the existing border, padding, and RoundedCornerShape behavior
intact.
In
`@feature/curation/src/main/java/com/linku/curation/ui/emotion/CurationEmotionSection.kt`:
- Around line 44-46: The month value in CurationEmotionSection is being cached
with remember, so it can become stale when the screen stays composed across a
month boundary. Remove the remember around the Calendar-based month calculation
in CurationEmotionSection and compute it fresh each composition, or hoist the
current month from a parent/state holder if it should be shared. Keep the fix
localized to the month/title logic so the displayed month always reflects the
current date.
In
`@feature/curation/src/main/java/com/linku/curation/ui/header/CurationHeader.kt`:
- Around line 31-33: The header image in CurationHeader is being treated as
decorative even though it conveys the title text, so update the Image setup to
provide an appropriate contentDescription instead of null, or refactor the
header so the title is rendered as real text alongside any decorative icon. Use
the existing CurationHeader composable and the img_curation_title resource as
the locating symbols when making the accessibility fix.
In
`@feature/curation/src/main/java/com/linku/curation/ui/main_card/CurationCardItem.kt`:
- Around line 91-99: The shadow on CurationCardItem’s Box is using the default
rectangular shape while the content is clipped to RoundedCornerShape, so the
outline doesn’t match. Update the modifier chain in CurationCardItem so the same
RoundedCornerShape(24.scaler) is passed to shadow() and clip(), keeping the card
background and shadow consistent. Use the Box modifier block in CurationCardItem
as the place to apply the shared shape.
---
Outside diff comments:
In
`@feature/curation/src/main/java/com/linku/curation/ui/calendar/CalendarIconBox.kt`:
- Around line 41-46: The date calculation in CalendarIconBox is being frozen by
remember, so year and monthLabel won’t update as time changes while the
composable stays alive. Remove the remember around prevMonth in CalendarIconBox,
or hoist the displayed year/month into state from the parent so the UI
recomposes with the current month.
In
`@feature/curation/src/main/java/com/linku/curation/ui/main_card/CurationMainCard.kt`:
- Around line 49-63: The image fallback logic in CurationMainCard still treats
the literal "null" as a valid URL because it only checks
imageUrl.isNullOrBlank(). Update the conditional in CurationMainCard to match
the same invalid-URL handling used by CurationCardItem, so both blank values and
the "null" string route to the fallback Image and only real URLs reach
SubcomposeAsyncImage.
In
`@feature/curation/src/main/java/com/linku/curation/ui/screen/CurationKeywordDetailScreen.kt`:
- Around line 37-49: The CurationKeywordDetailScreen composable currently
forwards onBack only to the content and does not handle the system back action,
so add a BackHandler in CurationKeywordDetailScreen that invokes onBack when the
user presses back. Keep the fix localized to CurationKeywordDetailScreen and
ensure CurationKeywordDetailContent still receives the same onBack callback for
UI-driven back actions.
---
Nitpick comments:
In `@design/src/main/java/com/linku/design/top/bar/TopBar.kt`:
- Line 55: Remove the remaining personal memo comment in TopBar.kt; the stray
note inside the TopBar file should be cleaned up before merge. Locate the
comment near the TopBar implementation and delete it, keeping only
production-ready code and any intentional documentation comments.
In `@feature/curation/src/main/java/com/linku/curation/CurationApp.kt`:
- Around line 23-25: `CurationApp`의 `composable("curation_list")` 등 각
destination 본문에서 `showNavBar(...)`를 직접 호출하지 말고, 상태 갱신을 `SideEffect` 또는
`LaunchedEffect`로 옮기거나 `MainApp`에서 `currentRoute` 기반으로 파생되게 바꾸세요. `CurationApp`의
navigation setup에서 `showNavBar` 호출 위치를 찾아 컴포지션 중 상태 변경이 발생하지 않도록 정리하면 됩니다.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a07c75b1-5038-429b-9c8a-f7272ab36de8
📒 Files selected for processing (31)
app/src/main/java/com/linku/MainApp.ktcore/src/main/java/com/linku/core/repository/CurationRepository.ktdata/src/main/java/com/linku/data/api/CurationApi.ktdata/src/main/java/com/linku/data/di/repository/CurationRepositoryModule.ktdata/src/main/java/com/linku/data/implementation/repository/CurationRepositoryImpl.ktdata/src/main/java/com/linku/data/mapper/SocialProfileMapper.ktdesign/src/main/java/com/linku/design/theme/color/ThemeColorScheme.ktdesign/src/main/java/com/linku/design/top/bar/TopBar.ktfeature/curation/src/main/java/com/linku/curation/CurationApp.ktfeature/curation/src/main/java/com/linku/curation/CurationDetailViewModel.ktfeature/curation/src/main/java/com/linku/curation/CurationViewModel.ktfeature/curation/src/main/java/com/linku/curation/ui/CurationScreen.ktfeature/curation/src/main/java/com/linku/curation/ui/calendar/CalendarBox.ktfeature/curation/src/main/java/com/linku/curation/ui/calendar/CalendarIconBox.ktfeature/curation/src/main/java/com/linku/curation/ui/detail_card/HighlightCard.ktfeature/curation/src/main/java/com/linku/curation/ui/effect/highlight/RadialGradientCircle.ktfeature/curation/src/main/java/com/linku/curation/ui/emotion/CurationEmotionBar.ktfeature/curation/src/main/java/com/linku/curation/ui/emotion/CurationEmotionChip.ktfeature/curation/src/main/java/com/linku/curation/ui/emotion/CurationEmotionSection.ktfeature/curation/src/main/java/com/linku/curation/ui/header/CurationHeader.ktfeature/curation/src/main/java/com/linku/curation/ui/main_card/CurationCardItem.ktfeature/curation/src/main/java/com/linku/curation/ui/main_card/CurationMainCard.ktfeature/curation/src/main/java/com/linku/curation/ui/main_card/CurationMainCardPager.ktfeature/curation/src/main/java/com/linku/curation/ui/recommend_list/CurationRecommendedLinksSection.ktfeature/curation/src/main/java/com/linku/curation/ui/screen/CurationCard1Screen.ktfeature/curation/src/main/java/com/linku/curation/ui/screen/CurationCard3Screen.ktfeature/curation/src/main/java/com/linku/curation/ui/screen/CurationDetailScreen.ktfeature/curation/src/main/java/com/linku/curation/ui/screen/CurationKeywordDetailScreen.ktfeature/curation/src/main/java/com/linku/curation/ui/screen/detail/CurationMonthDetailOverlay.ktfeature/curation/src/main/java/com/linku/curation/ui/screen/detail/CurationMonthDetailScreen.ktfeature/curation/src/main/java/com/linku/curation/ui/util/CurationBackground.kt
💤 Files with no reviewable changes (5)
- feature/curation/src/main/java/com/linku/curation/ui/screen/CurationDetailScreen.kt
- feature/curation/src/main/java/com/linku/curation/ui/screen/detail/CurationMonthDetailOverlay.kt
- feature/curation/src/main/java/com/linku/curation/ui/screen/detail/CurationMonthDetailScreen.kt
- feature/curation/src/main/java/com/linku/curation/ui/detail_card/HighlightCard.kt
- feature/curation/src/main/java/com/linku/curation/CurationDetailViewModel.kt
KateteDeveloper
left a comment
There was a problem hiding this comment.
"지민님" 코멘트 잘 읽어봤습니다
| fun CurationEmotionBar( | ||
| modifier: Modifier = Modifier, | ||
| progress: Float = 0.75f, | ||
| rank: Int = 0, //0,1,2 (혹시 마음에 안 들면 1번부터 하게 편하게 수정해주세요~!) |
There was a problem hiding this comment.
api 연동하는 사람이 하는게 더 좋지 않을까? 그래서 그냥 저렇게 놓았는데 @codebidoof 전 princehw에게 맞추겠습니다. 원하는 걸 말해봐
|
|
||
| //TODO : 다음 PR에서 구현할거예요.... | ||
| @Composable | ||
| fun CurationCard1Screen( |
There was a problem hiding this comment.
"지민님" TODO 주석 읽어봐주세요:)
나중에 구현한다 적혀 있습니당
설마 제가 저 밤티 이름을 채택할리가요
| fun CurationCardItem( | ||
| imageUrl: String?, | ||
| modifier: Modifier = Modifier, | ||
| imageUrl: String? = "", // null로 놓으면 지민이가 코멘트를 남기겠지... |

📝 설명
큐레이션 화면 리팩토링 및 감정 분석 섹션 신규 구현
🔧 리팩토링
CurationScreen 구조 개선
SharedTransitionLayout+Scaffold제거 →Box + Column + TopBar단순 구조로 변경CurationMonthDetailOverlay(오버레이 방식) 제거onCard1Click/onCard3Click콜백으로 화면 전환 구조 변경CurationApp.kt에curation_card1,curation_card3라우트 추가컴포넌트 분리
CurationBackground— 배경 원형 그라데이션 + 로고 이미지 유틸 컴포넌트로 분리 (showLogo파라미터)CurationHeader— 큐레이션 타이틀 + 닉네임 그라데이션 텍스트 헤더 컴포넌트로 분리CurationMainCardPager 개선
isDetailOpen파라미터 제거animateDpAsState× 2 →animateFloatAsState+graphicsLayer(scaleX/Y)로 변경→ 카드 축소 시 내부 텍스트·이미지도 함께 스케일됨
tween()→spring(DampingRatioMediumBouncy)으로 변경하여 자연스러운 탄성 애니메이션 적용colorTheme.gray[600]/colorTheme.gray[300]CurationCardItem 개선
LocalDate(API 26 필요) →java.util.Calendar로 교체style = TextStyle(fontFamily = Paperlogy.font, ...)래퍼 제거 (전역 폰트 패밀리 적용 중)Text3개 → 1개로 합침colorTheme로 교체ThemeColorScheme 추가 항목
curationGradient— 큐레이션 헤더 텍스트 그라데이션curationCardBackground— 카드 fallback 배경색curationCardOverlayGradient— 카드 이미지 위 오버레이 그라데이션emotionTitleGradient— 감정 분석 섹션 타이틀 그라데이션✨ 신규 구현
빈 화면 플레이스홀더
CurationCard1Screen— 카드 1번 연결 화면 (추후 구현)CurationCard3Screen— 카드 3번 연결 화면 (추후 구현)감정 분석 섹션 (
ui/emotion)CurationEmotionBar— 순위별 자동 컬러 프로그레스 바 (rank 0→blue[300], 1→blue[200], 2→blue[100])CurationEmotionChip— 테두리 키워드 칩CurationEmotionSection— 이전 달 상황/감정 요약 섹션 통합 컴포넌트🖼️ UI 프리뷰
✔️ PR 유형
어떤 변경 사항이 있나요?
📎 관련 이슈 번호
#144
Summary by CodeRabbit
New Features
Bug Fixes