'ddd'에 해당되는 글 2건

  1. 2008.07.21 [펌]스프링 프레임워크와 DDD
  2. 2008.06.29 [펌]DDD(Domain Driven Design) 도메인 주도 개발

[펌]스프링 프레임워크와 DDD

ITWeb/개발일반 2008.07.21 10:30

ref. http://www.zdnet.co.kr/builder/dev/web/0,39031700,39170214,00.htm


[DDD ③] 스프링 프레임워크와 DDD

이일민(toby.epril.com 운영자)   2008/07/19
[지디넷코리아]스 프링프레임워크(SpringFramework, 이하 스프링)의 첫 번째 메이저 업그레이드 버전인 2.0이 처음 발표되었을 때 개발자들이 가장 관심을 가지고 주목했던 것은 스프링을 통한 DDD(Driven Driven Design)였다. 대부분의 개발자들에게 아직 생소했던 개념이었던 DDD를 과감하게 주요 기능으로 내세우면서 등장한 스프링은 과연 DDD와 어떤 관련이 있는 것일까? 스프링2.x를 통해서 DDD를 적용하는 전략은 어떤 것들이 있는지 살펴보자.

  스프링 2.0

스프링2.0 버전은 2005년 말에 열렸던 TheSpringExperience 컨퍼런스에서 처음 소개가 되었다. 그때까지 1.3버전으로 준비되고 있었던 스프링의 차기 버전이 컨퍼런스 기간에 2.0이라는 메이저버전으로 버전자체의 업그레이드가 일어났다.

그 결정의 배경은 스프링의 다음 버전에 등장하는 기능들의 중요도와 변화의 영향력이 메이저 업그레이드를 하는 것이 바람직할 만큼 중요하다는 공감이 있었기 때문이다.

스프링 2.0에 소개된 새로운 기능에는 XML 설정의 단순화나 스키마의 도입 또 자바5의 새롭게 소개된 언어특성의 적용 등 그동안 지속적으로 요구되어졌기 때문에 당연히 들어갈 것으로 기대했던 내용들이 대거 포함되어 있었다.

그런데 그 중에서 필자의 눈을 사로잡는 생소한 단어가 눈에 띄었는데 그것이 바로 DDD다. TDD는 많이 들어봤어도 DDD는 무엇인가 궁금해하면서 DDD에 대해서 찾아보니 이미 몇 년 전부터 엔터프라이즈 아키텍처 기술에 관한 이야기들이 나올 때마다 자주 등장했던 Eric Evans의 책 제목인 Domain Driven Design의 약자인 DDD였다.

스프링 2.0
AOP, IoC/DI, PSA같은 시대를 앞서나가는 새로운 컨셉트와 기능들을 과감하게 소개하고 이를 현장에 접목시키는데 앞서왔던 스프링이었던지라 많은 스프링 개발자들은 지속적으로 엔터프라이즈 개발에 필요로 한 유용한 기술과 전략이 스프링의 업그레이드과정을 통해서 소개될 것을 기대해왔다.

하지만 DDD라는 단어와의 만남은 그리 쉽게 예측할 수 없었던 것이라 스프링 커뮤니티와 관련 개발자들 사이에서도 적지 않은 화제를 불러일으키게 되었다. 대다수의 스프링 개발자들은 2.0에 대한 발표소식을 들으며, 함께 소개된 DDD에 대해서도 많은 관심을 가지기 시작했다.

2006년 가을에 스프링 2.0의 정식버전이 릴리즈 되고 나서 열렸던 첫 번째 스프링 컨퍼런스인 TheSpringExperience 2006에서는 컨퍼런스의 네 개 주요트랙중의 하나가 DDD였을 정도였으니 스프링과 DDD는 매우 깊은 관계를 가지고 있음을 짐작할 수 있다.

TSE 2006 DDD트랙의 첫 번째 세션의 발표를 바로 Domain Driven Design이라는 책을 통해서 DDD라는 개념을 소개하고 이를 보급시키는데 앞장서고 있는 Eric Evans이 맡았다. Eric은 2007년 유럽에서 열린 스프링원 컨퍼런스에서도 키노트 발표를 담당했을 정도로 스프링과 깊은 관계를 가지고 있다.

DDD란 무엇인가?
이처럼 스프링과 DDD의 깊은 관계가 발생한 이유는 무엇일까? 그것은 스프링이 지금까지 지향해온 핵심가치와 DDD의 그것이 유사하기 때문이라고 생각된다.

스프링의 등장배경과 원리를 소개한 책인 J2EE Development without EJB라는 책의 첫 장에서는 스프링이 지향하는 핵심가치를 소개한다. 그 중 가장 눈에 띄는 것이 있다면 바로 OO(Object Oriented)라는 것이다. 스프링이 추구하는 핵심가치는 바로 객체지향이다.

자바라는 객체지향언어를 사용하는 프레임워크인 스프링이니 당연히 OO적일텐데 왜 그것을 핵심가치라고 하면서 강조하고 등장한 것일까? 그것은 자바의 근본이라고도 할 수 있는 객체지향이 사실은 엔터프라이즈 환경에서 상당히 무시당하고 있다는 안타까운 현실에서 나온 것이다.

스프링은 그것을 사용하는 개발자들에게 자바가 객체지향 언어라는 가장 기초적인 사실을 다시 상기시켜주면서 그 기초에 충실할 때에 가장 복잡하게 생각되는 엔터프라이즈 개발이 사실은 쉽고 단순해진다는 것을 알려주려는 의도를 가지고 만들어 진 것이다.

DDD 또한 그와 유사하다. DDD는 어떤 천재적인 기술자에게서 갑자기 소개된 새로운 개념과 아이디어가 아니다. 소프트웨어 설계라는 것이 존재했던 가장 초기부터 추구하고 가져왔던 가장 기초가 되는 기본에 다시 충실하자는 이야기이다. 그래서 어떤 사람들에게는 매우 진부하고 당연하게 들리기도 한다.

Eric Evans의 DDD 책을 읽어본 많은 사람들이 의외로 실망하는 이유가 바로 거기에 있다. 이미 잘 알고 있다고 생각하는 당연한 내용들이 많기 때문이다.

하지만 그것에 충실하는 것이 의외로 현장에서 잘 이루어져 있지 않고, 세세한 전략들이 충분히 제시되고 있지 않다는 것이 현실임을 안다면 소프트웨어 설계의 기본으로 돌아가자는 DDD의 주장이 매우 강력하고 중요한 것이라는 점을 인식할 수 있을 것이다.

스프링프레임워크의 모체인 Interface21의 Ramnivas Laddad가 정리한 DDD의 세 가지 특징을 살펴보자.

첫째는 도메인 그 자체와 도메인 로직에 초점을 맞춘다는 것이다. 일반적으로 많이 사용하는 데이터중심의 접근법을 탈피해서 순수한 도메인의 모델과 로직에 집중하는 것을 말한다.

둘째는 보편적인(ubiquitous) 언어의 사용이다. 도메인 전문가와 소프트웨어 개발자 간의 커뮤니케이션 문제를 없애고 상호가 이해할 수 있고 모든 문서와 코드에 이르기까지 동일한 표현과 단어로 구성된 단일화된 언어체계를 구축해나가는 과정을 말한다. 이로서 분석 작업과 설계 그리고 구현에 이르기까지 통일된 방식으로 커뮤니케이션이 가능해진다.

