SlideShare ist ein Scribd-Unternehmen logo
1 von 52
Downloaden Sie, um offline zu lesen
DDD Start 부록
"수다"
신림프로그래머, 최범균, 2016-07-16
madvirus@madvirus.net
A/S 안내
• 책의 오류/오타 안내
– 다음 javacan 카페 à DDD Start QA 게시판
• http://cafe.daum.net/javacan/Qv4t/1
2
3
#1 수다
Bounded Context + Microservice
기능 측면에서 단일 시스템의 성장
4
단일코드
통합DB
거대한 강결합
5
서비스 레이어
Data 레이어
프리젠테이션
레이어
도메인 측면에서 문제
6
서비스 레이어
Data 레이어
프리젠테이션
레이어
통합DB:
언어 경계 없음
수직적으로
언어 경계 없음
컨텍스트 안에서만
존재하는 의미가
사라짐
잘 나눈 패키지로 문제 완화
7
user project …
여전히 경계가 모호해질 가능성
8
user project
User Project
USER PROJECTUSER_PROJ
* *
BC별 프로젝트로 분리
9
user
User
project
ProjectMemberService Adapter * 1
USER PROJECTMEMBER
분리에 따른 몇 가지 이점
• 명시적인 (강제) 언어 경계 à bounded
• 컨텍스트별 독립적인 발전
• 인터페이스에 기반한 컨텍스트 간 통신
10
Microservice의 특성
• James Lewis, Martin Fowler에 따르면
– 서비스로서 컴포넌트화
– 비지니스 수행에 따른 구성
– 프로젝트가 아닌 제품
– 똑똑한 엔드포인트와 더미(Dumb) 파이프
– 분산화 거버넌스
– 분산화된 데이터 관리
– 인프라 자동화
– 장애 방지 설계
– 진화하는 설계
11
*	http://martinfowler.com/articles/microservices.html
서비스로서 컴포넌트화
• 독립 배포 à 서비스의 응집도(경계) 높아짐
• 명시적 인터페이스 à 공개 인터페이스
12
비지니스 수행에 따른 구성
13
발췌: http://martinfowler.com/articles/microservices.html
분산화된 데이터 관리
14
발췌: http://martinfowler.com/articles/microservices.html
진화하는 설계
• 서비스별 독립적인 변경(교체/업그레이드)
15
MS à BC
16
언어의 경계를 찾아
Bounded Context를
구성하는데
도움을 줌
서비스로서 컴포넌트화
비지니스 수행에 따른 구성
분산화된 데이터 관리
진화하는 설계
고민거리
• MS로의 전환?
– 참가자 소환
17
18
수다 정리
19
#2 수다
Event Sourcing + Aggregate
주문의 변경 내역
20
state: PAYMENT_WAITING
lines: [ {prod:P001, price:1000,
quantity:1, amounts: 1000} ]
shippingInfo: {receiver: 'bk', address: addr}
주문함
lines: {prod:P001, price:1000,
quantity:1, amounts: 1000}
shippingInfo: {receiver: 'bk', address: addr}
결제함
state: PREPARING
lines: [ {prod:P001, price:1000,
quantity:1, amounts: 1000} ]
shippingInfo: {receiver: 'bk', address: addr}
배송지변경함
shippingInfo: {receiver: 'es', address: addr2}
state: PREPARING
lines: [ {prod:P001, price:1000,
quantity:1, amounts: 1000} ]
shippingInfo: {receiver: 'es', address: addr2}
발송함
state: SHIPPED
lines: [ {prod:P001, price:1000,
quantity:1, amounts: 1000} ]
shippingInfo: {receiver: 'es', address: addr2}
상태 변화 증분 = 이벤트
21
주문함
lines: {prod:P001, price:1000,
quantity:1, amounts: 1000}
shippingInfo: {receiver: 'bk', address: addr}
결제함
배송지변경함
shippingInfo: {receiver: 'es', address: addr2}
발송함
증분 누적 à 마지막 상태
22
주문함
lines: {prod:P001, price:1000,
quantity:1, amounts: 1000}
shippingInfo: {receiver: 'bk', address: addr}
결제함
배송지변경함
shippingInfo: {receiver: 'es', address: addr2}
발송함
state: SHIPPED
lines: [ {prod:P001, price:1000,
quantity:1, amounts: 1000} ]
shippingInfo: {receiver: 'es', address: addr2}
이벤트 소싱Event Sourcing
23
* http://martinfowler.com/eaaDev/EventSourcing.html
어플리케이션의 모든 상태 변화를
순서에 따라 이벤트로 보관한다.
Capture all changes to an
application state as a sequence of
events.
도메인 객체와 이벤트 소싱
• 도메인 객체 조회
– 저장한 이벤트로부터 도메인 객체 생성
• 도메인 객체 변경
– 모든 상태 변화에 대한 이벤트를 저장
• 일관성의 기준인 애그리거트Aggregate 단위
24
이벤트 구성
• 구성
– 애그리거트 타입
– 애그리거트 식별자
– 버전
– 이벤트 타입
– 이벤트 시간
– 증분(변경) 내역(payload)
• 이벤트 구분(unique idx)
– 애그리거트 타입, 애그리거트 식별자, 버전
25
애그리거트 조회
• 리포지토리
26
public	class	OrderRepository	{
public	Order	findById(String	orderId)	{
List<Event>	events	=	eventStore.select(Order.class,	orderId);
if	(events.isEmpty())	{
return	null;
}
Order	order	=	new	Order();
for	(Event	evt	:	events)	{
order.handle(evt);
}
addUOW(order);
return	order;
}
애그리거트 조회
• 애그리거트는 이벤트 반영
27
public	class	Order	extends	Aggregate	{				
public	void	on(OrderPlacedEvent	evt)	{
this.lines	=	evt.getOrderLines();
this.shippingInfo	=	evt.getShippingInfo();
}
public	void	on(ShippingInfoChangedEventevt)	{
this.shippingInfo	=	evt.getShippingInfo();
}
public	void	on(ShippedEvent	evt)	{
this.state	=	SHIPPED;
}
public	abstract	class	Aggregate	{				
private	Integer	version;
public	void	handle(Event	evt)	{
this.version	=	evt.getVersion();
Events.handle(this,	evt);
}
}
애그리거트 변경
• 애그리거트에서 이벤트 발생
28
public	class	Order	extends	Aggregate	{
public	void	cancel()	{
….
OrderCanceledEvent	evt	=	
new	OrderCanceledEvent(getId(),	
version	+	1);
super.apply(evt);
}
public	abstract	class	Aggregate	{				
List<Event>	uncommittedEvents;
public	void	apply(Event	evt)	{
addUncommittedEvent(evt);
handle(evt);
}
public	List<Event>	getUncommittedEvents()	{
return	uncommittedEvents;
}
애그리거트 변경
• 트랜잭션에서 이벤트 저장
29
public	class	CancelOrderService	{
@Transactional
public	void	cancel(String	orderId)	{
Order	order	=	
orderRepository.findById(orderId);
checkNull(order);
order.cancel();
}
}
class	TransactionHandler	{
public	void	commit()	{
List<Aggregate>	aggs	=	getAllUOW();
for	(Aggregate	agg	:	aggs)	{
eventStore.append(
agg.getClass(),
agg.getUncomittedEvents()
);
}
}
애그리거트 생성
• 애그리거트 생성자 : 생성 이벤트 발생
30
public	class	PlaceOrderService	{
@Transactional
public	void	cancel(String	orderId)	{
Order	order	=	new	Order(…);
repository.save(order);
}
}
public	class	Order	extends	Aggregate	{
public	Order(…)	{
….
OrderCreatedEvent	evt	=	
new	OrderCreatedEvent(
getId(),	lines,	shippingInfo,
1);
super.apply(evt);
}
이벤트 소싱과 유지보수
• 새로운 데이터 추가
31
public	class	Order	extends	Aggregate	{
private	String	note;
public	Order(…)	{
….
OrderCreatedV2Event	evt	=	new	OrderCreatedV2Event(...);
super.apply(evt);
}
public	void	on(OrderCreatedEvent	evt)	{
…
this.note	=	"";
}
public	void	on(OrderCreatedV2Event	evt)	{
…
this.note	=	evt.getNote();
}
없어지는 것
- DB	작업 일정
- 매핑 설정 변경
이벤트 소싱 적용한 애그리거트
• 임피던스 미스매치(impedance mismatch) 없음
• 애그리거트 간 참조는 ID
• 비선점 잠금
32
성능
• 단일 애그리것트 조회 à 스냅샷
• 복합 조회 à CQRS
33
SQL(ORM) vs 이벤트 소싱
• 변화되는 것
34
영역 적용 전 (RDBMS/ORM) 적용 후
도메인 객체 로딩 SQL : SELECT 쿼리
ORM : 프레임워크가 매핑
설정을 이용해서 SELECT 쿼리
실행
- 이벤트로부터 도메인 객체 생성
- 도메인 객체의 이벤트 핸들러를
이용해 상태 변경 반영
도메인 기능 SQL : 서비스 클래스
ORM : (일부) 엔티티 클래스
- 도메인 객체가 수행
- 상태 변경을 위한 이벤트 생성
상태 변경 반영
(데이터 변경)
SQL : Insert/Update/Delete 쿼리
ORM : 엔티티 프로퍼티를
변경하면 ORM 프레임워크가
알맞은 쿼리 실행
- 도메인 객체가 발생한 이벤트를
저장소에 보관
장점
• DB에 의존적이지 않은 도메인 코드 구현
– 테이블이나 ORM 기술의 제한/제약에서 벗어남
• 기능 변경
– 하위 호환 처리가 상대적으로 쉬움
– 이벤트로부터 완전히 새로운 도메인 객체의 생성도 가능
• 버그 추적 용이
– 이벤트를 차례대로 검사하면서 버그 원인 추적 가능
• 객체 지향/DDD와 좋은 궁합
– 복잡한 도메인을 객체 지향적으로 구현하기에 좋음
• CQRS와 좋은 궁합
– 조회 관련 코드를 도메인에서 분리
– 조회 모델 분리로 조회 성능 향상 가능
35
단점
• 익숙하지 않음
– SQL 위주(데이터 중심) 개발 성향인 경우 적응 힘듬
• 단순 모델에는 적합하지 않음
– 단순 모델에 적용하기엔 구현이 복잡해짐
• 도구 부족
– 이벤트 소싱과 CQRS 지원 프레임워크 부족
• 운영시 어려움
– 이벤트 데이터만으로는 최신 상태의 빠른 확인 불가
• CQRS 필수!
36
37
두 번째 수다 정리
38
세 번째 수다
SAGA
길게 실행되는 프로세스
Long Running Business Process
39
주문하기 상품보내기 배송시작알리기
구매확정
요청하기
길게 실행되는 프로세스
40
주문하기 상품보내기
배송시작
알리기
구매확정
요청하기
배송시작함주문함
배송시작집하하기 전달
배송완료함
입금하기
결제함
길게 실행되는 프로세스/트랜잭션의 특징
• 여러 개의 작은 프로세스(트랜잭션)로 구성
• 하위 프로세스가 순서대로 실행되는 건 아님
• 여러 모듈/서비스가 (비동기로) 엮임
• 한 트랜잭션이 아님
• 실패는 롤백 대신 보상으로 처리
41
SAGA
• 여러 하위 트랜잭션 집합으로 구성된 LLT
– LLT: Long Lived Transaction
– 단일 실행 단위
• 각 하위 트랜잭션은 단독 트랜잭션
– 하위 트랜잭션 단위로 일관성 보장
• 각 하위 트랜잭션은 서로 연관
• 하위 트랜잭션 실패시, 보상 트랜잭션
– 일부만 성공해도 끝나지 않음
42
*	SAGAS (Hector	Garcia-Molina, 1987)
43
SAGA	à 프로세스 매니저
프로세스 매니저
• 여러 애그리거트/외부 시스템이 엮이는 긴
프로세스의 흐름 제어
– 각 구성 요소 간의 메시지 라우팅이 주된 역할
• 프로세스의 상태 보관
• 비즈니스 로직은 개별 구성 요소에서 처리
44
Saga / 프로세스 매니저
45
주문
프로세스 매니저
배송 서비스
결제 서비스
주문
애그리거트
재고
애그리거트
Paid
Event
배송지시
OrderCreated
Event
Delivery
Completed
Event
StockChanged
Event
통지 서비스
배송
시작
통지
배송
완료
구현
• 특정 이벤트에 Saga/프로세스 매니저 시작
• 수신한 이벤트에 따라 다음 기능 실행
– 실패시, 후속 보상 기능 실행
• 전체 프로세스가 끝나면 Saga/프로세스
매니저 종료
46
상태 존재 à 프로세스별 인스턴스
• 에어카텔 상품 구매 예
47
public	class	BookingProcessManager	{
private	BookingId	bookingId;
private	BookingState	hotelState;
private	BookingState	airState;
private	BookingState	carState;
public	void	handle(BookingCreatedEvent	evt)	{
this.bookingId	=	evt.getBookingId();
sendBookingRequest();
}
public	void	handle(HotelBookedEvent	evt)	{
hotelState	=	BookingState.BOOKED;
notifyIfAllBooked();
}
private	void	notifyIfAllBooked()	{
if	(hotelState	==	BOOKED	&&	airState	==	BOOKED	&&	carState	==	BOOKED)	{
notifyBookingCompletion();
}
}
실패 보상 처리
• 에어카텔 호텔 예약 실패 예
48
public	class	BookingProcessManager	{
public	void	handle(HotelBookingFailedEvent	evt)	{
cancelAirBooking();
cancelCar();
}
private	void	cancelAirBooking()	{
if	(airState	==	BOOKED)	cancelAirBooking();
else	airState	=	CANCEL_REQUIRED;
}
public	void	handle(AirBookedEvent	evt)	{
if	(airState	==	CANCEL_REQUIRED)	{
cancelAirBooking();
}	else	{
airState	=	BOOKED;
notifyIfAllBooked();
}
}
필요한 것
• SAGA/매니저 상태 영속화
– 상태가 유실되지 않아야 함
• 이벤트 à 해당 SAGA/매니저
– 효과적인 SAGA 검색 수단 필요
• SAGA 타임아웃
49
특징
• 개별 애그리거트는 자기 자신의 도메인
로직에만 집중하면 됨
• 한 비즈니스 프로세스와 관련된 흐름 제어가
한 곳에 모임
– 프로세스 변경 용이
• (주로) 비동기 이벤트 기반
• SAGA/프로세스 매니저 인스턴스 관리 위한
기반 프레임워크 필요
50
51
세 번째 수다 정리
52
마무리

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

overview of spring4
overview of spring4overview of spring4
overview of spring4
 
04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)04.실행환경 실습교재(화면처리)
04.실행환경 실습교재(화면처리)
 
20131217 html5
20131217 html520131217 html5
20131217 html5
 
02.실행환경 교육교재(데이터처리)
02.실행환경 교육교재(데이터처리)02.실행환경 교육교재(데이터처리)
02.실행환경 교육교재(데이터처리)
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
 
01.개발환경 교육교재
01.개발환경 교육교재01.개발환경 교육교재
01.개발환경 교육교재
 
03.실행환경 교육교재(배치처리)
03.실행환경 교육교재(배치처리)03.실행환경 교육교재(배치처리)
03.실행환경 교육교재(배치처리)
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수
 
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
 
자바 웹 개발 시작하기 (6주차 : 커뮤니티를 만들어보자!)
자바 웹 개발 시작하기 (6주차 : 커뮤니티를 만들어보자!)자바 웹 개발 시작하기 (6주차 : 커뮤니티를 만들어보자!)
자바 웹 개발 시작하기 (6주차 : 커뮤니티를 만들어보자!)
 
React 튜토리얼 2차시
React 튜토리얼 2차시React 튜토리얼 2차시
React 튜토리얼 2차시
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
 
자바 웹 개발 시작하기 (9주차 : 프로젝트 구현 – 추가적인 뷰)
자바 웹 개발 시작하기 (9주차 : 프로젝트 구현 – 추가적인 뷰)자바 웹 개발 시작하기 (9주차 : 프로젝트 구현 – 추가적인 뷰)
자바 웹 개발 시작하기 (9주차 : 프로젝트 구현 – 추가적인 뷰)
 
Spring boot 5장 cli
Spring boot 5장 cliSpring boot 5장 cli
Spring boot 5장 cli
 
자바 웹 개발 시작하기 (2주차 : 인터넷과 웹 어플리케이션의 이해)
자바 웹 개발 시작하기 (2주차 : 인터넷과 웹 어플리케이션의 이해)자바 웹 개발 시작하기 (2주차 : 인터넷과 웹 어플리케이션의 이해)
자바 웹 개발 시작하기 (2주차 : 인터넷과 웹 어플리케이션의 이해)
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
 
Java naming strategy (자바 명명 전략)
Java naming strategy (자바 명명 전략)Java naming strategy (자바 명명 전략)
Java naming strategy (자바 명명 전략)
 
Spring boot 공작소(1-4장)
Spring boot 공작소(1-4장)Spring boot 공작소(1-4장)
Spring boot 공작소(1-4장)
 
What is the meteor?
What is the meteor?What is the meteor?
What is the meteor?
 

Ähnlich wie Ddd start 부록 지앤선&ksug

AWS re:Invent 특집(2) – 서버리스(Serverless) 마이크로서비스를 위한 일곱 가지 모범 사례 (윤석찬)
AWS re:Invent 특집(2) – 서버리스(Serverless) 마이크로서비스를 위한 일곱 가지 모범 사례 (윤석찬)AWS re:Invent 특집(2) – 서버리스(Serverless) 마이크로서비스를 위한 일곱 가지 모범 사례 (윤석찬)
AWS re:Invent 특집(2) – 서버리스(Serverless) 마이크로서비스를 위한 일곱 가지 모범 사례 (윤석찬)
Amazon Web Services Korea
 

Ähnlich wie Ddd start 부록 지앤선&ksug (20)

Cloud migration pattern using microservices
Cloud migration pattern using microservicesCloud migration pattern using microservices
Cloud migration pattern using microservices
 
유엔진 오픈소스 클라우드 플랫폼 (uEngine Microservice architecture Platform)
유엔진 오픈소스 클라우드 플랫폼 (uEngine Microservice architecture Platform)유엔진 오픈소스 클라우드 플랫폼 (uEngine Microservice architecture Platform)
유엔진 오픈소스 클라우드 플랫폼 (uEngine Microservice architecture Platform)
 
Event storming based msa training commerce example add_handson_v3
Event storming based msa training commerce example add_handson_v3Event storming based msa training commerce example add_handson_v3
Event storming based msa training commerce example add_handson_v3
 
Cloud-Barista 제3차 오픈 컨퍼런스 : CB-Dragonfly - 멀티 클라우드 통합 모니터링 프레임워크(Multi-Cloud ...
Cloud-Barista 제3차 오픈 컨퍼런스 : CB-Dragonfly - 멀티 클라우드 통합 모니터링 프레임워크(Multi-Cloud ...Cloud-Barista 제3차 오픈 컨퍼런스 : CB-Dragonfly - 멀티 클라우드 통합 모니터링 프레임워크(Multi-Cloud ...
Cloud-Barista 제3차 오픈 컨퍼런스 : CB-Dragonfly - 멀티 클라우드 통합 모니터링 프레임워크(Multi-Cloud ...
 
Data in Motion을 위한 이벤트 기반 마이크로서비스 아키텍처 소개
Data in Motion을 위한 이벤트 기반 마이크로서비스 아키텍처 소개Data in Motion을 위한 이벤트 기반 마이크로서비스 아키텍처 소개
Data in Motion을 위한 이벤트 기반 마이크로서비스 아키텍처 소개
 
Observability customer presentation samuel-2021-03-30
Observability customer presentation samuel-2021-03-30Observability customer presentation samuel-2021-03-30
Observability customer presentation samuel-2021-03-30
 
[Partner TechShift] 클라우드 사업을 위한 3가지 소프트웨어 딜리버리 전략
[Partner TechShift] 클라우드 사업을 위한 3가지 소프트웨어 딜리버리 전략[Partner TechShift] 클라우드 사업을 위한 3가지 소프트웨어 딜리버리 전략
[Partner TechShift] 클라우드 사업을 위한 3가지 소프트웨어 딜리버리 전략
 
MSA 전략 2: 마이크로서비스, 어떻게 구현할 것인가?
MSA 전략 2: 마이크로서비스, 어떻게 구현할 것인가?MSA 전략 2: 마이크로서비스, 어떻게 구현할 것인가?
MSA 전략 2: 마이크로서비스, 어떻게 구현할 것인가?
 
Azure를 이용한 Join 없는 글로벌 분산 시스템 설계하기
Azure를 이용한 Join 없는 글로벌 분산 시스템 설계하기Azure를 이용한 Join 없는 글로벌 분산 시스템 설계하기
Azure를 이용한 Join 없는 글로벌 분산 시스템 설계하기
 
AWS re:Invent 특집(2) – 서버리스(Serverless) 마이크로서비스를 위한 일곱 가지 모범 사례 (윤석찬)
AWS re:Invent 특집(2) – 서버리스(Serverless) 마이크로서비스를 위한 일곱 가지 모범 사례 (윤석찬)AWS re:Invent 특집(2) – 서버리스(Serverless) 마이크로서비스를 위한 일곱 가지 모범 사례 (윤석찬)
AWS re:Invent 특집(2) – 서버리스(Serverless) 마이크로서비스를 위한 일곱 가지 모범 사례 (윤석찬)
 
Things Factory Introduction (한글)
Things Factory Introduction (한글)Things Factory Introduction (한글)
Things Factory Introduction (한글)
 
Serverless Architecture - 김현민
Serverless Architecture - 김현민Serverless Architecture - 김현민
Serverless Architecture - 김현민
 
Microservices
Microservices Microservices
Microservices
 
엔터프라이즈 클라우드 마이그레이션 준비와 실행. 그리고, 클라우드 운영 모범 사례 공유-최지웅, 오픈소스컨설팅 CTO / 장진환, 스마일샤...
엔터프라이즈 클라우드 마이그레이션 준비와 실행. 그리고, 클라우드 운영 모범 사례 공유-최지웅, 오픈소스컨설팅 CTO / 장진환, 스마일샤...엔터프라이즈 클라우드 마이그레이션 준비와 실행. 그리고, 클라우드 운영 모범 사례 공유-최지웅, 오픈소스컨설팅 CTO / 장진환, 스마일샤...
엔터프라이즈 클라우드 마이그레이션 준비와 실행. 그리고, 클라우드 운영 모범 사례 공유-최지웅, 오픈소스컨설팅 CTO / 장진환, 스마일샤...
 
[2017 AWS Startup Day] 서버리스 마이크로서비스로 일당백 개발조직 만들기
[2017 AWS Startup Day] 서버리스 마이크로서비스로 일당백 개발조직 만들기[2017 AWS Startup Day] 서버리스 마이크로서비스로 일당백 개발조직 만들기
[2017 AWS Startup Day] 서버리스 마이크로서비스로 일당백 개발조직 만들기
 
오픈소스 프레임워크 기반 웹 서비스 설계 (Example)
오픈소스 프레임워크 기반 웹 서비스 설계 (Example)오픈소스 프레임워크 기반 웹 서비스 설계 (Example)
오픈소스 프레임워크 기반 웹 서비스 설계 (Example)
 
Giip bp-giip connectivity1703
Giip bp-giip connectivity1703Giip bp-giip connectivity1703
Giip bp-giip connectivity1703
 
2016 SINVAS DAY - 프레임워크 기반 운영 시스템 설계 모델 현행화 방안
2016 SINVAS DAY - 프레임워크 기반 운영 시스템 설계 모델 현행화 방안2016 SINVAS DAY - 프레임워크 기반 운영 시스템 설계 모델 현행화 방안
2016 SINVAS DAY - 프레임워크 기반 운영 시스템 설계 모델 현행화 방안
 
Microservice Architecture
Microservice ArchitectureMicroservice Architecture
Microservice Architecture
 
Event Storming and Implementation Workshop
Event Storming and Implementation WorkshopEvent Storming and Implementation Workshop
Event Storming and Implementation Workshop
 

Mehr von beom kyun choi

ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
beom kyun choi
 

Mehr von beom kyun choi (20)

DDD로 복잡함 다루기
DDD로 복잡함 다루기DDD로 복잡함 다루기
DDD로 복잡함 다루기
 
TDD 발담그기 @ 공감세미나
TDD 발담그기 @ 공감세미나TDD 발담그기 @ 공감세미나
TDD 발담그기 @ 공감세미나
 
keras 빨리 훑어보기(intro)
keras 빨리 훑어보기(intro)keras 빨리 훑어보기(intro)
keras 빨리 훑어보기(intro)
 
DDD 준비 서문래
DDD 준비 서문래DDD 준비 서문래
DDD 준비 서문래
 
Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀
 
MVP 패턴 소개
MVP 패턴 소개MVP 패턴 소개
MVP 패턴 소개
 
파이썬 언어 기초
파이썬 언어 기초파이썬 언어 기초
파이썬 언어 기초
 
Spring Boot 소개
Spring Boot 소개Spring Boot 소개
Spring Boot 소개
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰
 
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
 
Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
리뷰의 기술 소개
리뷰의 기술 소개리뷰의 기술 소개
리뷰의 기술 소개
 
스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해
 
자바8 스트림 API 소개
자바8 스트림 API 소개자바8 스트림 API 소개
자바8 스트림 API 소개
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
 
Zookeeper 소개
Zookeeper 소개Zookeeper 소개
Zookeeper 소개
 
하둡2 YARN 짧게 보기
하둡2 YARN 짧게 보기하둡2 YARN 짧게 보기
하둡2 YARN 짧게 보기
 
차원축소 훑어보기 (PCA, SVD, NMF)
차원축소 훑어보기 (PCA, SVD, NMF)차원축소 훑어보기 (PCA, SVD, NMF)
차원축소 훑어보기 (PCA, SVD, NMF)
 
객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회
 
Storm 훑어보기
Storm 훑어보기Storm 훑어보기
Storm 훑어보기
 

Ddd start 부록 지앤선&ksug

  • 1. DDD Start 부록 "수다" 신림프로그래머, 최범균, 2016-07-16 madvirus@madvirus.net
  • 2. A/S 안내 • 책의 오류/오타 안내 – 다음 javacan 카페 à DDD Start QA 게시판 • http://cafe.daum.net/javacan/Qv4t/1 2
  • 4. 기능 측면에서 단일 시스템의 성장 4 단일코드 통합DB
  • 5. 거대한 강결합 5 서비스 레이어 Data 레이어 프리젠테이션 레이어
  • 6. 도메인 측면에서 문제 6 서비스 레이어 Data 레이어 프리젠테이션 레이어 통합DB: 언어 경계 없음 수직적으로 언어 경계 없음 컨텍스트 안에서만 존재하는 의미가 사라짐
  • 7. 잘 나눈 패키지로 문제 완화 7 user project …
  • 8. 여전히 경계가 모호해질 가능성 8 user project User Project USER PROJECTUSER_PROJ * *
  • 10. 분리에 따른 몇 가지 이점 • 명시적인 (강제) 언어 경계 à bounded • 컨텍스트별 독립적인 발전 • 인터페이스에 기반한 컨텍스트 간 통신 10
  • 11. Microservice의 특성 • James Lewis, Martin Fowler에 따르면 – 서비스로서 컴포넌트화 – 비지니스 수행에 따른 구성 – 프로젝트가 아닌 제품 – 똑똑한 엔드포인트와 더미(Dumb) 파이프 – 분산화 거버넌스 – 분산화된 데이터 관리 – 인프라 자동화 – 장애 방지 설계 – 진화하는 설계 11 * http://martinfowler.com/articles/microservices.html
  • 12. 서비스로서 컴포넌트화 • 독립 배포 à 서비스의 응집도(경계) 높아짐 • 명시적 인터페이스 à 공개 인터페이스 12
  • 13. 비지니스 수행에 따른 구성 13 발췌: http://martinfowler.com/articles/microservices.html
  • 14. 분산화된 데이터 관리 14 발췌: http://martinfowler.com/articles/microservices.html
  • 15. 진화하는 설계 • 서비스별 독립적인 변경(교체/업그레이드) 15
  • 16. MS à BC 16 언어의 경계를 찾아 Bounded Context를 구성하는데 도움을 줌 서비스로서 컴포넌트화 비지니스 수행에 따른 구성 분산화된 데이터 관리 진화하는 설계
  • 20. 주문의 변경 내역 20 state: PAYMENT_WAITING lines: [ {prod:P001, price:1000, quantity:1, amounts: 1000} ] shippingInfo: {receiver: 'bk', address: addr} 주문함 lines: {prod:P001, price:1000, quantity:1, amounts: 1000} shippingInfo: {receiver: 'bk', address: addr} 결제함 state: PREPARING lines: [ {prod:P001, price:1000, quantity:1, amounts: 1000} ] shippingInfo: {receiver: 'bk', address: addr} 배송지변경함 shippingInfo: {receiver: 'es', address: addr2} state: PREPARING lines: [ {prod:P001, price:1000, quantity:1, amounts: 1000} ] shippingInfo: {receiver: 'es', address: addr2} 발송함 state: SHIPPED lines: [ {prod:P001, price:1000, quantity:1, amounts: 1000} ] shippingInfo: {receiver: 'es', address: addr2}
  • 21. 상태 변화 증분 = 이벤트 21 주문함 lines: {prod:P001, price:1000, quantity:1, amounts: 1000} shippingInfo: {receiver: 'bk', address: addr} 결제함 배송지변경함 shippingInfo: {receiver: 'es', address: addr2} 발송함
  • 22. 증분 누적 à 마지막 상태 22 주문함 lines: {prod:P001, price:1000, quantity:1, amounts: 1000} shippingInfo: {receiver: 'bk', address: addr} 결제함 배송지변경함 shippingInfo: {receiver: 'es', address: addr2} 발송함 state: SHIPPED lines: [ {prod:P001, price:1000, quantity:1, amounts: 1000} ] shippingInfo: {receiver: 'es', address: addr2}
  • 23. 이벤트 소싱Event Sourcing 23 * http://martinfowler.com/eaaDev/EventSourcing.html 어플리케이션의 모든 상태 변화를 순서에 따라 이벤트로 보관한다. Capture all changes to an application state as a sequence of events.
  • 24. 도메인 객체와 이벤트 소싱 • 도메인 객체 조회 – 저장한 이벤트로부터 도메인 객체 생성 • 도메인 객체 변경 – 모든 상태 변화에 대한 이벤트를 저장 • 일관성의 기준인 애그리거트Aggregate 단위 24
  • 25. 이벤트 구성 • 구성 – 애그리거트 타입 – 애그리거트 식별자 – 버전 – 이벤트 타입 – 이벤트 시간 – 증분(변경) 내역(payload) • 이벤트 구분(unique idx) – 애그리거트 타입, 애그리거트 식별자, 버전 25
  • 27. 애그리거트 조회 • 애그리거트는 이벤트 반영 27 public class Order extends Aggregate { public void on(OrderPlacedEvent evt) { this.lines = evt.getOrderLines(); this.shippingInfo = evt.getShippingInfo(); } public void on(ShippingInfoChangedEventevt) { this.shippingInfo = evt.getShippingInfo(); } public void on(ShippedEvent evt) { this.state = SHIPPED; } public abstract class Aggregate { private Integer version; public void handle(Event evt) { this.version = evt.getVersion(); Events.handle(this, evt); } }
  • 28. 애그리거트 변경 • 애그리거트에서 이벤트 발생 28 public class Order extends Aggregate { public void cancel() { …. OrderCanceledEvent evt = new OrderCanceledEvent(getId(), version + 1); super.apply(evt); } public abstract class Aggregate { List<Event> uncommittedEvents; public void apply(Event evt) { addUncommittedEvent(evt); handle(evt); } public List<Event> getUncommittedEvents() { return uncommittedEvents; }
  • 29. 애그리거트 변경 • 트랜잭션에서 이벤트 저장 29 public class CancelOrderService { @Transactional public void cancel(String orderId) { Order order = orderRepository.findById(orderId); checkNull(order); order.cancel(); } } class TransactionHandler { public void commit() { List<Aggregate> aggs = getAllUOW(); for (Aggregate agg : aggs) { eventStore.append( agg.getClass(), agg.getUncomittedEvents() ); } }
  • 30. 애그리거트 생성 • 애그리거트 생성자 : 생성 이벤트 발생 30 public class PlaceOrderService { @Transactional public void cancel(String orderId) { Order order = new Order(…); repository.save(order); } } public class Order extends Aggregate { public Order(…) { …. OrderCreatedEvent evt = new OrderCreatedEvent( getId(), lines, shippingInfo, 1); super.apply(evt); }
  • 31. 이벤트 소싱과 유지보수 • 새로운 데이터 추가 31 public class Order extends Aggregate { private String note; public Order(…) { …. OrderCreatedV2Event evt = new OrderCreatedV2Event(...); super.apply(evt); } public void on(OrderCreatedEvent evt) { … this.note = ""; } public void on(OrderCreatedV2Event evt) { … this.note = evt.getNote(); } 없어지는 것 - DB 작업 일정 - 매핑 설정 변경
  • 32. 이벤트 소싱 적용한 애그리거트 • 임피던스 미스매치(impedance mismatch) 없음 • 애그리거트 간 참조는 ID • 비선점 잠금 32
  • 33. 성능 • 단일 애그리것트 조회 à 스냅샷 • 복합 조회 à CQRS 33
  • 34. SQL(ORM) vs 이벤트 소싱 • 변화되는 것 34 영역 적용 전 (RDBMS/ORM) 적용 후 도메인 객체 로딩 SQL : SELECT 쿼리 ORM : 프레임워크가 매핑 설정을 이용해서 SELECT 쿼리 실행 - 이벤트로부터 도메인 객체 생성 - 도메인 객체의 이벤트 핸들러를 이용해 상태 변경 반영 도메인 기능 SQL : 서비스 클래스 ORM : (일부) 엔티티 클래스 - 도메인 객체가 수행 - 상태 변경을 위한 이벤트 생성 상태 변경 반영 (데이터 변경) SQL : Insert/Update/Delete 쿼리 ORM : 엔티티 프로퍼티를 변경하면 ORM 프레임워크가 알맞은 쿼리 실행 - 도메인 객체가 발생한 이벤트를 저장소에 보관
  • 35. 장점 • DB에 의존적이지 않은 도메인 코드 구현 – 테이블이나 ORM 기술의 제한/제약에서 벗어남 • 기능 변경 – 하위 호환 처리가 상대적으로 쉬움 – 이벤트로부터 완전히 새로운 도메인 객체의 생성도 가능 • 버그 추적 용이 – 이벤트를 차례대로 검사하면서 버그 원인 추적 가능 • 객체 지향/DDD와 좋은 궁합 – 복잡한 도메인을 객체 지향적으로 구현하기에 좋음 • CQRS와 좋은 궁합 – 조회 관련 코드를 도메인에서 분리 – 조회 모델 분리로 조회 성능 향상 가능 35
  • 36. 단점 • 익숙하지 않음 – SQL 위주(데이터 중심) 개발 성향인 경우 적응 힘듬 • 단순 모델에는 적합하지 않음 – 단순 모델에 적용하기엔 구현이 복잡해짐 • 도구 부족 – 이벤트 소싱과 CQRS 지원 프레임워크 부족 • 운영시 어려움 – 이벤트 데이터만으로는 최신 상태의 빠른 확인 불가 • CQRS 필수! 36
  • 39. 길게 실행되는 프로세스 Long Running Business Process 39 주문하기 상품보내기 배송시작알리기 구매확정 요청하기
  • 40. 길게 실행되는 프로세스 40 주문하기 상품보내기 배송시작 알리기 구매확정 요청하기 배송시작함주문함 배송시작집하하기 전달 배송완료함 입금하기 결제함
  • 41. 길게 실행되는 프로세스/트랜잭션의 특징 • 여러 개의 작은 프로세스(트랜잭션)로 구성 • 하위 프로세스가 순서대로 실행되는 건 아님 • 여러 모듈/서비스가 (비동기로) 엮임 • 한 트랜잭션이 아님 • 실패는 롤백 대신 보상으로 처리 41
  • 42. SAGA • 여러 하위 트랜잭션 집합으로 구성된 LLT – LLT: Long Lived Transaction – 단일 실행 단위 • 각 하위 트랜잭션은 단독 트랜잭션 – 하위 트랜잭션 단위로 일관성 보장 • 각 하위 트랜잭션은 서로 연관 • 하위 트랜잭션 실패시, 보상 트랜잭션 – 일부만 성공해도 끝나지 않음 42 * SAGAS (Hector Garcia-Molina, 1987)
  • 44. 프로세스 매니저 • 여러 애그리거트/외부 시스템이 엮이는 긴 프로세스의 흐름 제어 – 각 구성 요소 간의 메시지 라우팅이 주된 역할 • 프로세스의 상태 보관 • 비즈니스 로직은 개별 구성 요소에서 처리 44
  • 45. Saga / 프로세스 매니저 45 주문 프로세스 매니저 배송 서비스 결제 서비스 주문 애그리거트 재고 애그리거트 Paid Event 배송지시 OrderCreated Event Delivery Completed Event StockChanged Event 통지 서비스 배송 시작 통지 배송 완료
  • 46. 구현 • 특정 이벤트에 Saga/프로세스 매니저 시작 • 수신한 이벤트에 따라 다음 기능 실행 – 실패시, 후속 보상 기능 실행 • 전체 프로세스가 끝나면 Saga/프로세스 매니저 종료 46
  • 47. 상태 존재 à 프로세스별 인스턴스 • 에어카텔 상품 구매 예 47 public class BookingProcessManager { private BookingId bookingId; private BookingState hotelState; private BookingState airState; private BookingState carState; public void handle(BookingCreatedEvent evt) { this.bookingId = evt.getBookingId(); sendBookingRequest(); } public void handle(HotelBookedEvent evt) { hotelState = BookingState.BOOKED; notifyIfAllBooked(); } private void notifyIfAllBooked() { if (hotelState == BOOKED && airState == BOOKED && carState == BOOKED) { notifyBookingCompletion(); } }
  • 48. 실패 보상 처리 • 에어카텔 호텔 예약 실패 예 48 public class BookingProcessManager { public void handle(HotelBookingFailedEvent evt) { cancelAirBooking(); cancelCar(); } private void cancelAirBooking() { if (airState == BOOKED) cancelAirBooking(); else airState = CANCEL_REQUIRED; } public void handle(AirBookedEvent evt) { if (airState == CANCEL_REQUIRED) { cancelAirBooking(); } else { airState = BOOKED; notifyIfAllBooked(); } }
  • 49. 필요한 것 • SAGA/매니저 상태 영속화 – 상태가 유실되지 않아야 함 • 이벤트 à 해당 SAGA/매니저 – 효과적인 SAGA 검색 수단 필요 • SAGA 타임아웃 49
  • 50. 특징 • 개별 애그리거트는 자기 자신의 도메인 로직에만 집중하면 됨 • 한 비즈니스 프로세스와 관련된 흐름 제어가 한 곳에 모임 – 프로세스 변경 용이 • (주로) 비동기 이벤트 기반 • SAGA/프로세스 매니저 인스턴스 관리 위한 기반 프레임워크 필요 50