아키텍처는 코드를 구성하는 원칙이다. 구현한 코드가 어디에 배치돼야 하는지에 대한 길을 제시하여 로직이 무질서해지는 것을 방지한다. 아키텍처가 제시하는 원칙을 잘 따르면 어떤 로직을 어디에 구현할지를 고밍하지 않아도 된다. 이는 개발자가 DDD의 본질인 도메인을 파악하고 잘 표현하는 것에 집중할 수 있게 해 준다.
이번 시간에는 DDD에서 자주 언급되는 아키텍처들을 정리해보려고 한다.
계층형 아키텍처란 DDD에서 언급되는 아키텍처 중에서 가장 유명한 아키텍처로 말 그대로 여러 층이 쌓인 구조를 가진다.
다음과 같이 4개의 계층으로 구성되어 있다.
의존의 방향은 위에서 아래로 향한다. 이 방향을 거스르는 의존은 허용되지 않는다.
헥사고날 아키텍처(hexagonal architecture)는 육각형이 모티브인 아키텍처로 애플리케이션과 그 외 인터페이스를 자유롭게 탈착 가능하는 컨셉을 가지고 있다.
게임기를 예로 들 수 있다. 게임기는 게임 컨트롤러, 모니터 등 사용자와 직접 접하는 인터페이스를 갖는다. 그리고 이들은 다양한 제품을 사용자의 취향에 맞게 연결해 사용할 수 있다.
애플리케이션 외의 모듈은 다른 것으로 바꿔 끼울 수 있다. 인터페이스나 저장 매체가 바뀌어도 코어가 되는 애플리케이션에는 영향을 미치지 않는다.
헥사코날 아키텍처는 어댑터가 포트 모양만 맞으면 동작하는 것과 같다고 해서 포트앤어댑터라고 부르기도 한다. 이때 애플리케이션에 대한 입력을 받는 포트 및 어댑터를 프라이머리 포트, 프라이머리 어댑터라고 한다. 반대로 애플리케이션이 외부와 상호작용하는 포트를 세컨더리 포트, 이를 구현한 객체를 세컨더리 어댑터라고 한다.
class UserApplicationService {
private readonly userRepository: IUserRepository;
...
update(command: UserUpdateCommand) {
...
userRepository.save(user);
}
}
사용자 정보를 수정하는 update 메서드를 호출하는 클라이언트는 프라이머리 어댑터가 되고, update 메서드는 프라이머리 포트가 된다. 애플리케이션은 IUserRepository 라는 세컨더리 포트를 호출해 이를 구현한 구현체(세컨더리 어댑터)에 인스턴스 복원이나 저장을 요청한다.
계층형 아키텍처와의 차이점은 인터페이스를 이용해 의존 관계를 관리한다는 점이다. (계층형 아키텍처에서는 논리적으로 계층이 분리되어 있을 뿐, 인터페이스를 사용할지 여부는 강제되지 않는다.)
클린 아키텍처는 비지니스 규칙을 캡슐화한 모듈을 중심에 두고, 사용자 인터페이스나 데이터 스토어와 같은 세부사항은 가장 자리에 위치하는 구조를 가고 있다. 의존 관계의 방향을 바깥에서 안쪽으로 향하게 함으로써 세부 사항이 추상에 의존하는 의존 관계 역전 원칙을 만족한다.
Reference
도메인 주도 설계 철저 입문 (나루세 마사노부 저/심효섭 역)
https://wikibook.co.kr/article/layered-architecture/
https://appleg1226.tistory.com/45
https://velog.io/@so-eun/%ED%81%B4%EB%A6%B0-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98Clean-Architecture