셋째는 소프트웨어 엔티티와 도메인 컨셉트를 가능한 가장 가까이 일치시키는 것이다. 분석모델과 설계가 다르고 그것과 코드가 다른 구조가 아니라 도메인 모델부터 코드까지 항상 함께 움직이는 구조의 모델을 지향하는 것이 DDD의 핵심원리이다.

물론 DDD는 방법론이 아니다. 따라서 이런 경우 이렇게 하라는 식의 접근법 보다는 원칙과 핵심가치를 설명해주고 그것에 어떻게 집중할 것인가에 주목하게 하는 것이다. 모든 애플리케이션의 핵심은 결국 그 애플리케이션을 사용할 도메인과 그 로직이라고 본다면 소프트웨어 설계와 구현도 그 부분이 핵심이 되는 것이 마땅하다는 것이 DDD의 개념이라고 생각하면 된다.

DDD에서 스프링의 역할
그렇다면 스프링을 이용한 개발과 DDD는 무슨 직접적인 관련이 있는 것일까?

사실 스프링은 설계도구나 방법론이 아니다. 애플리케이션을 개발하는데 있어서 필요로 하는 기본 프레임워크일 뿐이다. 하지만 스프링은 처음부터 단순한 생산성과 품질향상을 위한 애플리케이션 프레임워크일 뿐만 아니라 개발자들에게 개발의 원칙과 지향해야 할 개발 원리를 설명하기 위해서 등장한 것이다.

따라서 스프링을 사용하면 자연스럽게 그 애플리케이션 코드는 스프링이 지향하는 개발원칙을 따라갈 수 있게 된다.

스프링의 핵심 가치는 위에서 언급한 객체지향(OO)과 단순함(Simplicity)이다.

자바는 처음 언어가 소개될 때 객체지향프로그래밍을 지원하는 강력한 언어라는 점을 가장 중요한 특징으로 내세웠다. 하지만 자바가 본격적으로 사용되는 엔터프라이즈 환경의 코드들을 가만히 살펴보면 과연 객체지향의 특성들이 잘 살아있는지, 그 장점을 잘 활용하고 있는지 생각하면 의문스럽기만 하다.

● Anemic Domain Model
이는 흔히 말하는 빈약한 도메인모델(anemic domain model)라는 말에 잘 나타나 있다. 객체지향에서 말하는 오브젝트는 상태(state)와 행위(behavior)로 구성되어 있어야 한다. 하지만 자바엔터프라이즈 개발에서 흔히 사용되는 방식은 단지 상태 값, 즉 데이터만 가지는 데이터홀더 개념의 단순 오브젝트이다.

이런 오브젝트로 구성된 도메인모델은 객체지향언어와 기술의 장점을 전혀 살릴 수 없는 한계를 가지고 있다. 따라서 구조적으로 불합리한 형태의 코드를 생산하게 한다.

문제는 이런 빈약한 도메인모델과 오브젝트 구조가 거의 엔터프라이즈 자바 개발의 전반에 걸쳐서 사용되고 있다는 점이다. 대부분의 서버사이드 아키텍처라고 제시되는 구조가 빈약한 도메인모델의 사용을 부추기고 있다는 점이 문제다.
빈약한 오브젝트는 자바빈 형태로 나타나는 <리스트 1>과 같은 형태를 가진다.


 <리스트 1> 빈약한 오브젝트(Anemic Object)의 예


class Customer {
Integer customerId
String name
String telephone
String address
Integer point
Date lastVisited

public Integer getCustomerId() {
return customerId
}
public void setCustomerId(Integer customerId) {
this.customerId = customerId;
}
public String getName() {
return name
}
public void setName(String name) {
this.name = name;
}
public String getTelephone() {
return telephone
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getAddress() {
return address
}
public void setAddress(String address) {
this.address = address;
}
public Integer getPoint() {
return point
}
public void setPoint(Integer point) {
this.point = point;
}
public Date getLastVisited() {
return lastVisited
}
public void setLastVisited(Date lastVisited) {
this.lastVisited = lastVisited;
}
}



빈약한 오브젝트가 가져오는 문제는 단지 객체지향 기술의 순수주의자들의 주장처럼 모든 객체는 행위가 포함 되야 한다는 정도에 그치는 것이 아니다.

모든 도메인은 행위에 해당하는 로직을 가지고 있고, 그 로직을 어떠한 형태로든 나타내야 하는데 그것이 도메인의 상태 정보만 가지고 있는 빈약한 오브젝트 속에서 모두 빠져나와 다른 형태로 구성된다는 점이다.

대부분의 자바 엔터프라이즈 아키텍처가 가지고 있는 이런 구조적인 한계들은 결국 과도한 서비스 레이어의 사용을 부추긴다.

도메인오브젝트의 데이터홀더(data holder)화와 서비스레이어의 비대해짐은 결국 트랜잭션 스크립트 패턴의 형태의 코드를 양산하게 된다. 트랜잭션 스크립트는 각 업무 트랜잭션을 하나의 메소드에 한 번에 구성하는 형태의 패턴이다. 이런 형태의 코드는 결국 객체지향적인 도메인모델의 장점을 살릴 수 없는 결과로 나아가게 된다.

<리스트 2>는 트랜잭션 스크립트 스타일의 서비스레이어의 예이다. Customer와 PointRule이라는 두 개의 도메인 오브젝트가 존재하지만 각 도메인에 종속된 로직들이 서비스레이어의 메소드에 산재되어 있는 구조이다.

addPoint 메소드는 Customer, PointRule을 받아서 또 다른 서비스 메소드를 사용해서 다 도메인 오브젝트의 로직에 해당하는 코드를 처리한다. 또한 withInOneMonth 메소드나 isVipCutomer 메소드의 경우도 도메인 오브젝트에 포함해야 하는 내용을 서비스 레이어에 노출한 형태이다.


