본문 바로가기
도메인 주도 설계

[동영상 정리]애플리케이션 아키텍처와 객체지향 - 조영호님

by simplify-len 2020. 8. 21.

 영화관에서 영화를 상영하는 도메인을 예제로 OOP를 설명합니다.

아키텍처

프로젝트에 참여하는 개발자들이 설계에 대해 공유하는 이해를 반영하는 주관적인 개념

: 주관적이다...

중요한것?

변경하기 어려운 것?

일찍 변경 하기 어려운 것?

관심사의 분리
서로 다르고 관련이 없는 책임들을 분리

레이어 아키텍쳐

좀 더 세분화할수 있다.그러나 우리는 위 3가지로만 나눠서 시작하겠습니다.

여기서 가장 중요한 레이어는 도메인 레이어입니다.

 

 

대부분 2가지 종류의 도메인 레이어를 설계합니다.

Transaction Script와 Domain Model의 차이점은 무엇일까?

도메인 레이어가 주도하기 때문에 도메인 레이어는 중요합니다.

 

아래는 도메인 컨셉입니다.

 

할인을 2가지 정책을 가질 수 있다.

퍼센트 또는 고정 할인가로 할 수 있다.

할인 Rule

 

최종적인 도메인

 

도메인에서 다뤄야할 부분이 많은데,

이때, 트랙잭션 스크립트로 한번 만들어보자.

트랜잭션 스크립트

트랜잭션 스크립트란?

절차적으로 코딩한다는 것을 의미한다.

데이터와 프로세스는 따로 생각합니다.

이 시스템에서 우리는 data를 어떻게 저장 할 것인가? 에 대해서 생각하기 때문에,  무엇을 저장할 것인가? 에 초점을 맞춥니다.

ER

이런게 나왔다면, 데이터 모델과 똑같은 클래스를 딱딱히 맞춥니다. 그러면 그것은 에너믹 도메인이라고 부릅니다.

Anemic Domain Model

그 뒤에 DAO를 짜기 시작한다.

데이터를 이렇게 나눠놓고, 우리는 프로세스를 생각한다.

아래는 스크립트를 짜기 위한 코드 모델링이다.

예매 처리 스크립트

 

위와 같은 방식이 잘못된 건가? 아니다.

하지만, 이걸 도메인 모델링으로 가져간다면 이렇게 짜지 않는다는 이야기이다.

간단하게 위 스도쿠 코드를 코드를 짜본다면 아래와 같은 것이다.

중앙 집중식 제어 스타일

Transactions script 라고 불리는 개발 방식이라 할 수 있다.

 

위 코드를 도메인 모델로 다시 코딩해보겠습니다.

도메인 모델을 객체지향적으로 코딩한다는 의미는

Process와, Data를 따로 생각하는 것이 아니라 같이 생각하면서 하나의 덩어리로 생각하겠다 라는 것이다.

 

객체지향 설계의 기본은 협력하는 객체들의 공동체

속성과 메서드를 가지고 있는 객체들끼리 협력하는 것

 

CRC Card라는 도구를 사용해서 객체의 역할을 정한다.
물리적인 종이와 같은 것을 활용해 객체 상호작용하는 것을 구조화한다.

CRC Card

 

누가 예매를 하는 것이 적절할까요?

객체란 것은 행동과 상태를 같이 가진다는 것.

이것은 다시 말하면, 상태를 변경한다는 것은 그 객체에 배치한다.

 

가장많이 정보를 알고 있는 object가 메소드를 실행하면 됩니다.

요구사항을 판단하고 이 요구사항을 가장 많은 데이터를 가진 객체에게 책임을 할당합니다.

책임 할당 패턴?

가격 계산 책임 할당
할인율 계산 책임 할당

 

개념적으로 어떤 객체들이 어떤 책임을 가져야하는지 요구사항으로부터 어플리케이션으로부터 유도됩니다. 그리고 그 요구사항을 해결하기 위한 객체가 하나 나오고, 이런 식으로 객체간의 협력구조가 생성됩니다.

할인 여부를 판단할 책임 할당
객체지향 구현

코드의 자세한 내용을 이해하기 보다는 객체들간에 협력하고 있다는 사실을 인지하자.

클래스 다이어그램

 

도메인 레이어를 우리는 지금까지 2가지로 코딩해보았습니다.

서로 접근방법이 다른데, 아키텍처 관점에서 살펴봅시다.

도메인 레이어를 어떻게 설계하냐에 따라 달라집니다.

도메인 모델을 사용할 때는 아래와 같은 설계가 만들어집니다.

 

