Community

도메인이란 무엇일까?

블로그 주소 : https://blog.naver.com/gomets_journey/223387194486 나는 이번 설계를 진행하면서 DDD의 가장 핵심 키워드는 SRP 즉, 단일 책임 원칙이라고 생각하였다. 그래서 다시 한 번 책임이란 과연 무엇인가 어디까지를 책임이라 보아야 하는가에 대해서 고민을 해보게 되었다. 어느 한 도메인이 존재할 경우 그 속성이 시간과 공간적인 특징을 가졌을 때 이들은 서로 다른 책임을 지닌다고 보아야 하는가 혹은 같은 책임을 지니고 있다고 보아야 하는가? 예를 들어, 앞서 설명한 Cafe 도메인의 경우 속성으로 주소, 위도, 경도 / 영업시간, 휴무일이 존재하였다. 그렇다면 [주소, 위도, 경도] -> 공간적인 특징 / [영업시간, 휴무일] -> 시간적인 특징 이 상이한 특징을 가진 두 개의 속성을 하나의 도메인으로 표현해야 하는가 혹은 분리를 하여야 하는 것인가? 이것은 어느 하나의 정답은 없다라고 생각한다. 만약 하나의 도메인으로 표현하는 경우 테이블 상으로 하나의 테이블로 표현할 수 있을 것이다. 이럴 경우 장점으로는 해당 테이블에서 데이터를 Read 할 경우 join의 경로가 그만큼 단축되기에 속도가 빠를 수 있다. 또한 클래스 복잡도가 다소 줄어들 수 있을 것이다. 그러나 단점으로는 이 프로그램이 차후 확장되어지는 경우 그때, 이 도메인이 많은 참조가 될 경우, 이 테이블을 참조하는 다른 테이블에서 필요하지 않은 정보들까지 받아오게 될 것이고, 이 말은 그만큼 DB 테이블의 데이터를 직간접적으로 간섭하는 경우가 생길 위험이 높아지므로 side effect가 발생될 위험도가 높아지고, 그들을 관리하는 것에 많은 시간과 비용이 소모될 것이다. 그렇다면 서로 다른 도메인으로 분리하여 표현하는 경우 즉, 두 개의 테이블로 표현하는 경우는 어떠할까? 이렬 경우 장점으로는 위의 상황과 반대가 될 것이다. 테이블마다 서로 공통적인 특징을 갖고 있는 속성들로만 묶여져 있으므로, 이 도메인이 확장되어 질때 그만큼 참조되는 데이터들의 가짓 수도 줄어들게 될 것이다. 이 말은 즉, 데이터 변동성의 위험이 줄어들게 되는 것을 의미하고, 우리가 관리하는데 시간과 비용이 줄어들게 될 것임을 알 수 있다. 하지만 단점으로는 그만큼 클래스 복잡도가 늘어나게 될 것이고, 두 개의 테이블로 나뉘어진 도메인의 모든 속성을 이용하려고 할 때는 그만큼 join이 걸리게되므로, 속도 저하가 생기게 될 것이다. 그러므로, 이들의 특징을 명확하게 이해하고 분별지어 우리의 프로그램에 상황에 맞추어 선택하여야 할 것 이다. 자 이제 도메인에 대해서 한 번 다른 시각으로 바라보도록 해보자. 이번에는 예시를 들어서 이야기 해보도록 한다. 우리는 버스터미널을 바라볼 때, 버스를 가장 작은 객체로 볼 수 있을 것인가? 이들을 더 나눌 수 없을 것인가? 생각해보자. 나는 개인적으로 버스는 더 작은 책임으로 나눌 수 있다라고 생각한다. 버스는 사이드미러, 핸들, 기어봉, 계기판과 같은 조작 부분 / 의자, 손잡이처럼 손님들의 안전을 책임지는 부분 / 출입문처럼 손님들이 타고 내리는 것을 책임지는 부분 / 창문, 안내판 처럼 손님들의 무료함을 달래기 위한 부분으로 1차적으로 나눌 수 있을 것이다. 여기서 흥미로운 점은 창문과 사이드미러이다. 이 둘은 현실 세계에서는 비슷한 재질을 갖고 있기에 같은 도메인으로 구분짓을 수 있을 것 이다. 하지만 소프트웨어 세계에서는 이 둘은 서로 다른 책임을 지니고 있다라고 보기에 서로 다른 도메인으로 분리하여야 한다는 것이다. 또한, 창문과 안내판은 현실 세계에서는 서로 다른 재질을 갖고 있고 공간적으로도 분리되어져 있기에 서로 다른 도메인으로 바라보아야 할 것 같지만, 소프트웨어 세계에서는 이들 또한 같은 책임을 지닌다고 볼 수 있어 같은 도메인이라 할 수 있을 것이다. 또한, 안내판의 경우 광고를 보여주는 기능에서, 현재 나의 정류소 위치와 다음 정류소를 알려주는 기능이 추가되었을 때 실제 사물은 하나일지라도, 서로 다른 도메인으로 분리할 수 있을 것이다. 조작 부분의 경우에도 더 책임을 세분화한다면, 핸들과 기어봉과 같은 실제 물리적인 조작이 들어가는 부분과 운전자에게 정보를 제공해주는 계기판 부분으로 책임을 분리할 수 있을 것이다. 마지막으로, 하나의 메서드가 무거운 기능 혹은 독립적인 기능을 반복적으로 수행하였을 경우 이를 어느 도메인에 속하게 할 경우 그것은 메서드로 표현이 되어질텐데 그럴경우 해당 도메인은 그 메서드로 인해 부하가 걸리게 되고, 실질적으로 돌아가야하는 메인 메서드는 동작이 다소 방해받게 될 것이다. 이럴 경우또한 또 하나의 도메인으로 분류하여야 하지 않을까? 여기까지가 지금 내가 생각해온 도메인이다. 이 내용들이 옳바르지 않고, 부정확할 수도 있지만 이러한 과정들이 중요하다고 믿는다. 앞서 최종 도메인에 대해서 피드백을 받게 되었다. 그 내용은 다음과 같다. 1. 도메인 주도 설계의 '도메인'개념이 엔티티 개념과 혼용되는 것 같다. => 이 부분은 나도 지극히 동감하는 중이다. 도메인과 엔티티 두 개의 개념을 아직 명확하게 분리하지 못하고 있는 듯 하다. 2. Repository에서 질의문을 통해 평균 별점을 처리하는게 도메인에서 처리하는 것보다 좋은 방식인지는 잘 모르겠다. => 이 부분은 아직 이해하지는 못하였다. 그 분의 말씀으로 '도메인' 개념은 사실 MSA와 맞닿아있다라고 하였다. 비즈니스 컨텍스트가 서로 분리된 두 경계 사이를 바운디드 컨텍스트로 잡아서 분리된 서버를 관리하기 위해 도메인이라는 개념을 도입한 것이다. 하지만 내가 올린 글에는 BaseEntity를 도메인으로 잡으시는데에서 의아했다. BaseEntity는 결국 데이터를 위한 메타정보를 담는 상속목적의 테이블인데 이게 하나의 도메인이라면 비즈니스 컨텍스트를 가져야할 것 같은데 그런 것은 아닌 듯 하다라는 말씀이다. [=> 이 부분은 이제 나도 완전 동감하는 바이다. BaseEntity는 하나의 도메인으로 볼 수 없다.] 그리고 각 테이블 자체가 도메인으로 분리될 필요성이 있는가? 라고 생각했을 때 그 분이 느끼기에는 저기에서 부닐되어야 하는 도메인은 [보안/인증] / [멤버] / [카페+메뉴] / [리뷰+코멘트+북마크] / [검색] 으로 느껴진다라고 하였다. DDD를 적용시키는 것은 좋은데 단일하고 작은 서버 내부에서 DDD를 너무 엄격하게 적용해서 사실 한 도메인이 너무 잘게 쪼개져버린 것 아닌가라는 느낌이 들었다라고 하였다. 그리고 두 번째는 헥사고날 아키텍처를 그 분의 회사에서 추구하고 있는데, 평균 별점을 계산하는 로직 자체는 그냥 단순히 합계 평균으로 구할수도 있지만 예전 사이드 프로젝트에서 별점 기능 만들 때 최근 N달간의 리뷰만 집계 이런식으로 처리했던 경험이 있다라고 하셨다. 이런 식으로 점점 비즈니스 로직에 끼게 되는 경우가 있는데 그 점을 고려했을 때 사실 '순수한' 도메인을 유지하기 위해서는 대부분의 로직이 도메인에 들어가야 된다고 생각했다라고 하셨다. [=>이 부분은 저번 상상기업 프로젝트를 진행하면서 개인적으로 느꼈던 부분이었다. 이렇게 했을 경우 장점으로는 개인적으로 서비스 계층의 가독성이 굉장히 좋아지기에, 다른 개발자들이 서비스 계층을 바라보았을 때 이 기능이 무엇을 하는지 손쉽고도 빠르게 이해할 수 있기에 유지 보수 및 확장에 유리함이 있을 것이라고 생각한다.] 이전에 나도 그렇게 생각하였던 부분도 있었고, 피드백을 받으면서 새로운 시각으로 접근하고 다시 바라볼 수 있게 되는 것도 있었으나, 아직 이해를 하지 못한 부분도 존재한다. 아직 부족한 점이 많다.

알림

알림이 없습니다