 <리스트 2> Big Service Layer의 예


class CustomerService {
CustomerDao customerDao;
PointRuleDao pointRuleDao;

public void addPoints() {
List customers = customerDao.getAllCustomers();
PointRule pointRule = pointRuleDao.getCurrentPointRule();

for(Customer customer : customers) {
if (withInOneMonth(customers.getLastVisited())) {
if (isVipCustomer(customer, pointRule)) {
customer.setPoint(customer.getPoint() + VIP_POINTS);
}
else {
customer.setPoint(customer.getPoint() + MEMBER_POINTS);
}
}
}
}

boolean withInOneMonth(Date lastVisited) {
...
}

boolean isVipCustomer(Customer customer, PointRule pointRule) {
...
}
}



이런 형태의 거대한 서비스 레이어(big service layer) 형태는 객체지향의 설계원칙에 맞지 않을 뿐더러 도메인로직을 여러 곳에 산재하게 만들 뿐더러 코드의 중복과 오브젝트의 재활용성을 극히 떨어뜨리게 한다.

데이터중심의 설계와 개발에 익숙한 개발자들은 적절한 도메인모델을 이용해서 개발하는데 경험이 없거나 익숙하지 않기 때문에 이런 방식을 선호하거나 별 문제의식 없이 사용하는 경우가 많다. 또 어떤 기술은 기술자체가 이런 구조적인 한계를 노출하고 있다.

대표적인 것이 EJB의 엔티티빈 기술이다. 스프링을 비롯한 새로운 프레임워크와 기술들이 POJO를 선호하는 이유가 있다면 이 또한 자바의 객체지향적인 특징의 기본으로 돌아갈 수 있는 가장 단순하면서도 이상적이기 때문이다.

<그림 1>은 전형적인 3-tier 구조의 J2EE 아키텍처이다. 도메인 로직이 서비스 레이어에 집중되어있고 도메인모델 오브젝트는 단지 DTO와 같은 역할을 하는 데이터홀더로 사용되는 형태이다. 사실 이런 형태가 자바 엔터프라이즈 개발에서 거의 표준과 같이 인식되고 있다는 것은 심각한 문제이다.

심지어는 초기 스프링의 예제나 스프링 개발자들에 의해서 쓰여진 스프링 서적의 샘플 코드도 이런 구조를 그대로 사용했다는 것은 이런 모델이 얼마나 자연스럽게 개발자들에게 받아들여지고 사용되어져 왔는지 짐작하게 해준다.

<그림-1> Anemic domain model + Big service layer 아키텍처


● Rich Domain Model
빈약한 도메인모델의 한계와 문제점을 인식한 개발자들은 점차로 풍성한 도메인 모델(rich domain model)이나 지능적인 도메인 모델(smart domain model)이라고 불리는 형태로의 전환을 시도한다.

지능적 도메인 모델의 특징은 도메인 오브젝트에 단순한 데이터 값의 저장을 위한 getter/setter가 아닌 도메인과 직접 관련이 되어있는 로직을 담았다는 것이다.

제한적이지만 도메인에 극히 종속적인 로직은 도메인 오브젝트에 담았기 때문에 포터블한 도메인 오브젝트로 발전할 뿐더러 상당수의 로직 부분이 서비스 레이어에서 제거 될 수 있게 하는 좋은 효과를 가져왔다.


 <리스트 3> 풍성한 도메인 오브젝트의 적용 예


class Customer {
Integer customerId
String name
String telephone
String address
Integer point
Date lastVisited
Date registered

public booean isVipCustomer(PointRule pointRule) {
return this.customerLevel > pointRule.getVipLevel(this.registered)
&& isValidRegiststedCustomer();
}

public voiddoVipPointUpgrade(PointRule pointRule) {
if (isVipCustomer(pointRule) && ...)
customer.setPoint(customer.getPoint() + pointRule.VIP_POINTS);
}
else {
customer.setPoint(customer.getPoint() + pointRule.MEMBER_POINTS);
}
}
...

}



<리스트 3>에서는 기존에 서비스 레이어에 있던 도메인 로직이 도메인 오브젝트 안으로 이동한 모습을 볼 수 있다. 이렇게 도메인의 로직이 이동을 하게 되면 서비스 레이어에 중복되고 산재해서 나타나던 도메인 로직이 사라지고 일관성 있게 도메인 오브젝트에 처리를 맞길 수 있는 형태로 발전하게 된다.

<리스트 4>는 풍성한 도메인 오브젝트를 사용하는 서비스레이어의 변화된 모습이다.


 <리스트 4> 풍성한 도메인 오브젝트를 사용하는 서비스 레이어의 예


class CustomerService {
CustomerDao customerDao;
PointRuleDao pointRuleDao;

public void addPoints() {
List customers = customerDao.getAllCustomers();
PointRule pointRule = pointRuleDao.getCurrentPointRule();

for(Customer customer : customers) {
customer.doVipPointUpgrade(pointRule);
}
}
}



● DDD 아키텍처
풍성한 도메인 모델을 사용하는 것만으로도 도메인 모델 중심의 구현과 일치가 어느 정도 가능해졌다. 하지만 DDD에서 지향하는 도메인 레이어라는 개념은 이보다 더 발전된 형태의 아키텍처이다.

<그림 2>는 기존의 3-tier아키텍처와는 다른 형태의 DDD에서 많이 사용하는 구조이다. 기존의 아키텍처와의 가장 큰 변화라면 도메인 레이어의 도입이다. 기존의 도메인 모델/오브젝트는 단지 DTO의 역할을 하거나 데이터 홀더로 사용되어져 왔다면 DDD의 도메인 모델은 독립적인 형태의 레이어를 이루고 있는 것을 볼 수 있다.

<그림 2> DDD아키텍처


도메인 레이어는 비즈니스 애플리케이션의 심장과 갈은 역할을 한다. 모든 도메인 정보와 기능과 로직과 룰이 이 레이어에 집중되고 관리된다. 도메인 전문가와 소프트웨어 개발자들이 지속적으로 함께 살펴보며 다듬어 나갈 수 있는 그 도메인모델을 그대로 반영할 수 있는 구조가 만들어지게 되는 것이다.

이 경우 서비스 레이어는 비즈니스 로직을 직접 가지고 있지 않으면서 소프트웨어의 기능들을 적절한 도메인 레이어와의 협력을 통해서 처리할 수 있는 코디네이터 역할을 담당하게 된다. 따라서 서비스 레이어는 매우 얇아지게 된다.

또 한 가지 큰 변화는 저장소(repository) 또는 데이터액세스 레이어와의 연동을 이제는 도메인 레이어가 직접하게 된다는 것이다. 기존의 풍성한 도메인 모델에서는 도메인모델에게 넘겨줄 필요한 도메인 객체의 생성을 서비스레이어가 담당하게 되었다. 따라서 모든 레이어간의 연동이 서비스 레이어에 집중되는 한계를 가질 수밖에 없었다.

하지만 DDD 아키텍처에서는 도메인모델이 자신이 필요로 하는, 퍼시스턴스 관리를 위한 리포지토리 또는 인프라스트럭처 서비스와 직접 연동하는 것이 가능하다.

<리스트 5>는 도메인 레이어의 형태로 재구성한 Customer 클래스이다. 풍성한 도메인 모델 구조에서는 서비스 레이어가 데이터 액세스 레이어에 요청을 해서 PointRule를 받아 이를 Customer 오브젝트에 넘겨줘야 했지만, 여기서는 직접 PointRuleRepository에 요청해서 필요한 것을 받아서 사용할 수 있다.

따라서 도메인 오브젝트는 서비스 레이어의 도움이 없이도 독립적으로 도메인 로직을 처리할 수 있는 독립된 레이어 형태로 구성이 가능하게 된 것이다.


 <리스트 5> 도메인 레이어의 Customer 클래스


class Customer {
PointRuleRepository pointRuleRepository;

Integer customerId
...
Date lastVisited
Date registered

public booean isVipCustomer(PointRule pointRule) {
return this.customerLevel > pointRule.getVipLevel(this.registered)
&& isValidRegiststedCustomer();
}

public voiddoVipPointUpgrade() {
pointRuleRepository.getCurrentPointRule();

if (isVipCustomer(pointRule))
customer.setPoint(customer.getPoint() + VIP_POINTS);
}
else {
customer.setPoint(customer.getPoint() + MEMBER_POINTS);
}
}




  DI/AOP와 DDD

