항해99 | [실전프로젝트] Redis Stream을 활용한 알림 기능 구현기

docu·2023년 5월 15일
0

항해99

목록 보기
11/15

기능 구현에 앞서

프로젝트에서 구현하고자 했던 알림 기능은 웹푸시 알림이 아닌 쪽지처럼 쌓이는 형태의 알림이었다. 웹푸시 알림에 대한 정보는 많았지만 이런 알림은 찾으면서도 자료가 많이 없어서 많이 힘들었다. 검색해보면서 pub/sub, kafka, socket, stream 등 알림에 쓰일만한 기능 키워드들을 우선 탐색해보았다.

redis pubsub
'pub/sub으로 알림 기능을 구현할 수 있다'까지 설명된 블로그는 많았으나 사실 실제 코드로 나타난 자료가 없어서 잘 와닿지 않았다. pub/sub + socket 조합은 알림을 전달하는 방식인 것 같고 저장되는 방식은 아니라고 이해했다. 전송한 메시지의 내용을 저장하지 않고, 클라이언트에게 전달한 후 이를 바로 삭제한다는 점이 쌓이는 형태의 알림창인 우리의 기능과는 다르다고 생각했다.

kafka
아파치 카프카는 대규모 분산 시스템에서 데이터를 처리하는 데 특화된 기술이라고 한다. 큰 규모의 서비스에서 쓰이는 것 같았고 이미 이메일 인증을 레디스로 하고 있어서 레디스로 마음이 더 기울게 됐다.

redis stream
http://redisgate.kr/redis/command/streams.php
이 자료를 처음보고 소비자 그룹의 개념과 xreadgroup, xpending 커맨드를 봤을때 이걸로 알림 기능이 구현 가능할 것 같다는 생각이 들었다.
stream + SSE/폴링 https://velog.io/@saeeng/SSE-Server-Sent-Event 방식으로 알림 기능을 구현해보고자 했다.

내가 필요한 기능이 구현된 자료가 거의 없었고 한 기능에만 오래 매달릴 수 없는 상황이여서 사실 마음에 제일 끌리는것에 부딪혀보는게 최선이었다.

구현 방법 ✅

createStream : 회원가입 시, id 별로 stream key 생성 (코드) ☛ 회원가입api, 소셜로그인 strategy에서 import해서 사용
saveToStream : 알림 저장 시, 알림 받을 회원의 스트림에 생성시간 타임스탬프가 id인 엔트리를 추가하고 XREADGROUP 호출하여 consumer(알림받을 회원)에게 할당(코드)☛ 아트그램/전시 좋아요, 댓글, 답글 작성하는 메서드에서 import해서 사용
confirmNoti : 알림 조회시, XACK 처리 (코드) ☛ PATCH /notification API
getNotiList : 알림 목록 제공 시, XPENDING으로 읽지 않은 알림과 읽은 알림을 구분한 데이터를 XREVRANGE로 최신순으로 제공(코드) ☛ GET /notification API

도전

- stream x command 관련 오류

우선 터미널로 기본적인 스트림 커맨드를 연습해봤고 vscode로 redis를 연결하는 것부터 정말 어려웠다. 원하는대로 쳤는데 stream 명령어를 인식하지 못하는 것 같았다. stream은 redis 5.0이상에서 지원되었기 때문에 ioredis를 추가적으로 사용했고 redis-server의 버전도 최신버전으로 설치해서 문제를 해결할 수 있었다.

- 참고자료의 부족

웹푸시 형식의 알림 기능에 대한 자료는 많았지만 프로젝트에서 의도한 형식의 알림기능은 참고할만한 자료가 정말 없었다. stream에 대한 자료는 정말 없었고 있어도 'pub/sub을 알림기능에 쓸수있다~' 정도의 자료만 있었고 코드구현한 예시를 참고하기 어려워서 며칠동안 머리를 싸맸던 기억이 있다. 커맨드 하나하나를 어떻게 쓸지 생각하고 고민하는게 도전이었다.

