Foundry
메시징
중급
핵심

이벤트 기반 아키텍처

이벤트 발행-구독 패턴, MSA의 핵심 통신 방식

무엇을 했다는 이벤트를 발행하고 관심 있는 쪽이 받아 처리합니다. 결합도가 낮아지지만 전체 흐름이 코드 한 곳에 안 보여 추적이 어려워집니다.

이벤트 기반 아키텍처

핵심 개념

  • 이벤트 발행(Publish): 서비스가 상태 변경 시 이벤트 발행
  • 이벤트 구독(Subscribe): 관심 있는 서비스가 이벤트 수신
  • 서비스 간 직접 호출 없이 느슨한 결합 유지

패턴

패턴설명복잡도
Pub/Sub발행-구독낮음
Event Sourcing이벤트 자체를 저장높음
CQRS읽기/쓰기 모델 분리중간

실무 포인트

  • 주문 → 결제 → 배송: 각 단계를 이벤트로 연결
  • 이벤트 유실 방지: Outbox 패턴 (DB+이벤트 원자적 저장)
  • 디버깅 어려움 → 이벤트 추적(Tracing) 도구 필수
면접에서 이렇게 나옵니다

Q.이벤트 드리븐 아키텍처란?

서비스가 서로를 직접 부르지 않고 일어난 사실을 알리고, 관심 있는 쪽이 반응하는 구조입니다.

항목명령 방식이벤트 방식
메시지 성격이것을 해달라이런 일이 있었다
아는 대상누구에게 시키는지 안다누가 듣는지 모른다
추가부르는 쪽을 고쳐야 한다구독자를 새로 붙이면 된다
흐름 파악코드를 따라가면 보인다흩어져 있어 어렵다

주문이 생겼을 때를 비교하면 이렇습니다.

방식주문 서비스가 하는 일
명령재고 차감을 호출하고, 알림 발송을 호출하고, 적립을 호출한다
이벤트"주문 생성됨" 을 발행한다. 나머지는 각자 구독한다

두 번째에서 적립 기능을 추가할 때 주문 서비스를 고치지 않는다는 것이 이 구조의 값입니다.

대가내용
흐름이 보이지 않는다누가 무엇에 반응하는지 코드에 안 나온다
결과적 일관성즉시 반영되지 않는다
디버깅트레이싱 없이는 추적이 어렵다
계약 관리이벤트 형식을 바꾸면 모르는 구독자가 깨진다

흔한 실수: 이벤트에 명령을 담는 것. "재고를 차감하라"는 이벤트가 아니라 명령입니다. 이벤트는 이미 일어난 사실을 과거형으로 알리고, 무엇을 할지는 받는 쪽이 정합니다.

Q.동기 vs 비동기 통신 트레이드오프는?

항목동기비동기
결과 확인즉시나중에. 별도 경로 필요
지연상대의 시간이 내 응답에 더해진다내 응답은 빠르다
장애 전파상대가 느리면 나도 느려진다상대가 죽어도 메시지는 남는다
부하 완충없다. 그대로 전달된다큐가 받아 둔다
오류 처리실패를 바로 알려준다재시도와 실패 큐를 설계해야 한다
흐름 파악쉽다어렵다
일관성즉시결과적

판단 기준은 사용자가 그 결과를 지금 알아야 하는가입니다.

상황선택
결제 승인동기. 결과 없이는 다음 화면을 못 만든다
주문 확정 후 알림비동기. 지금 알 필요가 없다
재고 차감동기. 실패하면 주문을 받을 수 없다
통계 집계비동기

한 요청 안에서 섞는 것이 보통입니다. 꼭 필요한 것만 동기로 처리하고 나머지를 큐로 넘기면, 응답은 빠르고 실패 지점은 줄어듭니다.

흔한 실수: 비동기가 더 빠르다고 답하는 것. 전체 처리 시간은 오히려 늡니다. 짧아지는 것은 사용자가 기다리는 구간입니다.

Q.이벤트 소싱(Event Sourcing)이란?

현재 상태를 저장하지 않고 변경 사건을 순서대로 저장하는 방식입니다. 상태는 그 사건들을 재생해서 만듭니다.

방식저장하는 것
일반잔액 = 8,000원
이벤트 소싱입금 10,000 → 출금 3,000 → 입금 1,000
얻는 것내용
완전한 이력언제 왜 바뀌었는지 전부 남는다
과거 상태 재현특정 시점으로 되돌려 볼 수 있다
감사금융이나 회계에서 요구하는 추적성
사후 분석나중에 필요해진 집계를 과거 데이터로 만들 수 있다
대가내용
조회가 어렵다현재 상태를 얻으려면 재생해야 한다
스냅샷 필요사건이 많아지면 중간 상태를 저장해 둬야 한다
이벤트 변경 불가저장된 사건은 못 고친다. 보정 사건을 추가한다
학습 비용팀 전체가 이 모델을 이해해야 한다

그래서 전면 도입보다 이력과 감사가 중요한 일부 영역에만 쓰는 편이 현실적입니다. 잔액 변동, 주문 상태 변화 정도입니다.

흔한 실수: 이벤트 드리븐 아키텍처와 같은 것으로 보는 것. 전자는 저장 방식이고 후자는 서비스 간 통신 방식입니다. 각각 따로 쓸 수 있습니다.

Q.CQRS 패턴을 설명해주세요

쓰기 모델과 읽기 모델을 분리하는 패턴입니다. 같은 데이터를 다루지만 구조를 따로 둡니다.

측면쓰기 모델읽기 모델
최적화 대상정합성과 규칙 검증조회 속도
구조정규화화면에 맞게 미리 합쳐 둔 형태
저장소관계형 DB검색 엔진, 캐시, 별도 테이블

분리하는 이유는 두 요구가 충돌하기 때문입니다. 쓰기는 정규화가 유리하고, 조회는 조인 없이 한 번에 읽는 편이 빠릅니다. 하나의 모델로는 둘 다 만족하기 어렵습니다.

동기화는 이벤트로 합니다. 쓰기가 일어나면 이벤트를 발행하고 읽기 모델을 갱신합니다. 그래서 읽기 모델은 항상 조금 뒤처집니다.

대가내용
결과적 일관성쓴 직후 조회에 반영되지 않을 수 있다
복잡도모델이 둘, 동기화 경로가 하나 늘어난다
정합성 점검두 모델이 어긋났는지 확인할 절차가 필요하다

흔한 실수: 읽기와 쓰기를 분리하니 무조건 도입하는 것. 조회 요구가 특별히 복잡하지 않으면 대가만 남습니다. 그리고 읽기 전용 복제본을 쓰는 것과 혼동하기 쉬운데, 복제본은 같은 모델의 사본이고 CQRS 는 모델 자체가 다릅니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

메시징 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.