[Feat] 프로필 컬렉션 및 콘텐츠 목록 조회 API 연동#147
Conversation
📝 WalkthroughWalkthrough프로필 페이지에 생성·저장 컬렉션 및 저장된 작품 API 연동을 추가하고, 키워드 모델을 재설계하며 DTO·매퍼·레포지토리·뷰모델·UI를 연결하도록 변경했습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Screen as ProfileScreen
participant VM as ProfileViewModel
participant UserRepo as UserRepository
participant ContentRepo as ContentRepository
participant UserApi as UserApi
Screen->>VM: 프로필 요청
VM->>UserRepo: getUserProfile()
UserRepo->>UserApi: GET /user/{id}/profile
UserApi-->>UserRepo: UserProfileResponseDto
UserRepo-->>VM: UserProfileModel
VM->>VM: getSectionInfo()
par 병렬
VM->>UserRepo: getUserCreatedCollections(userId)
UserRepo->>UserApi: GET /user/{id}/created-collections
UserApi-->>UserRepo: CreatedCollectionListResponseDto
UserRepo-->>VM: CollectionListModel
VM->>UserRepo: getUserBookmarkedCollections(userId)
UserRepo->>UserApi: GET /user/{id}/bookmarked-collections
UserApi-->>UserRepo: BookmarkedCollectionListResponseDto
UserRepo-->>VM: CollectionListModel
VM->>ContentRepo: getBookmarkedContentList(userId)
ContentRepo-->>VM: BookmarkedContentListModel
end
VM->>Screen: 업데이트된 ProfileUiState (keywords, savedContents, createCollections, savedCollections)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 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
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
🤖 Fix all issues with AI agents
In `@app/src/main/java/com/flint/domain/model/user/KeywordListModel.kt`:
- Around line 77-80: The preferenceType getter currently uses
PreferenceType.valueOf(color) which is case-sensitive; normalize the input by
calling color.uppercase() (or locale-safe variant) before valueOf to handle
lowercase/mixed-case values and keep the existing runCatching fallback to
PreferenceType.BLUE; update the getter in the preferenceType property (the
runCatching { PreferenceType.valueOf(...) } block referencing color and
PreferenceType) to use the normalized string.
🧹 Nitpick comments (3)
app/src/main/java/com/flint/data/dto/collection/response/RecentCollectionListResponseDto.kt (1)
32-33: 프로퍼티명과 SerialName 불일치 - 일관성 개선을 고려해 주세요.서버 필드명 통일에 맞춰
@SerialName("profileImageUrl")로 변경한 것은 적절합니다. 다만, 프로퍼티명profileUrl과 직렬화명profileImageUrl이 일치하지 않아 코드 가독성과 유지보수 측면에서 혼란을 줄 수 있습니다.♻️ 프로퍼티명 일관성 개선 제안
`@SerialName`("profileImageUrl") - val profileUrl: String? + val profileImageUrl: String?이 변경을 적용할 경우, 해당 프로퍼티를 참조하는 mapper 및 다른 코드도 함께 수정해야 합니다.
app/src/main/java/com/flint/data/dto/user/response/BookmarkedCollectionListResponseDto.kt (1)
7-10: collections 기본값으로 안정성 보강 고려 (Line 7-10)
서버가collections를 누락/NULL로 내려주면 역직렬화가 실패할 수 있어 기본값을 두는 편이 안전합니다.♻️ 제안 수정안
data class BookmarkedCollectionListResponseDto( `@SerialName`("collections") - val collections: List<BookmarkedCollectionItemResponseDto> + val collections: List<BookmarkedCollectionItemResponseDto> = emptyList() )app/src/main/java/com/flint/data/dto/user/response/CreatedCollectionListResponseDto.kt (1)
7-10: collections 기본값으로 안정성 보강 고려 (Line 7-10)
collections가 누락될 경우 역직렬화 실패 가능성이 있어 기본값을 추가하는 편이 안전합니다.♻️ 제안 수정안
data class CreatedCollectionListResponseDto( `@SerialName`("collections") - val collections: List<CreatedCollectionItemResponseDto> + val collections: List<CreatedCollectionItemResponseDto> = emptyList() )
| val id: String, | ||
| @SerialName("thumbnailUrl") | ||
| val thumbnailUrl: String, | ||
| val thumbnailUrl: String?, |
There was a problem hiding this comment.
p3: thumbnailUrl이 null일 수 있나요? profileImageUrl만 null일 수 있다고 들었던 것 같아서요. 👀
There was a problem hiding this comment.
확인해보니까,, thumnailUrl이 null로 오더라구요?..필드 아예 없다고 에러 터지길래 우선 그냥 null 허용 해두었습니다
| data class KeywordListModel( | ||
| val keywords: ImmutableList<KeywordItemModel> = persistentListOf(), | ||
| ) { |
There was a problem hiding this comment.
p3: ImmutableList<KeywordItemModel> 형태로 사용할 수도 있을 것 같아요. 객체로 만들어주신 이유가 있나요? 👀
There was a problem hiding this comment.
저도 처음에 그런 식으로 구현했었는데요, @kimjw2003 께서 해당 방식으로 구현해주셔서 여쭤보니까 keywords 외에 기타 정보(ex. page, cursor)가 들어올 상황을 대비해 객체로 만드는 걸 선호하신다고 하시더라구요. 설득돼서 저도 그쪽으로 맞추기로 했습니다ㅎㅎ
| val profile = userRepository.getUserProfile(userId = null).getOrThrow() | ||
| val keywords = userRepository.getUserKeywords(userId = null).getOrThrow() |
There was a problem hiding this comment.
p3: 어제 얘기 나눠본 부분인 것 같은데 async를 사용하지 않은 이유가 무엇일까요? 👀
There was a problem hiding this comment.
로딩 범위를 고민하다가 프로필을 먼저 불러온 다음 컬렉션 정보를 update 하는 식으로 구현해보려고 했는데요,,ㅎㅎ
그 과정에서 누락한 부분인 것 같습니다. 짚어주셔서 감사합니다:)
📮 관련 이슈
📌 작업 내용
📸 스크린샷
Screen_recording_20260121_061909.mp4
😅 미구현
🫛 To. 리뷰어
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.