상세 컨텐츠

본문 제목

나만의 안드로이드 앱 만들기(중급자 편) - 클린 아키텍쳐 구현(clean architecture)

나만의 안드로이드 앱 만들기/중급자

by Victorywskim 2023. 12. 24. 01:23

본문

반응형

 

 

이전 편에서는 클린 아키텍쳐에 대해 간략하게 소개해드렸습니다.

관련 내용 확인이 필요하시다면 아래 링크 참고 부탁드립니다.

 

나만의 안드로이드 앱 만들기(중급자 편) - 클린 아키텍쳐 개요(clean architecture)

안드로이드 개발을 하다 보면, 앱의 규모가 커지고 복잡해지면서 유지보수가 어려워지는 경우가 종종 발생합니다. 이러한 문제를 해결하기 위해 클린 아키텍처를 적용하는 것이 좋습니다. 또한

victorywskim.tistory.com

 

이번에는 직접 구현해보는 작업을 진행해보려 합니다.

 

아키텍쳐는 3계층으로 구분하고, domain-data-presentation 으로 구현합니다.

 

  • domain
    • 비즈니스 로직 기반의 모듈로 코틀린으로만 구성하고 안드로이드 의존성은 배제합니다.
  • data
    • 데이터 입출력 기반의 모듈로 서버 api 및 로컬 데이터(sharedPreference or database) 등을 관리합니다.
  • presentation 
    • 실질적인 앱으로 UI 와 유저와의 상호작용을 담당하는 모듈입니다.

 

각 계층들은 모듈 단위로 구성하고 의존 관계를 통해 계층간 관계를 설정하게 됩니다.

 

클린 아키텍쳐 구성은 다음과 같은 순서로 진행합니다.

  1. 모듈을 통해 각 계층을 생성합니다.
  2. 생성한 모듈 내 구조를 설정합니다.
  3. gradle 을 통해 의존 관계를 설정합니다.
  4. 기존 모듈에 있던 클래스들을 각 계층 내 목적에 맞는 위치로 이전합니다.
  5. 테스트를 진행합니다.

아키텍쳐 구성은 프로젝트 생성할때 먼저 설정하는 것이 맞습니다.

그래야 적용하기도 용이하고 소요도 적습니다.

어느정도 개발이 완료된 프로젝트에 클린아키텍쳐 도입이 불가한 것은 아니지만, 소요가 상상 이상으로 커지는 일이 되니 이 점은 충분한 검토가 필요합니다.

 

저는 기존에 개발된 프로젝트를 이용해서 아키텍쳐를 적용하는 과정으로 진행해보겠습니다.

 

작업 예정 코드 링크

 

GitHub - tmvlke/SimpleDutch: 심플더치 프로젝트 입니다.

심플더치 프로젝트 입니다. Contribute to tmvlke/SimpleDutch development by creating an account on GitHub.

github.com

 

1. 모듈을 통해 각 계층을 생성합니다.

 

기존 프로젝트에는 app 및 buildSrc 모듈 만 존재합니다.

data, domain 이라는 모듈을 추가해줍니다.

 

모듈 추가 방법은 다음과 같습니다.

 

그리고 기존 app 모듈을 presentation 으로 변경해줍니다.

 

완료하고 프로젝트 뷰를 보면 다음과 같은 형태가 됩니다.

 

2. 생성한 모듈 내 구조를 설정합니다.

 

domain

domain 모듈은 다음과 같습니다.

  • proguardSafeZone
    • entity 부터 vo 등을 보관하고 proguard 에서 항상 배제하여 난독화에서 자유로운 디렉터리입니다.
  • repository
    • 데이터를 저장하고 검색이 필요한 항목을 관리합니다.
    • domain 에는 interface 만 있고 implements 는 data 계층에 있습니다.
  • usecase
    • 서비스의 핵심 비즈니스 로직을 관리 합니다.
  • utils
    • 날짜 포맷과 같이 서비스 전역에서 사용될 수 있는 유틸 클래스를 관리합니다.

 

data

 

domain 모듈은 다음과 같습니다.

  • dataSource
    • dataStorage에 접근하여 데이터를 입/출력합니다.
  • dataStorage
    • server 및 local 의 데이터에 직접 접근합니다.
  • di
    • repository 및 dataSource 등 의존성을 관리합니다.
  • repository
    • dataSource 를 통해 usecase 에 데이터 입/출력을 수행합니다.

 

