๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
DDD

ใ€Œ๋„๋ฉ”์ธ ์ฃผ๋„ ๊ฐœ๋ฐœ ์‹œ์ž‘ํ•˜๊ธฐใ€10์žฅ ์ด๋ฒคํŠธ ์ •๋ฆฌ

by joaa 2023. 5. 8.

๐ŸŽˆ 10.1. ์‹œ์Šคํ…œ ๊ฐ„ ๊ฐ•๊ฒฐํ•ฉ ๋ฌธ์ œ

์‡ผํ•‘๋ชฐ์—์„œ ๊ตฌ๋งค ํ›„ ์ทจ์†Œ๋ฅผ ํ•˜๋ฉด ํ™˜๋ถˆ๋˜์–ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ.

๋„๋ฉ”์ธ ๊ฐ์ฒด์— ์„œ๋น„์Šค๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•˜๋Š” ์ƒํ™ฉ.

๋ณดํ†ต ๊ฒฐ์ œ ์‹œ์Šคํ…œ์ด ์™ธ๋ถ€์— ์กด์žฌํ•˜๋ฏ€๋กœ RefundService๋Š” ์™ธ๋ถ€์— ์žˆ๋Š” ๊ฒฐ์ œ ์‹œ์Šคํ…œ์ด ์ œ๊ณตํ•˜๋Š” ํ™˜๋ถˆ ์„œ๋น„์Šค๋ฅผ ํ˜ธ์ถœํ•จ. 

//๋„๋ฉ”์ธ ์„œ๋น„์Šค๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ๊ฒฝ์šฐ
public class Order{
	public void cancel(RefundService refundService){
    	//์ฃผ๋ฌธ ๋กœ์ง
    	verifyNotYetShipped();
        this.state = OrderState.CANCELED;
        
        //๊ฒฐ์ œ ๋กœ์ง
        this.refundStatus = State.REFUND_STARTED;
        try{
        	refundService.refund(getPaymendId());
            this.refundStatus = State.REFUND_COMPLETED;
        } catch(Exception ex){
        	???
        }
    }
    ...

 

//์‘์šฉ ์„œ๋น„์Šค์—์„œ ํ™˜๋ถˆ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ
public class CancelOrderService{
	private RefundService refundService;
    
    @Transactional
    public void cancel(OrderNo orderNo){
    	Order order = findOrder(orderNo);
        order.cancel();
        
        order.refundStarted();
        try{
		refundService.refund(order.getPaymentId());
		order.refundCompleted();
        } catch(Exception e){
        	???
        }
    }
    
