Spring MVC

springmvc.egloos.com


포토로그


2012/08/25 22:56

Service Domain Driven Design

도메인 주도 설계에서 말하는 'Service'란 근본적으로 'Entity'나 'Value Object'와 다르지 않다. 물론 다르지 않다는 개념 자체가 'Service'가 데이터 단위로 활용된다거나 일정한 값을 가지고 있다는 뜻은 아니고 동일하게 도메인 레이어 (또는 계층)에서 'Entity'나 'Value Object'와 같은 오브젝트 따위로 취급되는 것을 일컫는다.

이게 개념은 말처럼 쉬운데 사실 기존의 개발풍토에 익숙한 개발자라면 실질적으로 깨닫고 코드로 옮기기까지 매우 많은 시행착오를 겪을 수 있다. 왜냐하면 보통 개발환경에서 통념 상 'Service'는 하나의 계층으로 'DAO' 계층에서 작성된 오브젝트를 근간으로 크리티컬한 로직을 작성하거나 처리하는 용도로 사용되곤 하지만 도메인 주도설계에서 'Service'는 객체의 행위 또는 활동을 표현하는 단위로 사용되기 때문이다.

필자가 겪은 시행착오를 하나 살펴보자. 다음의 코드는 처음 서비스 오브젝트를 만들 때 습관적인 개발방식에 따라 작성한 서비스 인터페이스이다.
public interface UserService {
User add(User user);
User update(User user);
void remve(User user);
...
}

좀 급하게 만드느라 약간 'DAO (Data Access Object)'스런 코드를 만들긴 했지만 어찌됬든 일반적인 개발환경의 관점에서 바라보자면 위의 코드는 충분히 서비스 계층에서 끌고 나갈 수 있는 코드이기도 하다. 이런 코드를 도메인 주도설계에서는 맹목적인 서비스라고도 하는데 서비스 자체가 하나의 도메인 오브젝트('Entity' 또는 'Value Object')에 종속적이고 행동이나 활동에 근간을 두지 않고 'Management'의 성격을 띄게 때문이다.

도메인 주도설계에서는 이러한 'Management', 즉 생존주기와 관련된 것들은 도메인 스스로가 결정하게 되어있으며 이것을 기존의 코드 방식처럼 다른 서비스 또는 'DAO'에 위임하는 것을 지향하지 않는다.

그렇다면 위의 코드를 도메인 주도설계 목적에 맞게 바꾸어 본다면 어떻게 바뀔 수 있을까? 아마 아래와 같이 작성할 수도 있겠다.

public interface AccountService {
User register(final String email, final String password);
User unsubscribe(final User user);
...
}

필자는 위의 'UserService'를 'AccountService'로 바꾼 다음에 그 성격을 사용자의 생존주기에 대한 행위를 기준으로 작성하였다. 서비스를 작성할 때 주의해야 할 점은 자신이 만든 메서드를 직접 소리내어 말해보았을 때 이것이 어색함없이 받아들일 수 있어야 하는데 도메인 주도설계가 줄곧 말하는 유비쿼터스 언어의 특성을 살리기 위해서도 그러하고 기본적으로 좋은 메서드를 만드는 좋은 방법 때문이기도 하다.

'register' 메서드와 'unsubscribe' 메서드를 소리내어 말해보자. 각각 "이메일과 패스워드로 사용자를 등록합니다.", "사용자를 탈퇴시킵니다."라고 말할 수 있겠다. 그리고 이런 방식으로 서비스를 작성하다보면은 서비스가 특정 도메인에 종속되지 않고 독립적인 성격을 띈 도메인 오브젝트로 만들어낼 수 있다.

물론 도메인 주도설계 방식으로 'Service'를 만들 때 주의해야 할 점은 'Entity' 또는 'Value Object'에서도 충분히 다룰 수 있는 기능들을 모조리 'Service'로 제작해서는 안된다는 것이다. 보통 많은 개발자들이 도메인 오브젝트에 어떠한 로직을 집어넣기 보단 빈약한 도메인 오브젝트 방식(프로퍼티와 'get...', 'set...' 으로 캡슐화만한 오브젝트)으로 작업해오다보니 도메인에 어떠한 로직이 들어가야 올바른지 헷갈려 하는 경우가 많다. 게다가 도메인 주도설계는 아키텍터, 또는 어플리케이션 특성에 따라 매우 주관적인 코드가 될 수 있으므로 이런 로직들에 대해서는 개발자들 간의 충돌이 일어날 수도 있고, 어떠한 부분에서는 매우 애매모호한 경우가 발생하여 개발에 차질을 빚기도 한다.

이러한 상황에서 명확한 기준은 가급적 'Entity', 'Value Object'. 특히 'Root Entity'에 대해서는 'Aggregate' 경계 내의 오브젝트에 대한 통제 권한을 스스로 관리하게끔하고 그 이외의 서로 다른 'Aggregate'를 가진 도메인 끼리에 대해서는 서비스로 제작하여 처리하는게 올바른 듯 하다.

덧글

  • 2014/09/04 07:24 # 삭제 답글

    좋은 사이트! 너무 많은 정보!
  • 2014/09/27 11:33 # 삭제 답글

    그것은 당신이이 주제를 이해하는 방법을 잘 알 수있다. 이 웹 사이트의 페이지를 북마크, 추가 기사를 위해 다시 올 것이다. 당신, 내 친구, 난 이미 여기 저기 검색하고 간단하게 만날 수 없습니다 단순히 정보를 발견했다. 완벽한 어떤 사이트.
댓글 입력 영역