이번에 우테코 팀 프로젝트를 진행하며 서비스 의존을 하자는 의견을 냈고, 팀원이 서비스간 의존을 피하는게 좋다고 하여 이것이 가능한지, 그리고 무엇이 효율적인지 공부하고 정리해보려고 한다
.
우리가 흔히 말하는 4계층 아키텍처는 다음과 같은 책임 분리를 따른다:
| 계층 | 예시 | 책임 |
|---|---|---|
| Controller (Web Layer) | @RestController | 외부 요청 처리 및 DTO 변환 |
| Application Layer | XXXService | 유즈케이스 조합, 트랜잭션 관리, 외부 시스템 호출 |
| Domain Layer | Aggregate, DomainService | 도메인 규칙, 상태 변화, 비즈니스 의사결정 |
| Infrastructure Layer | Repository, 외부 API Client | 영속성, 외부 통신 세부 구현 |
핵심은 도메인은 그 자체로 존재하며 외부 의존성, Application을 참조하지 않고, Application만이 Domain을 관리 한다는 점이다.
예를 들어 다음과 같은 구조를 보자:
public class OrganizerService {
private final EventService eventService;
}
겉보기엔 자연스럽지만, 이는 Application Layer끼리 서로 참조하고 있는 구조다. 이렇게 되면 다음 문제가 발생한다:
Application → Domain → Infrastructure 순으로 단방향 의존이 있어야 하는데, Service 간 참조가 늘어나면 그 방향이 뒤틀린다.
하나의 서비스 변경이 다른 서비스에 영향을 준다. 이는 테스트, 유지보수, 리팩터링을 어렵게 만든다.
다들 Serivce의 버그를 디버깅할때 이 서비스 저 서비스 이동한 경험이 있을 것이다.
"OrganizerService에서 Event를 생성하는 게 맞나?", "이건 EventService에서 처리해야 하지 않나?" 와 같은 논의가 계속된다.
최악의 경우 심지어는 Event 생성을 두곳에서 하는 경우도 생기게된다
public List<Event> findByParticipant(Long participantId) {
return eventRepository.findByParticipantId(participantId);
}
ApplicationService끼리 참조하지 않고도, 필요한 도메인 데이터를 직접 리포지토리로 가져올 수 있다.
이벤트 도메인 자체가 Participant 개념을 알고 있어야 한다면, 도메인 규칙으로 통합한다.
→ 즉, 애초에 그 책임이 Domain에 있는지부터 다시 검토해야 한다.
List<Event> events = participantService.findAllEvents(participantId);
return events.stream()
.map(event -> event.getName())
.toList();
이건 캡슐화 파괴인가?
캡슐화는 "데이터를 숨기는 것"이 아니라, "의사결정(=도메인 로직)의 주체를 명확히 하는 것"이다.
결국 캡슐화는 사이드이펙트를 없애기 위한 원칙이다.
| 원칙 | 설명 |
|---|---|
| 서비스 간 참조는 최대한 피한다 | 서비스는 독립적인 유즈케이스 단위로 설계되어야 한다 |
| 도메인 로직은 도메인 안에서 판단한다 | getter로 데이터 빼서 판단하지 말고, event.isBelongsTo(participant) 같은 메서드를 도메인에 둔다 |
| Application Service는 orchestration만 한다 | 상태 변화, 판단은 Domain에서 해야 한다 |
| 기능 명은 책임과 부작용을 명확히 드러내야 한다 | createEventAndSendMail()처럼, 숨겨진 행동이 없게 한다 |
도메인 주도 설계와 4계층 아키텍처의 핵심은 의존 방향과 책임의 명확화다.
둘 모두에 매몰될 필요는 없다.
하지만 두 가지 모두 객체를 좀 더 명확하게 관리하려고 하는 점에서 나온 것들이다.
객체를 명확하게 관리한다는면에서는 한번 열심히 지켜보는것도 학습면에서 좋을지도?
DDD 개념들을 열심히 적용할 생각은 없지만 한번 학습은 해보려고한다.