λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ›οΈ Architecture

[이벀트 μ†Œμ‹±κ³Ό λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€ μ•„ν‚€ν…μ²˜] CH.3 이벀트 μ†Œμ‹± I

by GroovyArea 2025. 3. 4.

이번 챕터λ₯Ό μ½μœΌλ©΄μ„œ, 기쑴에 λ‚΄κ°€ μž‘μ„±ν•˜λ˜ μŠ€νƒ€μΌμ˜ λͺ¨ν˜Έν•œ κ°œλ…λ“€μ΄ λͺ…ν™•νžˆ 정리 λ˜λŠ” λŠλ‚Œμ΄ λ“€μ—ˆλ‹€.

이런 κ°œλ…μ„ λͺ…ν™•νžˆ μΈμ§€ν•˜λ©΄μ„œ, μ•žμœΌλ‘œμ˜ μ½”λ“œλ₯Ό μž‘μ„±ν•  λ•Œλ©΄ kotlin μŠ€νƒ€μΌμ˜ νŒ¨ν‚€μ§€ 정리에 μ’€ 더 집쀑해야 λ˜κ² λ‹€λŠ” 생각도 λ“€μ—ˆλ‹€.

 

λͺ¨λ“  λ‚΄μš©μ„ μ •λ¦¬ν•˜μ§„ μ•Šμ„ 것이며, 기쑴에 μ•Œκ³  있던 λ‚΄μš© 이외에 μƒˆλ‘­κ²Œ λ°›μ•„ 듀인 λ‚΄μš©λ§Œ 정리할 것이닀!!

 

도메인 이벀트

λ³€κ²½μ˜ λ‹¨μœ„λ₯Ό λΉ„μ¦ˆλ‹ˆμŠ€ 처리 κ³Όμ •μ—μ„œ λ°œμƒν•œ 결과둜 μ •μ˜

μ΄λ²€νŠΈλž€ μ‚¬μš©μžκ°€ 무엇인가 μ²˜λ¦¬ν•˜λ„λ‘ "μ‹œμŠ€ν…œ"에 μš”μ²­ν•œ κ²ƒμž„μ„ μ•Œ 수 μžˆλŠ” νžŒνŠΈμ΄λ©΄μ„œ 변경이 λ°œμƒν•œ μ΄μœ μž„μ„ μ•Œ 수 μžˆλ‹€.

 

이λ₯Ό ν…Œλ©΄, PasswordChanged λΌλŠ” 객체의 넀이밍을 보면, λ„λ©”μΈμ—μ„œ μ–΄λ–€ 일이 μΌμ–΄λ‚¬λŠ”μ§€ μ¦‰μ‹œ 이해가 κ°€λŠ₯ν•˜λ‹€.

 

public class QuantityChanged {
	private String eventId;
    private String productNo;
    private int quantity;
    private long time;
    
    private QuantityChanged() {
    	this.eventId = UUID.randomUUID().toString();
        this.time = System.currentTimeMillis();
    }
    
    public QuantityChanged(String productNo, int quantity) {
    	this();
        this.productNo = productNo;
        this.quantity = quantity;
    }

ν•΄λ‹Ήκ³Ό 같은 도메인 μ΄λ²€νŠΈκ°€ μžˆλ‹€λ©΄,

μ• κ·Έλ¦¬κ±°νŠΈμ—μ„œλŠ” μ•„λž˜μ™€ 같이 event λ₯Ό 보관할 수 μžˆλ‹€.

 

class Cart {

	private val cardId: String
    private val items: List<Item>
    
    private val events: List<Event>
    
    public Cart(cartId: String) {
    	// ...
        
        this.events = ArrayList<>()
    }
    
    fun changeQuantity(productNo: String, quantity: Int) {
    	// ...
        
        val event = QuantityChanged(productNo, quantity)
    	events.add(event)
    }

μ• κ·ΈλŸ¬κ±°νŠΈλŠ” μœ„μ™€ 같이 변경에 λŒ€ν•œ 이벀트λ₯Ό λ³΄κ΄€ν•œλ‹€.

이벀트 κ°μ²΄λŠ” μ•„λž˜μ™€ 같이 좔상화가 κ°€λŠ₯ν•˜λ‹€.

 

abstract class Event {
	
    private val eventId: String
    private val time: Long
    private val cartId: String
    
    fun Event() {
    	this.event = UUID.randomUUID().toString()
        this.time = System.currentTimeMillis()
    }
    