그렇다면 과연 이런 DDD의 아키텍처 구조와 스프링은 무슨 상관이 있다는 것인가? 사실 스프링이 직접적으로 DDD 아키텍처를 강제하거나 그런 구조로 만들어져 있는 것은 아니다.

스프링은 매우 범용적인 자바엔터프라이즈 개발에 사용되어질 수 있도록 만들어진 프레임워크이다. 그러면서도 DDD아키텍처를 적용할 때에 꼭 필요하다고 생각되는 기능을 제공한다.

도메인 모델와 의존삽입(DI)
위와 같은 도메인 레이어를 만들 때 가지는 문제점에 대해서 생각해보자.

첫 번째 문제는 도메인 오브젝트에 리포지토리나 다른 인프라스트럭처 서비스를 어떻게 삽입 할 것인가의 문제가 있다. 스프링이 지원하는 의존삽입(DI)을 사용하면 간단하게 처리할 수 있을 것 같다. 하지만 도메인 오브젝트는 의존삽입을 적용하기에 적절하지 않다.

스프링에서 빈(bean)으로 등록할 수 있는 것과 또는 없는 것, 하지 말아야할 것을 구분할 때 항상 등장하는 예가 바로 도메인 오브젝트다. 도메인 오브젝트가 스프링의 빈으로 등록되지 말아야 하는 첫 번째 이유는 빈약한 도메인 모델처럼 단순한 데이터만을 가지는 형태이기 때문이다. 즉 의존관계가 없다는 것이다.

따라서 굳지 빈으로 등록할 이유가 없다. 그냥 new 키워드를 통해서 생성하면 된다.

두 번째 문제는 도메인 오브젝트의 생성이 애플리케이션 코드에서 직접 일어나지 않고 써드파티(3-rd party) 프레임워크 등에서 만들어지는 경우가 있기 때문이다. 대표적으로 O/R매핑 툴인 하이버네이트를 사용한다면 find나 get 등에 의해서 전달되는 도메인 오브젝트는 모두 하이버네이트 내부에서 직접 생성이 된다.

따라서 그 오브젝트의 라이프사이클을 스프링에 위임할 수 없기 때문에 빈으로 쓰는 것이 부적절하다.

문제는 빈약한 도메인 모델을 사용한다면 상관없지만, DDD에서의 요구되는 도메인 오브젝트를 사용하려면 외부의 서비스나 리포지토리의 삽입이 필수적으로 요구된다. 하지만 위의 두 가지 제약 때문에 따라서 단순히 빈으로 등록해서 사용하는 것은 불가능하다.

바로 이런 문제를 해결할 수 있는 방법으로 등장한 것이 스프링 2.0의 DDD지원기능이다. 엄밀히 말해서 스프링에 DDD기능이란 없다. 단지 위와 같은 특성을 가지고 있는 도메인 모델에 의존삽입이 가능하게 하기 위해서 스프링 2.0에 특별히 도입된 기능이 있을 뿐이다.

● @Configurable
사실 이를 위해서 스프링이 제공하는 기능은 무척 간단하다. @Configurable이라는 새롭게 도입된 어노테이션과 AspectJ의 도움으로 스프링이 직접 생성하지 않는 도메인 오브젝트에도 의존삽입이 가능하게 해주는 것이다.

원리는 간단하다. AspectJ가 지원하는 LTW(Load Time Weaving)기능을 이용해서 오브젝트가 생성되는 시점의 조인 포인트에서 오브젝트에 자동결합(autowiring) 방식으로 의존성을 삽입해주는 것이다.

스프링의 의존삽입 기능은 XML과 같은 형태로 외부에서 정의하는 방법 외에도 프로그래밍 적으로 사용할 수 있는 자동결합 방식도 가능하다. 이를 이용하면 빈의 이름과 일치하는 setter를 찾아서 자동으로 삽입을 시키는 것이 가능하다.

AspectJ 5의 LTW를 이용하면 별도의 AOP를 위한 컴파일 작업 없이도 클래스가 로딩되는 시점을 이용해서 어느 곳에서 생성되는지와 상관없이 자동으로 의존삽입을 시킬 수 있다. 따라서 @Configurable이 적용되어 있는 모든 도메인 오브젝트에 적절한 외부 의존성을 삽입시켜줄 수 있다.

<리스트 6>은 @Configurable을 정의한 Customer클래스이다. 사실 스프링 2.0의 DDD 지원기능은 막상 적용하려고 보면 무척 간단하다. 물론 그 내부에서 처리되어지는 것들은 매우 복잡한 방식으로 이루어지고 있지만 말이다.


 <리스트 6> @Configurable이 적용된 Customer클래스


@Configurable
class Customer {
PointRuleRepository pointRuleRepository;

public void setPointRuleRepository(PointRuleRepository pointRuleRepository) {
this.pointRuleRepository = pointRuleRepository;
}
...

}



● 도메인 모델과 AOP
의존삽입이 가능하다는 것은 모든 빈 형태로 존재하는 각종 서비스들을 다 이용할 수 있다는 것이다. 이 외에도 도메인 모델에 필요로 하는, AOP에서 자주 등장하는 횡단관심(Crosscutting Concerns)도 모두 적용할 수 있다. 트랜잭션 지원이나 로깅, 보안, 트레이싱 같은 것들을 도메인 오브젝트에 적용하는 것도 스프링 빈의 형태로 정의되기 때문에 모두 할 수 있다.

@Configurable을 정의하기 위해서는 스프링 설정파일에 다음과 같이 prototype 형태로 정의하는 것이 필요하다. 빈으로 등록된 이유는 일반적인 형태의 삽입 대상이 되기 위함은 아니다. 따라서 이 도메인 오브젝트 빈을 다른 빈의 의존관계로 만들면 안 된다.

&ltbean class="com.mycompany.Customer" scope="prototype">
&ltpropety ... />
&ltbean>

빈의 형태로 등록이 되었기 때문에 스프링 AOP의 기능을 모두 적용할 수 있다. 스프링 2.0의 의존삽입과 AOP는 DDD를 본격적으로 구현해서 사용하려면 반드시 필요한 기술이라고 여겨지고 있다. 이제까지 풍성한 도메인 모델 정도의 구현에 만족했던 개발자들에게 도메인 레이어의 구분이라는 본격적인 DDD 구현의 실마리를 찾아준 것이다.

  스프링 DDD의 적용전략

스프링이 제공해주는 DI/AOP를 이용하면 DDD의 도메인 레이어 구현을 위해서 필요로 하는 기술적인 요구사항은 충족될 수 있다. 하지만 이것만으로 바로 DDD방식의 구현에 도전하는 개발자들은 다들 한번쯤 좌절을 겪기 마련이다. 기존의 빈약한 도메인 모델구조에서는 경험하지 못했던 아키텍처상의 더 많은 변수들이 있기 때문이다.

첫 번째로 고민해 볼 것은 리포지토리의 사용방식이다.

스프링 시큐리티를 만든 Ben Alex나 스프링웹플로우의 Keith Donald는 하이버네이트와 같은 투명한영속성(transparent persistence) 방식의 ORM 기술을 선호하는 편이다.

그 이유는 투명한 영속성을 사용하는 방식은 명시적으로 리포지토리에 update문을 호출하지 않아도 퍼시스턴스 오브젝트에 발생하는 변화를 감지해서 자동이로 이를 데이터베이스와 싱크를 맞춰주기 때문이다.