    ...

๋ฌธ์ œ 1. ์™ธ๋ถ€ ์„œ๋น„์Šค๊ฐ€ ์ •์ƒ์ด ์•„๋‹ ๊ฒฝ์šฐ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•˜๋Š”๊ฐ€?

๋ฌธ์ œ 2. ์™ธ๋ถ€ ์„œ๋น„์Šค ์„ฑ๋Šฅ์— ์ง์ ‘์ ์ธ ์˜ํ–ฅ์„ ๋ฐ›๊ฒŒ ๋จ.

๋ฌธ์ œ 3. Order๋Š” ์ฃผ๋ฌธ์„ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ์ฒด์ธ๋ฐ ๊ฒฐ์ œ ๋„๋ฉ”์ธ์˜ ํ™˜๋ถˆ ๊ด€๋ จ ๋กœ์ง๊ณผ ๋’ค์„ž์ด๊ฒŒ ๋จ. ํ™˜๋ถˆ ๊ธฐ๋Šฅ์ด ๋ฐ”๋€Œ๋ฉด Order๋„ ์˜ํ–ฅ์„ ๋ฐ›์Œ์„ ์˜๋ฏธ -> ์ฃผ๋ฌธ ๋„๋ฉ”์ธ ๊ฐ์ฒด์˜ ์ฝ”๋“œ๋ฅผ ๊ฒฐ์ œ ๋„๋ฉ”์ธ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝํ• ์ง€๋„ ๋ชจ๋ฅด๋Š” ์ƒํ™ฉ์€ ์ข‹์ง€ ์•Š์Œ

๋ฌธ์ œ 4. ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ๋•Œ ๋กœ์ง์ด ์„ž์ด๊ณ  ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ๊ฐ€ ๋” ๋ณต์žกํ•ด์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•จ. 

 

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋“ค์€ ์ฃผ๋ฌธ ๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ์™€ ๊ฒฐ์ œ ๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ ๊ฐ„์˜ ๊ฐ•๊ฒฐํ•ฉ high coupling ๋•Œ๋ฌธ์ด๋‹ค. 

์ฃผ๋ฌธ์ด ๊ฒฐ์ œ์™€ ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜์–ด ์žˆ์–ด ์ฃผ๋ฌธ ๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ๊ฐ€ ๊ฒฐ์ œ ๋ฐ”์šด๋””๋“œ ์ปจํ…์ŠคํŠธ์— ์˜ํ–ฅ์„ ๋ฐ›์Œ.

 

์ด๋Ÿฐ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ์„ ์—†์• ๋Š” ๋ฐฉ๋ฒ•: ์ด๋ฒคํŠธ. 

ํŠนํžˆ ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‘ ์‹œ์Šคํ…œ ๊ฐ„์˜ ๊ฒฐํ•ฉ์„ ํฌ๊ฒŒ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์Œ.

 

๐ŸŽˆ 10.2. ์ด๋ฒคํŠธ ๊ฐœ์š”

์ด๋ฒคํŠธ: '๊ณผ๊ฑฐ์— ๋ฒŒ์–ด์ง„ ์–ด๋–ค ๊ฒƒ'

10.2.1 ์ด๋ฒคํŠธ ๊ด€๋ จ ๊ตฌ์„ฑ ์š”์†Œ

๋„๋ฉ˜์ธ ๋ชจ๋ธ์— ์ด๋ฒคํŠธ๋ฅผ ๋„์ž…ํ•˜๋ ค๋ฉด ์ด๋ฒคํŠธ์˜ ๊ตฌ์„ฑ์š”์†Œ์ธ ์ด๋ฒคํŠธ, ์ด๋ฒคํŠธ ์ƒ์„ฑ ์ฃผ์ฒด, ์ด๋ฒคํŠธ ๋””์ŠคํŒจ์ฒ˜(ํผ๋ธ”๋ฆฌ์…”), ์ด๋ฒˆํŠธ ํ•ธ๋“ค๋Ÿฌ(๊ตฌ๋…์ž)๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ. 

์ด๋ฒคํŠธ ์ƒ์„ฑ ์ฃผ์ฒด: ์—”ํ‹ฐํ‹ฐ, ๋ฐธ๋ฅ˜, ๋„๋ฉ”์ธ ์„œ๋น„์Šค์™€ ๊ฐ™์€ ๋„๋ฉ”์ธ ๊ฐ์ฒด. ๋„๋ฉ”์ธ ๊ฐ์ฒด๋Š” ๋„๋ฉ”์ธ ๋กœ์ง์„ ์‹คํ–‰ํ•ด์„œ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๊ด€๋ จ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด. 

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ: ์ด๋ฒคํŠธ ์ƒ์„ฑ ์ฃผ์ฒด๊ฐ€ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ์— ๋ฐ˜์‘. ์˜ˆ๋ฅผ ๋“ค์–ด '์ฃผ๋ฌธ ์ทจ์†Œ๋จ ์ด๋ฒคํŠธ'๋ฅผ ๋ฐ›๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ํ•ด๋‹น ์ฃผ๋ฌธ์˜ ์ฃผ๋งŒ์ž์—๊ฒŒ SMS๋กœ ์ฃผ๋ฌธ ์ทจ์†Œ ์‚ฌ์‹ค์„ ํ†ต์ง€. 

์ด๋ฒคํŠธ ๋””์ŠคํŒจ์ฒ˜: ์ด๋ฒคํŠธ ์ƒ์„ฑ ์ฃผ์ฒด์™€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์—ฐ๊ฒฐํ•ด ์ฃผ๋Š” ๊ฒƒ. 

 

10.2.2 ์ด๋ฒคํŠธ์˜ ๊ตฌ์„ฑ

์˜ˆ) ๋ฐฐ์†ก์ง€ ๋ณ€๊ฒฝํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ

์ด๋ฒคํŠธ๋ฅผ ์œ„ํ•œ ํด๋ž˜์Šค. ์ด๋ฒคํŠธ๋Š” ํ˜„์žฌ ๊ธฐ์ค€์œผ๋กœ ๊ณผ๊ฑฐ์— ๋ฒŒ์–ด์ง„ ๊ฒƒ์ด๋ฏ€๋กœ ์ด๋ฆ„์— ๊ณผ๊ฑฐ ์‹œ์ œ ์‚ฌ์šฉํ•จ. 

public class ShippingInfoChangedEvnet{
	private String orderNumber;
    private long timestamp;
    private ShippingInfo newShippingInfo;
    
