코틀린 & 컴포즈 & Java/컴포즈 Compose

[Compose] Paging3 클린 아키텍처 적용하다 의문점

코딩하는후운 2025. 2. 6. 15:11
반응형

Paging3 클린 아키텍처 적용

Paging3를 클린 아키텍처에 적용하다가 의문점이 생겼다.

Domain 레이어에 있는 androidx.paging이 안드로이드 종속성이 있지 않나?
사용하면 안되지 않나?
그래서 찾아 보았다.

 

클린 아키텍처에서 Paging 3의 역할

각 계층의 역할

 

Paging 3의 안드로이드 종속성 정리

Paging 3은 여러 개의 모듈로 나뉘어 있으며, 각 모듈이 제공하는 기능을 이해해야 한다.

📌  1. androidx.paging:paging-common (안드로이드 종속성 없음 ✅)

implementation "androidx.paging:paging-common:3.x.x"

 멀티플랫폼(Kotlin Multiplatform)에서도 사용 가능
 안드로이드 종속성이 없으며, Domain 계층에서도 사용할 수 있음

📌 포함된 주요 클래스

  • PagingData
  • PagingSource
  • PagingConfig
  • LoadResult
  • RemoteMediator

📌 Domain 계층에서도 사용 가능!
👉 이 모듈에 포함된 클래스는 Android에 종속되지 않으므로, UseCase에서도 PagingData를 유지할 수 있다.

📌  2. androidx.paging:paging-runtime (안드로이드 종속성 있음 🚨)

implementation "androidx.paging:paging-runtime:3.x.x"

 안드로이드 종속성이 있음 → Data 계층 및 Presentation 계층에서만 사용 가능
 Pager 및 PagingDataAdapter와 같은 Android 특정 기능이 포함됨

📌 포함된 주요 클래스

  • Pager
  • PagingDataAdapter
  • PagingSourceFactory
  • cachedIn(viewModelScope)

📌 이 모듈에 포함된 클래스는 Android 종속적이므로, Domain 계층에서는 사용하면 안 된다.
👉 특히 Pager는 Repository에서만 사용해야 한다.

📌 3. androidx.paging:paging-compose (Compose UI 관련, 안드로이드 종속성 있음 🚨)

implementation "androidx.paging:paging-compose:3.x.x"

✔ Jetpack Compose에서 Paging을 사용할 때 필요한 모듈
✔ Compose UI 계층에서만 사용 가능
✔ 안드로이드 종속성이 있으므로 Domain 및 Data 계층에서는 사용 불가

📌 포함된 주요 클래스

  • LazyPagingItems
  • collectAsLazyPagingItems()
  • LazyColumn { items(lazyPagingItems) }

📌 이 모듈은 UI 계층에서만 사용해야 하며, Repository나 UseCase에서 사용하면 안 된다.

 

클린 아키텍처에서 Paging 3을 올바르게 적용하는 방법

1. Repository에서 PagingData 제공 (Data Layer)

class MyRepository(private val apiService: MyApiService) {
    fun getPagedData(): Flow<PagingData<MyData>> {
        return Pager(
            config = PagingConfig(pageSize = 20),
            pagingSourceFactory = { MyPagingSource(apiService) }
        ).flow
    }
}

 Pager는 안드로이드 종속성이 있으므로 Repository에서만 사용.
 반환값이 Flow<PagingData<MyData>>이므로 Domain에서도 사용할 수 있음.

2. UseCase에서 PagingData를 그대로 전달 (Domain Layer)

class GetPagedDataUseCase(private val repository: MyRepository) {
    operator fun invoke(): Flow<PagingData<MyData>> {
        return repository.getPagedData()
    }
}

 UseCase에서도 PagingData를 그대로 유지할 수 있음!
 PagingData는 안드로이드 종속성이 없으므로 Domain 계층에서도 사용 가능!

3. ViewModel에서 PagingData 처리 (Presentation Layer)

@HiltViewModel
class MyViewModel @Inject constructor(
    private val getPagedDataUseCase: GetPagedDataUseCase
) : ViewModel() {
    val myPagingData: Flow<PagingData<MyData>> = getPagedDataUseCase()
        .cachedIn(viewModelScope) // ViewModel에서 캐싱 유지
}

 여기서 cachedIn(viewModelScope)를 적용해야 UI에서 collectAsLazyPagingItems()로 사용할 수 있음.
 이 부분은 안드로이드 종속성이 있으므로 반드시 ViewModel에서 처리해야 함.

 

정리

 

📌 결론:

✔ PagingData, PagingSource, PagingConfig는 Domain 계층에서도 사용할 수 있다.
✔ Pager, LazyPagingItems, cachedIn()은 Android 종속성이 있으므로 UI나 Repository에서만 사용해야 한다.
✔ UseCase에서는 PagingData를 그대로 유지하면 된다. (변환할 필요 없음!)

 

참조 :
https://medium.com/bforbank-tech/paging-3-through-clean-architecture-4d771ab19fa8
https://leveloper.tistory.com/208

 

반응형