    fun getPayload(): String = JsonUtil.toJson(this)
    
}

class QuantityChanged: Event { // ... }

 

 

μ»€λ§¨λ“œμ™€ 이벀트

μ»€λ§¨λ“œλž€

- ν–‰μœ„λ₯Ό μ‹€ν–‰ν•˜λŠ” 방법

- μ‚¬μ΄λ“œ μ΄νŽ™νŠΈκ°€ μžˆλŠ” μž‘μ—…

- μ‹œμŠ€ν…œ μƒνƒœλ₯Ό λ³€κ²½ν•˜λŠ” μ˜λ„λ₯Ό 가진 λ©”μ‹œμ§€ (ν˜„μž¬ μ§„ν–‰ν˜•μ΄λ‹€.)

- μ‚¬μš©μž λ˜λŠ” μ‹œμŠ€ν…œμ˜ λ‹€λ₯Έ λΆ€λΆ„μ—μ„œ 생성

 

μ΄λ²€νŠΈλž€

- 이미 λ°œμƒν•œ 사싀에 κ΄€ν•œ μ„€λͺ…

- λ°œμƒν•œ κ²ƒμœΌλ‘œ κ³Όκ±°ν˜•μœΌλ‘œ 넀이밍

- μ΄λ²€νŠΈλŠ” μ‹œμŠ€ν…œ λ‚΄μ—μ„œ λ°œμƒν•œ 것이닀.

- λ©”μ†Œλ“œκ°€ λ°˜ν™˜ν•œ 것이 μ•„λ‹Œ, λͺ…령을 μ‹€ν–‰ν•œ 결과이닀.

 

이벀트 λͺ¨λΈλ§μ„ μ‹œμž‘ν•˜λ©΄, μ‹œμŠ€ν…œμ˜ λ™μž‘μ— λŒ€ν•΄μ„œ μƒκ°ν•˜κ²Œ λœλ‹€.

μ»€λ§¨λ“œμ™€ 이벀트λ₯Ό 톡해 λΉ„μ¦ˆλ‹ˆμŠ€ ν”„λ‘œμ„ΈμŠ€λ₯Ό λͺ…ν™•ν•˜κ³  μ‰½κ²Œ 식별할 수 μžˆλ‹€.

 

application service 둜 전달 λ˜λŠ” 객체인 request dto λ₯Ό command 라고 칭해도 λ˜μ§€ μ•Šμ„κΉŒ?

μ™ΈλΆ€λ‘œλΆ€ν„° μš”μ²­ μ˜€λŠ” μš”κ΅¬ 사항에 λŒ€ν•΄ ν–‰μœ„λ₯Ό μ‹€ν–‰ν•˜κ²Œ ν•˜λŠ” 주체이자 객체이지 μ•Šμ€κ°€?

 

λ§λΆ™μ΄μžλ©΄, command, event postfix λ₯Ό 뢙이기 보단, ν–‰μœ„μ— 더 μ§‘μ€‘ν•œ 넀이밍을 μž‘μ„±ν•˜λ„λ‘ λ…Έλ ₯ν•΄λ³΄μž.

λ‚΄κ°€ μš”μƒˆ service, repository, dto λŒ€μ‹  ν–‰μœ„λ₯Ό μˆ˜ν–‰ν•˜λŠ” 객체 μžμ²΄μ— 이름을 뢙이렀고 λ…Έλ ₯ν•˜λŠ” μ΄μœ μ΄λ‹€.

 

μ»€λ§¨λ“œλŠ” 자기 μžμ‹ μ— μœ νš¨μ„± 검사λ₯Ό μ‹€ν–‰ν•˜κ²Œ 해도 μ’‹λ‹€κ³  ν•œλ‹€.

 

이벀트 μ†Œμ‹±μ—μ„œλŠ” μ»€λ§¨λ“œμ™€ 이벀트λ₯Ό μ²˜λ¦¬ν•˜λŠ” λ©”μ†Œλ“œλ₯Ό 각각 ν•Έλ“€λŸ¬ λΌ μΉ­ν•œλ‹€.

도메인 이벀트둜 λ„λ©”μΈμ˜ λ³€κ²½ 이벀트λ₯Ό μ‰½κ²Œ 기둝할 수 μžˆλ‹€.

이벀트 μ†Œμ‹±μ€ μžμ—°μŠ€λ ˆ μ• κ·Έλ¦¬κ±°νŠΈμ— λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ΅¬ν˜„ν•˜λŠ” νš¨κ³Όκ°€ 있으며 λ…λ¦½μ μ΄λ©΄μ„œ μ‹€μš©μ μΈ λ‹¨μœ„ ν…ŒμŠ€νŠΈλ₯Ό κ°€λŠ₯μΌ€ ν•œλ‹€.

λ°˜μ‘ν˜•