[카카오 프로젝트] RabbitMQ 구현

paduck·2023년 4월 29일
0

프로젝트

목록 보기
11/11

개요

일단 웃긴 점은 나의 지식이 부족했다는 점이다...

느낀 점

당연하게도, 메시지 브로커를 통해 클라이언트로 데이터를 전달할 수 있을 줄 알았지만 그럴 수가 없었다.
결국 서버의 데이터를 클라이언트로 전달하기 위해 메시지 처리 방식 외에 추가적인 기술 도입이 필요했다.
이 점에서 앞선 글에서 언급했던 것처럼 WebSocket을 구현하고 싶었지만, 개발 일정도 많이 밀려있었고 가장 중요한 건 나 혼자서 로직을 조금 작성한다고 돌아가지 않는다는 점이었다.
학교 재학 중에 Node를 통해 잠깐 Socket.io를 만졌었는데, 그 때는 서버에서도 클라이언트에서 소켓 상 메시지를 전달하는 로직, 각 계층 간에 데이터를 보여주고 출력하는 로직 등 다양한 부분을 작성했어야 한다고 생각하고 있었는데 협업하는 과정에서 나 혼자 이 코드를 작성해 나간다면 차후 수정이나 추가 기능 구현에 있어서 많은 방해가 될 것 같았다.
그래서 그나마 팀원과의 충돌이 적은 SSE를 선택하게 되었다.
또, 단순 알림만 처리하는 목적이 크기 때문에 RabbitMQ를 선택하기는 했는데, 막상 개발 과정에 들어가다보니 어떤 식으로 작동하고, 어느 부분에서 에러가 났는지 로그를 보고, 모니터링을 해야 할 것 같다는 생각이 계속 들었다. 그래서 일단은 로그 파일을 찍게 설정을 추가하기는 했는데 그렇다 보니, 이럴꺼면 카프카를 써서 로깅도 처리해서 모니터링까지 공부해볼껄 이라는 생각이 조금씩 들었다...
더군다나, 여러 큐 패턴을 사용해보는 장점이 있을 줄 알았는데, 이미 필요한 기능을 개발하고 알림에서조차 문제 없이 개발이 끝나지 않으니까 기능에 대한 확장 또한 쉽사리 결정하기가 어려웠다.

그래서 어쨋든, 결론은 알림을 구현했고 참 다사다난했다는 점이다.
전체적인 코드나 설정, 폴더 구조 등에 대한 내용은 Github에 다 있으니, 이건 링크로 첨부하고 뭔가 하면서 느꼈던 부분이나 트러블, 플로우에 따라 정리하려고 한다.

서비스 흐름

코드 작성 흐름

  1. 최초 로그인시 DB에 요청해 구독 목록을 가져와 EventSource로 알림을 기다린다.
  2. 구독 엔드포인트로 사용자가 요청을 한다
    이 과정에서 큐가 생성되고, DB 구독 테이블에 저장을 한다(재로그인 시 등의 상황에서 알림 요청을 보내기 위해)

  3. 구독 취소 엔드포인트로 사용자가 요청을 한다
    이 과정에서 큐가 삭제되고, DB 구독 테이블에서 데이터가 지워진다
  4. 멘토의 액션에 따라 메시지가 큐로 발행된다

** 동일한 로직으로 입장 시간을 기다리는 알림에도 적용된다.

멘토

멘토의 역할은 발행이 전부다
방을 만들면 멘토 기준으로 구독한 사용자와 멘토의 이름으로 된 큐에 상황에 맞는(시작 10분 전, 방 생성)에 대한 텍스트를 큐로 보낸다

멘티

멘티는 구독과 브라우저의 EventSource 객체 생성이 주다
확인되는 멘토에 대한 구독, 구독 취소를 통해 큐를 생성하고 메시지를 기다릴 수 있는 EventSource URL 요청을 보낸다.

혹은, 일정에 참여하게 되면 해당 일정 시간과, 방 이름으로 더 세분화된 큐를 생성하고 메시지를 기다릴 수 있게 요청을 보낸다.

이 부분에서 중요한 점은 브라우저의 한계이다.
EventSource를 통해 요청을 하고 있는데, 서비스에 적용해보니 응답을 기다리는 시간은 1분이고, 응답이 실패하면 자동적으로 재요청을 보내는데 내가 설계할 수 있는 부분은 이 재요청 간격 뿐이었다. 초기에는 요청을 줄이기 위해(서버 부하 줄이기) 간격 시간을 주었지만, 냉정하게 봤을 때 이 간격에 걸렸을 때 메시지 발행이 이루어진다면 알림을 받을 수 없기 때문에 서부 부하를 감안하고, 간격 없이 계속 재요청을 보내게 로직을 구현했다.

