[FEAT/#59] 마이페이지 뷰 컴포넌트 조립 #61
Conversation
- MyPage-Component 내에 있는 Header 조립 - MyPage 내에 MyPage_Body 구현 - MyPagePreview 구현 - ktLint 실행
- MyPage 내에 MyPage_Body Icon을 Box로 감싸는 구조로 변경 - ktLint 실행
- MyPageInfo Model 클래스 구현 - companion object로 Fake data 구현
- companion object로 Fake data 구현
- MypageViewModel 구현 - 관련 UIState 수정
- MypageViewModel loadMyPage 관련 코드 삭제 - UiState 변수 이름 변경 - ViewModel과 Screen 적용
- ktLint 실행 - 코드 정리
WalkthroughMyPageRoute가 Hilt로 MyPageViewModel을 주입하고 uiState를 collectAsStateWithLifecycle로 구독해 UiState.Success일 때 MyPageScreen에 MyPageUiState를 전달하여 렌더링하도록 변경되었고, MyPageUiState·MyPageViewModel·MyPageInfo 및 MyPageScreen의 UI 레이아웃(헤더, 구분선, 이미지, 프리뷰 등)이 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Route as MyPageRoute
participant VM as MyPageViewModel
participant State as StateFlow<UiState<MyPageUiState>>
participant Screen as MyPageScreen
participant UI as 사용자 인터페이스
Route->>VM: hiltViewModel()로 ViewModel 주입
VM->>State: _uiState 초기화 (UiState.Success(FakeUsers))
Route->>State: uiState.collectAsStateWithLifecycle()
State-->>Route: UiState.Success(MyPageUiState)
Route->>Screen: MyPageUiState 전달 (paddingValues, uiState.data)
Screen-->>UI: nicknameText, skinCareDay 등 렌더링
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧹 Recent nitpick comments
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used📓 Path-based instructions (1)**/*.kt⚙️ CodeRabbit configuration file
Files:
🧠 Learnings (1)📚 Learning: 2026-01-12T19:49:27.085ZApplied to files:
🧬 Code graph analysis (1)app/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.kt (1)
⏰ 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)
🔇 Additional comments (3)
✏️ Tip: You can disable this entire section by setting 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: 2
🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/mypage/model/MyPageInfo.kt`:
- Around line 5-9: MyPageInfo is an unused duplicate of MyPageUiState (both
define nicknameText and skinCareDay); remove the MyPageInfo data class to
eliminate dead code, or if you intend to keep it, add a clear TODO comment on
the MyPageInfo declaration explaining its future purpose and ensure any intended
usages are implemented or referenced from MyPageUiState to avoid duplication.
In `@app/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.kt`:
- Around line 33-48: UiState 처리에서 Loading과 Failure에 대한 UI가 빠져있고 else로 Empty를
암묵적으로 처리하고 있으니, when 블록을 수정해 UiState.Loading 케이스에서 로딩 인디케이터(예:
CircularProgressIndicator)를 렌더링하고 UiState.Failure 케이스에서 에러 메시지/재시도 버튼을 렌더링하도록
추가하고, else -> {} 대신 명시적으로 UiState.Empty 케이스를 추가해 빈 상태용 콘텐츠(또는 아무것도 렌더링하지 않는 의도라면
주석으로 명시)를 구현하세요; 해당 변경은 MyPageScreen 호출부와 동일한 when 문(변수명 uiState, 상태 클래스
UiState.Loading/Failure/Empty)을 수정하면 됩니다.
🧹 Nitpick comments (1)
app/src/main/java/com/cherrish/android/presentation/mypage/MyPageUiState.kt (1)
5-16: @immutable 적용과 UiState 구조가 적절합니다.불변 타입(String, Int)만 포함하고 있어
@Immutable어노테이션이 올바르게 적용되었습니다. Compose의 안정성(stability) 보장에 도움이 됩니다.다만,
FakeUsers는 단일 사용자 데이터를 나타내므로FakeUser로 네이밍하는 것이 더 명확합니다.♻️ 네이밍 개선 제안
companion object { - val FakeUsers = + val FakeUser = MyPageUiState( nicknameText = "홍길동", skinCareDay = 3 ) }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.ktapp/src/main/java/com/cherrish/android/presentation/mypage/MyPageUiState.ktapp/src/main/java/com/cherrish/android/presentation/mypage/MyPageViewModel.ktapp/src/main/java/com/cherrish/android/presentation/mypage/model/MyPageInfo.kt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: - Jetpack Compose 구조, 상태 관리, recomposition 최적화에 집중
- ViewModel, UiState, 단방향 데이터 흐름 패턴 검토
- 불필요한 recomposition 가능성, remember/derivedStateOf 적절한 사용 확인
- 네이밍 컨벤션, 가독성, Google 권장 Android 아키텍처 준수 여부
Files:
app/src/main/java/com/cherrish/android/presentation/mypage/model/MyPageInfo.ktapp/src/main/java/com/cherrish/android/presentation/mypage/MyPageViewModel.ktapp/src/main/java/com/cherrish/android/presentation/mypage/MyPageUiState.ktapp/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.kt
🧠 Learnings (1)
📚 Learning: 2026-01-12T19:49:27.085Z
Learnt from: nhyeonii
Repo: TEAM-Cherrish/Cherrish-Android PR: 41
File: app/src/main/java/com/cherrish/android/presentation/challenge/ChallengeScreen.kt:30-39
Timestamp: 2026-01-12T19:49:27.085Z
Learning: When a Jetpack Compose screen composable receives a Scaffold paddingValues: PaddingValues parameter (commonly from Scaffold), apply it to the root container's modifier first (e.g., .padding(paddingValues)) before applying any additional padding. This ensures content respects system bars (status/navigation) and avoids layout overlap. This pattern should be followed across presentation screens under app/src/main/java/com/cherrish/android/presentation/ to maintain consistent insets handling.
Applied to files:
app/src/main/java/com/cherrish/android/presentation/mypage/model/MyPageInfo.ktapp/src/main/java/com/cherrish/android/presentation/mypage/MyPageViewModel.ktapp/src/main/java/com/cherrish/android/presentation/mypage/MyPageUiState.ktapp/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.kt
🧬 Code graph analysis (1)
app/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.kt (1)
app/src/main/java/com/cherrish/android/presentation/mypage/component/MyPageHeader.kt (1)
MyPageHeader(22-56)
⏰ 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: PR Build Check
- GitHub Check: PR Lint Check
🔇 Additional comments (3)
app/src/main/java/com/cherrish/android/presentation/mypage/MyPageViewModel.kt (1)
11-18: ViewModel 기본 구조가 적절합니다.Hilt 주입과 StateFlow 패턴이 올바르게 구현되었습니다.
asStateFlow()를 사용하여 읽기 전용으로 노출하는 것도 좋습니다.현재
UiState.Success로 초기화되어 있고, 실제 데이터 로딩 로직이 없습니다. 추후 Repository/UseCase를 주입받아 데이터를 불러올 때UiState.Loading→Success/Failure전환 로직이 필요합니다.app/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.kt (2)
51-88: MyPageScreen 구현이 적절합니다.
paddingValues가 루트 컨테이너에 먼저 적용되어 시스템 바(status/navigation bar) 처리가 올바릅니다.MyPageHeader에uiState의 데이터가 정확히 전달되고 있습니다.Box에weight(1f)를 사용하여 유연한 레이아웃을 구성한 점이 좋습니다.플레이스홀더 아이콘(
ic_launcher_foreground)은 PR 목표에 따라 임시로 사용된 것으로 이해됩니다. Based on learnings, paddingValues가 올바르게 적용되었습니다.
90-97: Preview 구성이 적절합니다.
@Preview어노테이션과FakeUsers를 활용한 미리보기 설정이 올바르게 구현되었습니다. UI 검증에 유용합니다.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| @Immutable | ||
| data class MyPageInfo( | ||
| val nicknameText: String, | ||
| val skinCareDay: Int | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# MyPageInfo 사용 현황 확인
rg -n "MyPageInfo" --type=ktRepository: TEAM-Cherrish/Cherrish-Android
Length of output: 100
🏁 Script executed:
# MyPageUiState 정의 찾기 (구조 비교용)
rg -n "class MyPageUiState|data class MyPageUiState" --type=kt -A 5Repository: TEAM-Cherrish/Cherrish-Android
Length of output: 100
🏁 Script executed:
# MyPageInfo 사용 현황 확인 (파일 타입 제약 제거)
rg -n "MyPageInfo" --include="*.kt"Repository: TEAM-Cherrish/Cherrish-Android
Length of output: 515
🏁 Script executed:
# MyPageUiState 정의 찾기 (구조 비교용)
rg -n "class MyPageUiState|data class MyPageUiState" --include="*.kt" -A 6Repository: TEAM-Cherrish/Cherrish-Android
Length of output: 515
🏁 Script executed:
# MyPageInfo.kt 파일의 전체 내용 확인
cat -n app/src/main/java/com/cherrish/android/presentation/mypage/model/MyPageInfo.ktRepository: TEAM-Cherrish/Cherrish-Android
Length of output: 326
🏁 Script executed:
# MyPageInfo 사용 현황 확인
rg "MyPageInfo" app/src/main/javaRepository: TEAM-Cherrish/Cherrish-Android
Length of output: 175
🏁 Script executed:
# MyPageUiState 정의 찾기 (구조 비교)
rg "data class MyPageUiState|class MyPageUiState" app/src/main/java -A 6Repository: TEAM-Cherrish/Cherrish-Android
Length of output: 773
🏁 Script executed:
# MyPageInfo import 확인
rg "import.*MyPageInfo" app/src/main/javaRepository: TEAM-Cherrish/Cherrish-Android
Length of output: 56
🏁 Script executed:
# MyPageUiState.kt 전체 내용 확인
cat -n app/src/main/java/com/cherrish/android/presentation/mypage/MyPageUiState.ktRepository: TEAM-Cherrish/Cherrish-Android
Length of output: 556
MyPageInfo는 사용되지 않는 중복 코드입니다.
MyPageInfo와 MyPageUiState가 동일한 프로퍼티(nicknameText, skinCareDay)를 가지고 있으며, MyPageInfo는 코드베이스 어디에서도 임포트되거나 사용되지 않고 있습니다. 현재 완전히 미사용 상태인 코드이므로, 명확한 사용 계획이 없다면 삭제하거나 TODO 주석으로 의도를 명시할 것을 권장합니다.
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/mypage/model/MyPageInfo.kt`
around lines 5 - 9, MyPageInfo is an unused duplicate of MyPageUiState (both
define nicknameText and skinCareDay); remove the MyPageInfo data class to
eliminate dead code, or if you intend to keep it, add a clear TODO comment on
the MyPageInfo declaration explaining its future purpose and ensure any intended
usages are implemented or referenced from MyPageUiState to avoid duplication.
| when (val state = uiState) { | ||
| is UiState.Loading -> { | ||
| } | ||
|
|
||
| is UiState.Failure -> { | ||
| } | ||
|
|
||
| is UiState.Success -> { | ||
| MyPageScreen( | ||
| paddingValues = paddingValues, | ||
| uiState = state.data | ||
| ) | ||
| } | ||
|
|
||
| else -> {} | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find UiState definition
rg -n "sealed class UiState|sealed interface UiState|data class UiState|enum class UiState" --type=kt -A 10Repository: TEAM-Cherrish/Cherrish-Android
Length of output: 100
🏁 Script executed:
# Search for UiState definition with broader pattern
rg -n "class UiState|interface UiState" --type=kt -B 2 -A 8 | head -50Repository: TEAM-Cherrish/Cherrish-Android
Length of output: 100
🏁 Script executed:
# Examine the MyPageScreen.kt file
cat -n app/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.ktRepository: TEAM-Cherrish/Cherrish-Android
Length of output: 3746
🏁 Script executed:
# Find UiState definition in the core.common.state package
find . -path "*/core/common/state/*" -name "*.kt" | head -20Repository: TEAM-Cherrish/Cherrish-Android
Length of output: 143
🏁 Script executed:
# Search for UiState definition more broadly
rg -l "UiState" --glob="*.kt" | xargs grep -l "sealed class UiState\|sealed interface UiState\|class UiState\|interface UiState" | head -10Repository: TEAM-Cherrish/Cherrish-Android
Length of output: 141
🏁 Script executed:
# Examine the UiState definition
cat -n ./app/src/main/java/com/cherrish/android/core/common/state/UiState.ktRepository: TEAM-Cherrish/Cherrish-Android
Length of output: 444
Loading/Failure 상태에 대한 UI 처리가 누락되었으며, Empty 상태도 명시적으로 처리해야 합니다.
현재 UiState.Loading과 UiState.Failure 상태에서 아무것도 렌더링하지 않으므로 데이터 로딩 시 사용자 피드백이 부족합니다. 또한 UiState가 sealed interface인 경우, Line 47의 else -> {} 분기는 UiState.Empty 케이스를 암묵적으로 처리하고 있습니다. Empty 상태도 명시적으로 처리하거나, 해당 상태가 발생하지 않아야 한다면 아무것도 렌더링하지 않는 것을 명확히 해야 합니다.
- Loading/Failure: 로딩 인디케이터, 에러 메시지 등의 UI 피드백 필요
- Empty: 명시적 케이스 처리 필요 (현재 else로 암묵적 처리 중)
🤖 Prompt for AI Agents
In `@app/src/main/java/com/cherrish/android/presentation/mypage/MyPageScreen.kt`
around lines 33 - 48, UiState 처리에서 Loading과 Failure에 대한 UI가 빠져있고 else로 Empty를
암묵적으로 처리하고 있으니, when 블록을 수정해 UiState.Loading 케이스에서 로딩 인디케이터(예:
CircularProgressIndicator)를 렌더링하고 UiState.Failure 케이스에서 에러 메시지/재시도 버튼을 렌더링하도록
추가하고, else -> {} 대신 명시적으로 UiState.Empty 케이스를 추가해 빈 상태용 콘텐츠(또는 아무것도 렌더링하지 않는 의도라면
주석으로 명시)를 구현하세요; 해당 변경은 MyPageScreen 호출부와 동일한 when 문(변수명 uiState, 상태 클래스
UiState.Loading/Failure/Empty)을 수정하면 됩니다.
| is UiState.Loading -> { | ||
| } | ||
|
|
||
| is UiState.Failure -> { | ||
| } | ||
|
|
||
| is UiState.Success -> { | ||
| MyPageScreen( | ||
| paddingValues = paddingValues, | ||
| uiState = state.data | ||
| ) | ||
| } |
There was a problem hiding this comment.
비어있는 분기 처리에 대해 주석 등으로 설명이 있다면 좀더 이해하기 쉽지 않을까요?
There was a problem hiding this comment.
리뷰 감사합니다 ^^ 그런데 분기처리는 서버와 연결 할 때 연결할 예정입니다아 ~~😊
sohee6989
left a comment
There was a problem hiding this comment.
수고하셨습니다!
리뷰 한 번만 확인 부탁드립니다~!!
|
|
||
| @Immutable | ||
| data class MyPageInfo( | ||
| val nicknameText: String, |
There was a problem hiding this comment.
p3: nickname 같은 경우에는 변수명으로 nicknameText 대신 nickname으로 써도 의미가 잘 전달될 것 같은데 nickname은 어떠신가요??
There was a problem hiding this comment.
오 그러네요 아마 거의 nickName은 String 값일테니까요 !! 그리고 nickName은 Text 대신 따로 없으니까요 ! 좋습니당
| profileIcon = R.drawable.ic_launcher_foreground, | ||
| nicknameText = uiState.nicknameText, | ||
| skinCareDay = uiState.skinCareDay, | ||
| modifier = Modifier.fillMaxWidth() |
There was a problem hiding this comment.
p3: (단순 궁금) 여기 fillMaxWidth 안 줘도 지 않나여?!
| modifier = Modifier.height(height = 10.dp) | ||
| ) | ||
|
|
||
| Box( |
There was a problem hiding this comment.
p3: 여기 Box 안 써도 되지 않나여?!
There was a problem hiding this comment.
추가로 [디바이더 a 아이콘 b 디바이더] a,b에 weight 1f 먹이면 그 공간 사이에 1:1 비율로 가지면서 기기대응도 잘 될겁니다~!!
There was a problem hiding this comment.
box를 주지 않고 weight를 각각 주면 Icon이 center로 오지 않더라고요 ,,! 그래서 Box로 묶어주고 양 위에 weight를 구현했습니다 !
| Icon( | ||
| imageVector = ImageVector.vectorResource(id = R.drawable.ic_launcher_foreground), | ||
| contentDescription = null, | ||
| modifier = Modifier.padding(horizontal = 52.dp) |
There was a problem hiding this comment.
p2: 만약 피그마 임시 영역처럼 주고 싶으면
fillMaxWidth 써야되여~!!
nhyeonii
left a comment
There was a problem hiding this comment.
굿굿 ~~ 고생해써용 ㅎㅎ 리뷰 한번만 확인해주세여 ~~
| Text( | ||
| text = "MyPage", | ||
| modifier = modifier.padding(paddingValues) | ||
| Column(modifier = modifier.padding(paddingValues)) { |
There was a problem hiding this comment.
P1 : 요기 .fillMaxSize() 속성 필요할 것 같아유 !
There was a problem hiding this comment.
.background(color = Cherrish.colors.gray0) 설정도 필요합니다아 ~~
There was a problem hiding this comment.
앗 넵넵 추가 하겠습니다 ! 그런데 Column이 최상위에 있어서 .fillMaxSize()를 사용하는 건가요 ??
|
|
||
| HorizontalDivider( | ||
| color = CherrishTheme.colors.gray100, | ||
| modifier = Modifier.height(height = 10.dp) |
There was a problem hiding this comment.
P1 : 얘는 Divider 이니까 modifier보다는 thickness = 10.dp 사용해줄까요??!
There was a problem hiding this comment.
아아 찾아보니 Modifier는 보통 레이아웃을 적고, thickness는 스타일에 사용하는 거군요 !!! 감사합니당 ~
|
|
||
| HorizontalDivider( | ||
| color = CherrishTheme.colors.gray100, | ||
| modifier = Modifier.height(height = 10.dp) |
There was a problem hiding this comment.
P1 : 얘도 thickness = 10.dp로 줍시당 ㅎㅎㅎ
| companion object { | ||
| val FakeUsers = | ||
| MyPageUiState( | ||
| nicknameText = "홍길동", | ||
| skinCareDay = 3 | ||
| ) | ||
| } |
- 기존 Box가 아닌 Spacer로 변경 - Divider는 thichness를 10.dp 설정 - 불필요한 Modifier 삭제 - ktLint 실행
usuuhyn
left a comment
There was a problem hiding this comment.
굿굿띠 소히 나현 리뷰 덕에 쓸 게 없네용 ㅎㅎ 화이팅 ~~!!!
| profileIcon = R.drawable.ic_launcher_foreground, | ||
| nicknameText = uiState.nicknameText, | ||
| skinCareDay = uiState.skinCareDay, | ||
| modifier = Modifier.fillMaxWidth() |
- 앱 내 프로필이미지 추가 - 앱 내 body 추가
- 마이페이지 image 적용 - 마이페이지 Icon() -> Image()로 변경 - 전체적인 패딩 수정
| .fillMaxSize() | ||
| .padding(paddingValues) | ||
| .padding(top = 44.dp) | ||
| .background(color = CherrishTheme.colors.gray0), |
There was a problem hiding this comment.
P1 : 이거 padding 적용하기 전에 backgroundcolor를 먼저 적용해야 컬러가 제대로 들어갈 수 있어요 ! 모디파이어 순서 확인해보시는것도 좋을 것 같아요
There was a problem hiding this comment.
아아 넵 감사합니다 !!!!! 바로 수정하겠습니다
| profileIcon = R.drawable.img_mypage_profile, | ||
| nicknameText = uiState.nicknameText, | ||
| skinCareDay = uiState.skinCareDay, | ||
| modifier = Modifier.padding(horizontal = 16.dp) |
|
|
||
| ) | ||
|
|
||
| Spacer(Modifier.weight(weight = 1f)) |
There was a problem hiding this comment.
아아 요것도 수정되어있습니다 😭
| thickness = 10.dp | ||
| ) | ||
|
|
||
| Spacer(Modifier.weight(weight = 1f)) |
There was a problem hiding this comment.
아아 요것도 수정되어있습니다 😭
| Image( | ||
| painter = painterResource(id = R.drawable.img_mypage_preparing), | ||
| contentDescription = null, | ||
| modifier = Modifier.padding(horizontal = 26.dp) |
There was a problem hiding this comment.
앗 이거 적용한 버전이 git push가 안되어있었어요 ㅜㅜ 죄송해요 다시 바로 push 할게요 !!
- 마이페이지 텍스트구현 - weghit로 변경 - ktLint 실행
- 불필요한 공백 삭제 - 줄 바꿈 정리 - ktLint 실행




Related issue 🛠
Work Description ✏️
Screenshot 📸
Uncompleted Tasks 😅
N/A
To Reviewers 📢
마이페이지 관련 작업입니다. UI State와 Model 생성을 했는데, Model을 아직은 활용하지못했습니다 !!
hilt 적용을 최대한 오비님 코드 보고 구현했는데 부족한 점 말씀해주세용 ~~!!
Summary by CodeRabbit
New Features
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.