로그인 사용자를 나타내는 User클래스는 사양 변경이 잦아서 여러 가지 문제를 일으키기 쉬운 클래스이다.
로그인과 최소한의 정보를 갖도록 구현했다가 다양한 사양이 추가되어 모든 정보를 User클래스 인스턴스 변수에 추가 될 수 있다
class User {
id: number;
name: string;
email: string;
passwordDigest: string;
// 추후에 추가된 인스턴셔 변수들
address: string;
phoneNumber: string;
bio: string;
url: string;
discountPoint: string;
themeMode: string;
birthday: string;
}
User클래스 내에서 유효성 검사를 모두 처리하기 때문에 각각의 사용되는 곳에서 버그를 발생시키기 쉽다.
사전적 의미로는 ‘수많은 구성 요소로 이루어진 집합체로서, 각각의 부분이 유기적으로 연결되어, 전체적으로 하나의 목적을 갖고 움직이는 것’ 이라고 되어있다.
예시)
목적 달성을 더 효율적으로 하기 위해서 또 다른 시스템을 만들어 내는 것이다.
즉, 시스템은 목적 달성을 위한 수단이다.
모델이란 특정 목적 달성을 위해 최소한으로 필요한 요소를 갖춘 것이다.
온라인 쇼핑몰의 상품을 예시로 들면 상품에는 다양한 요소들이 있고 이를 모두 포함하는 모델은 목적이 불분명해진다.
하나의 상품 모델로 만들 것이 아니라 ‘주문 시의 상품 모델’, ‘배송 시의 상품 모델’ 처럼 별도의 모델로 분류해서
목적에 따라 모델링이 필요하다.
초반에 작성했던 User 클래스를 살펴보면, 안에 담긴 변수들이 모두 서로 다른 것과 관련된 요소이다.
즉, ‘여러 목적에 무리하게 사용되고 있으며, 모델링된 것처럼 보이지만 모델링되어 있지 않다’ 로 볼 수 있다.
이런 모델을 일관성 없는 모델 이라고 부른다.
User를 직역하면 사용자, 이용자이다. 시스템 사용자는 시스템의 외부에 존재하고 있고, 외부에 있는 정보와 내부에 있는 정보(이름, 생년월일, 이메일 등등)가 서로 얽혀있다.
이를 해소하려면 정보 시스템만이 갖는 특징을 활용해야 한다.
정보 시스템이란 현실 세계에 있는 개념만을 컴퓨터 세계에 투영하는 가상 현실이다. 정보 시스템은 현실 세계에 존재하는 개념을 컴퓨터 내부의 가상 세계안에 만들고, 개념적인 처리를 컴퓨터로 빠르게 만들어 효율을 높일 수 있다는 장점이 있다.
좋은 예시로는 깃허브의 사용자 설정화면이 있고, 목적에 따라 설정 항목이 구분되어 있다.
이처럼 정보 시스템에서는 ‘현실 세계에 있는 물리적인 존재’와 ‘정보 시스템에 있는 모델’이 무조건 일대일 대응되지 않고 일대다 대응되는 경우가 많다.
User클래스를 목적 기반으로 변경하면 다음과 같이 할 수 있다.
목적 | 목적 기반 이름 |
---|---|
개인 로그인 인증 | PersonalAccount |
법인 로그인 인증 | CorporateAccount |
특징 표현 | Profile |
목델링이 제대로 되지 않는 원인은 모델을 단순한 ‘대상’으로 해석하고 있기 때문이다.
사용자와 상품 모두 단순한 ‘대상’ 으로 해석하면, 여기에 모든 목적이 담긴다. → 데이터는 거대해지고 일관성이 없는 구조가 발생
사용자 모델링을 생각해보면 PersonalAccount는 개인 사용자가 로그인할 때 필요한 인증 수단,
Profile은 특징 표현 수단이다.
즉, 목적 중심으로 이름을 잘 설계하면, 목적을 달성하기에 적절한 모델을 설계할 수 있다.
목적과 책임은 서로 대응되는 관계이고, 단일 책임 원칙은 단일 목적 원칙이라고 바꿔 이야기할 수도 있다.
클래스를 ‘공통으로 사용 가능한 범용적인 부품으로 설계해야 한다’ (x)
특정 목적에 따라 특화되게 설계해야, 변경하기 쉬운 고품질 구조를 갖게 된다.
모델은 구조를 단순화한 것에 불과하므로, 모델을 기반으로 클래스를 설계하면서 세부적인 내용을 수정해야 한다.
‘모델 = 클래스’는 아니다.
클래스 설계와 구현에서 무언가를 꺠닫는다면 이를 모델에 피드백하여 모델을 더 정확하게 만든다.
반대로 모델 구조를 개선하면 클래스와 코드 품질 향상에 기여한다.
피드백 사이클을 계속 돌리는 것이 설계 품질을 높이는 방법이다.
상품 구매 모델링을 예시로 생각해보자.
상품 구입 | 구입 품목 |
---|---|
ID, 구입일시, 수령 희망일 | ID, 상품 ID, 대금, 수량 |
이렇게 모델링을 하게되면 상품 구매 뒤에 숨어있는 목적 때문에 기능을 발휘하기 어렵다.
‘상품 등의 매매 계약은 구매 회원의 구매 신청에 대하여 회사 또는 판매 회원이 승낙의 의사 표시를 함으로써 체결됩니다.’ 와 같은 내용이 있는데 이렇게 법적으로 생각하게 되면 모델링의 구성요소가 달라지게 된다.
매매 계약 | 목적물 |
---|---|
ID, 계약 체결 일시, 인도 희망일, 지불 기일, 결제 방법 | ID, 상품 ID, 대금, 수량 |
기능을 제대로 발휘하기 위해 ‘개념의 정체’ 와 ‘뒤에 숨어 있는 중요한 목적’ 을 잘 파악해야 한다.
예를 들어 고등어와 꽁치라는 모델이 있을때 어떻게 추상화 해야할까?
보통 ‘어류’라는 모델로 추상화를 진행한다. 여기서 돼지가 추가된다면 생물학적인 분류를 생각하여 포유류로 묶을 것이다.
이렇게 추상화를 하게 된다면, 각 모델이 어떤 역할을 하고 있는지 알 수가 없다. 모델은 목적 달성 수단이기에 ‘영양 섭취 수단’으로 추상화하게 된다면 확장성이 커지게 된다.
게시판, 이메일, 개인 블로그등을 사용했다가 이후에 SNS의 등장으로 인스타, 트위터등 여러가지 수단이 나왔을 때도 ‘정보 확산 수단’이라는 추상화를 진행한다면 확장성 넓게 구현할 수 있다.
이처럼 도메인 주도 설계에서는 ‘본질적인 과제를 해결하고, 기능성 혁신에 공헌하는 모델’을 깊은 모델이라고 부른다.
설계는 매일매일 반복해서 개선하면서 그 과정에서 깊은 모델이 만들어 진다.