이건 어쩔 수 없는 문제이고, 추후 접속 시에는 WebSocket으로 실시간 알림, 로그아웃 시에는 그에 따른 알림 처리 방안을 고려해야지 싶었다. 추가적으로는 다양한 상황에 따른 알림 처리가 필요할 것 같고, 사용자가 많아져 많은 데이터를 처리할 때 쯤에는 메시지 큐 기술 자체를 Kafka나 다른 안정적인 서비스로 변경해야 할 필요성이 있을 것 같다.

개발 중 이슈

백엔드

  1. 서버와 클라이언트 에서의 검증
    클라이언트는 사용자가 보려면 충분히 볼 수 있는 코드이다 보니, 이 부분에서 어떤 비즈니스적인 로직이 들어가면 문제가 될 수 있다고 한다. 그렇다 보니, 최대한의 로직을 서버에서 처리를 하고 클라이언트에서는 단순히 응답 값에 따른 액션을 주면 되는 형식으로 구현이 되게 수정하는 부분이 나름 시간을 많이 잡아먹었다.
    -> 일정 부분은 서버로 넘겼으나, 이 부분에도 적지 않은 시간이 소요될 것 같아 차후에는 설계를 진행할 때 조금 더 확실하게 정리하고 들어가는게 맞는 것 같다.

  2. 메시지 발행
    기본적으로는 사용자의 이벤트에 맞춰서 발행도 이루어지게 하면 됐다. 멘토에 대한 알림은 이렇게 처리하면 충분했는데(방을 만들 때 등), 특정 시간에 신청을 하는 것에 대한 알림을 보내줄 때는 문제가 된다는 걸 개발하면서 깨달았다. 만약, 이때 메시지를 발행시키려면 결국 클라이언트에서도 현재 시간과 시작 시간을 비교해야 하는 로직이 필요하다는게 문제였다.
    -> 신청의 경우에만 서버에서 구현했던 스케쥴링 로직에 publish 관련 코드를 옮겨서 해결했다.

  3. RabbitMQ 사용
    사실 이 부분에는 많은 경험이 필요할 것 같다. 일단은 생각한 걸 찾아보고, 코드로 구현하는데 거의 급급해서 리펙토링할 부분이 매우 많다고 생각하는데... 서비스 자체는 돌아가고 있으니까 시간을 가지고 천천히 공부해봐야 할 것 같다.
    가장 스트레스 받았던 부분은 거의 모든 상황에 대해 예외 처리 및 로깅을 해야 개발하면서 발생할 수 있는 문제들에 대해서 확인을 할 수 있었던 점이고 일반적인 어노테이션이 아니라 동적으로 무언가를 처리해야 해서, 조금 더 low한 코드들이 필요했다. 그래서 참고할만한 자료가 조금 적었다는 점..?


    -> 이럴 때 흔히 말하는 코드를 뜯어봐야 한다고 많이 느낀 것 같다. 예를 들면, 현재 오류가 발생하면 컨테이너가 대략 3번 정도 재생성 되면서 요청과 응답을 반복하는데 나는 이런 부분을 전혀 명시한 기억이 없었다. 그래서 아마 MQ 기술 자체에 Default 설정으로 컨테이너 오류 부분에 해당 로직이 있는 것 같은데, 실질적으로 공부할 기회나 사용할 기회가 주어진다면 이런 부분을 하나씩 뜯어봐야 할 것 같다.
    -> 추가적으로 지금 너무 무지성(?)으로 log를 찍고 있는데, 이게 코드 이해부터가 난관이었고 특히나 서버에서만 작동하는 로직이다 보니, 어떠한 TestCase를 만들면서 코드를 구현해야할지 전혀 감이 잡히지가 않아서...만들고 사용하면서 필요할 때만 log를 찍다보니 굉장히 지저분했는데, 차후에는 레퍼런스를 좀 더 많이 찾아보고 억지로라도 TDD로 작성하려 노력해봐야겠다.

프론트엔드

  1. EventSource에 대한 문제였는데 이는 위에 서술했으니 생략
    -> 결국, 다른 기술을 사용해서 해결하는 방법 밖에는 없는 것 같다

  2. useEffect, Rendering 등 기술적인 부분
    react에 대한 이해도가 아직 부족하다보니, 컴포넌트를 특정 상황에서 원할 때 랜더링 하게 만들고 바로 반영할 수 있게 state를 쓰는 부분이 어려웠다.
    특히, 알림/알림 취소 상태 값과 알림을 구독하는 부분에서 변경점이 생겼을 때 리랜더링 하는 부분이 문제였다. 우선은 구현이 먼지기 때문에 새로고침 되게끔 코드를 만든 상황이다
    -> 이 부분은 서버의 크기를 키워서 계속 API 요청을 날리는 방법이 가장 쉬운 방법일 것 같다.
    -> 혹은 각 컴포넌트 별로 API를 날려서 상태값으로 저장한 뒤, 그걸 바로 보여주면 간편하게 해결 될 것 같다.

profile
끈질기게 들러붙기

0개의 댓글