Post

[도메인 주도 개발 시작하기] 01 도메인 모델 시작하기

우테코 프리코스를 진행하면서 기능을 작은 단위로 분리하고 책임을 나누는 과정에서 학습이 더 필요하겠다고 느껴 읽어보기 시작했다! 우선 1장은 중요하다고 생각하는 부분이나 크게 와닿았던 부분들을 발췌해 정리해보았다.

01 도메인 모델 시작하기

도메인이란?

소프트웨어로 해결하고자 하는 문제영억으로, 한 도메인은 하위 도메인으로 나눌 수 있다.

특정 도메인을 위한 소프트웨어라고 해서 도메인이 제공해야 할 모든 기능을 직접 구현하는 것은 아니며, 일부 기능은 자체 시스템으로 구현하고 나머지 기능은 외부 업체의 시스템을 사용하기도 한다.

도메인 전문가와 개발자 간 지식 공유

요구사항을 올바르게 이해하는 것은 매우 중요한데, 이를 위해서는 개발자와 전문가가 직접 대화해야 한다. 전문가나 관련자가 요구한 내용이 항상 올바른 것은 아니며 때론 본인들이 실제 원하는 것을 정확하게 표현하지 못할 때도 있으므로 개발자는 요구사항을 이해할 때 왜 이런 기능을 요구하는지, 실제로 원하는 게 무엇인지 생각하고 전문가의 대화를 통해 진짜 원하는 것을 찾아야 한다.

도메인 모델

도메인 모델에는 다양한 정의가 존재하며 기본적으로 도메인 모델은 특정 도메인을 개념적으로 표현한 것이다.

도메인 모델을 사용하면 여러 관계자들이 동일한 모습으로 도메인을 이해하고 도메인 지식을 공유하는 데 도움이 된다.

도메인 모델을 표현할 때 UML 표기법(클래스 다이어그램, 상태 다이어그램 등) 뿐만 아니라 그래프, 수학 공식 활용 등 다양한 방식을 활용할 수 있으며, 도메인을 이해하는 데 도움이 된다면 표현 방식은 중요하지 않다.

또한, 앞서 언급했듯 다수의 도메인은 하위 도메인으로 구성되어 있는데, 도메인에 따라 용어 의미가 결정되므로 여러 하위 도메인을 하나의 도메인에 모델링해서는 안된다.
모델의 각 구성 요소는 특정 도메인으로 한정할 때 비로소 의미가 완전해지므로, 각 하위 도메인마다 별도로 모델을 만들어야 한다.

도메인 모델 패턴

도메인 계층을 구현할 때 사용하는 객체 모델을 언급할 때도 ‘도메인 모델’ 이라는 용어를 사용한다.
이때의 도메인 모델은 아키텍처 상의 도메인 계층을 객체 지향 기법으로 구현하는 패턴을 의미하며 도메인 계층은 도메인의 핵심 규칙을 구현한다. 중요한 업무 규칙과 같은 핵심 규칙을 구현한 코드는 도메인 모델에만 위치시킴으로써 규칙을 바꾸거나 확장할 때 다른 코드에 영향을 덜 주고 변경 내역을 모델에 반영할 수 있도록 한다.

처음부터 완벽한 개념 모델을 만들기보다는 전반적인 개요를 알 수 있는 수준으로 개념 모델을 작성한다. 프로젝트 초기에는 개요 수준의 개념 모델로 도메인에 대한 저체 윤곽을 이해하는 데 집중하고, 구현 과정에서 개념 모델을 구현 모델로 점진적으로 발전시켜 나가야 한다.

도메인 모델 도출

코딩 시작 전에는 요구사항과 관련자와의 대화를 통해 도메인을 이해하고 이를 바탕으로 도메인 모델 초안을 만드는 것이 선행되어야 한다.

덧붙여, 전반적인 기능 목록이나 모듈 구조, 빌드 과정은 코드를 보고 이해하는 것보다 상위 수준에서 정리한 문서를 참조하는 것이 소프트웨어 전반을 빠르게 이해하는 데 도움이 되므로 지식 공유를 위해 문서화 작업이 중요하다.

엔티티와 벨류

도출한 모델은 크게 엔티티와 밸류로 구분할 수 있다. 이 두가지를 제대로 구분해야 도메인을 올바르게 설계하고 구현할 수 있다.