또 도메인 오브젝트 그래프를 따라서 데이터를 자동으로 적절한 시점에서 가져오는 것도 가능하다. 따라서 도메인 로직에 빈번하게 리포지토리나 DAO를 호출하는 코드가 등장하지 않는다.

최초로 퍼시스턴스화 할 때와 초기조회, 삭제, 벌크 수정정도만이 사용되어지고 그 외의 퍼시스턴스 코드가 등장하지 않으니 이 방식을 사용한 코드는 순수한 자바 오브젝트만을 사용한 코드처럼 깔끔하고 명확하게 만들어질 수가 있다.

하지만 이 방식의 문제점을 지적하는 사람도 적지 않다. 대표적으로 역시 스프링의 핵심 개발자인 Ramnivas Raddad이다. 그는 하이버네이트나 JPA를 이용해서 투명한 영속성을 사용할 경우, 그 사용이 과도하게 되면 많은 데이터를 처리하는데 불필요한 오버헤드가 발생한다고 생각한다.

따라서 리포지토리의 데이터 로직을 좀 더 강화해서 매우 정교한 형태의 꼭 필요한 처리만 가능하게 하고 벌크처리는 DAO안에서 가능한 간략한 방식으로 일어나는 것이 좋다고 주장한다.

이렇게 될 경우 도메인 로직을 순수한 자바오브젝트로 표현하던 것을 일부 데이터베이스 스크립트 방식으로 만들게 되지만 전체 애플리케이션의 성능을 고려해 본다면 엔터프라이즈 환경에서는 충분히 타협할 수 있는 구조라는 것이다.

순수한 도메인 오브젝트 중심의 로직 구현방식과 데이터베이스와의 협조를 통한 중도적인 접근방법 중 어느 것이 항상 더 낫다고 볼 수는 없을 것 같다. 그럼에도 필자는 투명한 영속성을 지원하는 ORM을 사용하는 것이 DDD에서 가지는 장점이 매우 많다고 생각한다.

어쨌든 좀 더 오브젝트 중심의 코드가 만들어지기 때문이다. 다른 이유로 원천적으로 ORM 툴을 사용할 수 없는 경우가 아니라면, 그렇게 설계된 후에 필요에 따라서 성능을 위해서 개선하는 방식을 취하는 것이 바람직 할 것이다.

두 번째로 고려해야 할 것은 DTO이다.

ROO(Real Object Oriented)라는 애플리케이션 프레임워크를 만든 Ben Alex는 도메인 오브젝트는 도메인 레이어 밖에서는 존재해서는 안 된다고 주장한다.

따라서 그의 프레임워크에서는 도메인 레이어 밖으로 나오는 오브젝트는 DTO 형태로 복제가 되서 나온다. 서비스 레이어와 도메인 레이어 사이에 얇은 DTO를 위한 어셈블리 레이어를 가지고 있다.

또 모든 도메인 오브젝트는 근본적으로 수정가능하지 않아야(immutable) 한다고 주장하는 사람도 있다. 수정이 필요한 경우는 복제를 통해서 도메인 레이어에 요청해야 한다는 것이다.

필자와 같은 개발자들은 DTO를 쓰는 것을 바람직하지 않게 생각한다. 모든 레이어에 존재하는 도메인 모델(domain model everywhere) 방식을 선호한다. 이 경우 DTO를 지지하는 사람들이 문제로 지적하는 도메인 레이어 외부에서 변경이 일어난다는 문제가 발생한다.

예를 들어 프레젠테이션 레이어에서 임의로 도메인 오브젝트의 로직을 호출하거나 변경을 가할 수도 있다는 것이다. 이런 것을 원천적으로 차단하는 방법 중의 하나가 DTO이다. 하지만 도메인 오브젝트를 직접 사용한다고 할지라도 이런 문제를 해결할 방법이 있다.

역시 스프링 2.0에 등장하는 AspectJ를 이용한 SpringAOP를 적용하면 특정 레이어에서 특정 메소드에 접근하는 것을 강제적으로 차단할 수 있다. 이를 통해서 구지 매번 개발자들에게 개발정책을 교육하고 매번 점검하지 않더라도 이를 편리하게 강제할 수 있다.

  DDD의 미래

DDD는 많은 사람들의 주목을 받고 있는 것에 비해서 사실 상당히 인기가 없다. DDD에 대한 말은 많고 많은 개발자들이 이야기하고 있기는 하지만, 정작 이를 현장에 적용했다는 소식은 그다지 들리지 않는다.

이는 DDD에 대한 정확한 이해와 접근방법에 대한 학습이 부족한 원인도 있을 것이다. 하지만 더 큰 이유는 DDD가 단지 개발 기술이 아니기 때문이다. DDD 사실상 소프트웨어 설계에 관한 철학이다. 그 설계와 구현이 일치를 이뤄야 하기 때문에 스프링과 같은 툴들이 이를 지원하고 있을 뿐이다.

따라서 진정한 DDD를 적용하고 그 장점을 충분히 누리려면 사실 많은 연구와 훈련이 필요로 하다. 스프링과 같은 실전 개발을 위한 좋은 툴이 제공되고 있으니 이제 한번쯤 DDD에 대해서 깊이 연구해보고 도전해볼 때가 되지 않았을까? @


참고자료
1. Anemic Domain Model: http://martinfowler.com/bliki/AnemicDomainModel.html
2. Domian Driven Design with DI and AOP: Ramnivas Laddad
3. Spring 2.0 Reference Manual
4. Domain Driven Design: Eric Evans

* 이 기사는 ZDNet Korea의 제휴매체인 마이크로소프트웨어에 게재된 내용입니다.

신고
Trackback 0 : Comment 0

[펌]DDD(Domain Driven Design) 도메인 주도 개발

ITWeb/스크랩 2008.06.29 00:04
ref. http://www.zdnet.co.kr/builder/dev/web/0,39031700,39170212,00.htm

[DDD ①] 도메인 주도 개발

안영회((주)ITwise 컨설팅 컨설턴트)   2008/06/28
에 릭 에반스의 DDD(Domain-Driven Design)에서 가장 기억하고 싶은 내용은 ‘하나의 팀에서 하나의 언어로’라는 부분이다. 필자는 경험을 통해 개발(Development)을 끌고 가는 중심에는 해당 업무 즉, 도메인 프로그램 개발의 대상이 되는 업무 영역이 있다는 것을 알게 되었다. 결국, 이 묵직하게 자리하는 것이 시스템 개발의 성패를 좌우하게 된다는 점 배우게 되었다. 이 글에서는 이런 문제에 대한 완벽한 해답을 제시하기 보다는 현실적인 해결책에 대하여 이야기하고자 한다.

‘화성에서 온 남자 금성에서 온 여자’라는 유명한 책이 있다. 이 책에서는 남자와 여자가 본래는 서로 다른 별인 화성과 금성에서 살았기 때문에 애초에 서로 다른 존재이며, 서로 다른 가치관과 생각을 가지고 있었다고 이야기한다. 그런데, 이들이 지구로 옮겨오면서 자신들이 서로 다른 존재였다는 사실을 잊게 되면서 갈등이 생겨나기 시작했다는 내용을 담고 있다.

