비즈니스 로직을 외부 기술로부터 보호하기 위한 아키텍처

헥사고날 아키텍처는 2005년 Alistair Cockburn이 제안한 설계 방식으로,
애플리케이션의 핵심 도메인을 외부 의존성으로부터 분리하는 것을 목표로 한다.

다른 이름으로는:

  • Ports and Adapters Architecture
  • Onion Architecture
  • Clean Architecture (유사 개념)

라고도 불린다.


왜 등장했는가?

기존의 레이어드 아키텍처는 이런 구조였다.

 
 
Controller

Service

Repository

DB
 

문제는 무엇이었을까?

  • Service가 Repository에 강하게 의존
  • DB가 바뀌면 비즈니스 로직도 수정
  • 테스트 시 DB 필요
  • 외부 API 교체 시 서비스 코드 수정

즉, 비즈니스 로직이 인프라에 종속되는 구조였다.

헥사고날은 이 의존성을 뒤집는다.


핵심 개념

1️⃣ Port (포트)

비즈니스 로직이 외부와 통신하기 위한 인터페이스.

In Port

  • 외부 요청이 들어오는 인터페이스
  • UseCase

Out Port

  • 외부 시스템(DB, API 등)에 접근하기 위한 인터페이스

2️⃣ Adapter (어댑터)

Port를 실제로 구현하는 기술 코드.

예:

  • Controller
  • JPA Repository
  • Redis Client
  • Kafka Producer

3️⃣ Domain (핵심)

비즈니스 규칙이 존재하는 영역.

여기에는 다음만 존재해야 한다:

  • Entity
  • Value Object
  • Domain Service
  • Business Rule

여기에는 절대 없어야 하는 것:

  • JPA
  • Spring
  • HTTP
  • DB
  • 외부 API

구조 예시

 
 
user
├─ adapter
│ ├─ in (web)
│ └─ out (persistence)
├─ application
│ ├─ port
│ │ ├─ in
│ │ └─ out
│ └─ service
└─ domain
 

의존성 방향은 항상 안쪽을 향한다.

 
 
Adapter → Application → Domain
 

Domain은 아무것도 모른다.


코드 예시

In Port

 
 
public interface CreateUserUseCase {
void createUser(CreateUserCommand command);
}
 

Application Service

 
 
@Service
@RequiredArgsConstructor
public class CreateUserService implements CreateUserUseCase {

private final UserRepositoryPort userRepositoryPort;

@Override
public void createUser(CreateUserCommand command) {
User user = User.create(command);
userRepositoryPort.save(user);
}
}
 

Out Port

 
 
public interface UserRepositoryPort {
void save(User user);
}
 

Adapter (JPA 구현)

 
 
@Repository
@RequiredArgsConstructor
public class UserRepositoryAdapter implements UserRepositoryPort {

private final SpringDataUserRepository repository;

@Override
public void save(User user) {
repository.save(UserJpaEntity.from(user));
}
}
 

Application은 JPA를 모른다.
Domain은 Spring을 모른다.


헥사고날의 장점

1️⃣ 테스트가 쉬워진다

Out Port를 Mock으로 대체하면 된다.

DB 없이 테스트 가능.


2️⃣ 기술 교체가 자유롭다

  • JPA → MyBatis
  • MySQL → MongoDB
  • REST → Kafka

비즈니스 로직 수정 없이 교체 가능.


3️⃣ MSA 전환에 유리

각 도메인을 독립 모듈로 분리하기 쉬움.


4️⃣ 의존성 방향이 명확하다

항상 안쪽(도메인)을 향한다.

외부 기술은 플러그인처럼 붙는다.


단점

1️⃣ 초기 러닝커브

  • Port
  • Adapter
  • UseCase 분리

개념 이해가 필요하다.


2️⃣ 파일 수 증가

CRUD만 있는 작은 프로젝트에는 과할 수 있다.


언제 쓰는 것이 좋은가?

✔ 도메인 복잡도가 높은 시스템
✔ 결제, 정산, 금융 시스템
✔ 장기 유지보수 시스템
✔ 테스트 중요 시스템
✔ MSA 고려 시스템

❌ 단순 게시판 CRUD


레이어드 vs 헥사고날 비교

구분레이어드헥사고날
의존성 위→아래 외부→내부
테스트 DB 필요 Mock 가능
기술 교체 어려움 쉬움
구조 명확성 보통 매우 명확

결론

헥사고날 아키텍처는 단순히 폴더 구조가 아니다.

“비즈니스 로직을 보호하기 위한 설계 철학”이다.

기술은 바뀐다.
DB는 바뀐다.
프레임워크는 바뀐다.

하지만 도메인은 바뀌지 않는다.

핵심은 이것이다:

도메인을 중심에 두고, 외부 기술을 주변부로 밀어내는 것.

LIST

+ Recent posts