presentation

 

presentation 모듈은 다음과 같습니다.

  • common
    • ui 에서 사용할 base class 및 compose 관련 공통 component 를 관리합니다.
  • ui
    • 유저와 인터렉션을 할 뷰를 관리합니다.
3. gradle 을 통해 의존 관계를 설정합니다.

 

build.gradle.kts (domain)

...

dependencies {

    // coroutines
    api(SdDependency.Coroutines.core)
    api(SdDependency.Coroutines.android)

    // Hilt
    implementation(SdDependency.Hilt.android)
    kapt(SdDependency.Hilt.androidCompiler)

    // tdd
    testImplementation(SdTestDependency.Tdd.junit5)
    testRuntimeOnly(SdTestDependency.Tdd.junit5Engine)
    testImplementation(SdTestDependency.Tdd.junit5Params)
    testRuntimeOnly(SdTestDependency.Tdd.junit5ParamsEngine)

    testImplementation(SdTestDependency.Tdd.mockk)
}

...

 

domain 에서는 코루틴이나 힐트 같이 비즈니스 로직 구성에 필요한 라이브러리 위주로 구성합니다.

 

build.gradle.kts (data) 

...

dependencies {
    implementation(project(":domain"))

    // SharedPreferences
    implementation(SdDependency.preference)

    // gson
    implementation(SdDependency.gson)

    // hilt
    implementation(SdDependency.Hilt.android)
    kapt(SdDependency.Hilt.androidCompiler)

    // tdd
    testImplementation(SdTestDependency.Tdd.junit5)
    testRuntimeOnly(SdTestDependency.Tdd.junit5Engine)
    testImplementation(SdTestDependency.Tdd.junit5Params)
    testRuntimeOnly(SdTestDependency.Tdd.junit5ParamsEngine)

    testImplementation(SdTestDependency.Tdd.mockk)
}

...

 

data 는 domain 의 value object 와 repository 등을 알아야하기에 의존 관계를 연결해주고, 데이터 처리 관련 라이브러리를 추가해줍니다.

 

추후 room 이나 okhttp, retrofit 등이 필요한 경우 data 모듈에 추가하면 됩니다.

 

build.gradle.kts (presentation)

...

dependencies {

    implementation(project(":domain"))
    implementation(project(":data"))

    ...

    // tdd
    testImplementation(SdTestDependency.Tdd.junit5)
    testRuntimeOnly(SdTestDependency.Tdd.junit5Engine)
    testImplementation(SdTestDependency.Tdd.junit5Params)
    testRuntimeOnly(SdTestDependency.Tdd.junit5ParamsEngine)

    testImplementation(SdTestDependency.Tdd.mockk)

    testImplementation(SdTestDependency.Tdd.coroutines)

    // bdd1
    androidTestImplementation(SdTestDependency.Bdd.junit)
    androidTestImplementation(platform(SdTestDependency.Bdd.composeBom))
    androidTestImplementation(SdTestDependency.Bdd.composeJunit)

    // bdd2
    debugImplementation(SdTestDependency.Bdd.debugComposeTooling)
    debugImplementation(SdTestDependency.Bdd.debugComposeManifest)
}

...

 

presentation 은 domain 과 data 모두 연결해줍니다.

data 를 알아야 하는 이유는 repository 및 dataSource 관련 di 처리를 해야하기 때문입니다.

 

실제 로직에서는 data 모듈에 있는 파일에 직접적으로 접근하는 일은 없어야하며, viewModel 에서 usecase 를 통해 접근하여 사용해야 합니다.

 

그 외 compose 를 비롯해 coil 이나 animation 처리와 같은 안드로이드 의존성은 모두 여기에 추가하면 됩니다. 

 

4. 기존 모듈에 있던 클래스들을 각 계층 내 목적에 맞는 위치로 이전합니다.

 

data
domain

 

5. 테스트를 진행합니다.

 

 

build 를 진행하였고 성공했다는 결과를 얻었습니다.

 

 

앱도 잘 실행되는 것을 확인하였습니다.

 

전체 코드는 다음과 같습니다.

 

GitHub - tmvlke/SimpleDutch: 심플더치 프로젝트 입니다.

심플더치 프로젝트 입니다. Contribute to tmvlke/SimpleDutch development by creating an account on GitHub.

github.com

 

감사합니다.

반응형

관련글 더보기