그런데 이런 갈등은 비단 남녀 사이에만 존재하는 것이 아니다. 프로젝트에서도 마치 ‘화성에서 온 개발자 금성에서 온 고객’이라는 말로 비유할 만한 상황이 벌어진다. XP(Extreme Programming)에서 고객이 개발팀의 일원이 되어야 한다고 하는 말은 매우 공감할만한 이야기다. 밥도 같이 먹고 지속적으로 함께 일하다 보면 화성인과 금성인의 격차가 줄어들지도 모르는 탓이다.

  화성에서 온 개발자 금성에서 온 고객

하지만, 경험 많은 개발자(업무 분석가를 포함하여 시스템 개발에 종사하는 소프트웨어 엔지니어를 통칭하는 말)들은 단번에 비현실적이라고 말할 것이다. 업무분석가 역할을 해본 개발자라면 최종 사용자가 될 협업 담당자와 만나는 기회가 충분하지 않다는 사실을 잘 알고 있다.

그래서 복잡한 업무의 경우에는 고객이 아닌 해당 업무분야의 전문가를 포함시키는 경우가 일반적이다. 군 프로젝트에 가면 종종 전역한 장교들을 볼 수가 있고, 금융 프로젝트에서는 해당 업무에 정통한 사람들이 업무 분석가로 활동한다.

어느 정도 고객을 대신할 수 있는 업무 전문가가 있다고 문제가 시원하게 해결되는 것은 아니다. 외주 개발이 보편화된 현실을 감안하면, 서로 다른 행성(도메인)에 살다가 만나게 되는 화성인(개발자)과 금성인(고객)은 근본적으로 차이가 있다.

매일 프로그램의 성능을 고민하고, 새로운 기술 습득으로 일상을 보내던 개발자가 수십 년간 발전해온 산업을 단기간에 이해하는 것은 불가능하다. 반대로 고객의 경우에는 모든 일을 기술적으로 해석하고 사고하는 개발자를 이해하기 어려울 것이다.

이러한 상황을 더욱 악화시키는 것은 서로가 다른 언어를 쓴다는 사실이다. 의사소통을 통해 서로를 이해하기 위해서는 동일한 언어를 사용하는 것은 필수적인 사항인데 말이다.

서로 다른 말을 사용하는 고객과 개발자
개발자가 새로운 분야의 프로젝트를 만나면 도무지 알 수 없는 용어들을 접하게 된다. 특수성이 심한 업무는 고객의 업무 규정이나 보고서를 아무리 읽어도 해독이 불가능한 경우도 있다. 한 페이지의 절반가량을 차지하는 단어가 처음 보는 영문 약어로 기술되어 있는 문서를 상상해보라.

그럼 고객의 입장에서 생각해 보면 어떨까. 바쁜 시간에 불러내서 초보적인 질문에 답변을 해주고 있었다. 그러다가 앞으로 만들어질 프로그램에 궁금한 마음이 생겨, 개발자에게 물어보았더니 도무지 알아들을 수 없는 말만 한다.

이러한 어려움에도 불구하고 고객과 개발자가 잘 소통해야만 원하는 결과를 만들 수 있다. 반대로 이들이 서로 소통에 실패한다면, 원하는 결과는 나오지 않고 서로 잘못된 일만 반목하게 될 것이다. 고객과 개발자가 서로를 맹렬하게 비난하는 현장에 필자 스스로도 참여했던 아픈 경험이 있다.

개발자 사이에서도 각자의 언어가 있다
고객과 개발자 사이에서만 의사소통의 문제가 발생할까? <그림 1>에 표현한 것처럼 도메인을 구성하는 하나의 어휘나 개념이라도 개발자 유형에 따라 상이하게 받아들여진다.

이러한 현상은 서로 다른 유형의 개발자를 한 곳에 모아 동일한 도메인 용어를 가지고 논의를 해보면 쉽게 관찰할 수 있다. 고객을 표현하는 동일한 설계 모델이 없다면 이들 사이의 혼선은 쉽게 예상할 수 있다.

<그림 1> 개발자 유형에 따라 달라지는 도메인 개념의 표현 방법


UML 모델과 프로그램의 코드가 완벽하게 일치하지는 않는다. 마찬가지로 DB의 테이블 이름이나 칼럼 이름이 클래스 이름이나 속성 이름과 대응된다 하더라도 동일하지는 않다. 프로그래머와 DB 개발자 커뮤니티 사이에서는 오랜 동안 매우 다른 작명 관행을 유지해오고 있기도 하다.

화면 개발자의 경우도 크게 다르지 않다. 결국은 이들 사이의 구체적인 차이점을 배제한 추상화된 표현법을 공통의 언어로 활용할 수 있다. 일반적으로 설계 모델이 그러한 역할을 해야 한다.

하나의 팀, 하나의 언어
에릭 에반스는 프로젝트 팀이 지향할 목표지점을 분명하게 도식화했다. <그림 2>는 DDD 34쪽의 그림을 간략하게 요약한 것이다. Ubiquitous Language(이하 UL)는 고객과 개발자 양쪽에서 통용되는 어휘를 의미한다. 처음에는 교집합이 없이 나누어져 있다고 하더라도, 프로젝트를 진행하면서 교집합을 충분히 늘려가야 한다.

한편, 어떤 어휘의 경우는 공통의 어휘 구실을 하지 못할 수도 있다. 프로그램에 포함시킬 수 없는 업무의 어휘나 기술 자체에 대한 결정사항은 굳이 서로 논의하여 혼란을 야기할 필요는 없다.

<그림 2> Ubiquitous Language


개발자 사이에서는 물론이고, 고객과 개발자가 서로 같은 언어를 쓰기 위한 소프트웨어 커뮤니티의 노력이 없었던 것은 아니다. 다양한 표기법의 모델이 과거부터 존재해왔다. 그리고 이름에서도 드러나듯이 UML(Unified Modeling Language)은 모델링 언어를 표준화하기 위한 목적으로 나타난 것이다.

다만, UML로 작성한 모델이 모두에게 통용되고 있지는 못하다다는 점이 문제다.

  모델 주도의 설계(Model Driven Design)

