문제 상황: 도메인 간 강한 결합
프로젝트가 커지면서 도메인 간 협력이 복잡해졌습니다.
1. API 호출 중복
// EventService.java - 상품 정보 조회
private List<SearchProductResponse> productSearch(List<Long> productIds) {
// 13줄의 RestTemplate 코드...
}
// OrderService.java - 또 상품 정보 조회
private List<SearchProductResponse> productSearch(List<Long> productIds) {
// 거의 동일한 13줄 코드 반복...
}
// SubscribeService.java - 또또 상품 정보 조회
private SearchProductResponse getProductInfo(Long productId) {
// 또 다른 형태의 RestTemplate 코드...
}
2. 도메인 패키지 직접 탐색
다른 도메인의 기능을 사용하려면 해당 패키지를 뒤져야 했습니다.
3. 이벤트 발행/구독 코드 분산
// EventService.java - 이벤트 발행
eventPublisher.publishEvent(new WSEventProduct(
event.getEventId(),
productId,
event.getEventType(),
productName,
originalPrice,
discountPrice,
discount
));
// NotificationService.java - 이벤트 구독
@EventListener
public void handleProductEvent(WSEventProduct event) {
// 구독 로직...
}
문제는 다른 도메인에서 이벤트를 사용하려면:
- WSEventProduct 클래스가 어디에 있는지 찾아야 함
- 이벤트 발행 방법을 EventService 코드를 뒤져서 파악해야 함
- 도메인 패키지 간 직접적인 의존성 발생
해결책: Common 패키지로 공통화
패키지 구조

구현: API 호출 공통화
예시 : ProductApiClient - 모든 Product API 호출 담당

예시 : 이벤트 발행/구독 공통화
1. 공통 이벤트 DTO

2. 공통 이벤트 발행 클라이언트

개선 효과
1. 코드 중복 제거
- Before: 각 도메인마다 13줄의 RestTemplate 코드
- After: 1줄의 메서드 호출
2. 의존성 방향 개선
❌ Before:
event → product.dto (직접 의존)
order → product.controller (URL 탐색)
notification → event.dto (이벤트 클래스 탐색)
✅ After:
event → common (공통 모듈 의존)
order → common (공통 모듈 의존)
notification → common (공통 모듈 의존)
3. 도메인 지식 캡슐화
// Before: URL, HTTP 메서드, DTO 구조 모두 알아야 함
URI uri = UriComponentsBuilder
.fromUriString("http://localhost:8080")
.path("/api/products/search-product") // 어떻게 알지?
.encode()
.build()
.toUri();
// After: 메서드 이름만 알면 됨
List<ProductDto> products = productApiClient.getProducts(productIds);
핵심 설계 원칙
1. 단일 책임 원칙
- ProductApiClient: API 호출만 담당
- ProductEventPublisher: 이벤트 발행만 담당
- 각 도메인 Service: 비즈니스 로직만 담당
2. 의존성 역전 원칙
// ✅ 상위 모듈(도메인)이 하위 모듈(common)에 의존
@Service
public class EventService {
private final ProductApiClient productApiClient; // 인터페이스에 의존
}
3. 캡슐화
- URL, HTTP 메서드, 요청 형식 등 구현 상세사항을 Common에서 숨김
- 도메인은 비즈니스 로직에만 집중 가능
4. 재사용성
- 한 번 구현한 클라이언트를 모든 도메인에서 재사용
- 일관된 API로 학습 비용 최소화
결론
Common 패키지 도입으로 얻은 것들:
- 개발 생산성 향상
- 다른 도메인 패키지 뒤질 필요 없음
- 일관된 API로 학습 비용 감소
- 유지보수성 개선
- 중복 코드 제거
- 한 곳에서 관리하는 API 호출 로직
- 확장성 확보
- 새로운 도메인 추가 시 Common 활용
- 일관된 아키텍처 패턴
- 도메인 순수성
- 각 도메인이 비즈니스 로직에만 집중
- 기술적 관심사와 비즈니스 관심사 분리
"도메인 간 협력은 Common을 통해, 각 도메인은 자신의 책임에만 집중하자!"
'Spring 7기 프로젝트 > 플러스 팀 프로젝트' 카테고리의 다른 글
| Spring Boot에서 RestTemplate 내부 API 호출 시 JWT 토큰 전달하기 (2) | 2025.07.11 |
|---|---|
| 도메인주도 설계 및 데이터 흐름 시각화하기 (1) | 2025.07.10 |
| 도메인 주도 설계 : 다대다 관계에서 애그리거트 경계 설정하기 (0) | 2025.07.08 |