아쉬운 점

- 실시간 알림을 구현하지 못한 것

SSE 혹은 polling 방식으로 실시간으로 알림을 받아보는 것까지가 나의 목표였는데 굳이 실시간 알림까지는 필요없을 것 같고 마이페이지에 들어갔을때 확인되는 정도이면 될 것 같다는 의견이 다수여서 구현해보지 못한게 조금 아쉬웠다. sse까지 적용됐어야 redis stream의 실시간성이나 빠른 조회가 가능하다는 장점을 더 살려볼 수 있었을 것 같다.

- 알림이 많이 쌓였을 시의 삭제 방식에 대한 고민이 끝나지 않았다

결국 사용자가 늘어나고 알림을 무수히 쌓이게 될것이다. 무한하게 알림을 다 저장할 수는 없다. 이때 어떤 기준으로 알림을 삭제할까? 예를들어 1인당 600개까지만 알림이 저장되도록 혹은 일자를 기준으로 3개월 정도의 알림 데이터만 저장한다? 지금 전시나 아트그램 게시글도 soft delete방식을 채택하는데 이런 데이터도 결국 언젠간 삭제가 돼야할텐데 어떤 기준으로 삭제를 진행해야하는지에 대한 고민이 아직 있다.

- 알림 백업 필요성

사실 레디스 자체에서 디스크에 저장하는 방식이 기본적으로 있어서 내가 서버를 껐다 켜도 자료가 그대로 남아있어서 나는 알림 백업의 필요성에 대해서 크게 인지를 하지 못했다. 그치만 기술매니저님께서 백업의 필요성을 많이 강조하셨고 스케줄러를 사용해서 알림을 백업할 수 있다는 사실까지 알게 되었다.

- 알림창 무한스크롤

사실 메모리 기반의 데이터베이스라 그런지 조회해오는 속도가 느리지 않아서 그런가 무한스크롤의 필요성을 딱히 느끼지는 못하긴 했다. sequelize는 limit,offset이 있지만 stream은 직접 갯수를 지정해서 가져오는 방식 이외에는 limit, offset처럼 구현할 방법이 떠오르지 않았다. 소셜로그인 마무리 작업에 시간이 없어서 여기까지는 있으면 좋겠다까지만 생각하고 깊게 고민해보지 못했지만 다음에 비슷한 기능을 구현하게 된다면 꼭 염두해둬야할 부분일 것 같아 기록해본다.

느낀 점

- 뭐든 도전해볼 수 있을 것 같은 용기

그래도 혼자 redis stream으로 알림을 구현해보면서 자료들을 그대로 옮기거나 하는게 아니라 내가 직접 하나하나 만들어가는 경험들을 해보면서 많이 성장했고 내가 직접 하나의 기능을 처음부터 하나하나 완성해나가본 경험이 정말 소중했던 것 같다. 아직 반쪽짜리 기능인 것 같아 아쉬움이 있지만 그래도 앞으로 다른 기능 구현을 함에 있어서 자료가 없어도 뭐든 도전해볼 수 있을 것 같은 용기가 생긴 것 같다.

- 여전히 의문은 있다.

redis stream을 사용한게 최선의 선택이었을까? 그냥 mysql로 구현을 했다면? 사실 redis에 stream 형식으로 저장하니 id가 key값이 되어 저장이돼서 훨씬더 자료가 보기 좋고 조회하기 쉽게 저장이 된 것같고 만약에 notification이라는 mysql 테이블에 알림을 무수히 쌓았다면 입력 데이터가 많아질수록 조회 속도에서 차이가 있지 않을까라는 생각이 있다. 그치만 mysql에 저장한다면 백업의 필요성에 대해서는 고려하지 않아도 되고 무한스크롤 또한 쉽게 구현했을 수 있었을 것 같다.

배운 점

- redis의 stream 커맨드 사용법
- 알림 기능은 정말 고려할 부분이 많은 기능이구나

완성본

0개의 댓글