kee-log

Application Service는 어디에 있는가

Application Service는 어디에 있는가

CQRS의 Command Handler 안에서 로직을 더 잘게 쪼개고 싶을 때 처음 걸리는 질문이 있습니다. 이걸 "Application Service"라고 불러도 되는가? 이건 CQRS 용어인가, DDD 용어인가, Clean Architecture 용어인가?

결론부터 말하면 Application Service는 CQRS의 구성 요소가 아니라, Clean/Hexagonal Architecture의 Application Layer에 속하는 협력 객체입니다. CQRS의 Command Handler가 필요할 때 갖다 쓰는 도구일 뿐, CQRS 자체가 요구하는 개념은 아닙니다.

Command Handler와 Application Service를 언제 나누고 언제 합칠지에 대한 실전 판단 기준은 Command Handler와 Application Service, 뭐가 다른가에서 다뤘습니다. 이 글은 그보다 한 단계 앞에서, "Application Service"라는 용어 자체가 아키텍처마다 어떤 위치를 가리키는지를 정리합니다.

각 관점에서 같은 대상을 어떻게 부르는지 나란히 놓아보면 정리가 됩니다.

CQRS 관점

Command → Command Handler → 상태 변경
Query   → Query Handler   → 조회

Command Handler에 모든 로직을 우겨넣지 않기 위해 내부 협력자로 분리한 것이 Application Service입니다.

Command Handler
 → Application Service
    → Repository / Domain Entity / Port 사용

Clean Architecture 관점

Application Layer는 "무엇을 할지"를 조정(orchestration)하는 역할을 합니다. 도메인 규칙은 도메인 객체가 지키고, Application Layer는 그 규칙들을 엮어서 하나의 흐름으로 만듭니다.

Application Service
 → Repository Port
 → Domain Entity Method 호출
 → Result 반환

DDD 관점

DDD는 이 레이어의 서비스를 세 갈래로 구분합니다.

구분역할
Domain Service도메인 규칙 자체. Entity/ValueObject에 넣기 애매한 순수 비즈니스 규칙
Application Service유스케이스 흐름 조정, 트랜잭션, 저장소·외부 포트 호출, 도메인 객체 메서드 호출
Infrastructure ServiceDB, 외부 API, 메시지 브로커 등 기술 구현

여기서 실무 판단이 자주 갈리는 지점은 "이게 도메인 규칙 자체를 계산하는가, 아니면 도메인 객체를 조회해서 호출만 하는가"입니다. 예를 들어 재고를 조회해서 inventory.storeAt(...)을 호출하는 코드는, 재고 상태 전이 규칙 자체를 계산하는 게 아니므로 Domain Service가 아니라 Application Service입니다. 규칙을 계산하면 Domain, 규칙을 호출/조합하면 Application — 이 한 줄이 가장 실용적인 구분선이었습니다.

Hexagonal Architecture 관점

Hexagonal에서는 Application Service가 보통 Inbound Adapter와 Domain 사이의 UseCase 구현체, 혹은 UseCase 내부 협력 서비스로 나타납니다.

Inbound Adapter
 → Command Handler / UseCase
    → Application Service
       → Driven Port
          → Infrastructure Adapter

한 줄 정리

아키텍처 위치  : Application Layer
패턴 관점      : UseCase 내부 협력 객체 / Application Service
CQRS 관점      : Command Handler가 위임하는 내부 서비스
DDD 관점       : Domain Service가 아니라 Application Service
Hexagonal 관점 : Port를 사용해 업무 흐름을 조정하는 Application 내부 구성요소

판단 기준을 압축하면 이렇습니다.

  • 도메인 규칙 자체 → Domain Entity 또는 Domain Service
  • 유스케이스 흐름·저장소 조회·트랜잭션 전 단계 조합 → Application Service
  • 외부 기술 구현 → Infrastructure Adapter
  • 외부에서 호출하는 진입점 → Command Handler / UseCase / Driving Port

즉 Command Handler 내부를 Application Service로 쪼개는 건 CQRS를 대체하는 게 아니라, CQRS Handler 내부를 Application Layer답게 정리하는 작업일 뿐입니다.

다음 글에서는 이렇게 나눈 Application Service를 언제 인터페이스로 뽑아야 하는지를 다룹니다. → 인터페이스는 언제 만들어야 하는가