728x90
계층형 아키텍처의 문제
- 계층형 아키텍처는 토대가 DB이기 때문에, DB 주도 설계를 유도함
- 계층형 아키텍처는 DB중심적인 아키텍처이기 때문에 비즈니스 관점에서 맞지 않음 → 도메인 로직을 먼저 만들고 제대로 이해해야하 영속성과 웹계층을 만들 수있음
- 계층형 아키텍처는 같은 계층에 있는 컴포넌트나 아래 계층에 접근이 가능하기 때문에 암묵적으로 용인하면 영속성 → 도메인으로 접근하는 코드가 늘어나게 됨
- 계층형 아키텍처는 시간이 지나면서 시스템이 비대해질수록, 계층을 건너뛰어 접근하는 경우도 생기게 되면서, 도메인 로직이 전체에 걸쳐 책임이 섞이게 됨
- 계층형 아키텍처의 이러한 문제의 해결방법으로는 DIP(의존성 역전법칙)으로 해결을 했었음 → 모든 계층에 DIP로 해결해서 적용하면 헥사고날 아키텍처의 형태를 띄게 됨
계층형 아키텍처에서 헥사고날 아키텍처 진화 과정
- 계층형 아키텍처
- 의존성 역전 법칙을 적용한 계층형 아키텍처
- 헥사고날 아키텍처
위 이미지 순서처럼 의존성 역전법칙을 통하여 헥사고날 아키텍처 형태로 진화
헥사고날 아키텍처 정의
- 헥사고날 아키텍처는 어플리케이션 코어가 육각형으로 표현되기 때문에 정해졌음
- 어댑터와 연결되는 4개 이상의 면을 가질 수 있음을 보여주기 위해 사각형 대신 육각형(헥사고날)으로 정함
- 육각형 안에는 도메인 엔티티와 상호작용하는 유스케이스가 있음, 육각형에서 외부로 향하는 의존성이 없고 모든 의존성이 코어로 향함
- 포트 앤 어댑터 아키텍처라고도 불리기도함
헥사고날 아키텍처 요소 및 구성
포트(port) | 인터페이스로 계층간 경계를 지정하는 역할을 함, DI를 위한 추상화 애플리케이션 서비스와 어댑터 사이의 간접적인 계층이며, 계층에 대한 코드의 의존성을 없앰
|
어댑터(adapter) | 포트의 구현체이며 서비스를 호출하거나 서비스에 의해서 호출이 됨
|
유스케이스 |
시스템을 사용하는 클라이언트가 그 시스템을 통해 하고자하는 것, 도메인의 비즈니스 로직을 오케스트레이션하는 역할 (인풋 포트) (예시 : 기존계층형 서비스 역할) |
엔티티 | 도메인에서 다루는 핵심 개체 (예시 : 기존 계층형 아키텍처에서 JPA로 관리되는 엔티티) |
헥사고날 아키텍처 예시
패키지 구조 | 요약 |
|
@WebAdapter
@RestController
@RequiredArgsConstructor
class SendMoneyController {
private final SendMoneyUseCase sendMoneyUseCase;
@PostMapping(path = "/accounts/send/{sourceAccountId}/{targetAccountId}/{amount}")
public void sendMoney() {
....
public interface SendMoneyUseCase {
boolean sendMoney(SendMoneyCommand command);
....
@RequiredArgsConstructor
@UseCase
@Transactional
public class SendMoneyService implements SendMoneyUseCase {
private final LoadAccountPort loadAccountPort;
private final AccountLock accountLock;
private final UpdateAccountStatePort updateAccountStatePort;
private final MoneyTransferProperties moneyTransferProperties;
@Override
public boolean sendMoney(SendMoneyCommand command) {
....
public interface LoadAccountPort {
Account loadAccount(AccountId accountId, LocalDateTime baselineDate);
....
@RequiredArgsConstructor
@PersistenceAdapter
class AccountPersistenceAdapter implements
LoadAccountPort,
UpdateAccountStatePort {
private final SpringDataAccountRepository accountRepository;
private final ActivityRepository activityRepository;
private final AccountMapper accountMapper;
@Override
public Account loadAccount(
AccountId accountId,
LocalDateTime baselineDate) {
...
- 해당 구조로 하면 어댑터 같은 경우 쉽게 교체가 가능함
- 예를 들어 특정 DB를 변경해야 할 경우 아웃고잉포트들만 새로운 어댑터 패키지에 구현하고 기존 연동된 어댑터를 변경해주면 됨
참고 : https://github.com/wikibook/clean-architecture
헥사고날 아키텍처 요약
- 계층형 아키텍처인 Controller - Service - Data Layer를 분리하여, 느슨하게 커플링된 어플리케이션을 구성
- 어플리케이션 전체에 일관된 의존성 규칙을 적용하여, 자신이 코딩하지 않은 코드를 볼 때 비용을 낮춰줌 (유지보수성 증가)
- 분리된 계층의 의존성을 최소화하여 독립된 테스트를 구성하게 해줌
'OTHER' 카테고리의 다른 글
[OTHER] 동시성 문제 해결 방법 (0) | 2022.09.01 |
---|---|
[OTHER] 멱등성 (0) | 2022.04.25 |
[OTHER] Semantic Versioning (0) | 2022.04.07 |
[OTHER] TDD (테스트 주도 개발론) (0) | 2021.11.14 |
[OTHER] 마이크로 서비스 아키텍처 (0) | 2021.09.28 |