๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ์žฅ์›์ต ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๐Ÿ”ฌweb application/- System architecture

Event-Driven-Architecture ์— ๋Œ€ํ•œ Overview ์™€ ์—ฌ๋Ÿฌ ๊ณ ๋ ค์‚ฌํ•ญ๋“ค

by Wonit 2022. 8. 22.

๋ชฉ์ฐจ

  • Event ๋ž€
  • Event Driven Architecture ๋ž€
  • Event Driven Architecture ์˜ ๊ตฌํ˜„ ๋ชจ๋ธ
  • Event-Driven-Architecture ์—์„œ ๊ณ ๋ คํ•ด์•ผํ•  ๋ฌธ์ œ๋“ค

 

Event ๋ž€

 

Event ๋Š” ๋ฌด์—‡์ผ๊นŒ?

 

Event ์˜ ๊ฐœ๋…์€ ๊ฐ„๋‹จํ•˜๋‹ค.

 

์ด๋ฒคํŠธ๋Š” ๊ณผ๊ฑฐ์— ์ผ์–ด๋‚œ ์–ด๋– ํ•œ ์‚ฌ๊ฑด์ด๋‹ค.

 

Event-Streaming-Platform ์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด์„œ ๋ถ„์‚ฐ๋œ ํ™˜๊ฒฝ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๊ณ  ์–ด๋– ํ•œ side effect ๋ฅผ ์ผ์œผํ‚ค๊ฑฐ๋‚˜ ํŠน์ • process ๋ฅผ trigger ํ•˜๋ฉฐ ์–ด๋–จ ๋Œ€๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋™๊ธฐํ™”๋ฅผ ํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

 

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

 

์˜ˆ๋ฅผ ๋“ค์–ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์„ ๋ด๋ณด์ž.

 

@Service
@RequiredArgsConstructor
public class OrderCancelService {

    private final OrderRepository repository;

    public void cancelBy(Long orderId) {
        Order order = repository.findById(orderId).orElseThrow(NoSuchElementException::new);
        order.cancel();
        repository.save(order);
    }
}

OrderCancelService ๋Š” ์ฃผ๋ฌธ์„ ์ทจ์†Œํ•˜๋Š” ์–ด๋–ค ์ƒํ™ฉ์„ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•œ ๊ฒƒ์ด๋‹ค.

 

cancelBy ๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ฝ์–ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ๋“ค์„ ํ•œ๋‹ค.

 

  • orderId ๋กœ Order ๋ฅผ ์กฐํšŒํ•œ๋‹ค.
  • Order ๋ฅผ cancel, ์ทจ์†Œํ•œ๋‹ค
  • ์ทจ์†Œ๋œ order ๋ฅผ update ํ•œ๋‹ค.

 

์—ฌ๊ธฐ์— ์–ด๋–ค ์š”๊ตฌ์‚ฌํ•ญ์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

 

์ฃผ๋ฌธ์ด ์ทจ์†Œ๋˜๋ฉด ํ•ด๋‹น ์ฃผ๋ฌธ์— ๋”ฐ๋ฅธ ๋ฉค๋ฒ„์‹ญ์„ ํ•ด์ง€์‹œ์ผœ์•ผ ํ•œ๋‹ค

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

 

@Service
@RequiredArgsConstructor
public class OrderCancelService {

    private final OrderRepository orderRepository;
    private final MembershipRepository membershipRepository;

    public void cancelBy(Long orderId) {
        Order order = orderRepository.findById(orderId).orElseThrow(NoSuchElementException::new);
        order.cancel();
        orderRepository.save(order);

        // Membership ํ•ด์ง€
        Membership found = membershipRepository.findByOrderId(orderId).orElseThrow(NoSuchElementException::new);
        found.terminate();
        membershipRepository.save(found);
    }
}

 

ํ•ด๋‹น ์ฃผ๋ฌธ์˜ id ๋ฅผ ํ†ตํ•ด์„œ membership ์„ ์กฐํšŒํ•˜๊ณ  ๋˜ ์ €์žฅํ•˜๊ณ  ์žˆ๋‹ค.

 

