Event-Driven Architecture
일반적으로 API는 클라이언트가 요청한 값에 대해서 응답을 제공한다.
클라이언트(웹 애플리케이션, 모바일 앱, 서버)가 특정 데이터를 요청하면, API는 그 요청에 알맞은 데이터를 반환한다.
API는 클라이언트의 요청에 대해서만 응답을 반환하며, 클라이언트의 요청 없이 API가 데이터를 보내지 않는다.
하지만 API가 클라이언트의 요청 없이 데이터를 보내야 하는 상황이 있다. (이벤트, 실시간 알림 등)
API가 클라이언트의 요청 없이 데이터를 주도적으로 전달하기 위해 훅, 서버-사이드 이벤트(SSE), 웹소켓, 푸시 알림, 폴링/롱 폴링과 같은 기술들이 개발되었다. 이러한 기술은 클라이언트와 서버 간의 실시간 통신, 효율적인 데이터 전달, 그리고 더 나은 사용자 경험을 제공한다.
API가 클라이언트의 요청없이 데이터를 보내는 경우
1. 실시간 알림 시스템
- 사용자가 메시지를 받았거나, 중요한 업데이트가 발생했을 때 이를 실시간으로 전송한다.
- 채팅 애플리케이션, 이메일 알림, 소셜미디어 알림
2. 실시간 데이터 스트리밍
- 실시간 스포츠 경기 데이터처럼 실시간으로 변동되는 데이터를 클라이언트가 지속적으로 받아야하는 경우
- 주식 가격이나 환율이 실시간으로 변동할 때, 클라이언트에게 즉시 해당 데이터를 제공한다.
3. 자동회된 작업 처리
- 시스템에서 특정 조건이 만족되거나 이벤트가 발생했을 때, 자동으로 클라이언트에 데이터를 보내야 하는 경우
- 주문이 완료되었을 때, 결제 시스템이 자동으로 클라이언트에게 영수증을 전송하는 경우
- 백엔드 서버에서 데이터가 업데이트되었을 때, 관련 데이터를 자동으로 다른 서비스나 클라이언트에게 전달한다.
4. 상태 변화 모니터링
- 시스템의 상태가 변할 때 이를 즉시 클라이언트에 알려야 하는 경우
- 서버의 상태가 정상에서 오류로 변경되었을 때, 이를 실시간으로 모니터링 시스템에 알린다.
5. 트리거 기반 워크플로우
- 특정 이벤트가 발생하면 워크플로우를 자동으로 시작하고, 그에 따라 클라이언트에게 데이터를 보내야하는 경
웹훅(Webhook)
서버가 특정 이벤트를 발생시켰을 때, 미리 정의된 url로 http 요청을 보내는 방식
클라이언트가 서버에 따로 요청을 보내지 않아도 서버가 클라이언트에 데이터를 전송할 수 있다.
- 결제 완료, 사용자 등록, 데이터베이스 업데이트 등이 발생할 때 웹훅을 통해 관련 정보를 클라이언트에 전송한다.
- 클라이언트는 서버에 웹훅 URL을 등록하고, 서버는 특정 이벤트 발생 시 해당 URL로 HTTP POST 요청을 보낸다.
서버-사이드 이벤트(Server-Sent Events, SSE)
서버가 클라이언트에 실시간 데이터를 지속적으로 스트리밍 하는 방식 클라이언트가 한 번 서번에 연결을 맺으면, 서버는 클라이언트가 연결을 끊지 않는 한 실시간으로 데이터를 계속해서 전송할 수 있다.
- 실시간 주식 가격 업데이트, 뉴스 피드, 실시간 알림 등
- 클라이언트는 서버와 연결을 맺고, 서버는 그 연결을 통해 실시간으로 데이터를 전송한다. 주로 HTTP 프로토콜을 사용하며, 클라이언트는 이벤트를 수신한다.
웹소켓(WebSocket)
클라이언트와 서버 간의 실시간 양방향 통신을 가능하게 하는 프로토콜
연결이 한 번 성립되면, 클라이언트와 서버는 서로 데이터를 자유롭게 주고받을 수 있다.
- 실시간 채팅 애플리케이션, 실시간 게임, 협업 도구 등
- 클라이언트와 서버가 처음에 핸드셰이크를 통해 웹소켓 연결을 맺으면, 이후 양방향 데이터 전송이 가능하다.
푸시 알림(Push Notifications)
모바일 애플리케이션에서 많이 사용되는 방식으로 서버가 클라이언트(모바일)에 알림을 푸시하는 방식
푸시 알림은 서버가 클라이언트의 상태에 따라 메시지를 보낸다.
- 메시지 알림, 새 콘텐츠 업데이트 알림 등
- 푸시 서버를 통해 클라이언트에 알림을 전달한다. 클라이언트는 푸시 토큰을 서버에 등록해두고, 서버는 해당 토큰을 사용해 특정 클라이언트에 알림을 보낸다.
폴링(Polling)과 롱 폴링(Long Polling)
클라이언트가 주기적으로 서버에 데이터를 요청하는 방식
폴링은 클라이언트가 정해진 간격으로 서버에 요청을 보내고, 롱 폴링은 서버가 새로운 데이터가 있을 때까지 응답을 지연시킨 뒤
클라이언트에 응답을 보낸다.
- 실시간 알림에 사용되나 비효율적
- 클라이언트가 정해진 주기로 서버에 요청을 보내거나, 롱 폴링에서 클라이언트가 요청을 보내고 서버가 새 데이터가 생길 때까지 응답을 기다린 후 데이터를 보낸다.
위의 기술들은 클라이언트와 서버 간의 실시간 통신, 효율적인 데이터 전달, 그리고 더 나은 사용자 경험을 제공하기 위해 등장했으며, 이벤트 드리븐 방식으로 처리한다.
Event-Driven Architecture
분산된 애플리케이션 서비스들이 이벤트를 기반으로 통신하고 서로의 동작을 야기하는 패턴
이벤트 처리 과정
Event
- 시스템 내에서 발생하는 중요한 사건이나 상태 변화
- 버튼 클릭, 스크롤, 데이터베이스에 새로운 항목 추가, 특정 시간에 도달 등등
Event Source
- 시스템 내에서 중요한 상태 변화, 이벤트 감지
- 특정 비즈니스 이벤트를 트리거한다.
- 사용자의 행동(클릭, 입력), 시스템 내의 상태 변화(파일 생성, 데이터 업데이트) 등
Event Producer
- 이벤트 소스가 감지한 상태 변화, 동작을 바탕으로 이벤트 메시지 생성한다.
- 에빈트를 준비하고 발행한다.
- 데이터베이스에서 새로운 레코드가 생성되거나, 사용자 애플리케이션에서 특정 역할을 수행했을 때 이벤트 프로듀서가 이벤트 메시지를 생성한다.
Event Emitter
- 이벤트 프로듀서가 생성한 이벤트 메시지를 시스템 내에서 전파한다.
- 이벤트 메시지를 이벤트 브로커나 이벤트 버스로 전달한다.
Event Message
- 이벤트에 관한 정보를 담고 있는 데이터 구조
- 이벤트의 유형과 관련된 데이터를 포함한다.
- 이벤트에 대한 정보를 포함하며, 시스템 내 다른 컴포넌트들이 이 정보를 통해 작업을 수행한다.
구성요소
이벤트 타입 : 이벤트의 종류 (OrderCreated, UserSignUp)
페이로드 : 이벤트와 관련된 데이터 (주문 ID, 사용자 정보)
메타데이터 : 이벤트 발생 시간, 위치, 우선 순위 등 부가 정보
Event Broker/ Message Queue
- 이벤트 메시지를 수신하고, 이를 관리하여 등록된 이벤트 소비자에게 전달한다.
- 메시지 큐는 이벤트를 일시적으로 저장하고, 차례로 소비자에게 전달한다.
- 이벤트 프로듀서와 이벤트 컨슈머 간의 비동기적 통신을 가능하게 한다.
- Event Producer 큐에 이벤트 메시지를 넣고, Event Consumer 큐에서 메시지를 꺼내 처리한다.
- Apache Kafka, RabbitMQ, Amazon SQS.
Event Bus
- 이벤트 메시지를 발행하고, 여러 Event Consumer에 전달한다.
- 애플리케이션 내에서 이벤트를 라우팅하고 관리한다.
- 대규모 마이크로서비스 아키텍처에서 여러 서비스가 이벤트 버스를 통해 서로 이벤트를 주고 받는다.
Event Consumer
- 이벤트 메시지를 수신하고 그에 맞는 작업을 수행한다.
- Consumer은 특정 이벤트에 대해 등록되어 있으며, 이벤트가 발생하면 이를 처리한다.
- 주문이 생성되면, 주문 처리 서비스가 그 이벤트를 받아 결제 처리를 한다.
Event Stream
- 연속적으로 발생하는 이벤트를 시간 순서대로 기록하는 로그 또는 데이터 구조
- 스트림에서 발생한 이벤트들을 순차적으로 처리하며, 실시간 데이터 처리에 유용한다.
- Apache Kafka와 같은 시스템에서 이벤트 스트림을 관리하며, 실시간 데이터 파이프라인을 구축한다.
동작 방식
1. 이벤트 발생
- 특정 조건이나 사용자 행동을 인해 이벤트가 발생한다.
2. 이벤트 생성
- 이벤트 프로듀서가 상태 변화에 대한 이벤트 메시지를 생성한다.
3. 이벤트 전파
- 이벤트 프로듀서가 생성한 이벤트 메시지를 이벤트 브로커나 이벤트 버스로 전송한다.
4. 이벤트 전달
- 이벤트 브로커, 메시지 큐는 이벤트 메시지를 수신하고, 이를 관리하여 등록된 이벤트 소비자에게 전달한다.
- 이벤트 버스는 이벤트 메시지를 애플리케이션 내에서 라우팅하고, 여러 Consumer에 전달한다.
5. 이벤트 처리
- 이벤트 소비자가 이벤트 메시지를 수신한 후, 그에 맞는 작업을 수행한다.
- 주문이 생성되었을 때 결제를 처리하거나, 이메일을 전송하는 작업이 이루어질 수 있다.
6. 후속 작업
- 하나의 이벤트의 처리 결과로 다른 이벤트가 발생할 수 있으, 추가적인 이벤트가 발생할 수 있다.
- 결제가 완료되면 ‘결제완료’ 이벤트가 발생하고, 이를 기반으로 배송 시스템에서 작업이 시작될 수 있다.
특징
1. 비동기성 및 비차단 I/O
이벤트 드리븐 모델은 비동기로 동작하ㅏ기 때문에, 작업이 완료될 때까지 프로그램이 대기하지 않고 다른 작업을 수행할 수 있다.
따라서 시스템 자원을 낭비하지 않고 다른 작업을 처리할 수 있다.
2. 높은 동시성 처리
이벤트 드리븐 모델은 많은 동시 연결을 할 수 있다. 수천 개 이상의 동시 연결을 단일 스레드로 처리할 수 있기 때문에 확장성이 뛰어나다.
스레드 기반 모델의 경우 각 연결에 대해 별도의 스레드를 생성하기 때문에 많은 연결이 발생할 경우 스레드 관리가 복잡해지고 리소스 소모가 커진다.
3. 반응성 및 사용자 경험
UI 애플리케이션에서 사용자 입력에 즉각적으로 반응하여 빠른 응답을 제공하기 때문에 사용자 경험 반응성을 높일 수 있다.
4. 복잡한 상태 관리 용이
상태 기계와 같은 구조를 사용하여, 다양한 상태에서 발생하는 여러 이벤트를 효율적으로 처리할 수 있다.
5. 예측 가능성
각 이벤트에 대한 처리가 예측이 가능하기 때문에, 시스템과 신뢰성과 유지보수성을 높일 수 있다.
장단점
- 비동기적으로 처리하기 때문에, 시스템이 더 많은 이벤트를 처리할 수 있다. (확장성)
- 이벤트 처리 로직을 분리하여, 새로운 기능을 추가하거나 변경할 때 기존 시스템에 영향을 최소화할 수 있다. (유연성)
- 이벤트 발생 즉시 반응할 수 있어 실시간 시스템에 용이하다.
- 이벤트의 흐름을 추적하고 디버깅이 어려우며, 이벤트가 여러 시스템에 걸쳐 발생할 때 복잡도가 증가한다.
- 비동기 처리로 인해 데이터의 일관성을 유지하기 어려우며, 추가적인 설계, 관리가 필요할 수 있다.
- 이벤트나 버스의 관리 및 유지보수에 추가적인 리소스가 필요하기때문에 오버헤드가 발생할 수 있다.
사용 사례
- 사용자 인터페이스 : 버튼 클릭, 마우스 이동 등 사용자 입력에 반응하는 작업을 처리한다.
- 실시간 애플리케이션 : 채팅 애플리케이션, 실시간 알림 등에서 이벤트를 기반으로 데이터를 전송한다.
- 마이크로서비스 아키텍처 : 각 서비스가 독립적으로 이벤트를 발생시키고 이를 다른 서비스가 수신하여 처리한다.
- IoT 시스템 : 센서 데이터가 변경되거나 특정 조건이 충족될 때 이벤트를 발생시키고, 그에 대응하는 작업을 한다.
MSA와의 관계
마이크로서비스 아키텍처는 애플리케이션을 여러 개의 독립적인 서비스로 분리하는 설계 패턴으로
각 서비스는 특정 비즈니스 기능을 담당하며, 독립적으로 배포, 확장, 유지보수가 가능하다.
이벤트 드리븐 아키텍처는 마이크로 서비스 간 통신을 효과적으로 관리하는 데 유용하다.
서비스 간의 결합도를 낮추고, 서비스들이 더 독립적으로 동작하도록 한다.