SlideShare a Scribd company logo
1 of 131
Download to read offline
좌충우돌 ORM개발기
    Daum 김영한
목차
• 프로젝트 구조와 모순
• Why ORM?
• DEMO 프로젝트
• ORM 적용시 고민할 2가지 구조
 • Domain Model Everywhere
 • DTO, Pure Domain Model
프로젝트 구조와 모순
화면 중심 프로젝트

• 화면 중심으로 프로젝트 구조를 구성
• View 단위로 개발자 투입
• Service, Dao, Entity를 각자 만들어 써야
  함, 공유하는 것은 허용하지 않음
회원관리 화면 Package
 controller (MemberController)
 service (MemberService)
 dao (MemberDao)
 entity (Member)

상품 관리 화면 Package
 controller (ProductController)
 service (ProductService)
 dao (ProductDao)
 entity (Product)
회원관리화면   상품관리화면   주문관리화면




A개발자     B개발자     C개발자
회원관리화면   MemberController    MemberService    MemberDao    MemberEntity

A개발자



상품관리화면   ProductController   ProductService   ProductDao   ProductEntity


B개발자



주문관리화면    OrderController     OrderService    OrderDao      OrderEntity

C개발자
MemberController    MemberService    MemberDao    MemberEntity


회원관리화면

A개발자




 중복!!!
상품관리화면

B개발자
         ProductController




         OrderController
                             ProductService




                             OrderService
                                              ProductDao

                                              MemberDao




                                              OrderDao
                                                           ProductEntity

                                                           MemberEntity




                                                           OrderEntity

주문관리화면                                        MemberDao    MemberEntity

C개발자                                          ProductDao   ProductEntity
• 프로젝트가 계속 진행되면...
• 같거나 유사한 Query가 무수히 나타남
• 회원정보 조회의 경우 11번의 거의 동일
 한 쿼리 발견

• 수정이 아주 어려움
• 월화수목금금금... --;
화면중심 프로젝트 구조는
 수 많은 중복을 만든다.
일반적인 프로젝트


• 데이터와 비지니스 로직을 중심으로
 프로젝트를 설계한다.
회원관리, 상품관리
controller
 - MemberController
 - ProductController
service
 - MemberService
                  MemberController        MemberService              MemberDao
 - ProductService
dao
 - MemberDao
 - ProductDao
                  ProductController       ProductService             ProductDao
entity
 - Member
 - Product

                                 Member                    Product
실전에선
    멀티 프로젝트
FRONT   A,B개발자


ADMIN   C,D개발자


BATCH   E개발자
중복!!!

Member   Member
                    FRONT
 Dao      Entity



Member   Member     ADMIN
 Dao      Entity



Member   Member
                    BATCH
 Dao      Entity
멀티 모듈 프로젝트
             CORE

        Member   Member
         Dao      Entity




FRONT        ADMIN         BATCH
사용되는 Member의 정보
        회원
              나이       성별
        이름




             Member
              Entity



FRONT
사용되는 Member의 정보
    회원
          나이       성별
    이름


    주민    회원       전화
    번호    번호       번호


         Member
          Entity



         ADMIN
사용되는 Member의 정보
    회원
                   성별
    이름


    주민    회원
    번호    번호


         Member
          Entity



                        BATCH
데이터 불일치

• CORE로 통합시 또 다른 문제 발생
• SQL의 Projection은 각 모듈의 비즈니스
  로직과 View에 최적화

• findFrontMember
  findAdminMember ...???
데이터 불일치 해결 방안


• Row단위로 전체 조회
• 특별한 경우만 최적화
• 파레토법칙(20/80법칙)
하지만...
Join의 경우


멤버십
        회원   회원관리직원
 카드
멤버십
                   회원       회원관리직원
        카드



class Member {
	

 Card card;
	

 Manager manager;

	

 Card getCard();
	

 Manager getManager();
}
Join의 경우

member.gerManager() ???
    멤버십
                회원        회원관리직원
     카드



    Front
 SQL : Member Join Card
Code : member.getCard()
Join의 경우

NullPointException!!!
NullPointException!!!
NullPointException!!!
NullPointException!!!
Join의 경우
                      Admin

멤버십
         회원        회원관리직원
 카드



member.getCard() ???
       SQL : Member Join Manager
      Code : member.getManager()
Join의 경우

NullPointException!!!
NullPointException!!!
NullPointException!!!
NullPointException!!!
Join의 경우


         멤버십
                     회원        회원관리직원
          카드


          불필요한 조인, 성능 낭비
                   Batch
    SQL : Member Join Manager Join Card
Code : member.getManager(), member.getCard()
Join의 경우
                   Admin

멤버십
           회원     회원관리직원
 카드



Front
          Batch
Join의 경우

• Entity가 실행한 SQL에 데이터를 의존
• Entity에 구멍이남
• 결국 비즈니스 로직이 SQL에 의존
• 모든 데이터를 메모리에 올리는 것은 현
 실적이지 않음
프로젝트 구조와 모순의
     결론

• Entity가 SQL에 의존
• 구멍난 Entity
• 신뢰할 수 없는 Entity
• 진정한 의미의 계층 분할이 어려움
Why ORM?
ORM을 사용하는 이유
•   Projection 문제

•   Join 관련 데이터 연결 문제

•   Entity 데이터에 대한 신뢰

•   제대로 된 프로젝트 구조

•   CRUD SQL좀 알아서 해줬으면

•   진정한 객체 지향 개발 가능

•   도메인 주도 개발 가능
SQL을 사용해야 하는 이유


• 우리가 사용 중인 DB는 RDB다!!!
• 통계 데이터
• 아주 복잡한 View
ORM을 사용하는
     진짜 이유!


컴퓨터가 할 수 있는 일을 더이상 사람이
하지 말자 나는 SQL MAPPER가 아니다!
JDBC         xBatis




       ORM
여기서 잠깐!
ORM에 관한 오해
Q : OBJECT DB같은 것 아닌가요? 이미 망
한 기술로 알고 있는데요?

A : OBJECT DB가 아닙니다. ORM은 RDB
를 사용해야 한다는 것을 인정하고 RDB를
객체지향 적으로 사용 할 수 있도록 중간
역할을 하기위해 만들어 졌습니다. 그래서
이름도 Object-Relational-Mapping 입니다.
ORM에 관한 오해
Q : 성능이 느리다.
A : 지금 JAVA가 느리다고 하는 것과 비슷합니다.
잘 알고 쓰게되면 SQL보다 최적화 하기가 쉽습
니다. 가장 중요한 것은 파레토의 법칙입니다. 때
로는 순수SQL을 써서 최적화 해야 하는 경우도
있습니다.
예) 여러 Table에 insert시 Hibernate는 한번에
batch insert를 시도함, 1차 케시를 통해 한번 조회
한 데이터 조회시 메모리에서 읽어옴
ORM에 관한 오해

Q : ORM을 사용하면 SQL을 못쓴다.
A : 이거야 말로... ORM도 결국은 SQL을 작
성해서 DB 와 통신하게 됩니다. 필요하면
언제든지 직접 SQL을 작성 할 수 있습니
다. 물론 myBatis 같은 것과 함께 사용하는
것도 가능합니다.
ORM에 관한 오해

Q : SQL을 몰라도 되나요?
A : 오히려 SQL에 관해서 잘 알아야 합니
다. 최종적으로는 SQL이 생성되니까요.
ORM에 관한 오해
Q : 공부할 내용이 많으면 어쩌지...
A : 이건 인정합니다. --; 중요한 것은 ORM
의 철학을 이해하는 것입니다. 하지만 이
것저것 다 떠나서 단순하게 사용하더라도
충분히 유용합니다. 궁극적으로는 ORM을
활용해서 제대로 된 DDD(도메인 주도 개
발)를 하는 것이 목표라고 생각합니다.
ORM에 관한 오해


Q : 모두 iBatis, myBatis만 사용하는데요?
A : 진실은?
2012년 8월 한국 구글 검색

                        JPA
                        8%
           Hibernate
             12%                myBatis
                                 31%




                       iBatis
                        49%



 myBatis               iBatis   Hibernate   JPA
2012년 8월 인도 구글 검색
                    iBatis
           JPA       3%
           11%




                    Hibernate
                      86%


 myBatis   iBatis               Hibernate   JPA
2012년 8월 미국 구글 검색
                 myBatis
                    iBatis
                   2% 4%
           JPA
           16%




                     Hibernate
                       78%


 myBatis    iBatis               Hibernate   JPA
2012년 8월 전세계 구글 검색
                      myBatis
                          iBatis
                        3% 3%

           JPA
           33%




                               Hibernate
                                 61%




 myBatis         iBatis            Hibernate   JPA
ORM을 사용하고 싶은데
 어떻게 시작하나요?



• 공부해야 합니다!
• JPA?
• Hibernate?
• SpringDataJPA
• QueryDSL
DEMO 프로젝트
멤버십 프로젝트

• 사용된 기술 : JPA2, Hibernate, Spring-Data-
  JPA, QueryDSL, Spring, Maven
• source : https://github.com/holyeye/
  devon2012
도메인 모델

     1 :N              N :1      카드
