SSE 알림기능 feat.RxJS

산기슭곰발자·2024년 2월 16일

지난 게시글에 SSE 관련으로 글을 짤막하게 적었었다.
다만 개념적인 부분을 이해하기 어려운 부분이 있어 간단하게
정리를 해보려고한다(주관적)

통신은 Req, Res로 이루어지게 되어있다.
'요청'이 있다면 '응답' 이 응당 돌아오게 되어있다.

다만 'HTTP' 통신같은 경우에 1번의 Req(요청)이 주어지고 Res(응답)이 이루어지는 순간 FE와 BE의 통신은 종료가 된다. (1회성이라고 생각하면 될 것이다.)

위 사진과 같이 1회성의 요청과 응답으로 통신 경로가 차단되는 것이 아닌 요청을 한번 보내놓으면 계속해서 Res data를 보낼 수 있도록 경로를 열어두어 양방향 통신이 아닌 '단'방향 통신을 사용가능케 해주는 것이 SSE라고 생각하는게 조금더 편 할것이다.

(한번 수도꼭지를 열어놓고 새로운 물이있으면 계속 나오게 할 수 있는거라고 비슷하다고 생각하면 조금 편할까? 어느정도 상이한 개념이긴 하지만 이해에 도움이 된다.)

하지만 알림기능을 구현하고자 한다면 '양방향'통신의 대표격인 webSocket이 있을것이며 일정 term마다 일정 조건에 맞는 정보들을 보낼 수 있게하는 polling 또한 있을 것이다.

3초에 한번씩 정보를 보내라.. 등? 3000ms...

다만 그럼에도 불구하고 왜 SSE 를 사용하게 되었을까?

SSE를 사용하게된 이유

  1. 양방향 통신을 지속적으로 유지해야할 필요가 없었다. for example) 채팅 기능 등..
  2. 양방향 통신을 사용하거나 poliling방식을 사용하게되면 지속해서 해당 method가 실행이 되어야 하므로 리소스에 영향을 줄 수도 있다.
  3. sse로 구현하는것이 쉽다(유력후보다)

자 이제 통신을 어떤 방식으로 실행할 것인지에 대해서 결정을 짓게 되었으니 어떤 로직으로 서버에 새로운 정보가 업데이트가 되면 알림(즉 백엔드의 Res)을 FE에 보낼 것인지에 고민을 해보았다.

RxJS란?

RxJS는 Array와 Promise 성질을 모두 가진 이벤트를 다루는 새로운 객체타입 Observable를 제공하는 라이브러리입니다. 이 객체는 Array의 메소드(map, filter)와 같은 연산자를 제공하며 이를 통해 비동기 이벤트를 컬렉션 다루듯이 처리할 수 있게 만들어줍니다.

쉽다(어렵다)

간단하게 키워드로 따지고 보자면 Observable를 제공하는 라이브러리 라는것에 집중을 해보면 조금더 될 것이다.
나는 이 RxJS를 통하여 Obsevable(관찰가능한, 관찰자) 를 설정하여, 해당 관찰자가 지켜보는 서비스에서 변화가 발생할 때 SSE를 통한 단방향 통신을 이용하여 FE에 data를 전송해 줄 예정이다.

예제를 아주 간단한 그림으로 처리해볼 예정이다.

  • 우리는 택배 상하차 아르바이트를 한다. 물건을 분류해서 넣을 예정이다.

  • 우리는 각자의 필터에 거쳐진 물건들이 레일로 쏟아지고 있다. (update 되는 새로운 BE data들)

  • 조건에 맞는 물건들을 상주하고있는 직원(observer)들이 확인하여 물건을 가져온뒤 트럭(FE)에 보낸다.

즉 로직의 순서는 이렇게 될 것이다.

  1. 새로운 데이터가 BE에 업데이트
  2. 내부 로직으로 걸러지고 처리된 정보에 알맞는 조건이 걸린 정보들을 해당 로직을 observer가 확인
  3. 해당 로직을 구독(이용)하고있는 service에 해당 정보를 보내어 FE로 데이터를 전달(단방향 송신)

순으로 이루어 지게 될 것이다. RxJS에 대한 사전적인 정보는 구글에 너무나도 많다보니 구현되어있는 로직으로 설명을 할 것이다.

새로운 subject(주제)를 설정하며 새로운 객체로 지정한다.
observer는 해당 subject의 .asObservable(관찰가능한 사람으로써 라고 해석하면 이해하기 편할것이다.)
즉 우리는 해당 로직을통하여 새로운 subject와 새로운 관찰자(직원)을 채용했다.

해당 로직이 발동하면 pipe(택배를 예로들자면 레일로 물건을 올려준다.)

filter 및 map 은 내부처리 (조건)
가 일어난 이후에 return하여 정보를 반환한다.

( 첨부한 사진으로 따지자면, 레일에 물건이 올라오면 해당 조건으로 물건들이 걸러지고 보내질 것이다.)

여기까지 열심히 그렸던 그림에 대한 설명이 모두 되었다. 그러면 해당 Rxjs및 SSE를 구독하는 서비스는 어떻게 실제로 이루어 지는지는 사진으로 간략한 로직을 보여줄 예정이다.

    async createAlarm(userId: number, title: string, description: string) {
        // 알람을 여기서 저장하는 로직 작성
        const alarm = await this.alarmRepository.save({
            title,
            description,
            userId,
        });
        this.emitAlarmAddedEvent(userId, alarm.title, description);
    }
      // 댓글 추가 이벤트 발생 함수
    async emitAlarmAddedEvent(userId: number, title: string, description: string) {
        this.alarms$.next({ userId, title, description });
    }
    


(해당 subject를 구독하는 service에서 해당 createAlarm 함수를 통하여 함수를 만들며, 새로운 함수를 보내주게된다.)

그렇게된다면 alarmsRepository에 새로운 정보가 담길것이며 filter에 거쳐 맞는 userId를 찾아 알람을 보내주게된다.

간단하게 SSE와 RxJS로 알림기능을 구현해 보았다. 어렵게 구현해 보았다. 이럼으로써

새로운 정보가 업데이트되면 관찰자가 해당 데이터가 늘어난 것을 감지 필터링하여 해당 구독서비스의 알맞게 단방향 통신으로 그 정보를 FE로 쏘아주게된다.

profile
곰처럼 개발해보자.

0개의 댓글