왜 도메인 주도 설계를 할까?

김성수·2023년 5월 10일
2

김영한 강사님의 강의를 보다가
도메인 주도 설계라는 것을 배웠다.
개념이 이해가 되지 않아서
이해가될 때까지 공부해보았다.





도메인 주도 설계(DDD)란?

도메인 주도 설계(Domain-Driven Design, DDD)는 복잡한 도메인을 기반으로 소프트웨어를 설계하는 방법론이다. 소프트웨어 개발에 있어서 도메인은 비즈니스에서 중심이 되는 영역으로, DDD는 이 도메인 중심의 설계 방법론으로, 비즈니스 도메인을 중심으로 시스템을 설계하는 방법이다.





도메인 주도 설계 예시

재고 수량중복 회원 검증 이 두가지 비즈니스 로직을 기준으로 예를 들어보자.

재고 수량의 경우 상품 엔티티 내부에 비즈니스 로직을 작성한다.

반면에,

중복 회원 검증 비즈니스 로직의 경우 서비스 클래스에 작성한다.

둘 간의 차이는 뭘까?

왜 중복 회원 비즈니스 로직은 서비스 클래스에서 선언했고,

재고 수량 비즈니스 로직은 엔티티 클래스에서 선언했을까?


중복 회원

중복 회원의 경우를 살펴보자.

email을 기준으로 중복된 회원인지 아닌지를 판단한다고 가정해보자.

클라이언트에서 입력받은 email 값이 DB에 저장되어 있는지 없는지를 확인한 후에

DB에 값이 있다면 exception을, 없다면 회원 가입 처리를 하면될 것이다.

위 과정은 총 세 단계로 이뤄진다.

  1. DB에서 email을 찾는다. // select
  2. 중복된 이메일이 있는지 찾는다.
  3. 있다면 예외, 없다면 가입 //비즈니스 로직 및 insert

재고 수량

이번에는 재고 수량을 생각해보자.

1.DB에서 재고가 얼만큼 있는지 확인한다.
2.사용자가 요청한 변경된 재고 값을 비즈니스 로직으로 처리한다.
3.처리된 재고 수량을 DB에 저장한다.

위는 서비스 클래스에서 재고 수량 비즈니스 로직을 작성했을 때

거치게되는 과정이다.

반면에,

도메인에 재고 수량 비즈니스 로직을 선언하게 되면

비즈니스 로직을 통해 변경된 데이터 값이 메모리 상에 저장되어 있다가

트랜잭션이 commit되는 순간에 한번에 저장된다.

이렇게 함으로써 DB I/O를 줄일 수 있다.


즉, 쉽게 설명하자면

서비스 클래스에서 비즈니스 로직을 선언했을 때는

DB I/O가 각 단계마다 발생했었지만,

도메인 클래스에 비즈니스 로직을 선언하면

결과가 메모리 값에 존재하다가 commit 시점에 한번에

DB에 저장하므로 DB I/O가 줄어든다.





DB I/O가 줄어든다?

만약 재고 수량이 도메인이 아니라 서비스 클래스에 위치하게 된다면,

연속적으로 재고 수량이 변경될 때마다 DB에서 값을 불러오고 저장하는 로직이 실행될 것이다.

이 과정이 바로 DB I/O인데

도메인 계층에서는 비즈니스 로직을 실행하고 그 결과를 메모리에 저장해놓았다가 commit될 떄 한번에 DB에 저장하므로

DB I/O가 비교적 적은 수로 발생하게 된다.


재고 수량의 경우 사용자가 주문할 때마다 변경되고, 주문될 때마다 즉각적으로 변경될 필요가 없는 경우가 비교적 많다.

예를 들어 만개의 재고가 있는데 5명이 주문을 했다고 가정하자.

그러면 5개를 제거한 재고를 메모리상에 두었다가 commit하게 되면

5번 DB I/O가 발생할 것을 한번만 발생시킬 수 있게 되어 성능이 향상된다.

그리고

Transaction은 ACID 규칙을 지킨다.





ACID?

ACID란

Atomicity : 원자성
Cosistency : 일관성
Isolation : 독립성
Durability : 영속성

을 의미한다.

이곳에서 ACID를 모두 설명하기는 어렵고,

Isolation에 집중해보자.


도메인에 비즈니스 로직을 호출하게 되면 그 결과가 메모리에 저장된다고 위에서 설명했다.

그리고 commit하는 시점에 한번에 DB에 저장하는데,

만약 commit하기 전에 동시에 재고를 변경하는 다른 요청이왔다고 가정해보자.

재고가 만개가 있었고 10개의 재고가 팔렸는데 아직 Commit이 되지 않아서 DB에 저장되지 않은 상태이다.

그러면 현재 재고는 만개로 변하지 않은 상태일 것이다.

그 상태에서 새로운 5개의 재고가 또 팔렸다.

그러면 만개에서 -5를 하게되어

9995개의 재고가되게 되는 것이다.

먼저 팔린 10개의 재고는 허공으로 사라져버린 것이다.

원래라면 9985개의 재고가 남아야 하는데 말이다.

이러한 문제점을 방지하기 위해 Isolation Level을 잘 설정해야 한다.


Isolation Level을 높일 수록 동시성 처리 속도는 느려지지만 일관성과 안정성이 높아진다.

재고 수량 트랜잭션이 동시에 요청되었을 때 누락되는 값이 존재하지 않도록 적절한 Isolation Level 설정이 필요할 것이다.





도메인 주도 설계의 장점 세가지

도메인 주도 설계의 장점은 크게 세가지가 존재한다.


첫째 : DB I/O를 최소화시켜준다.
둘째 : 도메인 모델의 책임이 명확해진다.
셋째 : 코드의 응집력이 더 높아진다.

DB I/O 최소화에 대해서는 위에서 설명했다.

도메인 모델의 책임을 명확히 구분할 수 있다.

서비스 클래스의 경우 여러 도메인 엔티티를 가져다가 섞어서 사용하는 경우가 많기 때문에

도메인의 책임의 명확성이 떨어질 수 밖에 없다.

따라서, 도메인의 책임의 명확성을 높이기 위해서는 도메인 엔티티만으로 처리할 수 있는 비즈니스 로직은

도메인 엔티티 내부에 처리하는 것이 코드의 명확성을 높이고 유지보수하기 좋아질 수 있다.


코드의 응집력을 강화할 수 있다.

응집력은 하나의 클래스가 한가지 기능만 하는 것을 의미한다.

객체간의 응집력이 높아진다는건 결합도가 낮아진다는 것 그 말은 즉슨, 의존성이 낮아진다는 것을 의미한다.

따라서, 객체간의 변경이 서로에게 영향을 최소화할 수 있게되는 것이다.

객체지향의 핵심은 의존성을 낮추는 것이라고 배웠다.

거기서부터 객체 설계의 중점이 시작되는게 아닐까 생각해본다.





그래서 어떤 상황에 DDD를 할 것인가?

여러개의 도메인이 필요한 비즈니스 로직은 서비스 클래스에서 관리하는게 좋다.

그렇게함으로써 도메인의 역할 책임이 명확해지고,

코드의 가독성도 높아진다.

명확히 어떤 상황에 DDD를 사용해야 한다고 정의하기는 어려워 보인다.

비즈니스 요구사항에 따라 천차만별로 달라질 것이다.

상황에 따라 유동적으로 잘 결정해서 사용해야할 것 같다.

profile
깊이 있는 소프트웨어 개발자가 되고 싶습니다.

0개의 댓글