๊ทธ๋Ÿฐ๋ฐ ์„ค์ƒ๊ฐ€์ƒ์œผ๋กœ ์ƒˆ๋กœ์šด ์š”๊ตฌ์‚ฌํ•ญ์ด ๋˜ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

 

๋ฉค๋ฒ„์‹ญ์ด ํ•ด์ง€๋˜๋ฉด ํ•ด๋‹น ๋ฉค๋ฒ„์‹ญ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ํ•ด์ง€ ๋ฌธ์ž๋ฅผ ๋ณด๋‚ด๋‹ฌ๋ผ๊ณ  ํ•œ๋‹ค.

 

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋˜ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

 

@Service
@RequiredArgsConstructor
public class OrderCancelService {

    private final OrderRepository orderRepository;
    private final MembershipRepository membershipRepository;
    private final NotificationService notificationService;

    public void cancelBy(Long orderId) {
        Order order = orderRepository.findById(orderId).orElseThrow(NoSuchElementException::new);
        order.cancel();
        orderRepository.save(order);

        // Membership ํ•ด์ง€
        Membership found = membershipRepository.findByOrderId(orderId).orElseThrow(NoSuchElementException::new);
        found.terminate();
        Membership terminatedMember = membershipRepository.save(found);

        PhoneNumber number = terminatedMember.getPhoneNumber();
        notificationService.sendSms(number, "๋ฉค๋ฒ„์‹ญ์ด ํ•ด์ง€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์šฉํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.");
    }
}

 

์ด๋ ‡๊ฒŒ ํ•˜๋‚˜ํ•˜๋‚˜ ์š”๊ตฌ์‚ฌํ•ญ์ด ์ƒ๊ธธ ๋–„ ๋งˆ๋‹ค ์ฝ”๋“œ๊ฐ€ ์ˆ˜์ •๋˜์–ด์•ผ ํ•˜๊ณ  ๊ฒฐ๊ตญ ๊ฐœ๋ฐฉ ํ์‡  ์›์น™์„ ์–ด๊ธฐ๋Š” ๊ผด์ด ๋œ๋‹ค.

 

๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

 

OrderCancelService ๋Š” ๋ฌด์—‡์„ ํ•˜๋Š” ์ฑ…์ž„์„ ๊ฐ€์ง€๊ณ  ์žˆ์„๊นŒ?

 

๋ฌธ์ž ์ „์†ก? ๋ฉค๋ฒ„์‹ญ ํ•ด์ง€? ์ฃผ๋ฌธ ์ทจ์†Œ? ํ™˜๋ถˆ?

 

๋ฌผ๋ก  ์œ„์˜ ์ฝ”๋“œ๋Š” ์–ด๋Š ์ •๋„ ๋น„์•ฝ์ด ์กด์žฌํ•˜์ง€๋งŒ ์ด๋Ÿฐ์‹์œผ๋กœ ์ ์  ์‹œ๊ฐ„์ด ์ง€๋‚ ๋•Œ๋งˆ๋‹ค ๊ฐ์ž๊ฐ€ ๊ฐ€์ ธ์•ผํ•˜๋Š” ์ฑ…์ž„์ด ๋ถˆ๋ฌธ๋ช…ํ•ด์ง„๋‹ค.

 

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ• ์ค‘ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

 

 

์œ„์™€ ๊ฐ™์ด ์ด๋ฒคํŠธ, ์ฆ‰ ์–ด๋– ํ•œ ์‚ฌ๊ฑด์„ ์ด์šฉํ•ด์„œ ํ•ด๋‹น ์‚ฌ๊ฑด์— ๊ด€์‹ฌ์žˆ๋Š” ๊ฒƒ๋“ค์—๊ฒŒ ํ›„์† ์ž‘์—…์„ ์š”์ฒญํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

EDA, Event-Driven-Architecture ๋ž€ ๋ฌด์—‡์ผ๊นŒ

 