DB에서 읽는 작업이 필요하고, 메일이 필요하고, PUSH작업 등이 필요할 것이다.

 

도메인 로직과, 어플리케이션 로직은 다른 것이다.

어플리케이션 로직은, 그 로직을 하기 위해 필요한 전후 관계  DB을 읽고, 메일을 전송하고, PUSH 작업등.

이 둘을 명확히 분리해야 하는 이유는 결합도를 낮추고 응집도를 높이기 위해서이다.

그러므로, 도메인 레이어는 캡슐화해야 한다. 그렇게 함으로써 얻는 것이 바로 서비스 레이어이다.

 

도메인 모델을 갖고서, 순수한 도메인 로직만 가지고, 어플리케이션 로직은 도메인에 침투되지않도록 하고,

서비스 레이어가 붙는다.

서비스 레이어

서비스 레이어는 무엇인가?

서비스 레이어는 애플리케이션 경계, 로직을 만든다. 그리고 도메인 로직의 재사용성을 촉진합니다.

도메인 모델을 만들 때는 서비스 레이어가 들어갑니다. 그리고 대부분 트랜잭션 바운더리를 잡습니다.
시작하고 끝날 때 커밋하거나 롤백합니다. 어디서부터 트랜잭션을 시작해서 어디서 끝낼 것인가에 대해서 고려합니다.

도메인 로직을 처리하기 위해 필요한 준비작업 또는 예외에 대한 후처리에 대한 코드가 들어간다.

그러므로, 어플리케이션 로직에 대한 관심사는 서비스로 
도메인 로직에 관심사는 도메인으로 내려가는 것이다.

 

다시 트랜잭션 스크립트를 돌이켜보자.

이러한 로직은 서비스 로직을 필요로 하지 않습니다.

도메인 로직만 존재한다.

도메인 모델링을 하더라도, 데이터 소스를 담을 공간이 있어야 합니다. 그리고 대부분 그런 공간은 관계형 데이터베이스입니다.

그러면 관계형 데이터베이스에 도메인 객체를 어떻게 담아야할까요?

도메인을 작성할 때는 도메인에 기반하지만, 실제적으로 행위에 따라 동작된다.

그러나 데이터 관점에서는 중복이 미덕이다.

이 것이 미스매치된다.

이럴 때 우리는 데이터 매퍼라는 것을 활용합니다.

데이터 매퍼를 활용해서, 양쪽의 불일치를 해결합니다.

매퍼를 두고, 도메인 객체와 DB간의 결합도를 끊습니다. 이것이 데이터 매퍼를 사용하는 목표입니다.

가장 대표적인 것이 JPA

JPA

단순히 CRUD를 해결하기 위해서 쓰는것이 아니다. 서로의 길을 가기 위해서 그것을 연결하는 것이 JPA

그럼에도 불구하고, 객체지향적으로 완벽하게 코딩할 수는 없습니다.

 

데이터 관점에서 보면 

테이블에 데이터를 접근하기 위해 테이블 데이터 게이트웨이라는 것을 만들어 사용합니다. 흔히 부르는 DAO가 해당됩니다.

 

그럼 무엇을 사용해야 하는가?

> 변하지 않는 것은 모든 것이 변한다는 사실입니다.

만약에 요구사항이 변경된다면?

에서

 

로 변경될 경우 어떻게 해야할까?

 

트랜잭션 스크립트에서 코드를 수정할 경우,

엄청난 두려움이 있을 수 밖에 없습니다. 그리고 개념이 암묵적입니다.

 

그러나, 도메인 모델링이 된 코드의 경우는 다릅니다.

금액을 계산하는 행위는 같다.

컴포짓 디자인 패턴을 통해서 만들 수 있다.

기존 코드를 수정하지 않고, 새로운 클래스를 만듬으로써 문제를 해결했습니다.

이것이 바로 OCP라고 한다.

의존성 방향을 역전 시킵니다. 이것은 우리가 말하는 SOLID 원칙 중 하나에 해당됩니다.

도메인의 개념을 명시적으로 표현할 수 있는 길이 열립니다.

우리는 아래와 같은 다이어그램으로 얘기해도 됩니다.

도메인 추상화를 뽑고 뽑고 할 경우 도메인 추상화는 하다보면 도메인 아키텍처가 만들어집니다.

그러나 조영호님이 말하길 거짓말이라 표현될 수 있는 부분으로

요구사항이 어떻게 변결될지 모른다면

그러므로 최대한 단순하고 심플하게 만들어야 합니다. 그래야만 변경이 발생할 때마다 

이후로, 일단 변경의 방향과 속도를 알고 난 후에는 

 

댓글