[DDD] Whiteship’s DDD 아키텍처

기대는 하지 마시구요. @_@ 기존 틀(빈약한 도메인 객체 + 두꺼운 서비스 계층)에서 벗어난다는게 이렇게 머리 아픈 일인지 몰랐습니다. DDD 공부라도 제대로 했었어야 하는데.. 역시 개념없는 코드와 코드 없는 개념은 아무것도 아닌 것 같아요. 힘 없는 정의와 정의없는 힘처럼… 각설하고.. 오늘 구현해볼 아키텍처를 그려봤습니다.

일단 Web 계층에서는 Application 계층에 있는 Thin Facade 내지 서비스를 호출할 겁니다.

Thin Facade는 도메인 객체로 대부분의 역할을 위임할 겁니다.

도메인 계층에서는 Thin Facade로 부터 어떤 일을 위임 받은 도메인 객체는 비즈니스 로직을 담당할 것이고
– 컬렉션에 저장, 조회 등의 작업을 할 때는 계층에 위치한 Repository를 이용할 겁니다. 여기서 Repository는 DAO와는 개념이 다르다(참조: http://aeternum.egloos.com/1160846)는 것에 주의해 주세요.
– Repository는 모든 Entity가 아닌, Entry Point에 해당하는 Entity에 대한 것만 만들 겁니다.
– Email, JMS 등의 기능이 필요하다면 Infrastructure에서 제공하는 서비스를 이용할 겁니다.

시나리오 1: User


UserController가 요청을 받으면 UserFacade가 이 요청을 받아서 User의 특정 메서드를 호출하고, User는 UserRepository를 사용하여 원하는 작업을 한다.

시나리오 2: User->Address


위 상황에서 Value 타입인 Address가 추가 됐을 때 모습으로 별반 달라진 건 없음. Value 타입이 Entity 타입과 어떤 차이가 있는지 보여주는 시나리오.

시나리오 3: User->Address, Order


Order라는 새로운 Entity이자 Entry Type이 추가되자 Controller, Facde, Repository, Dao가 추가된다. User와 Order는 양방향 관계로 서로가 서로를 참조한다. 비즈니스 요구사항에 따라 방향성은 달라질 수 있다. 또한 현재는 각자가 자신의 Repository만 참조하고 있는데, 이 모습도 비즈니스 요구사항에 따라 달라질 수 있다. 중요한 건, 비즈니스 요구사항에 따라 도메인 객체만 변경하면 될 뿐, 나머진 그대로라는 것이다.

주의 할 것은 전체 아키텍처에서도 그렸듯이 도메인 계층에서 Application 계층을 참조하지 않는다는 것이다. Application 계층을 참조할 일이 있다는 것은 도메인 계층이 다시 Application 계층으로 일을 넘긴다는 것인데, 그렇게 되면 Thin Facade라는 가정이 어긋나게 되고 비즈니스 로직이 Application 계층쪽으로 새어나가게 될 것이다.

시나리오 4: User->Address, Order->OrderLine


이번에는 새로운 Entity OrderLine을 추가했다. 하지만 이 Entity는 Entry Point가 아니라 Order에 종속된 생명주기를 지나고 있다. 따라서 Order가 OrderLine까지 같이 관리하며 OrdeLineRepository는 만들지 않는다. 대신 Infrastructure에 OrderLineDao를 추가하여 OderRepository가 OrderLine을 DB에 넣을 때 이용할 수 있게 도와준다.

이제 구현해보는 일만 남았군요. 캬~~ 코딩하기 전에 그림 그려보는 것도 좀 도움이 되네요. 코딩하면서 계속 디자인을 바꾸니깐.. 테스트고 뭐고.. @_@ 일단 저렇게 큰그림 잡고 조금씩 테스트 해 가면서 기왕이면 TDD로 ㄱㄱ 해보렵니다! 파이팅!! 오늘은 이거 못 만들면 퇴근 못하니깐…ㄷㄷㄷㄷㄷ… 내일 스터디는 밤새고 가야할지도…??? 헤헷 후딱 하고 퇴근해버려야지~

10 thoughts on “[DDD] Whiteship’s DDD 아키텍처”

  1. 안녕하세요. 기선님. 두번째로 코멘트를 다는 것 같습니다. 아마 첫 번째는 기억도 못 하실거에요. ㅎㅎ

    다름이 아니고, 기선님이 여태 공부한 방법 좀 알려주세요. 되도록이면 Build order라고 해야 하나요?
    무리한 부탁이거나 말도 안되는 부탁일 수 있습니다.

    하지만, 뭔가 항상 공부하시는데, 계획적이고 목표지향대로 공부하시는 것 같습니다.
    처음에 스프링부터 하지는 않았을텐데,… 하여간 스프링전부터이던 스프링부터이던 좀 알려주세요.
    초보에게 빛을 주세요.

    1. 제 학습 로드맵을 요구하시는거군요?
      흠;; 하도 이것 저것 공부해서 로드맵이 어떻게 되는지 기억도 안나는데요.. 쉴 때 정리해 보겠습니다.

  2. 기선군에게 로드맵을 달라고 하는 분이 있네요. 비밀댓글 상상하기~ㅋ
    그나저나 데이터베이스는 언제 공부할꺼임? 로드맵이 필요하면 단기 숙성 로드맵이 나한테 있긴 있는데….

  3. 공부하자 마자 또 뚝딱뚝딱 금새 만드셨네요. 역시 멋지십니다. ^O^_b
    한참 해오던거 탈피하는게 쉽지 않죠.
    전 2학년 1학기 마치고, 완전한 DDD는 아니지만
    자연스럽게 DDD 스타일의 디자인 습관이 생겼었는데…
    (DDD를 배운건 아닌데, 그 과목에서
    Domain Modeling의 중요성에 대해 강조를 하다보니 그렇게 되더군요.)
    근데, 마지막 학년 마지막 학기에
    Java web app. development쪽을 좀더 공부하려고
    J2EE 과목을 들었더니… 그 망할 EJB (그것도 2.0) 때문에
    혼란이 오더군요.

    가령 JavaBean 만드는데, Order 같은거 합계 계산하는 method를
    Order bean에 넣었는데, JavaBean은 자료 전달만 해야한다고… :O
    실제 돌아가는 EJB하나 만드는데, Home, Remote interface를 꼭 만들어야하고,
    암튼 그래도 믿었습니다. EJB가 표준인데다가, 여러 기업들이 참여해서 만든거라서…

    그러다보니 졸업후에 EJB의 문제점을 알게되서 이거 없이 개발을 해도,
    스타일이 비슷하게 가더라구요. 그러다가 로드 존슨이 강의한 영상을 보고,
    ‘아… EJB한테 당했다!’ 라는 느낌이…ㅠ_ㅠ
    암튼 그 영상에서 DDD도 알게 되고, 바로 에릭 에반스가 강의한것도 찾아보고
    전에는 그냥 감으로 하던 도메인 모델링이
    체계가 잡혀 있다는것도 알게 되고, 참 좋더라구요. 🙂
    진작에 스프링에 손댈껄 그랬다는 후회도 되구요.
    암튼 늘 하던 방식 탈피하는데는 정말 노력이 필요하더군요.

    1. ㅋㅋ금새는 아니에요. 저 그림도 몇 번이나 고치고 다듬은건지 모르겠네요. 아직 DDD도 잘 모르는 상태에서 그린거라 DDD랑 안 어울리는 부분도 있을 것 같습니다.

      저는 애초에 EJB는 보지도 않고 스프링으로 개발을 시작해서 이전에 얼마나 불편했었는지 어깨너머로 들은게 전부라.. 공감할 만한 경험이 없네요.ㅎㅎ;

      로드존슨 아저씨 덕분에 개발자로 일하고 있는 것 같아서 항상 맘속에 고마움을 느끼고 있답니다.

  4. 아… 근데 저기 Repository에 DAO가 또 필요한 건가요?
    제 생각엔 좀 중복 되는거 같은데요.
    Repository interface를 implement 하는 class가 DAO를 대신해야 하는거
    아닐까 하는 생각이 듭니다만…
    따로 DAO를 가지게 되면 Repository 이외에도 해당 Entity를 찾을수 있는 객체가
    존재한다는 얘기니 중복되는게 아닌가 하는 생각이 들어서 말이죠.
    Infrastructure는 Hibernate 같은 ORM이 되어야 하는게 아닐까 싶습니다만…
    제가 뭐 잘알고 하는 얘긴 아니고, 저는 DDD초급자라서 제의견과 함께
    가르침을 구하는 겁니다…^^;

    1. 네, 저 둘은 어찌보면 중복으로 보이죠.

      그런데 제가 만든 DAO가 너무 하이버네이트 기술에 의존해 있다보니, 객체 컬렉션으로 인식해야 할 Repository랑은 잘 안 어울리는 것 같기도 하고,

      DAO는 GenericDAO를 상속 받아서 기본적인 DAO 기능들 + 하이버네이트 기능(flush, clean 같은것)까지 포함한 것을 제공하는 반면 Repository는 왠만하면 도메인에서 실제로 사용하는 메서드들만 두기 위해서 구분지었습니다.

      어느 글인지는 모르겠는데, 여기 저기 DDD관련 코드를 뒤적거리다가 Repository가 DAO를 가지고 있는 코드를 봤었는데, 거기서 착안해서 저렇게 그렸고 구현했습니다.

      기능적으로 중복이기는 한데, Entity가 DAO를 직접 사용하지 않고, Repository를 거쳐서 사용하게끔 할 생각입니다.

  5. 아… 그렇군요.
    제 생각에는 사용 기술보다 Problem Domain에게 영향을 더 받는
    Repository와 사용기술에 종속적인 DAO를 같이 쓰면
    기술적 제약에 따라 디자인 자체가 변경되는 문제가 생길것 같아서 말이죠.

    가령 DAO는 자체 디자인이 변경될 가능성이 Domain modeling 을 통해 만들어진
    object 보다 높으니, 이게 변경되면 DAO만 변경되는게 아니라
    이걸 쓰는 Repository 내부도 변경을 해야하니 유지보수에 도움이 되지 않을것 같아서요.

    디자인 자체가 바뀌지 않으면 내부적으로는 아무리 바뀌어도
    해당 디자인을 사용하는 객체들에게 크게 영향을 미치지 않을텐데
    DAO를 쓰다보면 이녀석의 디자인자체가 바뀔 가능성이 있어서 말이죠.

    아무튼 이건 제 생각이구요.
    기선님 방법도 궁금하니, 해보시고 가능하면
    결과 공유 좀 해주시면 좋겠네요. 🙂
    저도 나름대로 이거저거 해보고 공유하겠습니다. ^^;

    그리고 기선님께서 소개하신 글 보고 방문한 이터너티님의 블로그에서
    좋은글을 하나 발견했습니다.
    http://aeternum.egloos.com/1160846

    아…
    참고로, 이미 보셨을지도 모르지만,
    Eric Evans의 저서 Domain-Driven Design 에서
    Repository 안에 SQL 쿼리와 일정부분의 DB access 를
    구현한 코드를 본적이 있습니다.
    물론 개념을 제공하기 위한 예제 코드라서 완벽한 해답이라고
    할수는 없겠지만요.

    1. 네 저도 저 글을 읽어봤습니다.

      Repository에 필요한 기능을 구현하려다 보니 DAO가 바뀔 수는 있을 지언정, DAO가 독립적으로 자주 바뀔 일이 있을지는 잘 모르겠습니다.

      아직 설계만 잡아두고 구현을 충분히 하지 못해서 실용적인 디자인이지는 잘 모르겠습니다. DDD 학습도 충분치 못해서 DDD 아키텍처라고 내세우기도 좀 그렇구요. 둘 모두 구현해 가면서 차차 다듬어 봐야겠습니다.

      물론, 모든 내용은 될 수 있는 한 공유할 생각입니다. 항상 좋은 의견 감사합니다.

Leave a Reply

Your email address will not be published. Required fields are marked *