728x90

도메인을 제대로 만들지 못하면 요구사항을 충족하는 소프트웨어를 만들기란 힘들다는 것을 잘 알고있다.
도메인 영역은 기본 패시브로 잘 구현하되,
거기에 도메인에 활력을 불어넣어줄 표현영역, 응용영역도 잘 구현이 되어야 한다.

표현 영역

표현 영역은 사용자의 요청을 해석한다.

스프링으로 따져 생각해본다면 Controller로 생각하면 될 것 같다.

DDD에서 말하는 패키지 구조로 보면 interfaces가 될 것이다.

표현 영역은 URL, 요청 파라미터, 쿠키, 헤더 등등을 이용해서 클라이언트에서 원하는 작업을 받아서
응용 영역에 처리를 위임시킨다.

응용 영역

응용 영역은 표현 영역의 요청을 받아 처리를 하는 Service로 생각해볼 수 있다.


표현 영역에서 전달 받은 데이터는 일단 신뢰할 수 없는 데이터이므로,
값에 대한 검증이 있을 수 있고, 또 응용 영역에서 필요로 하는 데이터 타입으로 변환을 시켜주는 동작이 들어가야 한다.
그 후 응용 영역이 요구하는 객체를 생성하고 응용 서비스의 메소드를 호출한다.
그리고 작업이 완료되었을 때 반환되는 값을 토대로
응답 객체를 만들어서 알맞는 형식으로 응답을 내려준다.

응용 서비스의 역할

보편적인 응용 서비스의 구조는 이런식이다.

public Response applicationMethod(final long id) {
    //1.인프라 스트럭쳐에서 애그리거트를 불러온다.
    Domain domain = domainRepository.findById(id);

    //2. 애그리거트의 도메인 기능을 실행한다.
    domain.doSomething();

    //3. 결과를 반환해준다.
    return domain.toResponse();
}

조회해서 내려받는건 보통 이런식일거라고 생각한다.

그리고 생성이나 수정같은 경우에는 Request 요청 객체가 들어올때 유효성 검증을 실행하고,

그 후에 조건에 부합하는 경우에 생성, 수정을 해주면 된다.


단순 조회인 경우 서비스 레이어가 필요하지 않은 경우에는

Controller -> Repository 로만 구성해도 무방하다.

기존 Layered Architecture 로 구성했을 때, jpa 구현기술에 대한 의존이 있는 경우에

도메인이 인프라 스트럭쳐에 의존하게 된다.
DDD를 연습해보면서 느끼는 점은, 도메인에 대한 리포지토리를 인터페이스로 도출한 후에
구현체들을 인프라 스트럭쳐에 위치시키면 도메인이 구현 기술에 대한 의존이 없어지게 구성이 된다.
JpaRepository를 만든다고 한다면

DomainRepository <- DomainJpaRepository 로 의존이 반대로 흐르게 구성이 된다.

값 검증

값 검증은 표현 영역, 응용 영역 두곳에서 모두 수행이 가능하다.

  • 표현 영역
    • 필수 값, 값 형식, 범위 등등을 검증한다. (@Valid@Validated)
  • 응용 서비스
    • 데이터의 존재 유무와 같은 논리적 오류를 검증한다. (findById()orElseThrow 같은것들을 생각해보면 될듯????)

@RestControllerAdvice@ExcepitonHandler를 사용해서

요청 값에 대한 검증을 먼저 진행해준다.

728x90

'아키텍처' 카테고리의 다른 글

DDD 도메인  (0) 2022.08.11
Monolithic vs MSA  (0) 2022.08.10
728x90

도메인

도메인은 구현해야할 소프트웨어의 대상이다.
쇼핑몰을 생각해보면 쇼핑몰은 대상, 그리고 상품조회, 주문, 배송, 결제 등등이
하위 도메인이 된다.
그리고 도메인이라고 해서 고정된 하위 도메인이 존재하는건 아니다.
결제같은것을 PG사에 위임하니까 말이다.

