📕 0. SSE를 사용하여 실시간 알림 기능을 구현했던 이유
신한은행 X SSAFY 해커톤 대회를 진행할 때, 우리가 만든 어플에서 '부모'와 '아이'가 서로 상호작용할 때 실시간 푸시 알림을 보내야 하는 상황이 생겼는데, FCM(Firebase Cloud Messaging)나 웹소켓 방식을 사용하여 구현하기엔 절대적인 시간이 부족하기도 했고 내가 구현할 프로젝트에서는 실시간성과 단방향 통신만 갖추면 됐으므로 상대적으로 구현하기 쉬운 SSE(Server Sent Event)를 선택했음.
📕 1. SSE(Server Sent Events)란?
• SSE는 양방향인 웹소켓과 달리, Client가 Server로부터 데이터만 받을 수 있는 단방향 방식.
• 일반적인 HTTP 요청은 [요청-응답] 과정을 거치며 연결을 종료하지만, SSE는 클라이언트가 서버를 구독하면, 서버는 클라이언트가 요청하지 않아도 일방적으로 데이터를 보낼 수 있음.
• 양방향 채널인 경우 게임이나 SNS 메시지 등 양방향으로 실시간 업데이트해야 하는 경우에는 유리하지만,
클라이언트에서 서버로 데이터를 전송하지 않아도 되는 상황이라면 SSE와 같은 단방향 방식이 훨씬 가볍기 때문에 매력적인 선택지가 될 수 있음.
• SSE는 별도의 프로토콜을 사용하지 않고 HTTP 프로토콜만으로 사용할 수 있고 별도의 서버 구현이 필요하지 않기 때문에 용이.
• 접속에 문제가 있으면 자동으로 재연결 시도하지만, 클라이언트가 close해도 서버에서 감지하기 어려움.
📕 2. SSE(Server Sent Events) 구현 과정
1. [Client] SSE Subscribe 요청
• 이벤트 스트림을 구독하려면 자바스크립트에 내재된 EventSource 객체를 만들고 스트림의 URL을 전달해야 함.
• 쉽게 설명하면, 서버 측에 '나 여기서 너가 보내는 메시지 구독할게!'라고 알리는 느낌.
const eventSource = new EventSource(`이벤트 스트림을 구독할 URL을 이곳에 적어주세요`);
2. [Server] Subscription에 대한 응답
• 서버에서는 클라이언트의 구독을 받아들임.
3. [Server] 이벤트 전달
• 이후 서버는 원할 때마다 클라이언트에 데이터를 보낼 수 있음.
• 클라이언트에서는 addEvenetListner와 같은 코드를 통해 데이터가 서버로부터 넘어왔을 때의 동작을 설정할 수 있음.
useEffect(() => {
const eventSource = new EventSource(`이벤트 스트림을 구독할 URL을 이곳에 적어주세요`);
eventSource.addEventListener('sse', (event) => {
if (event.data === 'connect completed') {
console.log('SSE 연결 성공함');
return;
} else {
Swal.fire({
icon: 'success',
title: '새로운 알람이 도착했습니다!',
text: event.data.content,
confirmButtonColor: '#f8a70c',
});
console.log('sse통해 넘어오는 이벤트 데이터', event);
}
});
// 컴포넌트가 언마운트될 때 SSE 연결을 닫습니다.
return () => {
eventSource.close();
};
}, []);
내가 진행했던 프로젝트에서는 하단바를 공통 컴포넌트로 분리했는데,
모든 페이지에 하단바가 존재했기 때문에 하단바가 마운트 될 때마다 이벤트 스트림을 구독하는 방식으로 구현함.
1. 서버 측에 이벤트 스트림을 구독하고
2. 서버 측에서 넘어온 데이터가 'connect completed'면 넘어가고, 그 외의 데이터 ( 우리가 실제로 수신하길 바라는 알람 ) 이면 'SweetAlert2'의 'Swal.fire'을 활용하여 alert창을 띄워주는 형식으로 구현.
3. 그리고 하단바 컴포넌트가 언마운트 될 때 eventSource를 close 하는 방식을 사용했다.
📕 3. SSE(Server Sent Events) 구현 과정 중 발생한 문제점
처음 코드를 작성할 때 SSE 연결을 닫는 것을 고려하지 않았었다.
모든 페이지에 하단바가 있는 것을 이용해
하단바가 마운트 될 때마다 SSE 구독 이벤트를 서버에 전송시키는 로직을 구현했고
이로 인해 페이지를 이동할 때마다 서버에 SSE 구독을 신청하게 됐다.
내가 짠 코드에서는 이전 SSE 연결이 닫히지 않은 상태에서 새로운 SSE 구독을 계속 신청하고 있었기 때문에,
서버에 계속 부하를 주어서 실행되어야 할 다른 Axios 통신이 동작하지 않는 문제가 발생했었다.
해커톤 대회 마감 12시간도 남지 않았을 때 발생했던 오류라 애를 먹었었는데,
내가 1차적으로 찾은 해답은 페이지를 이동할 때마다 SSE 구독을 끊고,
다른 페이지로 이동했을 때 다시 구독 신청을 하는 방법으로 해결했다.
📕 4. 방식 개선하기 ( 추후 작성 할 부분 )
문제를 해결했고 시연할 때도 정상적으로 동작하긴 했지만
내가 해결한 방식처럼 방식처럼 페이지를 이동할 때마다 SSE 구독을 요청하는 것은
내가 생각하기에는 서버에 불필요한 부하를 주는 것 같아 비효율적이라는 생각이 들었다.
'📘React' 카테고리의 다른 글
[React] Swiper.js 라이브러리 사용시 vertical fade 중첩 오류 해결하기 (0) | 2024.06.17 |
---|---|
[React] 리액트에 대해 알아보자 (0) | 2023.10.30 |
[React] DatePicker를 이용해 달력 기능 구현하기. (0) | 2023.09.14 |
[React] 이미지 업로드 기능 구현하기 (0) | 2023.09.10 |
[React][WIL] 230717-0723 WIL(Weekly I Learned) (0) | 2023.07.23 |