1.Clean Architecture란?
Clean Code에서 언급된 Clean Architecture는 로버트 C. 마틴(“Uncle Bob”)이 제안한 소프트웨어 아키텍처 패턴 중 하나로, 응집력 있고, 유지보수하기 쉬운 애플리케이션을 설계하기 위한 접근 방식
Clean Architecture 정의
Clean Architecture는 소프트웨어 아키텍처의 핵심 목표를 다음과 같이 정의함.
- 유지보수성(Maintainability): 코드를 쉽게 읽고 변경할 수 있도록 구조화.
- 테스트 가능성(Testability): 비즈니스 로직과 UI, 데이터베이스 등을 분리해 독립적으로 테스트 가능.
- 의존성 관리(Dependency Management): 외부 시스템이나 프레임워크에 종속되지 않음.
- 플랫폼 독립성(Independence): 핵심 비즈니스 로직이 특정 UI 프레임워크나 데이터 소스에 의존하지 않음.
핵심 철학:
"비즈니스 로직과 애플리케이션의 핵심은 모든 외부 요소(UI, 데이터베이스 등)와 독립적이어야 한다."
Clean Architecture의 구조
Clean Architecture는 크게 동심원 계층 구조를 기반으로 설계되며, 각 원은 서로 다른 책임을 가집니다. 이 원칙의 핵심은 의존성 규칙(Dependency Rule)에 기반을 둡니다.
1. 의존성 규칙 (Dependency Rule)
- 의존성은 항상 안쪽으로 향해야 함.
- 바깥쪽 레이어는 안쪽 레이어에 의존할 수 있지만, 안쪽 레이어는 바깥쪽 레이어에 의존할 수 없음.
- 안쪽 레이어는 바깥쪽 레이어의 구현 세부 사항에 대해 알지 못해야 함.
2. Clean Architecture의 계층
1) Entities
- 가장 안쪽 레이어로, 애플리케이션의 핵심 비즈니스 로직과 규칙을 포함.
- 시스템에서 플랫폼 독립적이고 재사용 가능해야 함.
- 데이터 구조 및 비즈니스 규칙만 포함되며, 외부 세계와 독립적.
data class User(
val id: String,
val name: String,
val email: String
)
2) Use Case
- 도메인 계층으로, 특정 비즈니스 작업을 수행하는 애플리케이션의 핵심 로직을 캡슐화.
- 엔터티를 조작하거나 처리하는 방식 정의.
- 비즈니스 로직에 따라 데이터 흐름을 조정.
class GetUserProfileUseCase(private val userRepository: UserRepository) {
fun execute(userId: String): User {
return userRepository.getUserById(userId)
}
}
3) Interface Adapters
- Use Case와 외부 시스템 간의 상호작용을 처리.
- 데이터를 변환하거나 포맷팅하여 Use Case에 적합한 형태로 전달.
- 프레젠테이션 로직(UI 계층)과 도메인 로직을 분리.
class UserRepositoryImpl(private val api: ApiService) : UserRepository {
override fun getUserById(userId: String): User {
return api.fetchUser(userId)
}
}
4) Frameworks & Drivers
- 가장 바깥쪽 레이어로, UI, 데이터베이스, 네트워크 등 시스템의 세부 구현.
- 다른 레이어에 의존하지만, 해당 레이어에 의해 독립적으로 사용될 수 없음.
- 외부 종속성의 세부 사항을 추상화하여 안쪽 레이어로 전달.
예제:
- UI: Android Framework, XML, Jetpack Compose.
- 데이터베이스: Room, SQLite.
- 네트워크: Retrofit, OkHttp.