cover story3 DDD 개발의찰떡궁합 스프링프레임워크와 DDD 스프링프레임워크 (SpringFramework, 이하스프링 ) 의첫번째메이저업그레이드버전인 2.0 이처음발표되었을때개발자들이가장관심을가지고주 목했던것은스프링을통한 DDD(Driven Driven Design) 였다. 대부분의개발자들에게아직생소했던개념이었던 DDD 를과감하게주요기능으로내세 우면서등장한스프링은과연 DDD 와어떤관련이있는것일까? 스프링 2.x 를통해서 DDD 를적용하는전략은어떤것들이있는지살펴보자. 스프링 2.0 버전은 2005 년말에열렸던 TheSpring Experience 컨퍼런스에서처음소개가되었다. 그때까지 1.3버전으로준비되고있었던스프링의차기버전이컨퍼런스기간에 2.0이라는메이저버전으로버전자체의업그레이드가일어났다. 그결정의배경은스프링의다음버전에등장하는기능들의중요도와변화의영향력이메이저업그레이드를하는것이바람직할만큼중요하다는공감이있었기때문이다. 스프링 2.0에소개된새로운기능에는 XML 설정의단순화나스키마의도입또자바 5 의새롭게소개된언어특성의적용등그동안지속적으로요구되어졌기때문에당연히들어갈것으로기대했던내용들이대거포함되어있었다. 그런데그중에서필자의눈을사로잡는생소한단어가눈에띄었는데그것이바로 DDD다. TDD는많이들어봤어도 DDD는무엇인가궁금해하면서 DDD에대해서찾아보니이미몇년전부터엔터프라이즈아키텍처기술에관한이야기들이나올때마다자주등장했던 Eric Evans의책제목인 Domain Driven Design의약자인 DDD였다. 이일민 tobyilee@gmail.com 오픈소스기술을엔터프라이즈시스템에적용할수있는전략과기술연구에많은관심을가지고있다. 스프링프레임워크와하이버네이트등의오픈소스프레임워크의교육, 컨설팅, 기술지원을제공하고있는 Epril의대표컨설턴트로활동하고있다. 한국스프링사용자모임의기술고문으로도활동하며오픈소스기술의저변확대를위해서노력하고있다. 오픈소스기술에대한정보를공유하는 toby.epril. com 블로그를운영하고있다. 스프링 2.0 AOP, IoC/DI, PSA같은시대를앞서나가는새로운컨셉트와기능들을과감하게소개하고이를현장에접목시키는데앞서왔던스프링이었던지라많은스프링개발자들은지속적으로엔터프라이즈개발에필요로한유용한기술과전략이스프링의업그 134 m a s o
레이드과정을통해서소개될것을기대해왔다. 하지만 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 Develo pment without EJB라는책의첫장에서는스프링이지향하는핵심가치를소개한다. 그중가장눈에띄는것이있다면바로 OO(Object Oriented) 라는것이다. 스프링이추구하는핵심가치는바로객체지향이다. 자바라는객체지향언어를사용하는프레임워크인스프링이니당연히 OO적일텐데왜그것을핵심가치라고하면서강조하고등장한것일까? 그것은자바의근본이라고도할수있는객체지향이사실은엔터프라이즈환경에서상당히무시당하고있다는안타까운현실에서나온것이다. 스프링은그것을사용하는개발자들에게자바가객체지향언어라는가장기초적인사실을다시상기시켜주면서그기초에충실할때에가장복잡하게생각되는엔터프라이즈개발이사실은쉽고단순해진다는것을알려주려는의도를가지고만들어진것이다. DDD 또한그와유사하다. DDD는어떤천재적인기술자에게서갑자기소개된새로운개념과아이디어가아니다. 소프트웨어설계라는것이존재했던가장초기부터추구하고가져왔던가장기초가되는기본에다시충실하자는이야기이다. 그래서어떤사람들에게는매우진부하고당연하게들리기도한다. Eric Evans의 DDD 책을읽어본많은사람들이의외로실망하는이유가바로거기에있다. 이미잘알고있다고생각하는당연한내 용들이많기때문이다. 하지만그것에충실하는것이의외로현장에서잘이루어져있지않고, 세세한전략들이충분히제시되고있지않다는것이현실임을안다면소프트웨어설계의기본으로돌아가자는 DDD의주장이매우강력하고중요한것이라는점을인식할수있을것이다. 스프링프레임워크의모체인 Interface21의 Ramnivas Lad dad가정리한 DDD의세가지특징을살펴보자. 첫째는도메인그자체와도메인로직에초점을맞춘다는것이다. 일반적으로많이사용하는데이터중심의접근법을탈피해서순수한도메인의모델과로직에집중하는것을말한다. 둘째는보편적인 (ubiquitous) 언어의사용이다. 도메인전문가와소프트웨어개발자간의커뮤니케이션문제를없애고상호가이해할수있고모든문서와코드에이르기까지동일한표현과단어로구성된단일화된언어체계를구축해나가는과정을말한다. 이로서분석작업과설계그리고구현에이르기까지통일된방식으로커뮤니케이션이가능해진다. 셋째는소프트웨어엔티티와도메인컨셉트를가능한가장가까이일치시키는것이다. 분석모델과설계가다르고그것과코드가다른구조가아니라도메인모델부터코드까지항상함께움직이는구조의모델을지향하는것이 DDD의핵심원리이다. 물론 DDD는방법론이아니다. 따라서이런경우이렇게하라는식의접근법보다는원칙과핵심가치를설명해주고그것에어떻게집중할것인가에주목하게하는것이다. 모든애플리케이션의핵심은결국그애플리케이션을사용할도메인과그로직이라고본다면소프트웨어설계와구현도그부분이핵심이되는것이마땅하다는것이 DDD의개념이라고생각하면된다. DDD 에서스프링의역할그렇다면스프링을이용한개발과 DDD는무슨직접적인관련이있는것일까? 사실스프링은설계도구나방법론이아니다. 애플리케이션을개발하는데있어서필요로하는기본프레임워크일뿐이다. 하지만스프링은처음부터단순한생산성과품질향상을위한애플리케이션프레임워크일뿐만아니라개발자들에게개발의원칙과지향해야할개발원리를설명하기위해서등장한것이다. 따라서스프링을사용하면자연스럽게그애플리케이션코드는스프링이지향하는개발원칙을따라갈수있게된다. 스프링의핵심가치는위에서언급한객체지향 (OO) 과단순함 (Simplicity) 이다. 자바는처음언어가소개될때객체지향프로그래밍을지원하는강력한언어라는점을가장중요한특징으로내세웠다. 하지 m a s o 135
cover story 3_ 스프링프레임워크와 DDD 만자바가본격적으로사용되는엔터프라이즈환경의코드들을가만히살펴보면과연객체지향의특성들이잘살아있는지, 그장점을잘활용하고있는지생각하면의문스럽기만하다. 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을받아서또다른서비스메소드를사용해서다도메인오브젝트의로직에해당하는코드를처리한다. 또한 within OneMonth 메소드나 isvipcutomer 메소드의경우도도메인오브젝트에포함되야하는내용을서비스레이어에노출한형태이다. 이런형태의거대한서비스레이어 (big service layer) 형태는객체지향의설계원칙에맞지않을뿐더러도메인로직을여러곳에산재하게만들뿐더러코드의중복과오브젝트의재활용성을극히떨어뜨리게한다. 136 m a s o
< 리스트 2> Big Service 의예 class CustomerService { CustomerDao customerdao; PointRuleDao pointruledao; public void addpoints() { List<Customer> 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) { 데이터중심의설계와개발에익숙한개발자들은적절한도메인모델을이용해서개발하는데경험이없거나익숙하지않기때문에이런방식을선호하거나별문제의식없이사용하는경우가많다. 또어떤기술은기술자체가이런구조적인한계를노출하고있다. 대표적인것이 EJB의엔티티빈기술이다. 스프링을비롯한새로운프레임워크와기술들이 POJO를선호하는이유가있다면이또한자바의객체지향적인특징의기본으로돌아갈수있는가장단순하면서도이상적이기때문이다. < 그림 1> 은전형적인 3-tier 구조의 J2EE 아키텍처이다. 도메인로직이서비스레이어에집중되어있고도메인모델오브젝트는단지 DTO와같은역할을하는데이터홀더로사용되는형태이다. 사실이런형태가자바엔터프라이즈개발에서거의표준과같이인식되고있다는것은심각한문제이다. 심지어는초기스프링의예제나스프링개발자들에의해서쓰여진스프링서적의샘플코드도이런구조를그대로사용했다는것은이런모델 이얼마나자연스럽게개발자들에게받아들여지고사용되어져왔는지짐작하게해준다. Presentation Rich Domain Model Anemic Domain Model Service < 그림 1> Anemic domain model + Big service layer 아키텍처 Data Access 빈약한도메인모델의한계와문제점을인식한개발자들은점차로풍성한도메인모델 (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) && ) m a s o 137
cover story 3_ 스프링프레임워크와 DDD customer.setpoint(customer.getpoint() + pointrule.vip_points); else { 면 DDD의도메인모델은독립적인형태의레이어를이루고있는것을볼수있다. customer.setpoint(customer.getpoint() + pointrule.member_points); Presentation Service Domain Data Access < 리스트 3> 에서는기존에서비스레이어에있던도메인로직이도메인오브젝트안으로이동한모습을볼수있다. 이렇게도메인의로직이이동을하게되면서비스레이어에중복되고산재해서나타나던도메인로직이사라지고일관성있게도메인오브젝트에처리를맞길수있는형태로발전하게된다. < 리스트 4> 는풍성한도메인오브젝트를사용하는서비스레이어의변화된모습이다. < 리스트 4> 풍성한도메인오브젝트를사용하는서비스레이어의예 class CustomerService { CustomerDao customerdao; PointRuleDao pointruledao; public void addpoints() { List<Customer> customers = customerdao.getallcustomers(); PointRule pointrule = pointruledao.getcurrentpointrule(); DDD 아키텍처 for(customer customer : customers) { customer.dovippointupgrade(pointrule); 풍성한도메인모델을사용하는것만으로도도메인모델중심의구현과일치가어느정도가능해졌다. 하지만 DDD에서지향하는도메인레이어라는개념은이보다더발전된형태의아키텍처이다. < 그림 2> 는기존의 3-tier 아키텍처와는다른형태의 DDD에서많이사용하는구조이다. 기존의아키텍처와의가장큰변화라면도메인레이어의도입이다. 기존의도메인모델 / 오브젝트는단지 DTO의역할을하거나데이터홀더로사용되어져왔다 < 그림 2> DDD 아키텍처 도메인레이어는비즈니스애플리케이션의심장과갈은역할을한다. 모든도메인정보와기능과로직과룰이이레이어에집중되고관리된다. 도메인전문가와소프트웨어개발자들이지속적으로함께살펴보며다듬어나갈수있는그도메인모델을그대로반영할수있는구조가만들어지게되는것이다. 이경우서비스레이어는비즈니스로직을직접가지고있지않으면서소프트웨어의기능들을적절한도메인레이어와의협력을통해서처리할수있는코디네이터역할을담당하게된다. 따라서서비스레이어는매우얇아지게된다. 또한가지큰변화는저장소 (repository) 또는데이터액세스레이어와의연동을이제는도메인레이어가직접하게된다는것이다. 기존의풍성한도메인모델에서는도메인모델에게넘겨줄필요한도메인객체의생성을서비스레이어가담당하게되었다. 따라서모든레이어간의연동이서비스레이어에집중되는한계를가질수밖에없었다. 하지만 DDD 아키텍처에서는도메인모델이자신이필요로하는, 퍼시스턴스관리를위한리포지토리또는인프라스트럭처서비스와직접연동하는것이가능하다. < 리스트 5> 는도메인레이어의형태로재구성한 Customer 클래스이다. 풍성한도메인모델구조에서는서비스레이어가데이터액세스레이어에요청을해서 PointRule를받아이를 Cus tomer 오브젝트에넘겨줘야했지만, 여기서는직접 Point RuleRepository에요청해서필요한것을받아서사용할수있다. 따라서도메인오브젝트는서비스레이어의도움이없이도독립적으로도메인로직을처리할수있는독립된레이어형태로구성이가능하게된것이다. < 리스트 5> 도메인레이어의 Customer 클래스 class Customer { PointRuleRepository pointrulerepository; 138 m a s o
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); 만을가지는형태이기때문이다. 즉의존관계가없다는것이다. 따라서굳지빈으로등록할이유가없다. 그냥 new 키워드를통해서생성하면된다. 두번째문제는도메인오브젝트의생성이애플리케이션코드에서직접일어나지않고써드파티 (3-rd party) 프레임워크등에서만들어지는경우가있기때문이다. 대표적으로 O/R매핑툴인하이버네이트를사용한다면 find나 get 등에의해서전달되는도메인오브젝트는모두하이버네이트내부에서직접생성이된다. 따라서그오브젝트의라이프사이클을스프링에위임할수없기때문에빈으로쓰는것이부적절하다. 문제는빈약한도메인모델을사용한다면상관없지만, DDD 에서의요구되는도메인오브젝트를사용하려면외부의서비스나리포지토리의삽입이필수적으로요구된다. 하지만위의두가지제약때문에따라서단순히빈으로등록해서사용하는것은불가능하다. 바로이런문제를해결할수있는방법으로등장한것이스프링 2.0의 DDD지원기능이다. 엄밀히말해서스프링에 DDD기능이란없다. 단지위와같은특성을가지고있는도메인모델에의존삽입이가능하게하기위해서스프링 2.0에특별히도입된기능이있을뿐이다. DI/AOP와 DDD 그렇다면과연이런 DDD의아키텍처구조와스프링은무슨관계가있다는것인가? 사실스프링이직접적으로 DDD 아키텍처를강제하거나그런구조로만들어져있는것은아니다. 스프링은매우범용적인자바엔터프라이즈개발에사용되어질수있도록만들어진프레임워크이다. 그러면서도 DDD아키텍처를적용할때에꼭필요하다고생각되는기능을제공한다. 도메인모델와의존삽입 (DI) 앞에서와같은도메인레이어를만들때가지는문제점에대해서생각해보자. 첫번째문제는도메인오브젝트에리포지토리나다른인프라스트럭처서비스를어떻게삽입할것인가의문제가있다. 스프링이지원하는의존삽입 (DI) 을사용하면간단하게처리할수있을것같다. 하지만도메인오브젝트는의존삽입을적용하기에적절하지않다. 스프링에서빈 (bean) 으로등록할수있는것과또는없는것, 하지말아야할것을구분할때항상등장하는예가바로도메인오브젝트다. 도메인오브젝트가스프링의빈으로등록되지말아야하는첫번째이유는빈약한도메인모델처럼단순한데이터 @Configurable 사실이를위해서스프링이제공하는기능은무척간단하다. @Configurable이라는새롭게도입된어노테이션과 AspectJ의도움으로스프링이직접생성하지않는도메인오브젝트에도의존삽입이가능하게해주는것이다. 원리는간단하다. AspectJ가지원하는 LTW(Load Time Weaving) 기능을이용해서오브젝트가생성되는시점의조인포인트에서오브젝트에자동결합 (autowiring) 방식으로의존성을삽입해주는것이다. 스프링의의존삽입기능은 XML과같은형태로외부에서정의하는방법외에도프로그래밍적으로사용할수있는자동결합방식도가능하다. 이를이용하면빈의이름과일치하는 setter를찾아서자동으로삽입을시키는것이가능하다. AspectJ 5의 LTW를이용하면별도의 AOP를위한컴파일작업없이도클래스가로딩되는시점을이용해서어느곳에서생성되는지와상관없이자동으로의존삽입을시킬수있다. 따라서 @Configurable이적용되어있는모든도메인오브젝트에적절한외부의존성을삽입시켜줄수있다. < 리스트 6> 은 @Configurable을정의한 Customer클래스이다. 사실스프링 2.0의 DDD 지원기능은막상적용하려고보면무척간단하다. 물론그내부에서처리되어지는것들은매우복 m a s o 139
cover story 3_ 스프링프레임워크와 DDD 잡한방식으로이루어지고있지만말이다. < 리스트 6> @Configurable 이적용된 Customer 클래스 @Configurable class Customer { PointRuleRepository pointrulerepository; public void setpointrulerepository(pointrulerepository pointrulerepository) { this.pointrulerepository = pointrulerepository; 도메인모델과 AOP 의존삽입이가능하다는것은모든빈형태로존재하는각종서비스들을다이용할수있다는것이다. 이외에도도메인모델에필요로하는, AOP에서자주등장하는횡단관심 (Crosscutting Concerns) 도모두적용할수있다. 트랜잭션지원이나로깅, 보안, 트레이싱같은것들을도메인오브젝트에적용하는것도스프링빈의형태로정의되기때문에모두할수있다. @Configurable을정의하기위해서는스프링설정파일에다음과같이 prototype 형태로정의하는것이필요하다. 빈으로등록된이유는일반적인형태의삽입대상이되기위함은아니다. 따라서이도메인오브젝트빈을다른빈의의존관계로만들면안된다. <bean class= com.mycompany.customer scope= prototype > <propety /> <bean> 빈의형태로등록이되었기때문에스프링 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는도메인오브젝트는도메인레이어밖에서는 140 m a s o
존재해서는안된다고주장한다. 따라서그의프레임워크에서는도메인레이어밖으로나오는오브젝트는 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 세미나주제제안이벤트 < 월간 > 마소창간 24 주년세미나의주제제안이벤트변화하는세상을이끄는 차세대웹개발전략세미나 의세부주제를제안해주세요. 좋은제안을주신분들중 10 분을추첨하여 < 월간 > 마소창간 24 주년세미나의초대권을드립니다. 참여방법 1. flytgr@gmail.com 으로메일을보낸다. 2. 메일제목에 [ 세미나제안 ] 이라는말머리를단다. 3. 세미나때듣고싶은개발플랫폼이나주제, 강사의이름 ( 선택사항 ) 을적는다. 4. 자신의성함, 전화번호, 주소를적는다. 5. 세미나초대권을기다린다. 참여기간 2007 년 10 월 20 일까지당첨자발표 < 월간 > 마소 11 월호및메일로개별통지 m a s o 141