Event-Driven-Architecture ๊ฐ€ ๋ฐ”๋กœ ์œ„์—์„œ ๋งํ•œ ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ์˜ ์‹ค๋งˆ๋ฆฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„ ๊ธฐ๋ฒ•์ด๋‹ค.

 

์œ„์—์„œ ๋ณด์—ฌ์ค€ ์ผ๋ จ์˜ ์ฝ”๋“œ๋“ค์€ ํ•˜๋‚˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐœํ–‰ํ•˜๋Š” ์ด๋ฒคํŠธ์ธ๋ฐ, ์ด๋ฅผ ์‹œ์Šคํ…œ์ ์œผ๋กœ ํ™•์žฅ์‹œํ‚จ ๊ฒƒ์ด ๋ฐ”๋กœ Event Driven Architecture ์ด๋‹ค.

 

์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์„ ํ–ฅํ•œ ์—ฌ์ • - ๋ฐ•์šฉ๊ถŒ๋‹˜ ๋ฐœํ‘œ ์ž๋ฃŒ์ค‘

 

์‹œ์Šคํ…œ์—์„œ ๋™๊ธฐ์ ์œผ๋กœ ์–ด๋– ํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๋ฉด ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๊ด€์‹ฌ์žˆ์–ด๋ผ ํ•˜๋Š” ๋‹ค๋ฅธ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์˜ ์•„ํ‚คํ…์ฒ˜์ด๋‹ค.

 

์ฆ‰, ์ „ํ†ต์ ์ธ ๋™๊ธฐ ๋ฐฉ์‹ (Request-Response) ์ด ์•„๋‹ˆ๋ผ ์–ด๋–ค ์ž‘์—…์ด ํŠน์ • ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ ์‹คํ–‰๋˜๊ณ  ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ๋”ฐ๋ฅธ ์ž‘์—…์„ trigger ํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•œ๋‹ค.

 

๊ทธ๋ž˜์„œ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜๋ฅผ asynchronous ํ†ต์‹ ์ด๋ผ๊ณ  ํ‘œํ˜„ํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์‹œ์Šคํ…œ์ด ๊ตฌ์„ฑ๋œ๋‹ค๋ฉด ํŠน์ • A ๋ผ๋Š” ์‹œ์Šคํ…œ์€ B ๋ผ๋Š” ์‹œ์Šคํ…œ๊ณผ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜๋Š” ๋ถˆํ•„์š”ํ•œ ๊ณผ์ •์ด ์‚ฌ๋ผ์ง€๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

๊ทธ๋ž˜์„œ Event ๋ฅผ ์ด์šฉํ•œ ๋น„๋™๊ธฐ ํ†ต์‹ ์„ Fire and Forgot ์ด๋ผ๊ณ  ํ‘œํ˜„ํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

 

์ด๋Ÿฌํ•œ Event-Driven-Architecture ๊ฐ€ ํ˜„๋Œ€์— ๊ฐ๊ด‘๋ฐ›๋Š” ์ด์œ ๊ฐ€ ์žˆ๋‹ค.

 

์‚ฌ์‹ค EDA ๋Š” ๊ฝค๋‚˜ ์˜ค๋ž˜๋œ ๊ฐœ๋…์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

martinfowler ์˜ ๋ธ”๋กœ๊ทธ์—์„œ EDA ๋ผ๋Š” ๊ฐœ๋…์ด 2007 ๋…„์˜ ๊ธ€, Focusing on Events ์—์„œ ์†Œ๊ฐœ๋˜๊ธฐ๋„ ํ–ˆ์œผ๋ฉฐ ๊ทธ๋ฆฌ ์ตœ์‹ ์˜ ๊ธฐ์ˆ ์€ ์•„๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ํ˜„๋Œ€์— ๋“ค์–ด์„œ EDA ์˜ ํ•ต์‹ฌ ์ปจ์…‰์ด Loosely Coupled ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐ๊ด‘๋ฐ›๋Š” MSA ์™€ ๋งŽ์ด ๋‹ฎ์•„์žˆ์œผ๋ฉฐ ์„œ๋กœ ์ƒํ˜ธ ๋ณด์™„์ ์ธ ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

 

