알림 구현하기 1 : 알림을 구현하는 다양한 방법

이돈이면 official·2023년 8월 20일
4
post-thumbnail

작성자: 우아한테크코스 5기 여우

안드로이드 애플리케이션을 만들게 되니
웹 개발할 때는 생각해본 적 없었던 기능을 하나 추가할 수 있게 됐어요!

그건 바로 알림 ⏰!!
게시글에 누군가 따봉을 남기거나 댓글을 남기면
글 작성자의 전자기기에 알림이 띠롱하고 나가는
간단하지만 신기한 기능이에요.

뭔가 커다란 챌린지가 될 것 같은 이 기능을
이돈이면 백엔드 팀 넷 중 누가 담당해야 할지
아주 오랫동안 심사숙고하진 않고 사다리 타기를 돌렸더니 제가 맡게 되었습니다.

아무튼 이제 4차 스프린트 내내 알림과 관련해 학습한 내용을
여러 포스팅에 걸쳐 공유하도록 하겠습니다.

알림을 구현하는 다양한 방법

일반적인 클라이언트 ↔ 서버의 상호작용은
클라이언트에서 http 프로토콜을 통해 먼저 서버로 요청을 보내면
서버가 요청에 알맞은 응답을 보내주는 방식입니다.

그런데 알림은 대충 생각해보아도
클라이언트가 아니라 서버에서 먼저 알림 정보를 전송해서 클라이언트가 받는,
일반적인 방식과 반대 방향으로 동작해요!

먼저 이런 신기한 알림 전송을 가능하게 하는 다양한 방법으로 어떤 것들이 있는지 찾아보았습니다.


1. 짧은 폴링 / Short Polling

폴링(Polling)이란,
간단히 이야기하면 ‘어떤 값을 확인하거나 갱신하는 과정’을 의미합니다.

이 폴링을 크게 두 분류로 나누면
일정한 간격 또는 주기적으로 데이터를 확인하거나 갱신하는 정기적 폴링(Regular Polling),
그리고 특정 이벤트가 발생했을 때만 데이터를 확인하거나 갱신하는 이벤트 기반 폴링(Event-based Polling)으로 나눌 수 있고,

정기적 폴링의 대표적인 예시로
짧은 폴링 (Short Polling)이 해당해요!

Short Polling이란 클라이언트가 일정한 짧은 주기로 지속해서 요청을 보내고,
서버에서 줄 새로운 데이터가 없는 경우 빈 응답을, 있는 경우 데이터를 담은 응답을 보내주는 방식입니다.

문제는 위 설명과 그림에서처럼
서버가 줄 데이터가 없음에도 계속 요청과 응답 작업을 반복하기 때문에
불필요한 트래픽이 많이 발생한다는 것,

그리고 이벤트가 발생했을 때 알려주는 것이 아니라
단순히 일정 주기를 두고 요청과 응답이 오가기 때문에
이벤트 발생을 실시간으로 반영하지 못한다는 단점이 있습니다.

좀 똥 같군요!
이벤트 기반 폴링을 쓴다면 더 나을까요?


2. 긴 폴링 / Long Polling

긴 폴링? 그거 그냥 요청 1초에 한 번 할거 1분에 한 번 하는 거 아니냐 크크루삥뽕

아닙니다.

Short Polling은 요청을 보내면 즉시 응답해야 하기 때문에
서버에서 줄 데이터가 없으면 빈 데이터를 보내야 했던 반면,

Long Polling 방식에서는
서버에서 클라이언트에게 줄 데이터가 없는 경우
곧바로 응답하지 않고 커넥션을 계속 유지하며,
서버에서 줄 데이터가 생겼을 때야 응답을 보내는 방식입니다.

짧은 폴링 방식에 비해 불필요한 요청과 응답을 반복하지 않아도 되고,
서버에게 이벤트가 발생하면 바로 응답을 주기 때문에
짧은 폴링에 비해 이벤트의 실시간성이 잘 보장된다는 장점이 있어요!

하지만 긴 폴링 방식도 단점은 있습니다.
대표적으로 클라이언트와 연결을 계속 유지하는 동안
서버 자원을 지속해서 소모하고 있게 된다는 단점이 있어요!

예를 들어 클라이언트가 스프링 부트로 만든 애플리케이션과 연결할 때
대부분 데이터베이스 커넥션 풀(DBCP)를 할당해주는데,
100만 명의 회원에게 Long Polling 방식으로 알림을 제공하고자 한다면
100만 개의 커넥션 풀을 소모하게 되는 것입니다.

또 다수의 서버를 가동하면서 부하 분산을 하는 구조라면
Long Polling을 위해 특정 서버와 연결되어있는 동안
발생할 수 있는 문제점들도 생각해볼 수 있겠네욥!

그리고 결국 클라이언트에서 먼저 요청을 보내야만 데이터를 받을 수 있다는 점에서도
약간의 아쉬움이 있습니다.
클라이언트의 요청이 없어도 서버에서 먼저 데이터를 발송하는 방법은 없을까요?


