아키텍처: 코드를 어떻게 작성하고 어디에 위치시켜야 하는가
일정 규모 이상이 되면 아키텍처는 서서히 무너지고, 계층 간 경계가 약화되고, 테스트하기 어려워지고, 새로운 기능을 구현하는 데 더 많은 시간이 든다.
= 의존성이 올바른(안쪽) 방향을 향하도록 강제한다.
= 점선(허용되지 않은 의존성)을 없앤다.
자바에서 제공하는 가장 기보적인 도구
payment
ㄴ account
ㄴ domain
ㄴ + Account
ㄴ + Activity
ㄴ application
ㄴ o SendMoneyService
ㄴ port
ㄴ in
ㄴ + SendMoneyUseCase
ㄴ out
ㄴ + LoadAccountPort
ㄴ + UpdateAccountStatePort
ㄴ adapter
ㄴ in
ㄴ web
ㄴ o AccountController
ㄴ out
ㄴ persistence
ㄴ o AccountPersistenceAdapter
ㄴ o SpringDataAccountRepository
o
: package-private, 포트를 통해 제공되기 때문에 외부에서 접근할 필요가 없다.+
: public, 다른 계층에서 domain 패키지 접근, web/persistence 어댑터에서 application 계층 접근코드가 컴파일된 후 런타임에 체크한다.
지속적인 통합 빌드 환경에서 자동화된 테스트 과정에서 가장 잘 동작한다.
public class DependencyRuleTests {
@Test
void domainLayerDoesNotDependOnApplicationLayer() {
noClasses()
.that()
.resideInAPackage("com.woowa.cleanarchitecture.account.domain..")
.should()
.dependOnClassesThat()
.resideInAnyPackage("com.woowa.cleanarchitecture.account.application..")
.check(new ClassFileImporter()
.importPackages("com.woowa.cleanarchitecture.account.."));
}
}
패키지로 아키텍처 경계를 구분하던 이제까지는 모든 코드가 monolithic(하나로 된 거대한) build artifact의 일부였다.
코드베이스를 빌드 아티팩트로 변환 전, 이 코드베이스가 의존하고 있는 모든 아티팩트가 사용 가능한지 확인한다. 사용 불가능하다면 아티팩트 리포지토리부터 가져온다. 이것도 실패한다면 컴파일도 전에 에러를 발생시킨다.
1. 기본적인 3개의 모듈 빌드 방식
아키텍처를 잘 유지해나가고 싶다면 의존성이 올바른 방향을 가리키는지 지속적으로 확인하자.