MSA ์™€ ๊ฐ™์€ ๋ถ„์‚ฐ ํ™˜๊ฒฝ์—์„œ๋Š” REST ํ˜•ํƒœ์˜ ํ†ต์‹ ์œผ๋กœ ์ธํ•œ Synchronous ์˜ ์—ฌ๋Ÿฌ ์ œ์•ฝ์‚ฌํ•ญ๋“ค, ์ด๋ฅผํ…Œ๋ฉด Transaction ๊ณผ ๋ฐ์ดํ„ฐ์˜ Consistency ๋‚˜ Materialized View ์ฒ˜๋Ÿผ ๋ฐ˜์ •๊ทœํ™”๋œ ํ™˜๊ฒฝ์—์„œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ํž˜๋“ค์—ˆ์—ˆ๊ณ , ์ด๋ฅผ ๋ณด์™„ํ•˜๋Š” Asynchronous ํ•œ ํ†ต์‹ ์ธ Event Driven ์ด ์ฃผ๋ชฉ์„ ๋ฐ›๋Š” ๊ฒƒ์ด๋‹ค.

 

Event-Driven-Architecture ์˜ ๊ตฌํ˜„ ๋ชจ๋ธ

 

Event-Driven-Architecture ๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ๋‹ค.

 

๋‹จ์ˆœํ•˜๊ฒŒ๋Š” Messaging Infra ๋ฅผ ์ด์šฉํ•ด์„œ Producer/Consumer ๋‚˜ Pub/Sub ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ, Event Store ๋ฅผ ํ™œ์šฉํ•˜์—ฌ Event Streaming Channel ์„ ๋งŒ๋“ค๊ณ  ๊ณ„์†ํ•ด์„œ event ๋ฅผ sourcing ํ•˜๋Š” ๋ฐฉ๋ฒ•๊นŒ์ง€...

 

๊ฒŒ์‹œ/๊ตฌ๋… ๋ชจ๋ธ


๊ทธ ์ค‘์—์„œ ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ชจ๋ธ์ธ Pub/Sub ๋ชจ๋ธ์— ๋Œ€ํ•ด์„œ ์ด์•ผ๊ธฐํ•ด๋ณด์ž๋ฉด, pub/sub ํ˜•ํƒœ์ธ ๊ฒŒ์‹œ ๊ตฌ๋… ๋ชจ๋ธ์€ Messaging Infra ๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•œ๋‹ค.

 

 

pub/sub ์—์„œ๋Š” ๋ˆ„๊ตฐ๊ฐ€๋Š” ์ด๋ฒคํŠธ๋ฅผ Messaging Infra ์— ๊ฒŒ์‹œ (publish) ํ•˜๋ฉด ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๊ด€์‹ฌ์žˆ๋Š” ๋‹ค๋ฅธ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋… (subscribe) ํ•ด์„œ ๊ฐ€์ ธ๊ฐ€๊ฒŒ ๋œ๋‹ค.

 

์ผ์ข…์˜ Broadcasting ํ˜•ํƒœ๋กœ Pub ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” Sub ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์กด์žฌ๋ฅผ ๋ชจ๋ฅด๊ฒŒ ๋œ๋‹ค.

 

๊ฒฐ๊ตญ ์„œ๋กœ ๋‹ค๋ฅธ ์ฑ…์ž„์„ ๊ฐ–๊ณ  ์žˆ๊ณ  ์ƒ๋Œ€์— ๋Œ€ํ•œ ๊ทœ์•ฝ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์žฅ์•  ๊ฒฉ๋ฆฌ(Fault Isolation) ๊ตฌ์กฐ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

 

Event-Driven-Architecture ์—์„œ ๊ณ ๋ คํ•ด์•ผํ•  ๋ฌธ์ œ๋“ค

 