엔티티

가장 큰 특징은 식별자를 가진다는 것이다. 엔티티 객체는 각각 고유하며 서로 다른 식별자를 가진다. 상태가 바뀌더라도 식별자는 바뀌지 않으며 엔티티를 생성하고 속성을 변경하고 삭제할 때까지 식별자는 유지된다. 따라서 두 엔티티 객체의 식별자가 같으면 두 엔티티는 같다고 판단한다.

식별자 생성 시점은 도메인의 특징과 사용 기술에 따라 다르며 크게 다음의 네 가지 방식으로 구분된다.

  • 특정 규칙에 따라 생성 주문번호: 날짜+주문시간
  • UUID나 Nano ID와 같은 고유 식별자 생성기 사용
  • 값 직접 입력 아이디, 이메일
  • 일련번호 사용(시퀀스나 DB의 자동 증가 칼럼 사용)

밸류 타입

밸류 타입은 개념적으로 완전한 하나를 표현할 때 사용한다. 예를 들어 우편번호, 도로명주소, 상세 주소 등의 필드를 Address라는 밸류 타입으로 관리할 수 있다. 또한 의미를 명확하게 표현하기 위해 밸류 타입을 사용하기도 한다. int 대신 돈을 의미하는 Money 타입을 만들면 코드를 이해하는 데 도움이 된다.

뿐만 아니라 밸류 타입을 위한 기능을 추가할 수 있다는 장점도 있다. Money 타입에 돈을 계산하는 기능을 추가할 수 있다.

밸류 타입은 변경 기능을 제공하지 않는 불변 타입으로 구현하여 외부에서 데이터를 변경하는 것을 막아 안전하게 코드를 작성할 수 있도록 해야하며, 데이터 변경 시에는 기존 데이터를 변경하는 것보다는 변경한 데이터를 갖는 새로운 밸류 객체를 생성하는 방식을 선호한다.

두 밸류 객체를 비교할 때는 모든 속성이 같은지 비교한다.

엔티티 식별자를 위한 밸류 타입을 사용해 의미가 더 잘 드러나도록 할 수도 있다. String 대신 OrderNo 타입을 생성해 id가 주문번호임을 알 수 있게 할 수도 있다.

추가적으로 도메인 모델에 get/set 메서드를 무조건 추가하는 것은 바람직하지 않다. 특히 set은 도메인의 핵심 개념이나 의도를 사라지게 하며, 도메인 객체 생성 시에도 온전하지 않은 상태가 될 수 있는 문제를 야기한다.
이를 막으려면 생성 시점에 생성자를 통해 필요한 데이터를 모두 받아야 한다. 또한 프레임워크가 필드에 직접 값을 할당하는 기능을 제공하고 있다면 set 메서드 대신 이 기능을 최대한 활용하도록 하자.

도메인 용어와 유비쿼터스 언어

코드를 작성할 때, 도메인에서 사용하는 용어를 코드에 반영하지 않으면 개발자는 그 코드의 의미를 해석해야 하는 부담이 생긴다.
적절한 명명은 코드를 도메인 용어로 해석하거나 도메인 용어를 코드로 해석하는 과정을 줄어들게 하며 코드의 가독성을 높여 코드 분석, 이해에 소여되는 시간을 줄여준다.

에릭 에반스는 도메인 주도 설계에서 언어의 중요성을 강조하기 위해 유비쿼터스 언어 라는 용어를 사용했는데, 전문가, 관계자, 개발자가 도메인과 관련된 공통의 언어를 만들고 이를 대화, 문서, 도메인 모델, 코드. 테스트 등 모든 곳에서 같은 용어를 사용하는 것을 의미한다. 이는 소통 과정에서 발생하는 용어의 모호함과, 도메인과 코드 사이에서 발생하는 불필요한 해석 과정을 줄일 수 있게 한다. 또한, 시간이 지날 수록 도메인에 대한 이해가 높아지므로 이를 잘 표현할 수 있는 용어를 찾아내고 이를 다시 공통의 언어로 만들어 다같이 사용한다. 물론 코드나 문서에도 반영해 산출물에 최신 모델을 적용한다.

도메인 용어에 알맞은 단어를 찾는 시간을 아까워하지 말자!! > 명명 규칙 조금 더 찾아봐야겠다

This post is licensed under CC BY 4.0 by the author.