개발을 하다 보면 “도메인”과 “엔티티”라는 용어는 한 번씩 듣게 된다.
그런데 누구는 도메인을 엔티티와 비슷한 개념으로 사용해서 이야기하는 것 같고, 누구는 도메인과 엔티티는 다르다! 라고 말을 하는 것을 종종 볼 수 있다.
나 또한 그랬고 두 개념이 어떻게 다른지, 실상 모르고 용어를 사용했었다.
결론부터 말하면 내가 이해한 도메인과 엔티티는 같은 의미로 사용될 수도 있고 아닐 수도 있다.
얘가 지금 무슨 소리 하는 거지 할 수 있다..
우선은 도메인과 엔티티는 내가 만들려는 애플리케이션의 아키텍처 설계에 따라 달라질 수 있다.
즉, 어떻게 설계했느냐에 따라 사용되는 용어의 의미가 달라질 수도 있고 같아질 수도 있다.
그래서 도메인, 엔티티 이야기를 할때는 맥락파악이 중요하다.
2가지 케이스로 나눌 수 있다.
1. “나는 도메인과 엔티티를 완전히 분리해서 사용할 거야!”라고 한다면 이 애플리케이션 한정 도메인과 엔티티를 이야기할 때는 다른 개념으로 인지하고 용어를 사용해야 한다.
2. “아니 나는 도메인이고 엔티티고 헷갈려 하나로 통일해서 그냥 엔티티만 사용할거야!” 라고 한다면 엔티티와 도메인은 같은 개념으로 볼 수 있다.
Domain == Entity
우선 일반적인 두번째 관점인 도메인과 엔티티를 같은 개념으로 보고 사용했을 때에 대해 알아보자.
나는 대부분의 애플리케이션의 형태가 도메인과 엔티티를 철저히 구분해서 사용하는 형태를 많이 보지 못했다. 전부 엔티티를 도메인처럼 사용하는 것을 많이 보았고, 나도 지금까지 엔티티 클래스에 비즈니스 로직을 넣어 개발을 해왔다.
무엇보다 첫번째 방법과 다르게 도메인 클래스를 만들지 않아도 돼서 클래스 수가 적어 관리하기가 편하다는 장점이 존재한다.
Domain != Entity
다음 생소할 수 있는 첫 번째 설계 관점에서 도메인과 엔티티의 역할에 대해 알아보자.
우리는 애플리케이션 내에서 데이터를 db에서 가져와서 사용한다. 이때 db의 row 데이터를 우리가 사용하는 언어(java, kotlin …)에 맞게 변환해서 애플리케이션에서 사용해야 하는데 이때 db 테이블과 1:1로 매핑되는 객체를 Entity라고 한다.
대표적으로 JPA ORM으로 예를 들면 @Entity 어노테이션이 붙은 클래스를 엔티티라고 말한다. 이 Entity는 layered architecture 관점에서 database layer에 속해있다는 것을 기억하자.
즉, Entity는 db의 데이터를 서빙하는 역할만 한다고 생각하면 편하다.
도메인은 무슨 역할을 하는가?
도메인은 Business layer에 속해있다. 즉, 핵심적인 비즈니스 로직을 갖고 있어 관련 기능들이 잘 응집되어 있는 객체이다.
우리가 기획자로부터 전달받은 요구사항을 풀어내야 하는 로직을 처리하는 객체로 애플리케이션 내에서 core 한 역할을 한다고 볼 수 있다.
우리는 이제 business layer 에서는 이 도메인을 사용해서 문제를 풀어나갈 것이기 때문에 Database layer에서 가져오는 Entity를 business layer에서 사용하기 위해 우리는 도메인 객체로 변환을 해서 사용해야 한다.
도메인 엔티티 굳이 왜 나눠서 사용해?
그러면 도메인과 엔티티를 철저히 구분해서 사용해서 얻을 수 있는 이점이 뭔지 알아보자
Layered Architecture를 적용하면 상위 계층이 하위 계층으로 호출하는 단방향 흐름이라는 것을 알 수 있다.
이 흐름의 문제점은 하위 계층의 변경이 상위 계층으로 전파가 된다는 것이다. database layer에서의 변경이 우리의 핵심인 business layer까지 영향을 미치게 된다. 즉, business layer가 보호받지 못하게 된다.
그래서 우리는 하위 계층의 변경이 상위 계층으로 전파가 되지 않도록 애플리케이션을 설계해야 한다.
도메인과 엔티티를 나눠 사용하면 위 원칙이 잘 지켜진다. 왜냐하면 비즈니스 레이어에 속한 도메인은 엔티티를 전혀 몰라도 되기 때문에 database layer 에서 무슨 일이 일어나든 나는 내 할 일만 잘하면 되기 때문이다. (그 유명한 관심사의 분리가 아주 잘 지켜졌다고 볼 수 있다.)
핵심적인 비즈니스 로직은 철저하게 도메인 객체 내에 응집되어 있기 재사용성과 유지보수하기가 매우 좋아진다.
그리고 도메인 객체만 잘 살펴도 애플리케이션의 핵심 로직이 무엇인지 파악할 수 있다는 장점도 있을 것 같다. (이 부분은 아직 경험한 바 없기 때문에 추측 정도로만..)
관심사의 분리?
조금 더 나아가서 관심사의 분리가 뭔지 짧게 짚고 넘어가자.
예를 들어 비즈니스 레이어에서는 데이터베이스 레이어에게 나는 Lecture 라는 형태의 도메인을 받는 것에만 관심이 있다. 즉, 데이터베이스 레이어에서 어떤 db와 의존해서 어떻게 엔티티로 변환해서 도메인으로 변환할지는 관심이 없고(네가 뭘 하든 나는 관심 없고) 나는 내가 원하는 것(Lecture)만 받아 내 역할만 수행하면 된다는 것이다.
예를 들어 식당에 가서 메뉴를 주문하면 우리는 요리사가 어떤 재료로 어떻게 요리하는지에는 관심이 없다.(나만 그런가?) 나는 내가 주문한 메뉴만 잘 나와 먹으면 되는 것 처럼 나는 내가 할 일에만 집중할 수 있도록 설계하는 것이 관심사의 분리이다.
정리
정리해보면 애플리케이션을 어떻게 설계하느냐에 따라 도메인과 엔티티의 용어 쓰임새가 달라질 수 있다고 생각이 된다.
누군가 도메인과 엔티티를 말할 때는 어떤 맥락에서 말을 하고 있는지 파악하면 이 사람이 어떤 개념의 도메인(or 엔티티)을 말하고 있는지 확실히 파악할 수 있다.