Android/Clean Architecture

[안드로이드] 클린 아키텍처(Clean Architecture) Mapper 클래스 그게 필요해?

c0de_h0ng 2022. 12. 21. 22:49
728x90

Mapper 클래스란?

클린 아키텍처 3 계층 중에 데이터 계층에 속한 클래스로 서버나, Room과 같은 로컬에서 받아온 데이터 모델과 UI/UX에 맞는 데이터 모델로 매핑하는 클래스

클린 아키텍처(Clean Architecture)를 프로젝트에 적용하면서 mapper 클래스의 기능, 사용성, 정의 등에 대해 고민을 한 적이 있다. 팀 내에서 반대 의견은 데이터 계층에 데이터 모델을 두지 말고 도메인 계층에 데이터 모델을 두면 되는데 왜 관리포인트 두 개를 만들면 오히려 유지보수 측면에서 비효율적이지 않은가였다.

처음에는 어?! 그런가..?라고 생각했지만 클린 아키텍처 협의 세미나 때 다음 아래와 같은 장점 및 정의를 제시하고 이에 팀원들이 동의해서 mapper 클래스 사용을 하기로 하였다.

프로젝트가 커질수록 데이터 모델이 스파게티 코드가 되면서 유지보수 측면에서 비효율적이다. 

물론 백엔드팀, 웹프론트팀, 앱개발팀 사이에 협의가 아주 잘돼서 아주 깔끔한 Api Response 구조가 내려온다면 위 의견에 동의할 순 없겠지만 현실 고증으로는 절대 그럴 수가 없다. 백엔드팀 및 웹 프론트팀에서 내려주는 api response를 가지고 앱개발팀은 입맛에 맞게 매핑을 해야 하는데 이를 그대로 사용한다면 뒷일은 크흠... 상상도 하기 싫다.

클린아키텍처 규칙에 어긋난다.

도메인 계층은 Android 의존성을 가지고 있지 않아야 한다라는 규칙에 어긋난다. 만약 도메인 계층에 데이터 모델을 두게 되면 room이나 @SerializedName을 사용해야 하므로 Android 의존성을 가지게 된다.

여러 가지 api response 구조를 내 입맛대로 사용할 수 있다.

아마 위 의견이 가장 마음에 와닿을 것이다. 프로젝트가 큰 앱은 Api를 제공하는 팀도 많을 것이다. 많은 팀들이 동일한 구조의 api response를 주기에는 현실적으로 불가능해 앱 개발 쪽에서 입맛에 맞게 포맷을 해야 한다. 

아래와 같은 개발 조건이 있다고 가정을 해보자.

화면 예시
1. 4가지 카테고리 탭이 존재
2. 각 탭은 4개의 백엔드 팀이 api를 각각 제공
3. 각 탭을 누를 때마다 RecyclerView로 표현하기
4. 각 탭의 결과인 RecyclerView 아이템 UI 모두 동일

이러한 조건일 경우에 mapper 클래스를 사용하면 4개의 팀이 어떻게 api response를 주든 앱 개발팀 내에서 정의한 대로 데이터를 사용하면 된다.

Mapper 클래스 정의

Mapper 클래스를 사용했을 때 방법을 기록해 보았다.

먼저 매핑에 관한 인터페이스를 생성한다.

interface DtoMapper<Domain, Dto> {
    fun asDomain(dto: Dto): Domain
}

이렇게 만든 인터페이스를 가지고 object 클래스를 사용해서 매핑 클래스를 정의하면 된다.

object SearchResultMapper : DtoMapper<SearchResult, SearchResultDto> {
    override fun asDomain(dto: SearchResultDto): SearchResult {
        return SearchResult(
            dto.keyword,
            dto.rank
        )
    }
}
fun SearchResultDto.asDomain() = SearchResultMapper.asDomain(this)

이렇게 만든 asDoamin() 확장함수를 매핑할 데이터 모델에 사용하면 된다.

response.data?.result?.asDomain()