필자가 보다 효과적인 모델링 방안을 고민하던 시점에 마침 한 권의 눈에 띄는 책을 만났다. 바로 에릭 에반스(Eric Evans)가 쓴 Domain-Driven Design(이하 DDD)이다. 이 책은 모델링에 대한 풍부한 경험이 없는 개발자에게는 그다지 유용한 책이 되지 않을 수 있다. InfoQ 사이트에서 요약된 이북을 다운로드 받을 수 있다(http://www.infoq.com/minibooks/domain-driven-design-quickly).

<화면 1> Domain-Driven Design의 표지


방대한 분량의 책 내용을 집약해서 전달하기 위해 곳곳에서 에릭은 DDD의 골격을 이루는 어휘들로 일종의 이동 경로를 그려놓았다. 그 중심에 있는 두 개의 어휘가 있는데 하나는 앞서 언급한 UL이다. 이는 (고객과 개발자) 모두에게 통용되는 언어를 의미한다. 다른 하나는 모델이 주도하는 설계(Model-Driven Design 이하 MDD)이다.

<그림 3>는 개발의 중심에서 서로 다른 노력을 응집시키는 구심점 역할을 하는 모델을 도식화 해본 것이다. 중심에서 발산해나가는 것은 다양한 유형의 개발 결과물 혹은 고객의 시스템에 대한 이해나 기대라고 가정해보자. 고객과 개발자, 유형이 다른 개발자 사이에서라면 모두 조금씩 다른 방향으로 발전하게 마련이다.

이 때 구심점이 되어 이들을 연결해주는 모델이 없다면 각각이 발산해 나가면서 괴리가 커질 것이다.

<그림 3> 개발의 중심에 자리한 모델


반면, 모델을 중심으로 강한 응집력이 갖게 된다면 모델은 바로 훌륭한 UL의 역할을 하는 것이다.

고객이 이해할 수 있는 모델
DDD에는 다음과 같은 내용이 나온다.

숙련된 업무 전문가(sophisticated domain experts)가 모델을 이해하지 못한다면, 모델에 문제가 있는 것이다.

만일 모델을 고객이 이해할 수 없다면 어떤 일이 벌어질까? 개발자는 고객과 의사소통을 하기 위해 모델 이외의 다른 무언가를 만들어야 한다. 물론, 이것보다는 모델을 고객과 소통할 수 있게 만들어야 한다.

종종 많은 사람들이 고객이 UML을 직접 활용하는 것은 무리라고 한다. 하지만, ERD를 놓고 고객과 개발자가 치열하게 논의를 하는 경우를 보는 일은 어렵지 않다. UML은 결코 ERD보다 복잡하지 않다.

만일 UML로 작성된 모델이 실효성을 발휘하고 있지 못하다면, 본질적인 정보를 표현하는데 초점을 맞추기 보다는 산출물의 형식이나 모델링 방식에 얽매이는 수준에 머물러 있기 때문이 아닌가 생각해봐야 한다.

만일 고객이 이해할 수 있는 표현법이 클래스다이어그램 하나라면 이를 활용하여 의사소통을 하라. 많은 어휘와 수사를 활용한다고 의사소통이 잘 되는 것은 아니다.

모델 사이의 괴리를 줄여라
CBD 도입 초창기 EJB가 유행할 때 모델링 도구를 이용하여 EJB를 구성하는 요소들을 모두 설계 모델에 표현하던 때가 있었다. <그림 4>는 분석 모델에서 고작 네 개의 클래스 혹은 인터페이스를 EJB로 변환한 것이다. 이러한 모델은 EJB의 구성요소를 이해하는 것 이외에 어떤 효용성을 지닐지 의문이다.

<그림 4>의 다이어그램을 가지고 고객과 의사소통 할 수 있겠는가? 실제 현장에서는 이보다 훨씬 복잡하여 지하철 노선도와 같은 그림이 될지도 모른다.

<그림 4> EJB 기반의 설계 모델


고객과는 분석 모델로 의사소통을 하고, 설계 모델은 개발자를 위한 것이라고 가정해보자. 사실 고객 중에는 최종 사용자만 있는 것이 아니라, 시스템을 유지 보수하는 고객도 있다는 것을 고려하면 이러한 가정은 그다지 유효하지 않다. 그럼에도 불구하고 기술과 업무가 혼재되어 마치 스파게티와 같은 모델이 개발자에게라도 도움이 되는가?

필자가 참여했거나 알고 있던 모든 프로젝트는 분석 모델과 설계 모델을 별도로 만든다(현재도 대부분의 SI 프로젝트에서는 분석 모델과 설계 모델을 별도로 만든다). 분석/설계를 담당한 개발자들에게 UML로 모델링 하는 것을 멘토링 하는 것이 익숙해질 시점에서 한 가지 의문이 들었다.

촉박한 일정과 이제 막 UML을 배워서 모델링을 하는 개발자들이 분석 모델과 설계 모델을 모두 만들어내는 것이 과연 옳은가 하는 점이다(필자가 현재 참여하고 있는 프로젝트에서도 이러한 모순을 최대한 해결하려고 노력하고 있다).

더군다나 J2EE 기반의 애플리케이션을 만드는데 자바를 한 번도 써보지 않았고, CBD(Component-Based Development)의 기반기술에 대한 이해가 전혀 없는 사람이 업무 분석 이후에 설계를 담당했다.

결론적으로 필자는 분석 모델과 설계 모델을 모두 표현하는 방식에 매우 비효율적이라고 생각한다(아쉽게도 필자가 참여했던 프로젝트를 포함하여 대형 SI업체가 주도하는 대부분의 프로젝트에서는 분석 모델과 설계 모델을 모두 만들어낸다).

대체로 분석 모델을 만들 때는 업무에 초점이 맞춰진다. 분석 모델을 토대로 설계 모델을 만들어낸다. 설계 모델 작업은 대개 프로그래밍으로 만들기 위해서 영문화 작업을 하고 나서, 기술 환경을 위한 변형 작업을 수행한다.

이 때, 분석 내용에 누락된 것이나 미진한 사항이 있다면 어떻게 할 것인가? 또한, 새로운 요구사항이 들어오면 분석과 설계에 모두 적용할 것인가? 양쪽에 모두 반영하게 되면 주어진 시간에 대해 노력이 분산되고, 한쪽에만 반영하면 분석 모델과 설계 모델 사이의 연계가 완벽하게 유지되지 못한다.

분석 모델과 설계 모델의 통합
성공을 거두지는 못했지만 OMG의 MDA(Model Driven Architecture)는 고객과 애플리케이션 개발자 사이에서 하나의 모델(Platform Independent Model)만으로 의사소통 하는 방향을 지향했다. 이를 가능하도록 하기 위해 MDA 기반 실행 환경에서 구체적인 기술적 결정을 전담하게 했다.

MDA와는 완전히 다른 접근이지만, 최근에는 POJO(Plain Old Java Object) 기반의 개발 방식이 대두되면서 하나의 모델만으로도 고객과 개발자가 의사소통 할 수 있는 환경이 부상했다. 스프링(Spring)이라는 공개 소프트웨어가 MDA 실행환경과 유사한 역할을 제공하면서 실제 애플리케이션 코드와 분석 모델 사이의 차이가 매우 좁아졌다.

<그림 5> POJO 기반의 엔터프라이즈 시스템 구현 기술


필자는 ERD가 고객과 통용이 되는 환경이라면, 적어도 UML로 작성한 클래스다이어그램으로 도메인의 핵심적인 어휘를 표현한다면 충분히 고객과 개발자가 업무에 관해 이야기 할 수 있다고 믿는다. 불필요한 정보나 표기법으로 복잡도만 가중시키지 않는다면, 고객이 클래스다이어그램을 가지고 이야기 하는 것에 흥미를 느낄 수도 있을 것이다.

<그림 6> 대학에 존재하는 사람의 유형을 표현한 클래스 다이어그램


또한, 고객과 개발자가 소통할 수 있다면 굳이 UML을 표기법으로 고집할 필요는 없다. RUP(Rational Unified Process)나 RUP에 기초한 방법론을 사용하는 경우에도 많은 경우, 비즈니스 모델링 산출물에는 UML을 굳이 쓰지 않는다. 이미 업무 흐름이나 주요 기능 구성을 표현하기 위해 고객들의 눈에 익은 표기법이 있기 때문이다.

하나의 모델을 향해 갈 때 만나게 되는 장벽
필자는 몇 년 전 분석 모델만을 사용하자는 의견을 제시한 일이 있다. 그리고 오랜 논의 끝에 분석 모델을 단지 영문으로 변환하는 수준에서 설계 모델을 만드는 방식으로 모델링 기법을 개선해나갔다. 이러한 과정 속에서도 많은 장벽을 마주치게 되었다. 주로 다음과 같은 반응이었다.

● 우리의 표준 방법론에 위배된다.
● 분석 모델과 설계 모델이 별로 차이가 없는 것이 말이 되느냐?
● 검증되지 않은 방법이다.

IT에도 일반 업무처럼 규정을 따르게 하는 조직의 운영방식이 투영된 것으로 해석할 수 있다. 혹은 아직 모델의 내용이나 효과를 논하는 수준이 되지 못하는 경우다. UML 모델을 처음 도입하는 시점에서 형식의 표준화로 최소한의 품질을 확보하려는 시점으로 볼 수 있다.

따라서 지나치게 형식에 얽매이는 경우를 아직은 어렵지 않게 만나게 된다. UML이 널리 쓰이고 있기 때문에 머지않아 이러한 문제는 결될 것이다.

이러한 장벽 이외에도 국내 언어 환경의 특수성에 기인한 문제도 넘어야 한다. 대부분의 국내 프로젝트에서 영어로 작성된 분석 모델은 상상하기는 힘들다. 반면에 설계 모델의 경우는 한글로 작성하면 코드와 대응시키기가 어렵다. 한글을 지원하는 프로그래밍 언어가 있다하더라도, 여전히 한글로 프로그래밍을 작성하는 경우는 찾아보기 힘들다.

  소프트웨어 엔지니어로서 해결해야 할 도전 과제

소프트웨어 엔지니어는 앞서 언급한 장벽들을 해결하는 것을 업으로 한다. 뜻이 있는 곳에 길이 있다고 시간이 소요될 뿐 항상 해결책은 있기 마련이다.

먼저 새로운 방식에 대한 거부감이나 저항이 있는 경우라면 점진적으로 개선하면 된다. 분석 모델과 설계 모델 두 개를 모두 유지하더라도 도메인이 잘 드러나는 분석 모델을 중점적으로 활용하고, 설계 모델을 보조적으로 사용할 수도 있다. 또한, 분석 모델을 통해 코드를 도출하고, 역공학(reverse engineering)을 이용해 설계 모델을 만들 수도 있다.

DDD에서 말하듯이 하나의 언어로 모두에게 통용되면 좋겠지만 모든 상황에서 이를 적용할 수는 없다. 반면에 어디에서든 상황에 맞게 점진적으로 적용하는 것은 가능하다. 도메인 개념을 표현하는 방식 혹은 도메인 개념을 구체화하는 과정에서의 산출물 표기가 서너 가지 이상이라면 한 가지씩 줄여나가는 것만 해도 의사소통의 복잡도는 줄어드는 것이다.

새로운 방식에 대한 고객과 개발자의 적응을 돕기 위해서는 조심스러운 접근이 필요하다. 가시적인 실효성을 직접 맛보게 함으로써 변화를 적극적으로 수용하게 하는 것이다.

요즘 필자는 설계 모델 대신에 분석 모델로 포착한 업무 어휘를 엑셀 문서로 정리하고, 이를 기반으로 자바 클래스와 화면에 데이터를 전달할 XML 문서를 생성하는 작업을 시도하고 있다.

분석 모델이 갖는 약점을 설계 결정을 담은 엑셀 문서가 보완하는 방식이다. 개발 과정이나 향후 유지보수 시점에서 엑셀 시트가 익숙하게 통용될 수 있다면 굳이 UML만 활용할 필요는 없는 것 아닌가?

도메인 모델의 실효성을 극대화하기 위해서 모델과 실제 구현 산출물 사이의 괴리를 줄여야 한다. 그래야만 개발자들도 도메인 모델에 더욱 노력을 쏟을 수 있다. 소프트웨어 엔지니어는 이를 위해 지속적으로 프로세스나 개발 도구를 개선해야 한다.

<그림 7>에 나타낸 것처럼 도메인 모델로부터 많은 개발 산출물이 자동으로 생성될 수 있다면, 모델은 더욱 널리 쓰이게 되어 궁극인 하나의 언어로 나아갈 것이다.

<그림 7> 도메인 모델을 활용한 개발 산출물의 자동 생성


한편, 분석 모델과 설계 모델의 차이가 한글과 영어라는 차이뿐이라면 굳이 두 개로 모델을 분리할 필요가 없다. EA(Enterprise Architect)와 같은 모델링 도구에서는 이름 외에도 별칭(Alias)을 추가로 지원한다. 이름은 한글을 사용하고, 별칭은 영어를 쓴다고 다이어그램에 따라서 한글로 보이게 하거나, 영문으로 나타낼 수 있다.

그런 기능을 지원하지 않는 모델링 도구를 쓴다고 해도 클래스 이름은 영문을 쓰고, 스테레오 타입에는 한글을 넣는 방법으로도 문제를 해결할 수 있다.

<화면 2> EA의 다이어그램 등록정보 설정 창


사용하는 언어가 다르다면 대화가 어려운 것은 상식적인 일이다. 언어가 같더라도 사용하는 어휘가 다르면 의사소통이 어렵기 마련이다. 고객이 원하는 시스템을 만들어내기 위해서 고객과 개발자는 충분한 대화 필요하고, 이를 통해 개발자는 고객의 요구를 충분하게 이해해야 한다.

소프트웨어 구현 기술은 비약적으로 발전해나가고 있지만, 고객의 요구사항도 따라서 복잡해져 가고 있다. 대부분의 프로젝트에서는 기술적인 문제로 실패하기 보다는 고객의 요구사항에 대한 낮은 이해가 실패의 원인으로 작용한다.

필자는 이 글에서 고객의 업무에 초점을 맞춘 도메인 모델이 갖는 의미를 강조하고자 했다. 도메인 모델의 고객과 개발자의 언어로서 통용되기 위해서는 지속적인 노력이 필요하다. 그러한 노력은 프로젝트의 성공을 위한 열쇠가 될 수 있다.

현실적으로 고객과 개발자, 그리고 서로 다른 유형의 개발자 사이에서 하나의 언어가 통용되게 하려면 많은 장벽을 넘어야 한다. 필자는 이 글에서 자세하게 이들 장벽을 살펴보지는 않았다. 사실 어떠한 장애물이 나타나도 그 상황에서 최적의 선택을 하면 그뿐이다.

짧은 글로 구체적인 실행 방안을 제공해주지는 못할 것이다. 그저 짧은 필력이나마 독자들에게 공통된 언어로써의 도메인 모델이 가치가 있다는 사실만 분명하게 전달할 수 있기를 바랄 뿐이다. @


참고자료
1. Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans, 33~34쪽.
2. http://www.agilemodeling.com/artifacts/classDiagram.htm



* 이 기사는 ZDNet Korea의 제휴매체인 마이크로소프트웨어에 게재된 내용입니다.
신고
Trackback 0 : Comment 0