회원           회원카드
                               적립률

                 1
                 :
                 N            Create

            카드적립 포인트
도메인 객체
@Getter @Setter
@Entity
public class Member extends BaseEntity<Long>{

	   private String name;
	   private int age;
	
	   @OneToMany(mappedBy="member")
	   List<MemberCard> memberCards = new ArrayList<MemberCard>();

	   public void addMemberCard(MemberCard memberCard) {
	   	 memberCards.add(memberCard);     @Getter @Setter
	   }                                  @Entity
}                                     public class Card extends BaseEntity<Long>{

                                      	   private String name;
                                      	   private int rate; //적립률
                                      	
                                      	   //create
                                      	   public CardPoint createCardPoint(int money) {
                                      	   	 return new CardPoint(name,money,rate);
                                      	   }
                                      	
                                      }
@Getter @Entity
public class MemberCard extends BaseEntity<Long>{

	   @OneToMany(cascade=CascadeType.PERSIST) @JoinColumn(name="memberCard_id")
	   private List<CardPoint> cardPoints = new ArrayList<CardPoint>();
	
	   @ManyToOne private Member member;
	   @ManyToOne private Card card;
	                         	   //BIZ
                          	   public void payMoney(int money) {
                          	   	 CardPoint createCardPoint = card.createCardPoint(money);
                          	   	 addCardPoint(createCardPoint);
                          	   }
                          	
                          	   //VIEW Logic
                          	   public int getTotalPoint() {
                          	   	 int totalPoint = 0;
                          	   	 for (CardPoint cardPoint : cardPoints) {
                          	   	 	 totalPoint += cardPoint.getPoint();
                          	   	 }
                          	   	 return totalPoint;
                          	   }
                          }
회원 조회, QueryDSL




	   @RequestMapping("member/home")
	   public String home(MemberCond cond, Model model) {

	   	   //QUERY DSL
	   	   QMember qMember = QMember.member;
	   	   BooleanExpression containsName = qMember.name.contains(cond.getName());
	   	   BooleanExpression gtAge = qMember.age.gt(cond.getAge());
	   	
	   	   model.addAttribute("members",memberRepository.findAll(containsName.and(gtAge)));

	   	   return "member/home";
	   }              public interface MemberRepository extends
                   JpaRepository<Member, Long>, QueryDslPredicateExecutor<Member>{

                   }

                                select * from Member member
                                where (member.name like '%서%') and member.age > 26
