Skip to content

[Feat] 프로필 컬렉션 및 콘텐츠 목록 조회 API 연동#147

Merged
nahy-512 merged 8 commits into
developfrom
feat/#146-profile-collection-content-api
Jan 21, 2026
Merged

[Feat] 프로필 컬렉션 및 콘텐츠 목록 조회 API 연동#147
nahy-512 merged 8 commits into
developfrom
feat/#146-profile-collection-content-api

Conversation

@nahy-512
Copy link
Copy Markdown
Contributor

@nahy-512 nahy-512 commented Jan 20, 2026

📮 관련 이슈

📌 작업 내용

  • 프로필 화면에서 컬렉션 및 콘텐츠 목록 조회 API 연동해요.

📸 스크린샷

스크린샷
Screen_recording_20260121_061909.mp4

😅 미구현

  • 로딩/실패 처리
  • userId 하드코딩
  • 내 프로필/타인 프로필 구분

🫛 To. 리뷰어

  • 서버에서 이미지 관련 필드명 다 통일되고, 이미지는 nullable하게 들어가는 거 같길래 dto 수정 좀 헀어요.
  • @kimjw2003 덕분에 편하게 작업했습니다ㅎㅎ 감사합니다

Summary by CodeRabbit

  • New Features

    • 프로필에서 사용자가 생성한 컬렉션과 저장한 컬렉션을 불러와 표시합니다. (데이터가 있을 때만 섹션 노출)
  • Improvements

    • 썸네일·프로필 이미지 필드가 nullable로 변경되어 이미지가 없어도 안전하게 처리됩니다.
    • 키워드 데이터 구조와 매핑 로직을 개선해 프로필 키워드의 안정성과 표시 품질 향상.

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

@nahy-512 nahy-512 self-assigned this Jan 20, 2026
@nahy-512 nahy-512 requested a review from a team as a code owner January 20, 2026 21:22
@nahy-512 nahy-512 added 🔖 API feat - API 연동 Feat ✨ 신규 기능을 추가하거나 기존 기능의 동작, 정책을 변경 labels Jan 20, 2026
@nahy-512 nahy-512 linked an issue Jan 20, 2026 that may be closed by this pull request
3 tasks
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 20, 2026

📝 Walkthrough

Walkthrough

프로필 페이지에 생성·저장 컬렉션 및 저장된 작품 API 연동을 추가하고, 키워드 모델을 재설계하며 DTO·매퍼·레포지토리·뷰모델·UI를 연결하도록 변경했습니다.

Changes

Cohort / File(s) 변경 내용
UI 컴포넌트 정리
\app/src/main/java/com/flint/core/designsystem/component/listItem/CollectionItem.kt`, `app/src/main/java/com/flint/core/designsystem/component/listView/CollectionSection.kt``
사용되지 않는 import 제거 (이미지/리소스/도메인 타입 정리).
사용자 API 엔드포인트 추가
\app/src/main/java/com/flint/data/api/UserApi.kt``
getUserBookmarkedCollections(userId)getUserCreatedCollections(userId) Retrofit 메서드 추가.
사용자 컬렉션 DTO 추가
\app/src/main/java/com/flint/data/dto/user/response/BookmarkedCollectionListResponseDto.kt`, `app/src/main/java/com/flint/data/dto/user/response/CreatedCollectionListResponseDto.kt``
북마크·생성 컬렉션용 DTO(리스트/아이템) 추가 및 직렬화 필드 매핑 선언.
기존 컬렉션/추천 DTO 변경
\app/src/main/java/com/flint/data/dto/collection/response/RecentCollectionListResponseDto.kt`, `app/src/main/java/com/flint/data/dto/home/response/RecommendCollectionResponseDto.kt``
thumbnailUrl을 nullable로 변경, profileUrl의 SerialName을 profileImageUrl로 변경.
컬렉션 매퍼 확장
\app/src/main/java/com/flint/domain/mapper/collection/CollectionMapper.kt``
Created/Bookmarked DTO → 도메인 모델 변환용 toModel() 확장 함수(목록·아이템) 추가.
키워드 모델 재설계
\app/src/main/java/com/flint/domain/model/user/KeywordListModel.kt`, 삭제: `app/src/main/java/com/flint/domain/model/user/UserKeywordResponseModel.kt``
기존 UserKeywordResponseModel 제거 및 KeywordListModel/KeywordItemModel 추가(페이크 데이터 포함).
키워드 매퍼 갱신
\app/src/main/java/com/flint/domain/mapper/user/KeywordMapper.kt``
사용자 키워드 DTO → KeywordListModel/KeywordItemModel 매핑 함수로 변경(기존 매핑 함수 교체).
컬렉션 도메인 모델 변경
\app/src/main/java/com/flint/domain/model/collection/CollectionListModel.kt``
CollectionItemModel.thumbnailUrl을 nullable로 변경(default null).
레포지토리 확장
\app/src/main/java/com/flint/domain/repository/UserRepository.kt``
getUserKeywords() 반환형을 KeywordListModel로 변경, getUserCreatedCollections()·getUserBookmarkedCollections() 추가 및 DTO→모델 매핑 적용.
프로필 뷰·화면 업데이트
\app/src/main/java/com/flint/presentation/profile/ProfileViewModel.kt`, `app/src/main/java/com/flint/presentation/profile/ProfileScreen.kt`, `app/src/main/java/com/flint/presentation/profile/uistate/ProfileUiState.kt``
ContentRepository 주입, 프로필 로드 이후 getSectionInfo()로 생성·저장 컬렉션 및 저장작품 동시 조회, UI 상태 필드명/타입 조정(savedContents, keywords: KeywordListModel), 화면에서 컬렉션 섹션 조건부 렌더링.
프로필 키워드 컴포넌트
\app/src/main/java/com/flint/presentation/profile/component/ProfileKeywordSection.kt``
파라미터 타입을 KeywordListModel로 변경하고 하위 컴포넌트에 KeywordItemModel 컬렉션 전달하도록 수정(프리뷰 포함).

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)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • giovannijunseokim
  • kimjw2003

