[Feat] 탐색 화면 API 연결#161
Conversation
- `CollectionsModel`: 도메인 레이어에서 사용할 컬렉션 데이터 모델 정의 - `CollectionsResponseDto`: API 응답 값 파싱을 위한 DTO 클래스 추가 (kotlinx.serialization 적용)
- `CollectionApi`에 `getCollections` 메서드 추가 - `cursor`와 `page`를 파라미터로 받는 GET 요청 정의
- `CollectionsResponseDto`를 `CollectionsModel`로 변환하는 Mapper 함수 추가 - `CollectionRepository`에 컬렉션 목록 조회(`getCollections`) 함수 추가
- `ExploreViewModel`을 생성하여 `CollectionRepository`로부터 컬렉션 목록을 가져오는 로직 추가 - `ExploreScreen`에서 `UiState`에 따라 로딩 인디케이터 표시 및 데이터 바인딩 처리 - `CollectionsModel`의 데이터 타입을 `ImmutableList`로 변경 및 관련 매퍼 수정 - `CollectionRepository.getCollections`의 반환 타입을 `Result<CollectionsModel>`로 명시 및 데이터 변환 로직 추가
- `getCollections` 함수 내에서 사용되지 않는 `uiState` 변수 제거
- `ExploreScreen`에서 `pagerState`를 기반으로 다음 페이지 로드 로직 추가 (`onLoadNextPage`) - `ExploreViewModel`에서 페이징 처리를 위한 `currentCursor`, `isLastPage` 등 상태 관리 및 데이터 추가 로직 구현 - `CollectionRepository` 및 `CollectionApi`의 파라미터 명칭 수정 (`page` -> `size`)
- `ExploreUiState`의 `currentCursor`를 `nextCursor`로 변경하고 타입을 `Long?`으로 수정 - `CollectionsResponseDto` 및 `CollectionsModel`의 Meta 정보에서 불필요한 필드(`currentPage`, `totalElements` 등) 제거 및 `nextCursor` 타입을 `Long?`으로 변경 - `CollectionRepository` 및 `CollectionApi`의 `getCollections` 함수 파라미터 타입을 `Long?`으로 변경 - `isLastPage` 판정 로직을 `nextCursor`의 null 여부로 단순화 - `ExploreViewModel`에서 데이터 로드 시 다음 커서 값을 전달하도록 수정
- `ExploreUiState`에 `canLoadMore` 속성을 추가하여 페이징 가능 여부 판단 로직 캡슐화 - `isLastPage` 제거 및 `nextCursor` 유무로 마지막 페이지 판단 로직 통합 - `ExploreViewModel`의 컬렉션 로드 로직을 `fetchCollections` 공통 메서드로 분리 및 구조 개선
- `Collection` 데이터 클래스 내 필드(`imageUrl`, `title`, `description`, `createdAt`) 순서 조정
📝 WalkthroughWalkthrough탐색 화면을 위한 페이지네이션 기반 컬렉션 API를 구현했습니다. API 계층에서 새로운 엔드포인트를 추가하고, 데이터 매핑을 거쳐 도메인 모델로 변환한 뒤, ViewModel을 통해 페이지네이션 상태를 관리하며, UI에서는 동적으로 컬렉션을 렌더링하는 end-to-end 통합입니다. Changes
Sequence DiagramsequenceDiagram
participant User as 사용자
participant Screen as ExploreScreen
participant ViewModel as ExploreViewModel
participant Repo as CollectionRepository
participant API as CollectionApi
participant State as UiState
User->>Screen: 화면 진입
Screen->>ViewModel: getInitialCollections 호출
ViewModel->>Repo: fetchCollections(cursor=null)
Repo->>API: getCollections(cursor=null, size=10)
API-->>Repo: BaseResponse<CollectionsResponseDto>
Repo->>Repo: toModel() 매핑
Repo-->>ViewModel: Result<CollectionsModel>
ViewModel->>State: UiState 업데이트<br/>(collections, nextCursor)
State-->>Screen: collectAsStateWithLifecycle
Screen->>Screen: 컬렉션 렌더링
User->>Screen: 마지막 페이지 근처 스크롤
Screen->>ViewModel: loadNextPage() 호출
ViewModel->>ViewModel: canLoadMore 확인
ViewModel->>Repo: fetchCollections(cursor=nextCursor)
Repo->>API: getCollections(cursor=nextCursor, size=10)
API-->>Repo: BaseResponse<CollectionsResponseDto>
Repo->>Repo: toModel() 매핑
Repo-->>ViewModel: Result<CollectionsModel>
ViewModel->>ViewModel: 기존 + 신규 데이터 병합<br/>isLoadingMore = false
ViewModel->>State: UiState 업데이트<br/>(확장된 collections, 새 nextCursor)
State-->>Screen: 상태 반영
Screen->>Screen: 추가 컬렉션 렌더링
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 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: 2
🤖 Fix all issues with AI agents
In `@app/src/main/java/com/flint/domain/mapper/collection/CollectionMapper.kt`:
- Around line 109-122: The mapping in CollectionsResponseDto.Meta.toModel()
converts nextCursor (String?) to Long? using toLongOrNull(), which will silently
drop non-numeric cursors and prematurely end pagination; either confirm the
backend always returns numeric cursors and keep the conversion, or change the
domain type to accept String? by updating CollectionsModel.Meta.nextCursor to
String? and stop calling toLongOrNull() in
CollectionsResponseDto.Meta.toModel(); locate the conversion in the toModel()
function and adjust the mapping accordingly (or add validation/parsing with
explicit error handling if numeric cursors are required).
In `@app/src/main/java/com/flint/presentation/explore/ExploreViewModel.kt`:
- Around line 75-77: The onFailure block in ExploreViewModel is empty so API
failures leave loading flags set and the UI stuck; update the onFailure handler
used with the API call (the onFailure lambda) to log the throwable, set any
loading flags (e.g., isLoading and isLoadingMore) back to false, and emit an
error or empty state to _uiState (or call the existing method that handles
errors) so the UI can hide spinners and allow retry/pagination again; ensure you
reference the same properties (isLoadingMore, _uiState) and the surrounding
fetch/load method in ExploreViewModel when making these changes.
🧹 Nitpick comments (1)
app/src/main/java/com/flint/presentation/explore/ExploreScreen.kt (1)
55-72: 에러 상태 처리 및 변수 섀도잉 개선이 필요합니다.
- Line 61:
uiState변수가 외부uiState를 섀도잉하여 혼란을 줄 수 있습니다.- Line 71:
else브랜치가 비어있어UiState.Error발생 시 빈 화면이 표시됩니다.♻️ 개선 제안
when (uiState) { UiState.Loading -> { FlintLoadingIndicator() } is UiState.Success -> { - val uiState = (uiState as UiState.Success<ExploreUiState>).data + val exploreData = (uiState as UiState.Success<ExploreUiState>).data ExploreScreen( - collections = uiState.collections, + collections = exploreData.collections, onWatchCollectionButtonClick = navigateToCollectionDetail, onMakeCollectionButtonClick = navigateToCollectionCreate, onLoadNextPage = viewModel::loadNextPage, modifier = Modifier.padding(paddingValues), ) } - else -> {} + is UiState.Error -> { + // TODO: 에러 UI 표시 (재시도 버튼 등) + } }
|
|
||
| import kotlinx.collections.immutable.ImmutableList | ||
|
|
||
| data class CollectionsModel( |
There was a problem hiding this comment.
p2
기존 CollectionListModel이랑 조금 헷갈릴 것 같은데, 저번에 얘기하기로는 explore 붙이기로 하지 않았었나요??
| val pagerState: PagerState = rememberPagerState(pageCount = { pageCount + 1 }) | ||
|
|
||
| LaunchedEffect(pagerState.currentPage) { | ||
| if (pagerState.currentPage >= pageCount - 3 && pageCount > 0) { |
There was a problem hiding this comment.
p3
pageCount - 3이 미리 컬렉션 정보를 불러오기 위함인가요?
# Conflicts: # app/src/main/java/com/flint/presentation/explore/ExploreScreen.kt
📮 관련 이슈
📌 작업 내용
📸 스크린샷
Screen_recording_20260122_001708.mp4
Summary by CodeRabbit
릴리스 노트
✏️ Tip: You can customize this high-level summary in your review settings.