회원 등록, SpringDataJPA




                      `
        	   @RequestMapping("member/saveMember")
        	   public String saveMenu(Member member) {

        	   	   memberRepository.save(member);
        	   	   return "redirect:/member/home";
        	   }


public interface MemberRepository extends
    JpaRepository<Member, Long>, QueryDslPredicateExecutor<Member>{

}
회원 수정, Web Binding




/member/memberUpdateForm?id= 1


                                                       Member
   	   @RequestMapping("member/memberUpdateForm")
   	   public String memberUpdateForm(@RequestParam("id") Member member, Model model) {

   	   	   model.addAttribute("member", member);
   	   	   return "member/memberSaveForm";
   	   }
회원카드 결제하기 = ORM 저장




 10000만원 결제, 10% 적립
Domain Driven Design 살짝 맛보기

                Aggregate ROOT
  MemberCard
                    회원카드
   Repository



  Aggregate(집합)


                  카드적립 포인트
회원카드 결제하기 = ORM 저장
	   @RequestMapping("memberCard/payMoney")
	   public String payMoney(
	   	   	   @RequestParam("memberCardId") MemberCard memberCard,
	   	   	   @RequestParam("money") int money) {
	   	
	   	                        `
        memberCardService.payMoney(memberCard, money);	 	
	   	   return "redirect:/memberCard/home";
	   }
                     @Service
                     @Transactional
                     public class MemberCardService {
                     	
                     	   public void payMoney(MemberCard memberCard, int money) {
                     	   	                   `
                             memberCard.payMoney(money);
                     	   }
                                public class MemberCard {
                     }
                                 	   @OneToMany(cascade=CascadeType.PERSIST) @JoinColumn(name="memberCard_id")
                                 	   private List<CardPoint> cardPoints = new ArrayList<CardPoint>();
                                 	
                                 	   public void payMoney(int money) {
                                 	   	   CardPoint createCardPoint = card.createCardPoint(money);
                                 	   	   cardPoints.add(createCardPoint);
                                 	   }
                                                       public class Card{

                                                        	   private String name;
      Auto SAVE                                         	
                                                        	
                                                            private int rate;
                                                            public CardPoint createCardPoint(int money) {
                                                        	   	   return new CardPoint(name,money,rate);
                                                        	   }
                                                        }
Spring-Data-JPA 소개
•   interface로 Repository 자동 생성
    (CRUD, 조회)

•   simple queries
    ex) findByName(String name)
       select * from member where name={name}
•   pagination
•   Web Binding

•   Specifications, QueryDSL지원
QueryDSL 소개

• type-safe JPA queries - 단단하다
• 단순하고 쉽다.
• 지속적인 버전업
• Spring Data에서도 사용가능
ORM 적용시 고민할
   2가지 구조
• ORM을 적용하는 방법은 크게 2가지
 • Domain Model Everywhere
 • Pure Domain Model
Domain Model Everywhere
          vs
  Pure Domain Model
Domain Model
        Everywhere

View   Controller      Service          Repository




                                 King

                       Entity
                    +Getter,Setter
                      +BizLogic
                     +ViewLogic
Domain Model
       Everywhere
• Domain Model을 모든 Layer에서 적극 사
  용하자.

• OSIV(Open Session In View) 사용
• Getter, Setter 사용
• DTO는 중복 악마다!
Domain Model
            Everywhere
•   장점

    •   개발하기에 빠르고 편리함

•   단점

    •   복잡한 View 표현 힘듬

    •   Domain Model의 Getter, Setter를 노출,View로직 추가

    •   Domain Model의 순수성이 떨어짐

    •   XML, JSON, 외부와의 통신API 위험 = 도메인 모델은 생
        각보다 자주 변함
Domain Model
        Everywhere

View   Controller      Service          Repository




                                 King

                       Entity
                    +Getter,Setter
                      +BizLogic
                     +ViewLogic
Pure Domain Model


View    Controller             Service               Repository




             DTO
                          Converter
                                          Entity
         +Getter,Setter
                                         +BizLogic
          +ViewLogic
Pure Domain Model

• 도메인모델에 Getter, Setter는 지옥행
• 도메인모델에 View로직은 지옥행
• OSIV(Open Session In View)는 지옥행
• 도메인모델을 객체답게 만들어라!
Pure Domain Model



Robert C. Martin
  (uncle bob)      필독서!!!
Pure Domain Model
        객체           자료 구조
    (Domain Model)    (DTO)


       OOP     일반적으로 Getter,
     캡슐화, 다형성 Setter 를 이용해서 내
    내부 변수를 노출 부 변수를 모두 노출
      하지 않음       사이비 캡슐화
Pure Domain Model
        객체           자료 구조
    (Domain Model)    (DTO)



                 +
Pure Domain Model
    객체           자료 구조
                              잡종
(Domain Model)    (DTO)



             +            =
Pure Domain Model
잡종
      이런 잡종 구조는 새로운 함수는 물론이고
       새로운 자료 구조도 추가하기 어렵다.

      양쪽 세상에서 단점만 모아 놓은 구조다.
      그러므로 잡종 구조는 되도록 피하는 편이
                좋다.
         - Clean Code, Chapter 6 객체와 자료구조 -
Pure Domain Model



• 그럼 어떻게 개발하라고요--;
Pure Domain Model


• CQRS Pattern, DTO 활용
• 도메인 모델 = 비즈니스 로직
• View는 DTO만 사용
CQRS


• Command Query Responsibility Segregation
• 등록,수정,삭제 같은 명령어와
  조회용 쿼리를 분리!
CQRS


• QueryService
• CommandService
Command    Query


  변경      가끔 변경됨    자주 변경됨


  검증        O         X


비즈니스 로직
            O         X
  수정
Pure Domain Model
•   장점

    •   순수한 Domain Model

•   단점

    •   DTO를 만드는 것은 귀찮다, 성가시다. 괴롭다.

    •   DTO는 또다른 중복이다.

    •   DTO와 Domain Model의 Convert를 고민해야 한다.
결론
그럼 어떻게 해요?
여기서 부턴 지극히 주관
    적입니다.
도메인 객체는
순수해야 한다!

순수한 객체
 No Getter, Setter!
  Law of Demeter
SRP, DIP, OCP, ISP, LSP
Domain Model Everywhere
   Getter, Setter 필수
 Entity = 자료구조+객체
 객체의 순수성을 파괴
  하는 사악한 방법!
이라고 믿고 살았습니다...
직접 개발해 보기 전까진...
진짜 ORM 개발을 해보신
  분은 아시겠지만...
도메인 모델만으로
모든 View를 표현하는 것은
   한계가 있습니다.
항상 DTO를 만드는 것은
           실용적이지 않습니다.
    항상 DTO를 만들면 도메인 객체에 Getter, Setter만들 필요가 없고,VIEW로직 필요 없고
  순도 100% 도메인 객체를 유지가능 합니다, 하지만 DTO를 아주 많이 만들어야 하고 또한
ENTITY를 DTO로 바꾸고 DTO를 ENTITY로 변경해야 하는 컨버팅 필요. 관리 포인트가 3가지로
               늘어남. 아주 괴로움. 때로는 배보다 배꼽이 큽니다!
결론

     Domain Model Everywhere 로 시작
     Domain Model로 처리하기 힘든
     복잡하고 특별한 경우에는
     CQRS, DTO를 사용
                  Domain Model Everywhere는 진짜 실용적이고 개발하기 편합니다.
                   DTO가 필수인 경우 = ex) 복잡한 View, [json, xml, 외부노출 API]
      CQRS, DTO, Domain Model Everywhere는 프로젝트 규모와 상황을 판단해서 적용해야 합니다.
지극히 주관적인 생각으로는 프로젝트 시작시 Domain Model Everywhere로 시작하고 CQRS, DTO는 필요성을 느끼게
    되면 추가해 가는 것이 좋다고 생각합니다. 순도 100%는 아니지만 80%는 지킬 수 있다고 생각합니다.
우리의 과제
• Domain Driven Design
• Pure Domain Model 을 유지하며 실용적
  으로 개발하는 방법

• DTO를 생성하는 방법, 활용법
 • ex) http://modelmapper.org/
 • ex) Builder Pattern
좋은 자료
•   이터너티님의 블로그(http://aeternum.egloos.com)

•   백기선님 블로그 (http://whiteship.me)

•   이미 2005년에 작성된 토비님의 아티클
    Domain Model vs. DTO : http://toby.epril.com/?p=99

•   실전 코드가 있는 자바지기님의 DTO에 관한 최
    근 아티클 : http://www.slipp.net/wiki/pages/viewpage.action?pageId=2031636

• Javacan님의 DDD 발표자료 :                                             http://javacan.tistory.com/entry/DDD-%EC
    %8C%A9%EA%B8%B0%EC%B4%88-%EC%84%B8%EB%AF%B8%EB%82%98-%EB%B0%9C%ED%91%9C-%EC%9E%90%EB%A3%8C
참고

• Clean Code (Chapter 6 객체와 자료 구조)
• http://codebetter.com/gregyoung/
  2010/02/16/cqrs-task-based-uis-event-
  sourcing-agh/
• http://martinfowler.com/bliki/CQRS.html
감사합니다.
시간이 부족해 발표하지 못한 내용입니다.
      Domain Model Everywhere에서
DTO, CQRS를 사용해 Pure Domain Model로
리펙토링되는 상황을 연출해 보았습니다.
Entity and View


• Entity는 비즈니스 로직을 위한 것이지
 View를 위한 것이 아니다.
Entity and View


         회원ENTITY
         +BIZ LOGIC
Entity and View

View A

            회원ENTITY
            +BIZ LOGIC
            +ViewA로직
View B
            +ViewB로직
            +ViewC로직
                .....

View C
         그래 나 뚱뚱하다!
Entity and View

• Entity가 View 로직 때문에 뚱뚱해진다.
• OSIV 사용
• JSON, XML 문제점
•   객체 그래프를 찾아 가는 것을 View개발자가 힘
    들어 한다. ex) member.getCard().getData()...
Entity and View


• View를 위한 DTO 가 필요한 시점
Entity and View

View A

            회원ENTITY
            BIZ LOGIC
            +ViewA로직
View B
            +ViewB로직
            +ViewC로직
                .....

View C
         그래 나 뚱뚱하다!
Entity and View

View A
          회원ENTITY
          BIZ LOGIC


View B


           회원DTO
          +ViewA로직
View C    +ViewB로직
          +ViewC로직
Entity and View

View A
          회원ENTITY
          BIZ LOGIC


View B
           회원DTO
          +ViewA로직
          +ViewB로직
View C    +ViewC로직



View D    회원관리DTO
          +ViewD로직
Entity and View

• View와 비즈니스 로직의 요구사항 다름
• Entity = 비즈니스 로직
• DTO = VIEW
뚱뚱한 Service


• 이제는 Service가 뚱뚱해 진다.
뚱뚱한 Service

View A

            회원ENTITY
            BIZ LOGIC
            +ViewA로직
View B
            +ViewB로직
            +ViewC로직
                .....

View C
         그래 나 뚱뚱하다!
뚱뚱한 Service

View A

             회원ENTITY
             BIZ LOGIC    회원Service
             +ViewA로직     +회원등록()
View B
             +ViewB로직     +회원수정()
             +ViewC로직     +회원탈퇴()
                 .....   +getMember()

View C
          그래 나 뚱뚱하다!
뚱뚱한 Service

View A       회원ENTITY
             BIZ LOGIC     회원Service
                           +회원등록()
                           +회원수정()
View B                     +회원탈퇴()

              회원DTO      +getMemberDTO()
             +ViewA로직
View C       +ViewB로직
             +ViewC로직
뚱뚱한 Service

View A
            회원ENTITY
            BIZ LOGIC        회원Service
                             +회원등록()
                             +회원수정()
View B                       +회원탈퇴()
             회원DTO
            +ViewA로직       +getMemberDTO()
            +ViewB로직    +getMemberManageDTO()
View C      +ViewC로직            ...DTO()


                        그래 나 뚱뚱하다!
View D      회원관리DTO
            +ViewD로직
뚱뚱한 Service


• 음... 이건 어떻게 하지?
뚱뚱한 Service


• 등록,수정,삭제 같은 명령어와 조회용 쿼
 리를 분리하자!
뚱뚱한 Service

View A
            회원ENTITY
                             회원Service
            BIZ LOGIC
                             +회원등록()
                             +회원수정()
View B                       +회원탈퇴()
             회원DTO
                           +getMemberDTO()
            +ViewA로직
                        +getMemberManageDTO()
            +ViewB로직
                                ...DTO()
View C      +ViewC로직

                        그래 나 뚱뚱하다!
View D      회원관리DTO
            +ViewD로직
뚱뚱한 Service

View A
            회원ENTITY
            BIZ LOGIC    회원CommandService
                           +회원등록()
                           +회원수정()
View B                     +회원탈퇴()
             회원DTO
            +ViewA로직
            +ViewB로직
View C      +ViewC로직
                            회원QueryService
                           +getMemberDTO()
                        +getMemberManageDTO()
            회원관리DTO             ...DTO()
View D
            +ViewD로직
CQRS


• Command Query Responsibility Segregation
• 등록,수정,삭제 같은 명령어와
  조회용 쿼리를 분리!
CQRS


• QueryService
• CommandService
Command    Query


  변경      가끔 변경됨    자주 변경됨


  검증        O         X


비즈니스 로직
            O         X
  수정
CQRS 적용 전
  출처 : http://martinfowler.com/bliki/CQRS.html
CQRS 적용 후
  출처 : http://martinfowler.com/bliki/CQRS.html
멀티 모듈인 경우


• 멀티 모듈인 경우를 생각해보자
CORE


             회원Service
             +회원등록()
             +회원수정()
             +회원탈퇴()

           +getMemberDTO()
        +getMemberManageDTO()
                ...DTO()




FRONT          ADMIN            BATCH
CORE

         회원CommandService
           +회원등록()
           +회원수정()
           +회원탈퇴()

            회원QueryService
           +getMemberDTO()
        +getMemberManageDTO()
                ...DTO()




FRONT          ADMIN            BATCH
CORE
        회원CommandService
          +회원등록()
          +회원수정()
          +회원탈퇴()


         회원QueryService
            +getMemberDTO()
         +getMemberManageDTO()
          +getFrontMemberDTO()
          +getBatchMemberDTO()




FRONT          ADMIN             BATCH
멀티 모듈인 경우


• 각각의 모듈에 특화된 Query
• Core에 두는 것이 옳은가?
CORE
        회원CommandService
          +회원등록()
          +회원수정()
          +회원탈퇴()


         회원QueryService
            +getMemberDTO()
         +getMemberManageDTO()
          +getFrontMemberDTO()
          +getBatchMemberDTO()




FRONT          ADMIN             BATCH
CORE
            회원CommandService
              +회원등록()
              +회원수정()
              +회원탈퇴()



            회원AdminQueryService
             회원QueryService
               +getMemberDTO()
                        회원BatchQueryService
        회원FrontQueryService




FRONT               ADMIN                     BATCH
CORE


                      회원CommandService
                        +회원등록()
                        +회원수정()
                        +회원탈퇴()




회원FrontQueryService    회원AdminQueryService    회원BatchQueryService


             FRONT          ADMIN            BATCH
멀티 모듈인 경우

• 모듈에 특화된 조회서비스는 해당 모듈
 에서 관리

• Core모듈의 복잡성이 줄어듬
• 비즈니스 로직은 Core에서 관리
감사합니다.

More Related Content

What's hot

ORM을 활용할 경우의 설계, 개발 과정
ORM을 활용할 경우의 설계, 개발 과정ORM을 활용할 경우의 설계, 개발 과정
ORM을 활용할 경우의 설계, 개발 과정Javajigi Jaesung
 
도메인 주도 설계의 본질
도메인 주도 설계의 본질도메인 주도 설계의 본질
도메인 주도 설계의 본질Young-Ho Cho
 
Domain-Driven-Design 정복기 1탄
Domain-Driven-Design 정복기 1탄Domain-Driven-Design 정복기 1탄
Domain-Driven-Design 정복기 1탄현 수
 
객체지향적인 도메인 레이어 구축하기
객체지향적인 도메인 레이어 구축하기객체지향적인 도메인 레이어 구축하기
객체지향적인 도메인 레이어 구축하기Young-Ho Cho
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepGuo Albert
 
Lecture 10 - Java Server Faces (JSF)
Lecture 10 - Java Server Faces (JSF)Lecture 10 - Java Server Faces (JSF)
Lecture 10 - Java Server Faces (JSF)Fahad Golra
 
DDD로 복잡함 다루기
DDD로 복잡함 다루기DDD로 복잡함 다루기
DDD로 복잡함 다루기beom kyun choi
 
Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsYura Nosenko
 
DDD와 이벤트소싱
DDD와 이벤트소싱DDD와 이벤트소싱
DDD와 이벤트소싱Suhyeon Jo
 
DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)beom kyun choi
 
Hibernate Presentation
Hibernate  PresentationHibernate  Presentation
Hibernate Presentationguest11106b
 
이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정Arawn Park
 

What's hot (20)

JUnit 5
JUnit 5JUnit 5
JUnit 5
 
ORM을 활용할 경우의 설계, 개발 과정
ORM을 활용할 경우의 설계, 개발 과정ORM을 활용할 경우의 설계, 개발 과정
ORM을 활용할 경우의 설계, 개발 과정
 
도메인 주도 설계의 본질
도메인 주도 설계의 본질도메인 주도 설계의 본질
도메인 주도 설계의 본질
 
Domain-Driven-Design 정복기 1탄
Domain-Driven-Design 정복기 1탄Domain-Driven-Design 정복기 1탄
Domain-Driven-Design 정복기 1탄
 
JPA and Hibernate
JPA and HibernateJPA and Hibernate
JPA and Hibernate
 
객체지향적인 도메인 레이어 구축하기
객체지향적인 도메인 레이어 구축하기객체지향적인 도메인 레이어 구축하기
객체지향적인 도메인 레이어 구축하기
 
Spring boot jpa
Spring boot jpaSpring boot jpa
Spring boot jpa
 
Node.js 기본
Node.js 기본Node.js 기본
Node.js 기본
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By Step
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
 
Lecture 10 - Java Server Faces (JSF)
Lecture 10 - Java Server Faces (JSF)Lecture 10 - Java Server Faces (JSF)
Lecture 10 - Java Server Faces (JSF)
 
Composite Design Pattern
Composite Design PatternComposite Design Pattern
Composite Design Pattern
 
DDD로 복잡함 다루기
DDD로 복잡함 다루기DDD로 복잡함 다루기
DDD로 복잡함 다루기
 
Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applications
 
DDD와 이벤트소싱
DDD와 이벤트소싱DDD와 이벤트소싱
DDD와 이벤트소싱
 
DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)
 
Hibernate Presentation
Hibernate  PresentationHibernate  Presentation
Hibernate Presentation
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Clean code
Clean codeClean code
Clean code
 
이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정
 

Viewers also liked

Ling to SQL and Entity Framework performance analysis
Ling to SQL and Entity Framework performance analysisLing to SQL and Entity Framework performance analysis
Ling to SQL and Entity Framework performance analysisAlexander Konduforov
 
JDXA, The KISS ORM for Android
JDXA, The KISS ORM for AndroidJDXA, The KISS ORM for Android
JDXA, The KISS ORM for AndroidDamodar Periwal
 
ORM: Object-relational mapping
ORM: Object-relational mappingORM: Object-relational mapping
ORM: Object-relational mappingAbhilash M A
 
Object Relational Mapping In Real World Applications
Object Relational Mapping In Real World ApplicationsObject Relational Mapping In Real World Applications
Object Relational Mapping In Real World ApplicationsPhilWinstanley
 
What's new, what's hot in PHP 5.3
What's new, what's hot in PHP 5.3What's new, what's hot in PHP 5.3
What's new, what's hot in PHP 5.3Jeremy Coates
 
QnA blog using Django - ORM, 회원가입, 로그인/로그아웃
QnA blog using Django - ORM, 회원가입, 로그인/로그아웃QnA blog using Django - ORM, 회원가입, 로그인/로그아웃
QnA blog using Django - ORM, 회원가입, 로그인/로그아웃Kwangyoun Jung
 
About Orm.fm
About Orm.fmAbout Orm.fm
About Orm.fmOrm Moon
 
Object-Relational Mapping and Dependency Injection
Object-Relational Mapping and Dependency InjectionObject-Relational Mapping and Dependency Injection
Object-Relational Mapping and Dependency InjectionShane Church
 
03 Object Relational Mapping
03 Object Relational Mapping03 Object Relational Mapping
03 Object Relational MappingRanjan Kumar
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHPRob Knight
 
좌충우돌 ORM 개발기 2012 DAUM DEVON
좌충우돌 ORM 개발기 2012 DAUM DEVON좌충우돌 ORM 개발기 2012 DAUM DEVON
좌충우돌 ORM 개발기 2012 DAUM DEVONYounghan Kim
 
Automated functional size measurement for three tier object relational mappin...
Automated functional size measurement for three tier object relational mappin...Automated functional size measurement for three tier object relational mappin...
Automated functional size measurement for three tier object relational mappin...IWSM Mensura
 
기술적 변화를 이끌어가기
기술적 변화를 이끌어가기기술적 변화를 이끌어가기
기술적 변화를 이끌어가기Jaewoo Ahn
 
SK플래닛_README_마이크로서비스 아키텍처로 개발하기
SK플래닛_README_마이크로서비스 아키텍처로 개발하기SK플래닛_README_마이크로서비스 아키텍처로 개발하기
SK플래닛_README_마이크로서비스 아키텍처로 개발하기Lee Ji Eun
 

Viewers also liked (16)

Ling to SQL and Entity Framework performance analysis
Ling to SQL and Entity Framework performance analysisLing to SQL and Entity Framework performance analysis
Ling to SQL and Entity Framework performance analysis
 
JDXA, The KISS ORM for Android
JDXA, The KISS ORM for AndroidJDXA, The KISS ORM for Android
JDXA, The KISS ORM for Android
 
ORM: Object-relational mapping
ORM: Object-relational mappingORM: Object-relational mapping
ORM: Object-relational mapping
 
Object Relational Mapping In Real World Applications
Object Relational Mapping In Real World ApplicationsObject Relational Mapping In Real World Applications
Object Relational Mapping In Real World Applications
 
What's new, what's hot in PHP 5.3
What's new, what's hot in PHP 5.3What's new, what's hot in PHP 5.3
What's new, what's hot in PHP 5.3
 
QnA blog using Django - ORM, 회원가입, 로그인/로그아웃
QnA blog using Django - ORM, 회원가입, 로그인/로그아웃QnA blog using Django - ORM, 회원가입, 로그인/로그아웃
QnA blog using Django - ORM, 회원가입, 로그인/로그아웃
 
About Orm.fm
About Orm.fmAbout Orm.fm
About Orm.fm
 
L16 Object Relational Mapping and NoSQL
L16 Object Relational Mapping and NoSQLL16 Object Relational Mapping and NoSQL
L16 Object Relational Mapping and NoSQL
 
Object-Relational Mapping and Dependency Injection
Object-Relational Mapping and Dependency InjectionObject-Relational Mapping and Dependency Injection
Object-Relational Mapping and Dependency Injection
 
03 Object Relational Mapping
03 Object Relational Mapping03 Object Relational Mapping
03 Object Relational Mapping
 
L18 Object Relational Mapping
L18 Object Relational MappingL18 Object Relational Mapping
L18 Object Relational Mapping
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHP
 
좌충우돌 ORM 개발기 2012 DAUM DEVON
좌충우돌 ORM 개발기 2012 DAUM DEVON좌충우돌 ORM 개발기 2012 DAUM DEVON
좌충우돌 ORM 개발기 2012 DAUM DEVON
 
Automated functional size measurement for three tier object relational mappin...
Automated functional size measurement for three tier object relational mappin...Automated functional size measurement for three tier object relational mappin...
Automated functional size measurement for three tier object relational mappin...
 
기술적 변화를 이끌어가기
기술적 변화를 이끌어가기기술적 변화를 이끌어가기
기술적 변화를 이끌어가기
 
SK플래닛_README_마이크로서비스 아키텍처로 개발하기
SK플래닛_README_마이크로서비스 아키텍처로 개발하기SK플래닛_README_마이크로서비스 아키텍처로 개발하기
SK플래닛_README_마이크로서비스 아키텍처로 개발하기
 

Similar to 좌충우돌 ORM 개발기 | Devon 2012

반복적인 코드 작업 자동화, Codebone으로 손쉽게
반복적인 코드 작업 자동화, Codebone으로 손쉽게반복적인 코드 작업 자동화, Codebone으로 손쉽게
반복적인 코드 작업 자동화, Codebone으로 손쉽게Sungju Jin
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Hyosang Hong
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Hyosang Hong
 
MyBatis에서 JPA로
MyBatis에서 JPA로MyBatis에서 JPA로
MyBatis에서 JPA로Dongmin Shin
 
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용중선 곽
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Javajigi Jaesung
 
Spring-Boot (springcamp2014)
Spring-Boot (springcamp2014)Spring-Boot (springcamp2014)
Spring-Boot (springcamp2014)sung yong jung
 
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드cranbe95
 
Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Younghan Kim
 
웹사이트기획 및 관리
웹사이트기획 및 관리웹사이트기획 및 관리
웹사이트기획 및 관리봉조 김
 
좋은 개발자 되기
좋은 개발자 되기좋은 개발자 되기
좋은 개발자 되기Sunghyouk Bae
 
SJBoard Project Portfolio
SJBoard Project PortfolioSJBoard Project Portfolio
SJBoard Project PortfolioJuyoungKang7
 
Tks프로젝트v2
Tks프로젝트v2Tks프로젝트v2
Tks프로젝트v2jrlim80
 
[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵
[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵
[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵NAVER Engineering
 
Oracle Digital Assistant 소개
Oracle Digital Assistant 소개Oracle Digital Assistant 소개
Oracle Digital Assistant 소개Mee Nam Lee
 
예비 개발자를 위한 소프트웨어 세상 이야기
예비 개발자를 위한 소프트웨어 세상 이야기예비 개발자를 위한 소프트웨어 세상 이야기
예비 개발자를 위한 소프트웨어 세상 이야기수보 김
 
[아꿈사/110903] 도메인주도설계 4장
[아꿈사/110903] 도메인주도설계 4장[아꿈사/110903] 도메인주도설계 4장
[아꿈사/110903] 도메인주도설계 4장sung ki choi
 
DB Monitoring 개념 및 활용 (박명규)
DB Monitoring 개념 및 활용 (박명규)DB Monitoring 개념 및 활용 (박명규)
DB Monitoring 개념 및 활용 (박명규)WhaTap Labs
 

Similar to 좌충우돌 ORM 개발기 | Devon 2012 (20)

반복적인 코드 작업 자동화, Codebone으로 손쉽게
반복적인 코드 작업 자동화, Codebone으로 손쉽게반복적인 코드 작업 자동화, Codebone으로 손쉽게
반복적인 코드 작업 자동화, Codebone으로 손쉽게
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
 
MyBatis에서 JPA로
MyBatis에서 JPA로MyBatis에서 JPA로
MyBatis에서 JPA로
 
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
프로그래밍 패러다임의 진화 및 Spring의 금융권 적용
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
 
Spring-Boot (springcamp2014)
Spring-Boot (springcamp2014)Spring-Boot (springcamp2014)
Spring-Boot (springcamp2014)
 
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
Ndc2011 성능 향상을_위한_데이터베이스_아키텍쳐_구축_및_개발_가이드
 
Hibernate 기초
Hibernate 기초Hibernate 기초
Hibernate 기초
 
Id generator
Id generatorId generator
Id generator
 
Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개
 
웹사이트기획 및 관리
웹사이트기획 및 관리웹사이트기획 및 관리
웹사이트기획 및 관리
 
좋은 개발자 되기
좋은 개발자 되기좋은 개발자 되기
좋은 개발자 되기
 
SJBoard Project Portfolio
SJBoard Project PortfolioSJBoard Project Portfolio
SJBoard Project Portfolio
 
Tks프로젝트v2
Tks프로젝트v2Tks프로젝트v2
Tks프로젝트v2
 
[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵
[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵
[TECHCON 2019: MOBILE - Android]3.안드로이드 개발자 로드맵
 
Oracle Digital Assistant 소개
Oracle Digital Assistant 소개Oracle Digital Assistant 소개
Oracle Digital Assistant 소개
 
예비 개발자를 위한 소프트웨어 세상 이야기
예비 개발자를 위한 소프트웨어 세상 이야기예비 개발자를 위한 소프트웨어 세상 이야기
예비 개발자를 위한 소프트웨어 세상 이야기
 
[아꿈사/110903] 도메인주도설계 4장
[아꿈사/110903] 도메인주도설계 4장[아꿈사/110903] 도메인주도설계 4장
[아꿈사/110903] 도메인주도설계 4장
 
DB Monitoring 개념 및 활용 (박명규)
DB Monitoring 개념 및 활용 (박명규)DB Monitoring 개념 및 활용 (박명규)
DB Monitoring 개념 및 활용 (박명규)
 

More from Daum DNA

Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)Daum DNA
 
Daum OAuth 2.0
Daum OAuth 2.0Daum OAuth 2.0
Daum OAuth 2.0Daum DNA
 
Daum 음성인식 API (김한샘)
Daum 음성인식 API (김한샘)Daum 음성인식 API (김한샘)
Daum 음성인식 API (김한샘)Daum DNA
 
Daum 검색/지도 API (이정주)
Daum 검색/지도 API (이정주)Daum 검색/지도 API (이정주)
Daum 검색/지도 API (이정주)Daum DNA
 
오픈 API 활용방법(Daum 사례 중심, 윤석찬)
오픈 API 활용방법(Daum 사례 중심, 윤석찬)오픈 API 활용방법(Daum 사례 중심, 윤석찬)
오픈 API 활용방법(Daum 사례 중심, 윤석찬)Daum DNA
 
Daum 티스토리 API (천정환)
Daum 티스토리 API (천정환)Daum 티스토리 API (천정환)
Daum 티스토리 API (천정환)Daum DNA
 
Daum 로그인 API (함태윤)
Daum 로그인 API (함태윤)Daum 로그인 API (함태윤)
Daum 로그인 API (함태윤)Daum DNA
 
FT직군의 현재와 미래 - 홍윤표
FT직군의 현재와 미래 - 홍윤표FT직군의 현재와 미래 - 홍윤표
FT직군의 현재와 미래 - 홍윤표Daum DNA
 
웹접근성과 장애인 차별 금지법 - 장성민
웹접근성과 장애인 차별 금지법 - 장성민웹접근성과 장애인 차별 금지법 - 장성민
웹접근성과 장애인 차별 금지법 - 장성민Daum DNA
 
반응형 웹 디자인은 만능인가? - 신현석
반응형 웹 디자인은 만능인가? - 신현석반응형 웹 디자인은 만능인가? - 신현석
반응형 웹 디자인은 만능인가? - 신현석Daum DNA
 
Daum devday 13 [bap]
Daum devday 13  [bap]Daum devday 13  [bap]
Daum devday 13 [bap]Daum DNA
 
Daum DevDay 13-힐링이 필요해
Daum DevDay 13-힐링이 필요해Daum DevDay 13-힐링이 필요해
Daum DevDay 13-힐링이 필요해Daum DNA
 
Daum DevDay 13 - 마음의 소리
Daum DevDay 13 - 마음의 소리Daum DevDay 13 - 마음의 소리
Daum DevDay 13 - 마음의 소리Daum DNA
 
Daum DevDay 13 - OpenBrace
Daum DevDay 13 - OpenBraceDaum DevDay 13 - OpenBrace
Daum DevDay 13 - OpenBraceDaum DNA
 
Daum DevDay 13 - Ogangjang
Daum DevDay 13 - OgangjangDaum DevDay 13 - Ogangjang
Daum DevDay 13 - OgangjangDaum DNA
 
Daum DevDay 13 - Mook
Daum DevDay 13 - MookDaum DevDay 13 - Mook
Daum DevDay 13 - MookDaum DNA
 
Daum DevDay 13 - Moonlight
Daum DevDay 13 - MoonlightDaum DevDay 13 - Moonlight
Daum DevDay 13 - MoonlightDaum DNA
 
Daum DevDay 13 - In-N-Out
Daum DevDay 13 - In-N-OutDaum DevDay 13 - In-N-Out
Daum DevDay 13 - In-N-OutDaum DNA
 
Daum DevDay 13 - i-DF
Daum DevDay 13 - i-DFDaum DevDay 13 - i-DF
Daum DevDay 13 - i-DFDaum DNA
 
Daum 키노트 | Devon 2012
Daum 키노트 | Devon 2012Daum 키노트 | Devon 2012
Daum 키노트 | Devon 2012Daum DNA
 

More from Daum DNA (20)

Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
 
Daum OAuth 2.0
Daum OAuth 2.0Daum OAuth 2.0
Daum OAuth 2.0
 
Daum 음성인식 API (김한샘)
Daum 음성인식 API (김한샘)Daum 음성인식 API (김한샘)
Daum 음성인식 API (김한샘)
 
Daum 검색/지도 API (이정주)
Daum 검색/지도 API (이정주)Daum 검색/지도 API (이정주)
Daum 검색/지도 API (이정주)
 
오픈 API 활용방법(Daum 사례 중심, 윤석찬)
오픈 API 활용방법(Daum 사례 중심, 윤석찬)오픈 API 활용방법(Daum 사례 중심, 윤석찬)
오픈 API 활용방법(Daum 사례 중심, 윤석찬)
 
Daum 티스토리 API (천정환)
Daum 티스토리 API (천정환)Daum 티스토리 API (천정환)
Daum 티스토리 API (천정환)
 
Daum 로그인 API (함태윤)
Daum 로그인 API (함태윤)Daum 로그인 API (함태윤)
Daum 로그인 API (함태윤)
 
FT직군의 현재와 미래 - 홍윤표
FT직군의 현재와 미래 - 홍윤표FT직군의 현재와 미래 - 홍윤표
FT직군의 현재와 미래 - 홍윤표
 
웹접근성과 장애인 차별 금지법 - 장성민
웹접근성과 장애인 차별 금지법 - 장성민웹접근성과 장애인 차별 금지법 - 장성민
웹접근성과 장애인 차별 금지법 - 장성민
 
반응형 웹 디자인은 만능인가? - 신현석
반응형 웹 디자인은 만능인가? - 신현석반응형 웹 디자인은 만능인가? - 신현석
반응형 웹 디자인은 만능인가? - 신현석
 
Daum devday 13 [bap]
Daum devday 13  [bap]Daum devday 13  [bap]
Daum devday 13 [bap]
 
Daum DevDay 13-힐링이 필요해
Daum DevDay 13-힐링이 필요해Daum DevDay 13-힐링이 필요해
Daum DevDay 13-힐링이 필요해
 
Daum DevDay 13 - 마음의 소리
Daum DevDay 13 - 마음의 소리Daum DevDay 13 - 마음의 소리
Daum DevDay 13 - 마음의 소리
 
Daum DevDay 13 - OpenBrace
Daum DevDay 13 - OpenBraceDaum DevDay 13 - OpenBrace
Daum DevDay 13 - OpenBrace
 
Daum DevDay 13 - Ogangjang
Daum DevDay 13 - OgangjangDaum DevDay 13 - Ogangjang
Daum DevDay 13 - Ogangjang
 
Daum DevDay 13 - Mook
Daum DevDay 13 - MookDaum DevDay 13 - Mook
Daum DevDay 13 - Mook
 
Daum DevDay 13 - Moonlight
Daum DevDay 13 - MoonlightDaum DevDay 13 - Moonlight
Daum DevDay 13 - Moonlight
 
Daum DevDay 13 - In-N-Out
Daum DevDay 13 - In-N-OutDaum DevDay 13 - In-N-Out
Daum DevDay 13 - In-N-Out
 
Daum DevDay 13 - i-DF
Daum DevDay 13 - i-DFDaum DevDay 13 - i-DF
Daum DevDay 13 - i-DF
 
Daum 키노트 | Devon 2012
Daum 키노트 | Devon 2012Daum 키노트 | Devon 2012
Daum 키노트 | Devon 2012
 

좌충우돌 ORM 개발기 | Devon 2012

  • 1. 좌충우돌 ORM개발기 Daum 김영한
  • 2. 목차 • 프로젝트 구조와 모순 • Why ORM? • DEMO 프로젝트 • ORM 적용시 고민할 2가지 구조 • Domain Model Everywhere • DTO, Pure Domain Model
  • 4. 화면 중심 프로젝트 • 화면 중심으로 프로젝트 구조를 구성 • View 단위로 개발자 투입 • Service, Dao, Entity를 각자 만들어 써야 함, 공유하는 것은 허용하지 않음
  • 5. 회원관리 화면 Package controller (MemberController) service (MemberService) dao (MemberDao) entity (Member) 상품 관리 화면 Package controller (ProductController) service (ProductService) dao (ProductDao) entity (Product)
  • 6. 회원관리화면 상품관리화면 주문관리화면 A개발자 B개발자 C개발자
  • 7. 회원관리화면 MemberController MemberService MemberDao MemberEntity A개발자 상품관리화면 ProductController ProductService ProductDao ProductEntity B개발자 주문관리화면 OrderController OrderService OrderDao OrderEntity C개발자
  • 8. MemberController MemberService MemberDao MemberEntity 회원관리화면 A개발자 중복!!! 상품관리화면 B개발자 ProductController OrderController ProductService OrderService ProductDao MemberDao OrderDao ProductEntity MemberEntity OrderEntity 주문관리화면 MemberDao MemberEntity C개발자 ProductDao ProductEntity
  • 9. • 프로젝트가 계속 진행되면...
  • 10. • 같거나 유사한 Query가 무수히 나타남 • 회원정보 조회의 경우 11번의 거의 동일 한 쿼리 발견 • 수정이 아주 어려움 • 월화수목금금금... --;
  • 11. 화면중심 프로젝트 구조는 수 많은 중복을 만든다.
  • 12. 일반적인 프로젝트 • 데이터와 비지니스 로직을 중심으로 프로젝트를 설계한다.
  • 13. 회원관리, 상품관리 controller - MemberController - ProductController service - MemberService MemberController MemberService MemberDao - ProductService dao - MemberDao - ProductDao ProductController ProductService ProductDao entity - Member - Product Member Product
  • 14. 실전에선 멀티 프로젝트 FRONT A,B개발자 ADMIN C,D개발자 BATCH E개발자
  • 15. 중복!!! Member Member FRONT Dao Entity Member Member ADMIN Dao Entity Member Member BATCH Dao Entity
  • 16. 멀티 모듈 프로젝트 CORE Member Member Dao Entity FRONT ADMIN BATCH
  • 17. 사용되는 Member의 정보 회원 나이 성별 이름 Member Entity FRONT
  • 18. 사용되는 Member의 정보 회원 나이 성별 이름 주민 회원 전화 번호 번호 번호 Member Entity ADMIN
  • 19. 사용되는 Member의 정보 회원 성별 이름 주민 회원 번호 번호 Member Entity BATCH
  • 20. 데이터 불일치 • CORE로 통합시 또 다른 문제 발생 • SQL의 Projection은 각 모듈의 비즈니스 로직과 View에 최적화 • findFrontMember findAdminMember ...???
  • 21. 데이터 불일치 해결 방안 • Row단위로 전체 조회 • 특별한 경우만 최적화 • 파레토법칙(20/80법칙)
  • 23. Join의 경우 멤버십 회원 회원관리직원 카드
  • 24. 멤버십 회원 회원관리직원 카드 class Member { Card card; Manager manager; Card getCard(); Manager getManager(); }
  • 25. Join의 경우 member.gerManager() ??? 멤버십 회원 회원관리직원 카드 Front SQL : Member Join Card Code : member.getCard()
  • 27. Join의 경우 Admin 멤버십 회원 회원관리직원 카드 member.getCard() ??? SQL : Member Join Manager Code : member.getManager()
  • 29. Join의 경우 멤버십 회원 회원관리직원 카드 불필요한 조인, 성능 낭비 Batch SQL : Member Join Manager Join Card Code : member.getManager(), member.getCard()
  • 30. Join의 경우 Admin 멤버십 회원 회원관리직원 카드 Front Batch
  • 31. Join의 경우 • Entity가 실행한 SQL에 데이터를 의존 • Entity에 구멍이남 • 결국 비즈니스 로직이 SQL에 의존 • 모든 데이터를 메모리에 올리는 것은 현 실적이지 않음
  • 32. 프로젝트 구조와 모순의 결론 • Entity가 SQL에 의존 • 구멍난 Entity • 신뢰할 수 없는 Entity • 진정한 의미의 계층 분할이 어려움
  • 34. ORM을 사용하는 이유 • Projection 문제 • Join 관련 데이터 연결 문제 • Entity 데이터에 대한 신뢰 • 제대로 된 프로젝트 구조 • CRUD SQL좀 알아서 해줬으면 • 진정한 객체 지향 개발 가능 • 도메인 주도 개발 가능
  • 35. SQL을 사용해야 하는 이유 • 우리가 사용 중인 DB는 RDB다!!! • 통계 데이터 • 아주 복잡한 View
  • 36. ORM을 사용하는 진짜 이유! 컴퓨터가 할 수 있는 일을 더이상 사람이 하지 말자 나는 SQL MAPPER가 아니다!
  • 37. JDBC xBatis ORM
  • 39. ORM에 관한 오해 Q : OBJECT DB같은 것 아닌가요? 이미 망 한 기술로 알고 있는데요? A : OBJECT DB가 아닙니다. ORM은 RDB 를 사용해야 한다는 것을 인정하고 RDB를 객체지향 적으로 사용 할 수 있도록 중간 역할을 하기위해 만들어 졌습니다. 그래서 이름도 Object-Relational-Mapping 입니다.
  • 40. ORM에 관한 오해 Q : 성능이 느리다. A : 지금 JAVA가 느리다고 하는 것과 비슷합니다. 잘 알고 쓰게되면 SQL보다 최적화 하기가 쉽습 니다. 가장 중요한 것은 파레토의 법칙입니다. 때 로는 순수SQL을 써서 최적화 해야 하는 경우도 있습니다. 예) 여러 Table에 insert시 Hibernate는 한번에 batch insert를 시도함, 1차 케시를 통해 한번 조회 한 데이터 조회시 메모리에서 읽어옴
  • 41. ORM에 관한 오해 Q : ORM을 사용하면 SQL을 못쓴다. A : 이거야 말로... ORM도 결국은 SQL을 작 성해서 DB 와 통신하게 됩니다. 필요하면 언제든지 직접 SQL을 작성 할 수 있습니 다. 물론 myBatis 같은 것과 함께 사용하는 것도 가능합니다.
  • 42. ORM에 관한 오해 Q : SQL을 몰라도 되나요? A : 오히려 SQL에 관해서 잘 알아야 합니 다. 최종적으로는 SQL이 생성되니까요.
  • 43. ORM에 관한 오해 Q : 공부할 내용이 많으면 어쩌지... A : 이건 인정합니다. --; 중요한 것은 ORM 의 철학을 이해하는 것입니다. 하지만 이 것저것 다 떠나서 단순하게 사용하더라도 충분히 유용합니다. 궁극적으로는 ORM을 활용해서 제대로 된 DDD(도메인 주도 개 발)를 하는 것이 목표라고 생각합니다.
  • 44. ORM에 관한 오해 Q : 모두 iBatis, myBatis만 사용하는데요? A : 진실은?
  • 45. 2012년 8월 한국 구글 검색 JPA 8% Hibernate 12% myBatis 31% iBatis 49% myBatis iBatis Hibernate JPA
  • 46. 2012년 8월 인도 구글 검색 iBatis JPA 3% 11% Hibernate 86% myBatis iBatis Hibernate JPA
  • 47. 2012년 8월 미국 구글 검색 myBatis iBatis 2% 4% JPA 16% Hibernate 78% myBatis iBatis Hibernate JPA
  • 48. 2012년 8월 전세계 구글 검색 myBatis iBatis 3% 3% JPA 33% Hibernate 61% myBatis iBatis Hibernate JPA
  • 49. ORM을 사용하고 싶은데 어떻게 시작하나요? • 공부해야 합니다!
  • 50. • JPA? • Hibernate? • SpringDataJPA • QueryDSL
  • 52. 멤버십 프로젝트 • 사용된 기술 : JPA2, Hibernate, Spring-Data- JPA, QueryDSL, Spring, Maven • source : https://github.com/holyeye/ devon2012
  • 53. 도메인 모델 1 :N N :1 카드 회원 회원카드 적립률 1 : N Create 카드적립 포인트
  • 54. 도메인 객체 @Getter @Setter @Entity public class Member extends BaseEntity<Long>{ private String name; private int age; @OneToMany(mappedBy="member") List<MemberCard> memberCards = new ArrayList<MemberCard>(); public void addMemberCard(MemberCard memberCard) { memberCards.add(memberCard); @Getter @Setter } @Entity } public class Card extends BaseEntity<Long>{ private String name; private int rate; //적립률 //create public CardPoint createCardPoint(int money) { return new CardPoint(name,money,rate); } }
  • 55. @Getter @Entity public class MemberCard extends BaseEntity<Long>{ @OneToMany(cascade=CascadeType.PERSIST) @JoinColumn(name="memberCard_id") private List<CardPoint> cardPoints = new ArrayList<CardPoint>(); @ManyToOne private Member member; @ManyToOne private Card card; //BIZ public void payMoney(int money) { CardPoint createCardPoint = card.createCardPoint(money); addCardPoint(createCardPoint); } //VIEW Logic public int getTotalPoint() { int totalPoint = 0; for (CardPoint cardPoint : cardPoints) { totalPoint += cardPoint.getPoint(); } return totalPoint; } }
  • 56. 회원 조회, QueryDSL @RequestMapping("member/home") public String home(MemberCond cond, Model model) { //QUERY DSL QMember qMember = QMember.member; BooleanExpression containsName = qMember.name.contains(cond.getName()); BooleanExpression gtAge = qMember.age.gt(cond.getAge()); model.addAttribute("members",memberRepository.findAll(containsName.and(gtAge))); return "member/home"; } public interface MemberRepository extends JpaRepository<Member, Long>, QueryDslPredicateExecutor<Member>{ } select * from Member member where (member.name like '%서%') and member.age > 26
  • 57. 회원 등록, SpringDataJPA ` @RequestMapping("member/saveMember") public String saveMenu(Member member) { memberRepository.save(member); return "redirect:/member/home"; } public interface MemberRepository extends JpaRepository<Member, Long>, QueryDslPredicateExecutor<Member>{ }
  • 58. 회원 수정, Web Binding /member/memberUpdateForm?id= 1 Member @RequestMapping("member/memberUpdateForm") public String memberUpdateForm(@RequestParam("id") Member member, Model model) { model.addAttribute("member", member); return "member/memberSaveForm"; }
  • 59. 회원카드 결제하기 = ORM 저장 10000만원 결제, 10% 적립
  • 60. Domain Driven Design 살짝 맛보기 Aggregate ROOT MemberCard 회원카드 Repository Aggregate(집합) 카드적립 포인트
  • 61. 회원카드 결제하기 = ORM 저장 @RequestMapping("memberCard/payMoney") public String payMoney( @RequestParam("memberCardId") MemberCard memberCard, @RequestParam("money") int money) { ` memberCardService.payMoney(memberCard, money); return "redirect:/memberCard/home"; } @Service @Transactional public class MemberCardService { public void payMoney(MemberCard memberCard, int money) { ` memberCard.payMoney(money); } public class MemberCard { } @OneToMany(cascade=CascadeType.PERSIST) @JoinColumn(name="memberCard_id") private List<CardPoint> cardPoints = new ArrayList<CardPoint>(); public void payMoney(int money) { CardPoint createCardPoint = card.createCardPoint(money); cardPoints.add(createCardPoint); } public class Card{ private String name; Auto SAVE private int rate; public CardPoint createCardPoint(int money) { return new CardPoint(name,money,rate); } }
  • 62. Spring-Data-JPA 소개 • interface로 Repository 자동 생성 (CRUD, 조회) • simple queries ex) findByName(String name) select * from member where name={name} • pagination • Web Binding • Specifications, QueryDSL지원
  • 63. QueryDSL 소개 • type-safe JPA queries - 단단하다 • 단순하고 쉽다. • 지속적인 버전업 • Spring Data에서도 사용가능
  • 64. ORM 적용시 고민할 2가지 구조
  • 65. • ORM을 적용하는 방법은 크게 2가지 • Domain Model Everywhere • Pure Domain Model
  • 66. Domain Model Everywhere vs Pure Domain Model
  • 67. Domain Model Everywhere View Controller Service Repository King Entity +Getter,Setter +BizLogic +ViewLogic
  • 68. Domain Model Everywhere • Domain Model을 모든 Layer에서 적극 사 용하자. • OSIV(Open Session In View) 사용 • Getter, Setter 사용 • DTO는 중복 악마다!
  • 69. Domain Model Everywhere • 장점 • 개발하기에 빠르고 편리함 • 단점 • 복잡한 View 표현 힘듬 • Domain Model의 Getter, Setter를 노출,View로직 추가 • Domain Model의 순수성이 떨어짐 • XML, JSON, 외부와의 통신API 위험 = 도메인 모델은 생 각보다 자주 변함
  • 70. Domain Model Everywhere View Controller Service Repository King Entity +Getter,Setter +BizLogic +ViewLogic
  • 71. Pure Domain Model View Controller Service Repository DTO Converter Entity +Getter,Setter +BizLogic +ViewLogic
  • 72. Pure Domain Model • 도메인모델에 Getter, Setter는 지옥행 • 도메인모델에 View로직은 지옥행 • OSIV(Open Session In View)는 지옥행 • 도메인모델을 객체답게 만들어라!
  • 73. Pure Domain Model Robert C. Martin (uncle bob) 필독서!!!
  • 74. Pure Domain Model 객체 자료 구조 (Domain Model) (DTO) OOP 일반적으로 Getter, 캡슐화, 다형성 Setter 를 이용해서 내 내부 변수를 노출 부 변수를 모두 노출 하지 않음 사이비 캡슐화
  • 75. Pure Domain Model 객체 자료 구조 (Domain Model) (DTO) +
  • 76. Pure Domain Model 객체 자료 구조 잡종 (Domain Model) (DTO) + =
  • 77. Pure Domain Model 잡종 이런 잡종 구조는 새로운 함수는 물론이고 새로운 자료 구조도 추가하기 어렵다. 양쪽 세상에서 단점만 모아 놓은 구조다. 그러므로 잡종 구조는 되도록 피하는 편이 좋다. - Clean Code, Chapter 6 객체와 자료구조 -
  • 78. Pure Domain Model • 그럼 어떻게 개발하라고요--;
  • 79. Pure Domain Model • CQRS Pattern, DTO 활용 • 도메인 모델 = 비즈니스 로직 • View는 DTO만 사용
  • 80. CQRS • Command Query Responsibility Segregation • 등록,수정,삭제 같은 명령어와 조회용 쿼리를 분리!
  • 82. Command Query 변경 가끔 변경됨 자주 변경됨 검증 O X 비즈니스 로직 O X 수정
  • 83. Pure Domain Model • 장점 • 순수한 Domain Model • 단점 • DTO를 만드는 것은 귀찮다, 성가시다. 괴롭다. • DTO는 또다른 중복이다. • DTO와 Domain Model의 Convert를 고민해야 한다.
  • 86. 여기서 부턴 지극히 주관 적입니다.
  • 87. 도메인 객체는 순수해야 한다! 순수한 객체 No Getter, Setter! Law of Demeter SRP, DIP, OCP, ISP, LSP
  • 88. Domain Model Everywhere Getter, Setter 필수 Entity = 자료구조+객체 객체의 순수성을 파괴 하는 사악한 방법!
  • 89. 이라고 믿고 살았습니다... 직접 개발해 보기 전까진...
  • 90. 진짜 ORM 개발을 해보신 분은 아시겠지만...
  • 91. 도메인 모델만으로 모든 View를 표현하는 것은 한계가 있습니다.
  • 92. 항상 DTO를 만드는 것은 실용적이지 않습니다. 항상 DTO를 만들면 도메인 객체에 Getter, Setter만들 필요가 없고,VIEW로직 필요 없고 순도 100% 도메인 객체를 유지가능 합니다, 하지만 DTO를 아주 많이 만들어야 하고 또한 ENTITY를 DTO로 바꾸고 DTO를 ENTITY로 변경해야 하는 컨버팅 필요. 관리 포인트가 3가지로 늘어남. 아주 괴로움. 때로는 배보다 배꼽이 큽니다!
  • 93. 결론 Domain Model Everywhere 로 시작 Domain Model로 처리하기 힘든 복잡하고 특별한 경우에는 CQRS, DTO를 사용 Domain Model Everywhere는 진짜 실용적이고 개발하기 편합니다. DTO가 필수인 경우 = ex) 복잡한 View, [json, xml, 외부노출 API] CQRS, DTO, Domain Model Everywhere는 프로젝트 규모와 상황을 판단해서 적용해야 합니다. 지극히 주관적인 생각으로는 프로젝트 시작시 Domain Model Everywhere로 시작하고 CQRS, DTO는 필요성을 느끼게 되면 추가해 가는 것이 좋다고 생각합니다. 순도 100%는 아니지만 80%는 지킬 수 있다고 생각합니다.
  • 94. 우리의 과제 • Domain Driven Design • Pure Domain Model 을 유지하며 실용적 으로 개발하는 방법 • DTO를 생성하는 방법, 활용법 • ex) http://modelmapper.org/ • ex) Builder Pattern
  • 95. 좋은 자료 • 이터너티님의 블로그(http://aeternum.egloos.com) • 백기선님 블로그 (http://whiteship.me) • 이미 2005년에 작성된 토비님의 아티클 Domain Model vs. DTO : http://toby.epril.com/?p=99 • 실전 코드가 있는 자바지기님의 DTO에 관한 최 근 아티클 : http://www.slipp.net/wiki/pages/viewpage.action?pageId=2031636 • Javacan님의 DDD 발표자료 : http://javacan.tistory.com/entry/DDD-%EC %8C%A9%EA%B8%B0%EC%B4%88-%EC%84%B8%EB%AF%B8%EB%82%98-%EB%B0%9C%ED%91%9C-%EC%9E%90%EB%A3%8C
  • 96. 참고 • Clean Code (Chapter 6 객체와 자료 구조) • http://codebetter.com/gregyoung/ 2010/02/16/cqrs-task-based-uis-event- sourcing-agh/ • http://martinfowler.com/bliki/CQRS.html
  • 98. 시간이 부족해 발표하지 못한 내용입니다. Domain Model Everywhere에서 DTO, CQRS를 사용해 Pure Domain Model로 리펙토링되는 상황을 연출해 보았습니다.
  • 99. Entity and View • Entity는 비즈니스 로직을 위한 것이지 View를 위한 것이 아니다.
  • 100. Entity and View 회원ENTITY +BIZ LOGIC
  • 101. Entity and View View A 회원ENTITY +BIZ LOGIC +ViewA로직 View B +ViewB로직 +ViewC로직 ..... View C 그래 나 뚱뚱하다!
  • 102. Entity and View • Entity가 View 로직 때문에 뚱뚱해진다. • OSIV 사용 • JSON, XML 문제점 • 객체 그래프를 찾아 가는 것을 View개발자가 힘 들어 한다. ex) member.getCard().getData()...
  • 103. Entity and View • View를 위한 DTO 가 필요한 시점
  • 104. Entity and View View A 회원ENTITY BIZ LOGIC +ViewA로직 View B +ViewB로직 +ViewC로직 ..... View C 그래 나 뚱뚱하다!
  • 105. Entity and View View A 회원ENTITY BIZ LOGIC View B 회원DTO +ViewA로직 View C +ViewB로직 +ViewC로직
  • 106. Entity and View View A 회원ENTITY BIZ LOGIC View B 회원DTO +ViewA로직 +ViewB로직 View C +ViewC로직 View D 회원관리DTO +ViewD로직
  • 107. Entity and View • View와 비즈니스 로직의 요구사항 다름 • Entity = 비즈니스 로직 • DTO = VIEW
  • 108. 뚱뚱한 Service • 이제는 Service가 뚱뚱해 진다.
  • 109. 뚱뚱한 Service View A 회원ENTITY BIZ LOGIC +ViewA로직 View B +ViewB로직 +ViewC로직 ..... View C 그래 나 뚱뚱하다!
  • 110. 뚱뚱한 Service View A 회원ENTITY BIZ LOGIC 회원Service +ViewA로직 +회원등록() View B +ViewB로직 +회원수정() +ViewC로직 +회원탈퇴() ..... +getMember() View C 그래 나 뚱뚱하다!
  • 111. 뚱뚱한 Service View A 회원ENTITY BIZ LOGIC 회원Service +회원등록() +회원수정() View B +회원탈퇴() 회원DTO +getMemberDTO() +ViewA로직 View C +ViewB로직 +ViewC로직
  • 112. 뚱뚱한 Service View A 회원ENTITY BIZ LOGIC 회원Service +회원등록() +회원수정() View B +회원탈퇴() 회원DTO +ViewA로직 +getMemberDTO() +ViewB로직 +getMemberManageDTO() View C +ViewC로직 ...DTO() 그래 나 뚱뚱하다! View D 회원관리DTO +ViewD로직
  • 113. 뚱뚱한 Service • 음... 이건 어떻게 하지?
  • 114. 뚱뚱한 Service • 등록,수정,삭제 같은 명령어와 조회용 쿼 리를 분리하자!
  • 115. 뚱뚱한 Service View A 회원ENTITY 회원Service BIZ LOGIC +회원등록() +회원수정() View B +회원탈퇴() 회원DTO +getMemberDTO() +ViewA로직 +getMemberManageDTO() +ViewB로직 ...DTO() View C +ViewC로직 그래 나 뚱뚱하다! View D 회원관리DTO +ViewD로직
  • 116. 뚱뚱한 Service View A 회원ENTITY BIZ LOGIC 회원CommandService +회원등록() +회원수정() View B +회원탈퇴() 회원DTO +ViewA로직 +ViewB로직 View C +ViewC로직 회원QueryService +getMemberDTO() +getMemberManageDTO() 회원관리DTO ...DTO() View D +ViewD로직
  • 117. CQRS • Command Query Responsibility Segregation • 등록,수정,삭제 같은 명령어와 조회용 쿼리를 분리!
  • 119. Command Query 변경 가끔 변경됨 자주 변경됨 검증 O X 비즈니스 로직 O X 수정
  • 120. CQRS 적용 전 출처 : http://martinfowler.com/bliki/CQRS.html
  • 121. CQRS 적용 후 출처 : http://martinfowler.com/bliki/CQRS.html
  • 122. 멀티 모듈인 경우 • 멀티 모듈인 경우를 생각해보자
  • 123. CORE 회원Service +회원등록() +회원수정() +회원탈퇴() +getMemberDTO() +getMemberManageDTO() ...DTO() FRONT ADMIN BATCH
  • 124. CORE 회원CommandService +회원등록() +회원수정() +회원탈퇴() 회원QueryService +getMemberDTO() +getMemberManageDTO() ...DTO() FRONT ADMIN BATCH
  • 125. CORE 회원CommandService +회원등록() +회원수정() +회원탈퇴() 회원QueryService +getMemberDTO() +getMemberManageDTO() +getFrontMemberDTO() +getBatchMemberDTO() FRONT ADMIN BATCH
  • 126. 멀티 모듈인 경우 • 각각의 모듈에 특화된 Query • Core에 두는 것이 옳은가?
  • 127. CORE 회원CommandService +회원등록() +회원수정() +회원탈퇴() 회원QueryService +getMemberDTO() +getMemberManageDTO() +getFrontMemberDTO() +getBatchMemberDTO() FRONT ADMIN BATCH
  • 128. CORE 회원CommandService +회원등록() +회원수정() +회원탈퇴() 회원AdminQueryService 회원QueryService +getMemberDTO() 회원BatchQueryService 회원FrontQueryService FRONT ADMIN BATCH
  • 129. CORE 회원CommandService +회원등록() +회원수정() +회원탈퇴() 회원FrontQueryService 회원AdminQueryService 회원BatchQueryService FRONT ADMIN BATCH
  • 130. 멀티 모듈인 경우 • 모듈에 특화된 조회서비스는 해당 모듈 에서 관리 • Core모듈의 복잡성이 줄어듬 • 비즈니스 로직은 Core에서 관리