Poem

🐰 새 데이터가 도착했네 — 깡총깡총,
컬렉션과 키워드가 모여 춤을 추고,
뷰모델은 조용히 섹션을 채우네,
API는 당근 배달부처럼 길을 내주고,
작은 당근 파티로 축하해요! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 프로필 화면의 컬렉션 및 콘텐츠 목록 조회 API 연동이라는 주요 변경사항을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 관련 이슈, 작업 내용, 스크린샷, 미구현 사항, 리뷰어 메모를 포함한 템플릿을 따르고 있습니다.
Linked Issues check ✅ Passed PR이 이슈 #146의 모든 주요 목표를 충족합니다: 생성한 컬렉션, 저장한 컬렉션, 저장한 작품 API 연동이 모두 구현되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 API 연동 구현, DTO 수정, 모델 구조 개선으로 이슈 #146의 범위 내에 있습니다. 불필요한 변경이 없습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

Copy link
Copy Markdown
Contributor

@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: 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()
 )

Comment thread app/src/main/java/com/flint/domain/model/user/KeywordListModel.kt
Copy link
Copy Markdown
Contributor

@giovannijunseokim giovannijunseokim left a comment

Choose a reason for hiding this comment

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

LGTM 👍

val id: String,
@SerialName("thumbnailUrl")
val thumbnailUrl: String,
val thumbnailUrl: String?,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p3: thumbnailUrlnull일 수 있나요? profileImageUrl만 null일 수 있다고 들었던 것 같아서요. 👀

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

확인해보니까,, thumnailUrlnull로 오더라구요?..필드 아예 없다고 에러 터지길래 우선 그냥 null 허용 해두었습니다

Comment on lines +7 to +9
data class KeywordListModel(
val keywords: ImmutableList<KeywordItemModel> = persistentListOf(),
) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p3: ImmutableList<KeywordItemModel> 형태로 사용할 수도 있을 것 같아요. 객체로 만들어주신 이유가 있나요? 👀

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

저도 처음에 그런 식으로 구현했었는데요, @kimjw2003 께서 해당 방식으로 구현해주셔서 여쭤보니까 keywords 외에 기타 정보(ex. page, cursor)가 들어올 상황을 대비해 객체로 만드는 걸 선호하신다고 하시더라구요. 설득돼서 저도 그쪽으로 맞추기로 했습니다ㅎㅎ

Comment on lines +32 to +33
val profile = userRepository.getUserProfile(userId = null).getOrThrow()
val keywords = userRepository.getUserKeywords(userId = null).getOrThrow()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p3: 어제 얘기 나눠본 부분인 것 같은데 async를 사용하지 않은 이유가 무엇일까요? 👀

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

로딩 범위를 고민하다가 프로필을 먼저 불러온 다음 컬렉션 정보를 update 하는 식으로 구현해보려고 했는데요,,ㅎㅎ
그 과정에서 누락한 부분인 것 같습니다. 짚어주셔서 감사합니다:)

@nahy-512 nahy-512 merged commit d3141c9 into develop Jan 21, 2026
2 checks passed
@nahy-512 nahy-512 deleted the feat/#146-profile-collection-content-api branch January 21, 2026 07:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔖 API feat - API 연동 Feat ✨ 신규 기능을 추가하거나 기존 기능의 동작, 정책을 변경

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] Profile 컬렉션, 작품 목록 API 연동

2 participants