도메인 모델 패턴

기존의 나는 흔히 말하는 MVC 레이어 아키텍처를 사용했다.

이미지 출처 바로가기

단순히 Controller, Service, Repository세개를 사용해서 구현했었다.

이것은 내가 넥스트스텝에서 TDD와 클린 코드를 수강했어도 변하지 못했다.
근데 이 방식이 아니라 DDD책을 보면서 주워들었던 도메인 모델 패턴을 봤다.
그래도 말만 바뀌었지 느낌은 전과 같았다.

의존은 화살표 방향으로 주입이 된다.

  • Presentation
    • 사용자의 요청을 처리하고 사용자에게 정보를 보여준다.
    • 사용자는 사람이 아니라 외부 시스템일 수 있다.
  • Application
    • 사용자가 요청한 기능을 실행
    • 비즈니스 로직을 구현하지는 않고 도메인의 계층을 조합해주기만 함
  • Domain
    • 이 설계의 가장 핵심
    • 시스템이 제공하는 도메인들의 규칙을 구현
  • InfraStructure
    • DB나 메시징 시스템 같은 외부 시스템의 연동을 처리함

핵심 규칙들은 도메인 모델에만 위치하기 때문에 규칙이 바뀌거나 확장해야 된다면
다른 코드에 영향을 끼치지않고 모델들에 반영해주어야 한다.
도출한 모델들은 엔티티와 값 타입으로 구분할 수 있다.

엔티티와 값타입을 제대로 구분하여야 도메인을 잘 설계하고 구현할 수 있다. 👍

엔티티

엔티티는 식별자를 가진다. 이 식별자는 엔티티 객체마다 고유해야 한다.

그래서 회원의 경우 회원번호가 서로 다르다.
이것이 바로 식별자가 되는것!!
다른 값이 바뀌어도 이 엔티티 객체가 생성되거나 삭제되기 전까지 유지된다.

그렇기 때문에 이 식별자 값이 같다면? 같은 객체❗️

그렇다면 이 식별자 값으로 equals(), hashCode()를 재정의 할 수 있다.

식별자 생성

그러면 식별자를 생성해야 하는데
엔티티의 식별자를 생성하는 시점은 도메인의 특징과 사용하는 기술에 따라 달라진다.

  1. 특정 규칙에 따라 생성
  2. UUID같은 고유 식별자 사용
  3. 값 직접 입력 (개인적으로 제일 안좋다 생각)
  4. 일련번호 사용 (시퀀스나 DB의 auto-increment)

모델

배송지의 집주소가 우편번호 + 도로명주소 + 상세주소 이렇게 같이 사용하는게 대부분인데,

세 가지 데이터는 다르지만 개념적으로는 하나로 일맥상통한다. 바로 주소

값 타입은 바로 이럴때 사용하는 것이다.
이 값타입의 장점은 이 값들만의 기능을 추가할 수 있다.
이 값객체의 값을 바꾸는건 기존 데이터를 두기보단 변경이 되면 새로 생성하는
불변 객체 를 생성하는 방식을 선호한다.
불변으로 만드는 이유는 안전한 코드를 작성할 수 있다는 곳에 있다.
setter 메소드로 값을 바꾼다면 다른 로직에서 잘못 반영이 되는 불상사를 초래할 수 있다.
그래서 두 값 객체를 비교할 때에는 모든 인자가 같은지를 체크해주어야 한다.

무지성 Getter/Setter 남용금지

getter는 어쩔수 없는 경우가 있다고 할지라도,
setter는 값이 깨지는것을 막을수는 없다. + 핵심 개념이나 로직을 망가뜨릴수 있다.

728x90

'아키텍처' 카테고리의 다른 글

DDD 표현 영역과 응용 영역  (0) 2022.08.11
Monolithic vs MSA  (0) 2022.08.10

+ Recent posts