    //์ƒ์„ฑ์ž, getter
}

 

์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒํ•˜๋Š” ์ฃผ์ฒด๋Š” Order ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ. 

public class Order {
	public void changeShippingInfo(ShippingInfo newShippingInfo){
    	verifyNotYerShipped();
        setShippingInfo(newShippingInfo);
        Events.raise(new ShippingInfoChangedEvent(number, newShippingInfo));
    }
    
    ...
}

 

10.2.3 ์ด๋ฒคํŠธ ์šฉ๋„

์ฒซ ๋ฒˆ์งธ: ํŠธ๋ฆฌ๊ฑฐ. ๋„๋ฉ”์ธ์˜ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€” ๋•Œ ๋‹ค๋ฅธ ํ›„์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉด ํ›„์ฒ˜๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํŠธ๋ฆฌ๊ฑฐ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ. 

๋‘ ๋ฒˆ์งธ: ์„œ๋กœ ๋‹ค๋ฅธ ์‹œ์Šคํ…œ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ๋™๊ธฐํ™”. ex) ๋ฐฐ์†ก์ง€๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ์™ธ๋ถ€ ๋ฐฐ์†ก ์„œ๋น„์Šค์— ๋ฐ”๋€ ๋ฐฐ์†ก์ง€ ์ •๋ณด๋ฅผ ์ „์†กํ•ด์•ผ ํ•จ. 

 

10.2.4 ์ด๋ฒคํŠธ ์žฅ์ 

์„œ๋กœ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ ๋กœ์ง์ด ์„ž์ด๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Œ. 

 

๐ŸŽˆ 10.3 ์ด๋ฒคํŠธ, ํ•ธ๋“ค๋Ÿฌ, ๋””์ŠคํŒจ์ฒ˜ ๊ตฌํ˜„

10.3.1 ์ด๋ฒคํŠธ ํด๋ž˜์Šค

์ด๋ฒคํŠธ ์ž์ฒด๋ฅผ ์œ„ํ•œ ์ƒ์œ„ ํƒ€์ž…์€ ์กด์žฌํ•˜์ง€ ์•Š๊ณ  ์›ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์ด๋ฒคํŠธ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋จ. ์ด๋ฆ„์— ๊ณผ๊ฑฐ ์‹œ์ œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ๋งŒ ์œ ์˜. 

์ด๋ฒคํŠธ ํด๋ž˜์Šค๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•ด์•ผ ํ•จ. 

 

10.3.2 Events ํด๋ž˜์Šค์™€ ApplicationEventPublisher

์ด๋ฒคํŠธ ๋ฐœ์ƒ๊ณผ ์ถœํŒ์„ ์œ„ํ•ด ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ApplicationEventPublisher๋ฅผ ์‚ฌ์šฉํ•จ. 

import org.springframework.context.ApplicationEventPublisher;

public class Events {
	private static ApplicationEventPublisher publisher;
    
    static void setPublisher(ApplicationEventPublisher publisher) {
    	Events.publisher = publisher;
    }
    
    public static void raise(Object event){
    	if(publisher != null){
        	publisher.publishEvent(event);
        }
    }
}

 

10.3.3 ์ด๋ฒคํŠธ ๋ฐœ์ƒ๊ณผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” @EventListener ์• ๋„ˆํ…Œ์ด์…˜์œผ๋กœ ๊ตฌํ˜„ํ•จ. 

@Service
public class OrderCanceledEventHandler {
	private RefundService refundService;
    
    public OrderCanceledEventHandler(RefundService refundService) {
    	this.refundService = refundService;
    }
    
    @EventListener(OrderCanceledEvent.class)
    public void handle(OrderCanceledEvent event){
    	refundService.refund(event.getOrderNumber());
    }
}

 

10.3.4 ํ๋ฆ„ ์ •๋ฆฌ

1. ๋„๋ฉ”์ธ ๊ธฐ๋Šฅ ์‹คํ–‰.