๋‹ค์Œ์€ EDA ๋ฅผ ์œ„ํ•œ๋‹ค๋ฉด ๊ณ ๋ คํ•ด์•ผํ•  ๋ฌธ์ œ๋“ค์ด๋‹ค.

 

  • ๋„๋ฉ”์ธ์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ๊ด€์ 
  • ๋ฉ”์‹œ์ง€์˜ ์‹ ๋ขฐ์„ฑ
  • ์žฅ์•  ํฌ์ธํŠธ
  • ์ ์ ˆํ•œ Infrastructure
  • Debuging

 

๋„๋ฉ”์ธ์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ๊ด€์ 

 

Event ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค๋Š” ๊ฒƒ์€ ๋Œ€๋ถ€๋ถ„ ์–ด๋– ํ•œ Domain Event ๊ฐ€ ๋ฐœ์ƒ๋˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•  ๊ฒƒ์ด๋‹ค.

 

๊ทธ๋Ÿผ ๊ทธ์— ๋งž๊ฒŒ ๋„๋ฉ”์ธ์— ๋Œ€ํ•œ ์„ค๊ณ„๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ๊ณผ๊ฑฐ์˜ ๋ฐฉ์‹๊ณผ๋Š” ์กฐ๊ธˆ ๋‹ค๋ฅธ ์ธ์‚ฌ์ดํŠธ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ •์ƒ ์‹œ๋‚˜๋ฆฌ์˜ค์— ๋Œ€ํ•œ Event ๋ฐœํ–‰๊ณผ Event ๋ฐœํ–‰์— ๋Œ€ํ•œ ์‹คํŒจ/์žฌ์‹œ๋„ ์ฒ˜๋ฆฌ ๋˜ํ•œ ๊ณ ๋ ค๋  ์ˆ˜ ์žˆ๋‹ค.

 

๋ฉ”์‹œ์ง€์˜ ์‹ ๋ขฐ์„ฑ

 

Event-Driven-Architecture ์—์„œ๋Š” ํ•˜๋‚˜์˜ ๋น„์ฆˆ๋‹ˆ์Šค ํŠธ๋žœ์žญ์…˜์„ ์„ฑ๊ณต์ ์œผ๋กœ ๋๋งˆ์น˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ „๋‹ฌ๋˜๋Š” ์ด๋ฒคํŠธ์˜ ์‹ ๋ขฐ์„ฑ์ด ์ค‘์š”ํ•˜๋‹ค.

 

์ด๋ฒคํŠธ๋Š” Exactly once, ๋ฐ˜๋“œ์‹œ ํ•œ๋ฒˆ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•œ๋‹ค.

 

๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ๋™์ผํ•œ ์ด๋ฒคํŠธ๊ฐ€ ์—ฌ๋Ÿฌ๋ฒˆ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋„๋ก ๋ฉฑ๋“ฑํ•˜๊ฒŒ ๊ตฌ์„ฑ๋  ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ด์•ผ ํ•œ๋‹ค.

 

๋˜ํ•œ ๋ฉ”์‹œ์ง€๋Š” ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜๋‹ค.

 

Event ๋Š” ๊ณผ๊ฑฐ์— ๋ฐœ์ƒํ–ˆ๋˜ ์–ด๋–ค ์‚ฌ๊ฑด์„ ์˜๋ฏธํ•˜๋Š”๋ฐ, ์ด ์‚ฌ๊ฑด์— ๋Œ€ํ•ด์„œ๋Š” ๊ณผ๊ฑฐ๋ผ๋Š” ์‹œ์ ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.

 

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒ๋œ ์ˆœ์„œ์— ๋”ฐ๋ผ์„œ ์‹œ์Šคํ…œ์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ณ  ๊ฒฐ์ •๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๋˜ํ•œ Scaling ๋œ Application ์—์„œ Event Message ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๊ทธ๋“ค ๊ฐ„์˜ race condition ์— ๋Œ€ํ•ด์„œ๋„ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค.

 

์žฅ์• ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ

 

Event-Driven-Architecture ์—์„œ ๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ ์—ฌํƒ€ ๋‹ค๋ฅธ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์—์„œ๋„ ์žฅ์• ์— ๋Œ€ํ•œ handling ์ด ์ค‘์š”ํ•˜๋‹ค.

 

