← 뒤로
프로젝트 요약
- 한 줄 요약: 도메인 경계/용어/의존성 규칙을 정리하고, 애플리케이션 레이어 조합 및 이벤트 기반 통신으로 순환 참조와 변경 전파 리스크를 줄였습니다.
- 진행/소속: 파트타임스터디
- 키워드: Adapter(Port/Adapter), Domain service / Application service, 이벤트 기반 통신
문제(AS-IS)

- 비개발자 동료와 로직 이해/용어 정의가 충돌하는 경우가 잦음
- 도메인 경계가 모호해 이슈 전파 범위 파악이 어려움
- 서비스 간 의존성 방향이 명확하지 않아 개발 시 순환 참조가 발생
목표(TO-BE)
- 역할 중심 도메인 분리 및 도메인 간 의존성 구체화
- 도메인 용어와 로직을 정리해 팀 전체에 공유
- 도메인 간 통신 방식/규칙을 명시적으로 고정
설계/선택(Key decisions)
- 도메인-DB 분리: 도메인이 DB/ORM에 직접 의존하지 않도록 Adapter(Port/Adapter) 패턴 적용
- 서비스 2계층: Domain service / Application service로 역할을 분리
- Domain service: 도메인 규칙/정책과 도메인 동작 정의
- Application service: 유스케이스 조합, 트랜잭션/락/외부 연동 관리
- 도메인 간 통신 규칙 고정: 아래 2가지만 허용
- Application service에서 여러 Domain service를 조합
- Application service 간 이벤트로 통신
결과(Impact)

- 커뮤니케이션 개선: 용어/경계/규칙이 정리되어 논의 비용이 감소
- 로직 파악 용이: 유스케이스 흐름이 Application service에 모여 변경 지점이 명확해짐
- 의존성 복잡도 감소: 이벤트 기반 통신으로 서비스 간 결합도를 낮춤
구현 상세
1) 도메인–DB 분리: Adapter(Port/Adapter) 패턴
- 배경: 도메인이 Repository/ORM에 직접 의존하면 인프라 변경(DB 전환 등)에 도메인 로직이 묶이고, 테스트/교체가 어려워짐
- 적용: 도메인은 “저장/조회” 포트(인터페이스)만 알고, 실제 DB 접근은 Adapter가 구현
- 도메인:
UserRepository, OrderRepository 같은 인터페이스만 유지
- 인프라: 인터페이스 구현체 배치
- 효과: 도메인 단위 테스트에서 DB 없이 Mock/Stub으로 검증 가능. DB/캐시 교체 시 Adapter 교체로 영향 범위 축소
2) 서비스 2계층: Domain service vs Application service
- Domain service
- 한 도메인 내 행위/규칙/정책만 담당
- 예:
주문 금액 계산, 할인 적용, 재고 차감 가능 여부 판단
- 트랜잭션/락/외부 API 호출/다른 도메인 직접 호출은 하지 않음
- Application service
- 여러 Domain service를 조합하고 트랜잭션 경계/락/외부 연동을 담당
- 예: “주문 생성” 유스케이스에서
OrderDomainService.create() + InventoryDomainService.reserve()를 하나의 트랜잭션으로 묶어 호출
- 효과: “규칙(무엇)”과 “흐름(어떻게)”이 분리되어 비즈니스 로직 파악과 수정 지점이 명확해짐
3) 도메인 간 통신 규칙: 조합 + 이벤트로 한정
아래 방법 외 도메인 서비스 간 직접 상호참조는 제한함.
- 방법 1 – Application service에서 Domain service 조합
- 하나의 유스케이스 안에서 여러 도메인 서비스를 호출할 때 사용
- 필요 시 의존 도메인의 Application service를 호출할 수도 있음
- 동기/비동기 모두 가능
- 적용 기준
- 강한 일관성이 필요한 경우
- 같은 DB/같은 요청 스코프에서 처리해야 하는 경우
- 트랜잭션 외부에서 처리해도 되는 연동은 비동기 조합으로 처리
- 방법 2 – Application service 간 이벤트
- 적용 기준
- Application service 로직 재사용이 필요한 경우
- 특히 의존성 “반대 방향” 통신이 필요한 경우
- 운영/안정성 고려
- 이벤트 발행은 Application service에서만 허용
- 도메인에서 발행 시 한 트랜잭션에서 이벤트가 다수 발행될 수 있고, 프레임워크별 지원(TransactionalEvent 등)이 달라 일관성 유지가 어려움
- 트래픽이 크지 않고 비용 효율이 필요해 별도 메시징 인프라는 도입하지 않음
- 이벤트 유실 대비책
- 유실이 치명적인(critical) 흐름에는 이벤트 도입을 지양
- graceful shutdown으로 재시작 시 누락 가능성을 낮춤
- 이벤트 예외 핸들러 등록(예외 발생 시 잔디 알림)
- 수동 호출 가능한 endpoint 및 일부 기능 어드민 구현
- 유실 가능 구간에는 outbox 패턴을 점진 도입 검토