2. ๋„๋ฉ”์ธ ๊ธฐ๋Šฅ์„ Events.raise()๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด. 

3. Events.rais()๋Š” ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ApplicationEventPublisher๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ ์ถœํŒ. 

4. ApplicationEventPublisher๋Š” @EventListener(์ด๋ฒคํŠธํƒ€์ž….class) ์• ๋„ˆํ…Œ์ด์…˜์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ์•„ ์‹คํ–‰ํ•œ๋‹ค. 

 

๐ŸŽˆ 10.4. ๋™๊ธฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฌธ์ œ

์ด๋ฒคํŠธ ์‚ฌ์šฉํ•ด์„œ ๊ฐ•๊ฒฐํ•ฉ ๋ฌธ์ œ ํ•ด์†Œํ•จ. ์™ธ๋ถ€ ์„œ๋น„์Šค์— ์˜ํ–ฅ์„ ๋ฐ›๋Š” ๋ฌธ์ œ๊ฐ€ ๋‚จ์•„ ์žˆ์Œ. 

//1. ์‘์šฉ ์„œ๋น„์Šค ์ฝ”๋“œ
@Transactional
public void cancel(OrderNo orderNo) {
	Order order = findOrder(orderNo);
    order.cancel(); //order.cancle()์—์„œ OrderCanceledEvent ๋ฐœ์ƒ
}

//2. ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ
@Service
public class OrderCanceledEventHandler {
	...์ƒ๋žต
    
    @EventListener(OrderCanceledEvent.class)
    public void handle(OrderCanceledEvent event) {
    	//์™ธ๋ถ€ ํ™˜๋ถˆ ์„œ๋น„์Šค์™€ ์—ฐ๊ฒฐ๋œ
    	//refundService.refund()๊ฐ€ ๋А๋ ค์ง€๊ฑฐ๋‚˜ ์ต์…‰์…˜์ด ๋ฐœ์ƒํ•˜๋ฉด?
        refundService.refund(event.getOrderNumber());
    }
}

์‹œ์Šคํ…œ ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํŠธ๋žœ์žญ์…˜๋„ ๋ฌธ์ œ. 

ํŠธ๋žœ์žญ์…˜์„ ๋กค๋ฐฑ ํ•ด์•ผ ํ• ๊นŒ? ํŠธ๋žœ์žญ์…˜์„ ๋กค๋ฐฑ ํ•˜๋ฉด ๋ฃจ๋งค ์ทจ์†Œ ๊ธฐ๋Šฅ์„ ๋กค๋ฐฑ ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ๊ตฌ๋งค ์ทจ์†Œ๊ฐ€ ์‹คํŒจํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Œ. 

์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ์˜ ์—ฐ๋™์„ ๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์„ฑ๋Šฅ๊ณผ ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„ ๋ฌธ์ œ๋ฅผ ํ•ด์†Œํ•˜๋Š” ๋ฐฉ๋ฒ•์€

1. ์ด๋ฒคํŠธ๋ฅผ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜

2. ์ด๋ฒคํŠธ์™€ ํŠธ๋žœ์žญ์…˜์„ ์—ฐ๊ณ„ํ•˜๋Š” ๊ฒƒ. 

 

๐ŸŽˆ 10.5. ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ

'Aํ•˜๋ฉด ์ด์–ด์„œ Bํ•˜๋ผ'๋Š” ๋‚ด์šฉ์„ ๋‹ด๊ณ  ์žˆ๋Š” ์š”๊ตฌ์‚ฌํ•ญ์€ ์‹ค์ œ๋กœ 'A ํ•˜๋ฉด ์ตœ๋Œ€ ์–ธ์ œ๊นŒ์ง€ B ํ•˜๋ผ'์ธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ.

ex) ์ด๋ฉ”์ผ ์ธ์ฆ, ์ฃผ๋ฌธ ์ทจ์†Œ ํ›„ ๊ฒฐ์ œ ์ทจ์†Œ ๋“ฑ

์š”๊ตฌ์‚ฌํ•ญ์€ ์ด๋ฒคํŠธ๋ฅผ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ. ์ฆ‰ A ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ณ„๋„ ์Šค๋ ˆ๋“œ๋กœ B๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ตฌํ˜„.

 

๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ ๋น„๋™๊ธฐ ๊ตฌํ˜„ ๋ฐฉ๋ฒ• ์ค‘ ๋‹ค์Œ ๋„ค ๊ฐ€์ง€๋ฅผ ์•Œ์•„๋ด„. 