3. 웹 소켓 / Web Socket

HTTP와는 별도의 프로토콜인 웹 소켓(Web Socket)은
클라이언트와 서버가 한 번 연결을 맺고 나면
그 연결이 쭉 유지되며, 이 연결을 통해 클라이언트와 서버가 양방향으로 통신할 수 있게 해줘요!

웹 소켓은 서버에서 이벤트가 발생할 경우
서버에서 먼저 데이터를 발송하는 서버 푸시(Server Push)가 가능하므로,
실시간 알림 기능을 구현하기에 매우 적합한 프로토콜입니다.

물론 클라이언트와의 연결을 계속 유지하고 있다는 점에서,
Long Polling 방식이 가지고 있는 서버 자원 소모 문제점을 똑같이 가지고 있어요.

그리고 HTTP와는 다른 새로운 형태의 프로토콜이기 때문에
웹 소켓에 대한 지식을 공부하고 적용하는 학습곡선이 필요하다는 단점 아닌 단점도 존재합니다.

근데 사실 ‘알림’은 서버에서 클라이언트로의 전송만이 필요하지
꼭 ‘양방향 통신’ 일 필요는 없는데요,
그런 점에서 양방향 통신인 웹 소켓을 알림 기능을 위해 도입하기에는
다소 무거울 수 있다는 생각이 듭니다.

데이터를 서버에서 클라이언트로 단방향으로만 전송하는 방법은 없는 걸까요?


4. 서버 전송 이벤트 / Server Sent Events

흔히 줄여서 SSE라고 부르는, 서버 전송 이벤트(Server Sent Events)는
클라이언트에서 서버로 요청을 보내면 일정 시간 동안 연결을 유지하면서
서버에서 이벤트가 발생했을 때 실시간으로 클라이언트에게 데이터를 넘겨주는
서버 → 클라이언트로의 실시간 단방향 통신 방법입니다.

엥 아까 Long Polling 방식이랑 뭐가 다르노 임마!

Long Polling 또한 클라이언트와 서버가 연결을 유지한다는 점에서 SSE와 같아 보이지만,

Long Polling은 서버에서 이벤트가 발생해 데이터를 응답하면
연결이 끊어지고 다시 연결해야 하지만

SSE는 서버에서 데이터를 응답하든 말든
일정 시간 동안은 연결을 끊지 않고 계속 유지한다는 차이가 있습니다.

그래서 서버에서 이벤트가 자주 일어나고,
서버에서 클라이언트로 정보를 자주 주어야 할 때에는
Long Polling을 쓰기에 좀 부담스럽죠!
아무래도 데이터를 한 번 받을 때마다 연결을 새로 해야 하니까요.

반면 SSE를 사용하면
일정 시간 동안 커넥션 연결을 쭉 해주는 것이 보장되어 있으므로,
서버에서 클라이언트로 데이터나 알림을 마음껏 줄 수 있다는 장점이 있습니다.

그리고 웹 소켓처럼 별도의 프로토콜을 사용하는 것이 아니라
우리에게 익숙한 HTTP 프로토콜을 사용한다는 점,

Spring Boot를 사용해 웹 애플리케이션을 만드는 경우
별도의 라이브러리를 사용하지 않아도 스프링에서 SSE를 지원하는 도구를 제공해준다는 점 등

팀 프로젝트에서 알림 발송 기능을 구현하기에는 SSE가 가장 적합해 보입니다.

물론 온오프라인 게임이나 채팅 등
클라이언트와 서버가 양방향으로 상호작용하는 것이 중요한 기능의 경우에는
단방향인 SSE보다 양방향인 웹 소켓 등이 더 적합할 수 있어요!

프로젝트에 적합한 방식을 찾아 적용하면 될 것 같습니다. 😊


아무튼 이렇게 알림 기능을 구현하기 위해 사용할 수 있는 다양한 후보군을 학습했습니다.
이돈이면 팀에서는 위 네 방식 중 특정한 하나를 딱 정하지 않고,
FCM(Firebase Cloud Messaging)이라는 도구를 사용해 알림 기능을 구현했어요!

FCM이란 무엇이고, 구체적으로 프로젝트에 어떻게 적용했는지는
별도의 포스팅으로 남기겠습니다. 😊👍🏻

profile
이돈이면 기술 블로그입니다 🫶🏻

2개의 댓글

comment-user-thumbnail
2023년 8월 20일

그림이랑 내용이 잘 정리되어 있어서 이해가 쉬웠어요. FCM에 대한 글도 기대가 됩니다!

답글 달기
comment-user-thumbnail
2024년 7월 12일

너무 감사합니다.
구형 폴링 시스템을 푸시 시스템으로 확장하기 위해서 자료 조사 중이었는데 많은 도움이 되었습니다 ㅎ

답글 달기