서론
단잠 알림 도입기 포스팅 입니다.
사실 FCM 으로 진행하기 위해 코드들을 모두 작성하여서
웹으로 모두 테스트까지 완료했었지만,,,,
xCode 베타 버전 문제인지 ...........
FCM 문제인지 .........
앱 개발자분과 이것저것 다 설정해봐도 어디가 문제인지 알 수가 없어서.....
래빗앰큐와 SSE를 이용해서 전반적인 알림을 구현하려고 합니다. ㅜㅜ
FCM 관련 포스팅은 작성 중에 있어서 빠른 시일내에 올릴 예정입니다.
결론적으로
RabbitMQ와 SSE를 사용한 알림 도입에 대해서
상세하게 기록하고자 포스팅을 작성하게 되었습니다 !
먼저 RabbitMQ를 알기 전에 표준 메시징 프로토콜인 AMQP에 대해서 알아보겠습니다.
(이후에 나오겠지만, RabbitMQ는 AMQP의 구현체입니다. 그래서 AMQP를 먼저 학습하였습니다.)
✔️AMQP 란? (Advanced Message Queuing Protocol)
MQ(Message Queuing) 기반의 프로토콜로 메세지 지향 미들웨어 (MOM) 을 위한 표준 응용 계층 프로토콜 입니다.
간단하게 메세지 통신을 위한 규약 스펙이라고 할 수 있습니다.
플랫폼에 종속적인 제품들 사이에서 서로 다른 이기종(하나 이상의 프로세서 또는 코어를 사용하는 시스템)간에 메시지를 교환하기 위해서는 메세지 포맷 변환을 위해 속도가 느린 메시지 Bridge나 시스템 자체를 통일 시켜야하는 불편함과 비효율성이 있었습니다.
앞선 문제를 해결하기 위해서, 서로 다른 시스템들 간의 최대한 효율적인 방법으로 메세지를 교환하기 위한 AMQP가 탄생하게 되었습니다.
AMQP는 JPMorgand이라는 미국 윌가 금융 핵심 회사에서 금융 시스템 플랫폼간 통신을 위해 개발된 미들웨어입니다. 그로인해 신뢰도가 높고, 중복 이슈가 거의 없기에 사용됩니다.
Message Broker
AMQP를 구현한 메시지 브로커는 총 4가지가 존재합니다.
- RabbitMQ
- OpenAMQ
- StormMQ
- Apache Qpid
통상적으로 RabbitMQ가 가장 많이 사용되는 구현체 입니다.
✔️RabbitMQ란 ?
RabbitMQ는 앞서 얘기한 AMQP 를 구현한 메시지 브로커로, 데이터를 생성하는 프로듀서(Producer)와 데이터를 처리하는 컨슈머(Consumer) 간에 중간다리 역할을 합니다.
주요 역할은 아래와 같습니다.
1. 메시지 큐잉(Message Queuing)
- 프로듀서가 생성한 메시지를 큐(queue)에 쌓아 두고, 이를 소비자들이 필요한 시점에 가져갈 수 있도록 합니다.
- 큐에 쌓인 메시지는 FIFO(First-In, First-Out) 방식으로 처리되는 것이 기본이지만, 라우팅 규칙에 따라 다르게 동작할 수도 있습니다.
2. 비동기 작업 처리
- 메시지가 큐에 저장된 후, 컨슈머는 메시지를 하나씩 가져가 비동기로 작업을 처리할 수 있습니다.
- 이를 통해 프로듀서와 컨슈머가 독립적으로 동작하며, 요청에 대한 처리 속도 차이가 발생해도 시스템이 멈추지 않습니다.
3. 시스템 간 연결(Decoupling)
- RabbitMQ는 서로 다른 애플리케이션이나 마이크로서비스 간의 연결을 간접적으로 수행합니다. 이를 통해서 서비스 간 결합도를 낮추고 유연한 시스템 설계가 가능해집니다.
4. 안정성 및 메시지 내구성
- RabbitMQ는 메시지를 디스크에 저장해 두거나, 장애 발생 시에도 데이터를 복구할 수 있는 메커니즘을 제공합니다.
- RabitMQ의 Qos(Quality of Service) 메시지 전달 보장은 아래와 같습니다.
- At Most Once: 메시지가 한 번만 전달될 수 있지만, 손실될 수 있습니다.
- At Least Once: 메시지가 최소 한 번은 반드시 전달되며, 중복될 가능성이 있습니다.
- Exactly Once: 추가적인 설정을 통해서 메시지가 정확히 한 번만 전달되도록 할 수 있습니다. (설정 꼭 필요!)
✔️중요 개념
다음은 중요 개념입니다. RabbitMq는 AMQP 기반이기 때문에 주요 기능이 AMQP를 따라갑니다.
Producer
- 요청을 보내는 주체로, 보내고자 하는 메시지를 큐에 바로 보내는 것이 아닌 exchange에 publish합니다.
- 큐에 직접적으로 접근하지 않습니다.
Exchange
- producer로부터 전달받은 메세지를 어떤 큐로 보낼지 결정하는 장소입니다. 아래 4가지 라우터 타입이 있습니다.
타입 | 설명 | 특징 |
Direct | 라우팅 키가 정확히 일치하는 큐에 메세지를 전송합니다. | 유니캐스트 |
Topic | 라우팅 키 패턴이 일치하는 큐에 메세지를 전송합니다. | 멀티캐스트 |
Headers | [key:value]로 이루어진 header 값을 기준으로 일치하는 Queue에 메세지를 전송합니다. 모든 Header가 일치할 때, 하나라도 일치할 때 메세지 전송 등의 옵션부여가 가능합니다. |
멀티캐스트 |
Fanout | 해당 Exchange에 등록된 모든 큐에 메세지를 전송합니다. | 브로드캐스트 |
Binding
- Exchange와 큐의 관계로, 보통 특정 exchange가 특정 큐를 binding 하도록 정의합니다. (브로드캐스트인 Fanout은 해당 되지 않습니다.)
Queue
- consumer가 메세지를 consume하기 전까지 보관하는 장소입니다.
Consumer
- producer로부터 메세지를 받아 처리하는 주체입니다.
💭Exchange 속성
Name
- Exchange 이름
Type
메시지 전달 방식
- Direct
- Fanut
- Topic
- Headers
Durability
브로커가 재시작 될 때 남아있는 지 여부
- Durable: 브로커가 재시작되어도 디스크에 저장되어 남아있습니다.
- Transient: 브로커가 재시작되면 사라집니다.
Auto-delete
- 마지막 Queue 연결이 해제되면 삭제
💭AMQP 수신 확인 모델
AMQP는 네트워크에 문제가 발생하거나 요청을 처리하지 못했을 경우를 대비해 2가지 수신 확인 모델을 가집니다.
- Consumer가 메세지를 받으면 브로커에게 통지하고, 브로커는 통지를 받았을 때만 Queue에서 해당 메시지를 삭제합니다.
- 브로커가 메시지를 전달하면 자동으로 삭제합니다.
💭 Exchange의 4가지 Type
앞에서 중요개념에 대해 설명할 때 보여드렸던 것처럼 Exchange는 4가지의 타입을 가집니다.
타입 | 설명 | 특징 |
Direct | 라우팅 키가 정확히 일치하는 큐에 메시지를 전송합니다. | 유니캐스트 |
Topic | 라우팅 키 패턴이 일치하는 큐에 메시지를 전송합니다. | 멀티캐스트 |
Headers | [key:value]로 이루어진 header 값을 기준으로 일치하는 Queue에 메시지를 전송합니다. 모든 Header가 일치할 때, 하나라도 일치할 때 메시지 전송 등의 옵션부여가 가능합니다. |
멀티캐스트 |
Fanout | 해당 Exchange에 등록된 모든 큐에 메시지를 전송합니다. | 브로드캐스트 |
다음은 각 Exchange 라우터 개념의 상세 내용입니다.
Direct Exchange (Unicast)
유니캐스트입니다. 1:1 관계로 라운드 로빈 방식(RP)을 사용하여 여러 consumer간 task를 분리합니다.
Exchange에 바인딩 된 Queue 중에서 메시지의 라우팅 키와 정확하게 매핑되어 있는 Queue로 메시지를 전달합니다.
Default Exchange가 Direct 타입입니다. RabbitMQ에서 생성되는 모든 Queue가 자동으로 바인딩 되며, 각 Queue의 이름이 라우팅 키로 지정됩니다.
Topic Exchange (Multicast)
Exchange에 바인딩 된 Queue 중에서 메시지의 라우팅 키가 패턴에 맞는 Queue에게 모두 메시지를 전달합니다.
Ex) Q1의 패턴: *.q1.*, Q2의 패턴: *.*.q2, lazy.#
라우팅 키가 example.q1.rabbit 일 경우 Q1에만 전달됩니다.
라우팅 키가 lazy.example.q2 일 경우 메시지가 Q2에 한 번만 전달 됩니다. -> 라우팅 패턴이 q2, lazy 총 2개가 일치하였지만 하나의 큐에는 항상 메시지가 한 번만 전달됩니다.
Headers Exchange (Multicast)
Topic Exchange와 유사하지만 라우팅을 위해서 Header를 쓴다는 점에서 차이가 있습니다.
라우팅 키 대신 메시지 헤더에 여러 속성들을 더해서 속성들이 매칭되는 큐에 메시지를 전달합니다.
Fanout exchange (Broadcast)
메시지의 라우팅 키를 무시하고 Excahnge에 바인딩 된 모든 Queue에 메시지를 전달합니다.
✔️SSE 채택 ?
저희에게 알림 필요한 곳은 현재는 2군데 입니다.
1. 회원가입 승인 시 회원가입 승인 알림 전달
2. 채팅 알림
현재 프로젝트에선 웹소켓을 통한 채팅을 진행하고 있습니다.
제 담당파트는 아니라서 채팅 구현애 대해선 해당 파트를 맡은 팀원분에게 여쭤보았습니다.
채팅 구현 팀원분 :
STOMP 관리를 RabbitMQ를 통해서 하고 있고,
채팅방에서 채팅 내역 채널 구독과 함께 STOMP 로 채팅 내역을 보내고 있습니다.
채팅시스템
- 채팅 내역은 STOMP와 WebSocket을 통해 클라이언트에 전달됩니다.
- RabbitMQ를 활용하여 채팅 내역을 관리합니다.
그렇다면 현재 구현된 채팅 시스템에서 WebSocket으로 알림을 전송할 수 있지 않을까 ?
채팅방의 경우 채팅방에 들어선 순간에 WebSocket에 연결됩니다.
알림의 경우에는 전체적인 모든 화면에서 알림을 비동기로 수신해야하기 때문에 다른 방식을 사용해야합니다.
그렇게 선택한 것이 SSE 입니다.
💭 구현 흐름
1. RabbitMQ에서 알림 관리
채팅 메시지 발행
- STOMP(WebSocket)로 클라이언트에 전달되는 메시지를 RabbitMQ의 기본 큐에 저장합니다.
알림용 큐 생성
- RabbitMQ에서 알림 전용 큐를 추가로 생성하여 메시지를 복사합니다.
- 알림 큐는 메인 화면 등 알림 수신을 위한 별도의 소비 경로로 사용합니다.
2. SSE를 통한 알림 전달
SSE 연결
- 클라이언트는 SSE를 통해 서버와 단방향 연결을 생성합니다.
- 서버에서 알림용 큐의 메시지를 소비하여 클라이언트로 전달합니다.
💭 SSE(Server-Sent Events)를 앱 알림으로 채택한 이유
- 단방향 실시간 데이터 푸시 적합성
- 알림은 서버에서 클라이언트로 전송되는 단방향 통신에 초점이 맞춰져 있습니다.
- SSE는 클라이언트에서 요청을 열어두고 서버가 이벤트를 전송할 수 있어, 단방향 데이터 전송에 적합합니다.
- HTTP 기반의 안정성
- SSE는 기존 HTTP 프로토콜 위에서 동작하므로 별도 프로토콜(WebSocket 등)을 설정할 필요가 없습니다.
- 방화벽, 프록시 등 네트워크 문제를 최소화할 수 있어 앱에서도 안정적으로 작동합니다.
- 자동 재연결 지원
- SSE는 연결이 끊어졌을 경우 클라이언트 측에서 자동으로 재연결을 시도합니다.
- 이는 앱에서 네트워크가 불안정한 환경에서도 안정적으로 알림을 받을 수 있게 해줍니다.
- 리소스 효율성
- WebSocket 대비 서버 및 네트워크 리소스 소비가 적습니다.
- 클라이언트와 서버 간 연결 관리가 간단하여 앱에서 유지보수와 성능 측면에서 유리합니다.
- RabbitMQ와의 연계 용이
- RabbitMQ의 알림용 큐에서 SSE로 데이터를 직접 전송함으로써 중간 로직이 단순화됩니다.
- RabbitMQ에서 생성된 알림 메시지를 비동기적으로 소비하여 SSE를 통해 클라이언트로 전달할 수 있습니다.
- 알림 시스템 구축에 적합
- 알림은 주로 즉시성과 신뢰성이 요구되며, SSE는 이를 충족하는 기술입니다.
- WebSocket처럼 양방향 통신이 필요하지 않은 알림 처리에 더 간결하고 효율적으로 동작합니다.
앞선 이유를 통해서 SSE를 알림 서비스에서 채택하게 되었습니다.
이후 포스팅에서 RabbitMQ와 SSE를 적용한 알림 서비스에 대한 개발 내용을 작성하도록 하겠습니다.
REPERENCE
[RabbitMQ] 기초 개념
AMQP를 구현한 오픈소스 메세지 브로커이다.producers에서 consumers로 메세지(요청)를 전달할 때 중간에서 브로커 역할을 한다.사용하는 케이스는 다음과 같다.요청을 많은 사용자에게 전달할 때요청
velog.io
[AMQP] AMQP란?
Advanced Message Queuing Protocol. MQ(Message Queuing)기반의 프로토콜이다.
velog.io
표준 메세징 프로토콜 정리 (AMQP, STOMP, MQTT)
AMQP는 메세지 지향 미들웨어 (MOM) 을 위한 표준 응용 계층 프로토콜입니다. 간단히 말하면, 메세지 통신을 위한 규약 스펙 입니다.플랫폼 종속적인 제품들 사이에서 서로 다른 이기종간에 메세지
velog.io
'개발 > 프로젝트' 카테고리의 다른 글
[단잠] SSE와 RabbitMQ를 이용한 알림 도입기 [2편] (0) | 2024.11.27 |
---|---|
[단잠] 트러블슈팅: SSE(Server-Sent-Events) 첫 연결 이후 바로 Connection closed가 되는 현상 (0) | 2024.11.26 |
[단잠] 대학교 기숙사 메이트 매칭 및 대학 생활 커뮤니티 서비스 회고 (2) | 2024.11.14 |
[FitTrip] 우리가 Setter를 지양했던 이유 (8) | 2024.11.12 |
[FitTrip] 캡스톤 프로젝트 / 함께하는 운동 커뮤니티 FitTrip 회고록 (8) | 2024.11.06 |