1. ๋กœ์ปฌ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•˜๊ธฐ

2. ๋ฉ”์‹œ์ง€ ํ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ

3. ์ด๋ฒคํŠธ ์ €์žฅ์†Œ์™€ ์ด๋ฒคํŠธ ํฌ์›Œ๋” ์‚ฌ์šฉํ•˜๊ธฐ

4. ์ด๋ฒคํŠธ ์ €์žฅ์†Œ์™€ ์ด๋ฒคํŠธ ์ œ๊ณต API ์‚ฌ์šฉํ•˜๊ธฐ

 

10.5.1 ๋กœ์ปฌ ํ•ธ๋“ค๋Ÿฌ ๋น„๋™๊ธฐ ์‹คํ–‰

์Šคํ”„๋ง์˜ @Async ์• ๋„ˆํ…Œ์ด์…˜์œผ๋กœ ์†์‰ฝ๊ฒŒ ๋น„๋™๊ธฐ๋กœ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. 

- @EnabledAsync ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด์„œ ๋น„๋™๊ธฐ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•œ๋‹ค. 

- ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์— @Async ์• ๋„ˆํ…Œ์ด์…˜์„ ๋ถ™์ธ๋‹ค. 

 

10.5.2 ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์„ ์ด์šฉํ•œ ๋น„๋™๊ธฐ ๊ตฌํ˜„

์นดํ”„์นด๋‚˜ ๋ž˜๋น—MQ์™€ ๊ฐ™์€ ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ. 

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด๋ฒคํŠธ ๋””์ŠคํŒจ์ฒ˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฉ”์‹œ์ง€ ํ์— ๋ณด๋ƒ„. 

๋ฉ”์‹œ์ง€ ํ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฉ”์‹œ์ง€ ๋ฆฌ์Šค๋„ˆ์— ์ „๋‹ฌํ•˜๊ณ , ๋ฉ”์‹œ์ง€ ๋ฆฌ์Šค๋„ˆ๋Š” ์•Œ๋งž์€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์ด์šฉํ•ด ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ. 

 

์ด๋ฒคํŠธ๋ฅผ ๋ฉ”์‹œ์ง€ ํ์— ์ €์žฅํ•˜๋Š” ๊ณผ์ •๊ณผ ๋ฉ”์‹œ์ง€ ํ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฝ์–ด์™€ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณผ์ •์€ ๋ณ„๋„ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๋กœ ์ฒ˜๋ฆฌ๋จ. 

 

 

 

10.5.3 ์ด๋ฒคํŠธ ์ €์žฅ์†Œ๋ฅผ ์ด์šฉํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ•ธ๋“ค๋Ÿฌ๋Š” ์Šคํ† ๋ฆฌ์ง€์— ์ด๋ฒคํŠธ๋ฅผ ์ €์žฅํ•จ. 

ํฌ์›Œ๋”๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ ์ด๋ฒคํŠธ ์ €์žฅ์†Œ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ€์ ธ์™€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•จ. 

ํฌ์›Œ๋”๋Š” ๋ณ„๋„ ์Šค๋ ˆ๋“œ๋ฅผ ์ด์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ ๋ฐœํ–‰๊ณผ ์ฒ˜๋ฆฌ๊ฐ€ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌ๋จ. 

์ด๋ฒคํŠธ ์ €์žฅ์†Œ์™€ ํฌ์›Œ๋”๋ฅผ ์ด์šฉํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ
API๋ฅผ ์ด์šฉํ•ด์„œ ์ด๋ฒคํŠธ๋ฅผ ์™ธ๋ถ€์— ์ œ๊ณตํ•˜๋Š” ๋ฐฉ์‹

ํฌ์›Œ๋” ๋ฐฉ์‹์ด ํฌ์›Œ๋”๋ฅผ ์ด์šฉํ•ด์„œ ์ด๋ฒคํŠธ๋ฅผ ์™ธ๋ถ€์— ์ „๋‹ฌํ•œ๋‹ค๋ฉด, API ๋ฐฉ์‹์€ ์™ธ๋ถ€ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ API ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ์ด๋ฒคํŠธ ๋ชฉ๋ก์„ ๊ฐ€์ ธ๊ฐ. API ๋ฐฉ์‹์—์„œ๋Š” ์ด๋ฒคํŠธ ๋ชฉ๋ก์„ ์š”๊ตฌํ•˜๋Š” ์™ธ๋ถ€ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ž์‹ ์ด ์–ด๋””๊นŒ์ง€ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ–ˆ๋Š”์ง€ ๊ธฐ์–ตํ•ด์•ผ ํ•จ. 

 