Event-Driven Architecture ์—์„œ๋Š” Messaging Infrastructure ๋ฅผ ํ†ตํ•ด์„œ ํ†ต์‹ ์ด ์ด๋ฃจ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— Messaging Infrastructure ์˜ Reliability ๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.

 

๋‹จ์ผ Channel ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ํ•ด๋‹น Channel ์— ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ SPOF (Single Point of Failure) ๊ฐ€ ๋  ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ Partitioning ๊ณผ ๊ฐ™์ด ์ด์— ๋”ฐ๋ฅธ ์ ์ ˆํ•œ Scaling ์ด ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด Scaling ๋œ Channel ์— ๋Œ€ํ•ด์„œ๋„ ์ˆœ์„œ๊ฐ€ ์ ์ ˆํžˆ ๋ณด์žฅ๋˜์–ด์•ผ ํ•˜๊ณ  ๋‹ค์‹œ ๋ฉ”์‹œ์ง€์˜ ์‹ ๋ขฐ์„ฑ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ๊ท€๊ฒฐ๋œ๋‹ค.

 

์ ์ ˆํ•œ Infrastructure

 

๋˜ํ•œ EDA ์—์„œ๋Š” ์ ์ ˆํ•œ ์ธํ”„๋ผ๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.

 

์ด๋ฒคํŠธ ์†Œ๋น„ ์‹คํŒจ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด์„œ DLQ ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ฑฐ๋‚˜ ๋ฐœ์ƒํ•˜๋Š” ๋ชจ๋“  Event ๋ฅผ ํ•œ๊ณณ์— ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ๋“ฑ message ์ž์ฒด๋ฅผ persist ํ•˜๊ฒŒ ๊ฐ€์ ธ๊ฐ€์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

 

๊ฒฐ๊ตญ EDA ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ด€์ ๊ณผ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ์„œ RDS ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  NoSQL ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

๋˜ํ•œ ๋ชจ๋“  ์ด๋ฒคํŠธ๊ฐ€ ํ•œ๊ณณ์— ์Œ“์ด๋Š” Event Store ๋ฅผ ๊ตฌ์„ฑํ•  ๊ฒฝ์šฐ Network Throughput ์„ ๊ฐ๋‹นํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ์„ค๊ณ„๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

 

Messaging Infrastructure ๊ฐ€ Apache Kafka ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋–„์™€ RabbitMQ ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ, SQS/SNS ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๊ฐ™์ด ์šฉ๋ก€์™€ ์šฉ๋ฒ•์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ ์ ˆํ•œ ์†”๋ฃจ์…˜์„ ์ฐพ๋Š”๊ฒƒ๋„ ํ•„์š”ํ•˜๋ฉฐ ๋‹น์—ฐํ•˜๊ฒŒ ๊ทธ์— ๋Œ€ํ•œ ํŒ€์˜ ๋…ธํ•˜์šฐ๊ฐ€ ์กด์žฌํ•ด์•ผ ํ•˜๋ฉฐ ์—ญ์‹œ ๋ฆฌ์†Œ์Šค๊ฐ€ ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

Debuging

 

Loosely Coupled ํ•œ ํ™˜๊ฒฝ์„ EDA ๋ฅผ ํ†ตํ•ด์„œ ๊ตฌ์ถ•ํ–ˆ๋‹ค๋ฉด ๋‹น์—ฐํ•˜๊ฒŒ Debuging ์ด ๋งค์šฐ ์–ด๋ ค์›Œ์ง์„ ์˜๋ฏธํ•œ๋‹ค.

 

ํ•œ Transaction ์—์„œ Synchronous ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋˜๋Š” ํ™˜๊ฒฝ์ด๋ผ๋ฉด ์–ด๋””์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ๋˜์—ˆ๋Š”์ง€ ๋น„๊ต์  ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋ถ„์‚ฐ๋œ ํ™˜๊ฒฝ์€ ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

 

์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” Open Tracing ์„ ๋„์ž…ํ•˜๋Š” ๋“ฑ Debuging ์„ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์žฅ์น˜๋“ค์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

References

๋Œ“๊ธ€