Polling과 Redis

Daniel_Yang·2024년 5월 19일
0

Redis

  • key 수신이벤트
    • Redis에는 키 및 값의 변경 사항을 실시간으로 수신할 수 있는 Pub/Sub 기능을 제공

      Redis EVENT NOTIFICATION

  • RedisMsgListener

    • onMessage에서 만료되었을 때 메시지
  • 설정

  session:
    store-type: redis
    redis:
      flush-mode: immediate
      namespace: @@@@@@ #같은 redis를 참조하는 컨테이너 존재시 변경
      configure-action: notify-keyspace-events #key이벤트 수신 알림 설정

Spring session data redis 서비스 적용 후기

  • 만료된 key에 대한 redis keyspace 알림 수신

[SpringBoot] Redis Key Expired Event Notification

Redis Keyspace Notifications에 대해 알아보자

환상(장)의 (ElastiCache + Spring Session + Spring Security) Memory Leak

EventSource

위의 SSE의 장점에서 보듯이 SSE는 구현이 아주 간편합니다. 클라이언트는 서버로부터 스트림을 받아 EventSource 객체를 통해 서버가 푸시하는 데이터를 받아 처리하기만 하면 됩니다.

먼저 클라이언트 측의 코드입니다.

var es = new EventSource(stream_url);

es.onmessage = function (event) {
    // 이벤트 설정이안된 기본 데이터 처리
};
es.addEventListener('myevent', function(e) {
    // 'myevent' 이벤트의 데이터 처리
}, false);

EventSource 객체의 속성은 다음과 같습니다.

  • onmessage 기본 메시지가 왔을 때 호출
  • onopen 접속이 맺어졌을 때 호출
  • onerror 오류 발생 시 호출

EventSource의 addEventListener()를 사용하면 위 3개의 이벤트뿐만 아니라 따로 지정된 이벤트의 데이터도 받아 처리할 수 있습니다.

Promise

프로미스는 비동기 작업을 조금 더 편하게 처리 할 수 있도록 ES6 에 도입된 기능입니다. 이전에는 비동기 작업을 처리 할 때에는 콜백 함수로 처리를 해야 했었는데요, 콜백 함수로 처리를 하게 된다면 비동기 작업이 많아질 경우 코드가 쉽게 난잡해지게 되었습니다.

  • resolve, reject
    • 프로미스의 resolvereject는 비동기 작업의 처리과정에서 성공/실패를 구분하는 방법이다.

    • 성공 할 때에는 resolve 를 호출해주면 되고, 실패할 때에는 reject 를 호출해주면 됩니다.

    • resolve 를 호출 할 때 특정 값을 파라미터로 넣어주면, 이 값을 작업이 끝나고 나서 사용 할 수 있습니다. 작업이 끝나고 나서 또 다른 작업을 해야 할 때에는 Promise 뒤에 .then(...) 을 붙여서 사용하면 됩니다.

      const myPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(1);
        }, 1000);
      });
      
      myPromise.then(n => {
        console.log(n);
      });
      
      const myPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
          reject(new Error());
        }, 1000);
      });
      
      myPromise
        .then(n => {
          console.log(n);
        })
        .catch(error => {
          console.log(error);
        });
      			```

EventListener

eventTarget.addEventListener('eventType', function)

이벤트를실행할타겟.addEventListener('이벤트타입', 실행할함수)

  • eventTarget(이벤트 타겟)은 해당 이벤트를 적용할 DOM을 가져와 준다.
  • eventType(이벤트 타입)은 말 그대로 어떤 타입의 이벤트를 적용할 것인지 써주면 된다. 대표적으로 click DOMContentLoadscroll submit등등이 있다. 타입을 써줄 때는 따옴표를 잊지 말고 감싸줘야 한다.
    • click: 요소를 클릭하면 이벤트 발생.
    • DOMContentLoaded: 페이지가 새로 로딩될 때마다 이벤트 발생.
    • scroll: 스크롤을 하면 이벤트 발생.
    • submit: 양식을 전송하면 이벤트 발생. (ex: input type이 submit일 때 submit 버튼을 누르는 것과 같음)
  • function(실행할함수)에는 이벤트를 발생시켰을 시 실행할 동작을 가져와 준다.

SSE 통신 방법

  • 백엔드
    • WebFlux
    • SseEmitter

SseEmitter

  • Spring에서 SSE 프로토콜을 지원하기 위한 클래스이므로 ⇒ 실시간으로 업데이트되는 데이터나 알림과 같은 이벤트를 클라이언트에게 전달 가능
  • 비동기적으로 이벤트 전송 가능 ⇒ 서버에서 이벤트가 발생하면 해당 이벤트를 즉시 클라이언트에게 전송 가능
  • 클라이언트의 재시도 및 연결 관리
    • SseEmitter는 클라이언트의 연결 상태를 관리하고, 클라이언트와의 연결이 끊어지는 경우에도 재시도 등의 처리를 지원
    • 클라이언트가 알림을 구독한 후 연결이 끊어지면, 클라이언트는 다시 연결을 시도하고 이전에 미수신한 이벤트를 잃지 않도록 처리 가능
  • 확장성
    • SseEmitter는 여러 클라이언트와 동시에 통신이 가능 ( 즉, 동일한 알림을 여러 클라이언트에게 전송 가능 )
    • 다수의 클라이언트에게 알림을 전달해야하는 경우에 유용

[Project] SSE(Servcer-Sent-Events)로 실시간 알림 기능 구현하기 !

주의

1. SseEmitter 생성

  • emitter를 생성할 때는 타임아웃을 설정해줄 수 있는데, 기본 값은 30초인 것으로 알고 있다.

2. Emitter handling

  • onTimeout: emitter가 timeout이 되었을 때,
  • onError: 에러가 났을 때
  • onCompletion: onCompletion은 완료된 emitter에 대한 처리인데, emitter 생성 후 저장해줬던 값을 삭제한다.

SseEmitter가 만료되면 클라이언트가 재연결 요청을 보내는데, 그때마다 새로운 emitter를 생성하게 되니 만료된 값은 삭제 처리를 하는 것이다. (emitter를 저장할 때 Map을 사용하고, 키가 동일하다면 굳이 삭제해줄 필요는 없겠지만 명시적으로는 괜찮다고 본다.)

3. dummy data 전송

SseEmitter 생성 이후 어떠한 데이터도 전송하지 않으면 타임아웃 되면서 503에러를 뱉는다고 한다.

구현 전 SSE에 대해 찾아보는 과정에서 주의 사항에 대해 미리 확인했었기 때문에 이 부분을 직접 겪진 않았다.

send() 메서드에서 예외처리하는 IllegalStateException은 만료된 emitter로 send() 메서드를 호출하면 발생하는 에러이다. (내부 코드에서 확인 가능) 에러 발생 시 해당 emitter를 지워준다.

(+) 추가로 이벤트를 전송할 때 .name("event-name")으로 이벤트 이름을 지정할 수 있고, 클라이언트에서는 지정된 이름의 알림을 받을 수 있다.

💡 subscribe() 와 send() 의 차이

  • subscribe() 메서드는 클라이언트와의 SSE 스트림 통신을 유지하면서 연결을 생성하고 유지⠀
  • send() 메서드는 알림을 생성하고 해당 알림을 수신하는 모든 클라이언트에게 전송⠀👉 subscribe() 메서드는 클라이언트의 요청에 응답하여 SSE 스트림을 제공하고, send() 메서드는 서버에서 알림을 생성하여 클라이언트에게 전송하는 역할

0개의 댓글