์ด๋ฒคํŠธ ์ €์žฅ์†Œ ๊ตฌํ˜„

- EventEntry: ์ด๋ฒคํŠธ ์ €์žฅ์†Œ์— ๋ณด๊ด€ํ•  ๋ฐ์ดํ„ฐ. EventEntry๋Š” ์ด๋ฒคํŠธ๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ id, ์ด๋ฒคํŠธ ํƒ€์ž…์ธ type, ์ง๋ ฌํ™”ํ•œ ๋ฐ์ดํ„ฐ ํ˜•์‹์ธ contentType, ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ ์ž์ฒด์ธ payload, ์ด๋ฒคํŠธ ์‹œ๊ฐ„์ธ timestamp๋ฅผ ๊ฐ–๋Š”๋‹ค. 

- EventStore: ์ด๋ฒคํŠธ๋ฅผ ์ €์žฅํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณต

- JdbcEventStore: JDBC๋ฅผ ์ด์šฉํ•œ EventStore ๊ตฌํ˜„ ํด๋ž˜์Šค.

- EventApi: REST API๋ฅผ ์ด์šฉํ•ด์„œ ์ด๋ฒคํŠธ ๋ชฉ๋ก์„ ์ œ๊ณตํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ. 

 

REST API ๊ตฌํ˜„

offset๊ณผ limit ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ด์šฉํ•˜๋Š” REST API๋ฅผ ์Šคํ”„๋ง MVC ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„ํ•จ. 

 

ํฌ์›Œ๋” ๊ตฌํ˜„

์Šคํ”„๋ง์˜ @Scheduled ์• ๋„ˆํ…Œ์ด์…˜ ํ˜น์€ ๋ณ„๋„ ์Šค์ผ€์ค„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ด์šฉํ•ด ๋ฉ”์„œ๋“œ๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์‹คํ–‰. 

 

๐ŸŽˆ 10.6. ์ด๋ฒคํŠธ ์ ์šฉ ์‹œ ์ถ”๊ฐ€ ๊ณ ๋ ค ์‚ฌํ•ญ

1. ์ด๋ฒคํŠธ ์†Œ์Šค๋ฅผ EventEntry์— ์ถ”๊ฐ€ํ• ์ง€ ์—ฌ๋ถ€

2. ํฌ์›Œ๋”์—์„œ ์ „์†ก ์‹คํŒจ๋ฅผ ์–ผ๋งˆ๋‚˜ ํ—ˆ์šฉํ•  ๊ฒƒ์ด๋ƒ์— ๋Œ€ํ•œ ๊ฒƒ

3. ์ด๋ฒคํŠธ ์†์‹ค์— ๋Œ€ํ•œ ๊ฒƒ

4. ์ด๋ฒคํŠธ ์ˆœ์„œ

5. ์ด๋ฒคํŠธ ์žฌ์ฒ˜๋ฆฌ

 

10.6.1 ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ์™€ DB ํŠธ๋žœ์žญ์…˜ ๊ณ ๋ ค

์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋ฅผ ๋™๊ธฐ๋ฅผ ํ•˜๋“  ๋น„๋™๊ธฐ๋กœ ํ•˜๋“  ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ์‹คํŒจ์™€ ํŠธ๋žœ์žญ์…˜ ์‹คํŒจ๋ฅผ ํ•จ๊ป˜ ๊ณ ๋ คํ•ด์•ผ ํ•จ. ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณตํ•  ๋•Œ๋งŒ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๊ณ ๋ คํ•ด์•ผ ํ•  ์‚ฌํ•ญ์ด ๋œ ๋ณต์žกํ•ด์ง„๋‹ค. 

์Šคํ”„๋ง์˜ @TransactionalEventListener ์• ๋„ˆํ…Œ์ด์…˜์€ ์Šคํ”„๋ง ํŠธ๋žœ์žญ์…˜ ์ƒํƒœ์— ๋”ฐ๋ผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•จ.