본문 바로가기
리액트

[리액트] 실시간 알림 SSE(Server-Sent Events) 헤더에 토큰 담아 보내기

by 지 요니 2023. 6. 27.

SSE를 사용해서 실시간 알림을 구현하던 중에 토큰을 헤더에 담아 보내주어야했다.

  const Access_key = sessionStorage.getItem("Access_key");
  const Refresh_key = sessionStorage.getItem("Refresh_key");

 useEffect(() => {
           const eventSource = new EventSource(
      `https://moment-backend.shop/sse/chat/alarm/${userId}`,
      {
        withCredentials: true,
        headers: {
          ACCESS_KEY: `${Access_key}`,
          REFRESH_KEY: `${Refresh_key}`,
        },
      }
    );
    eventSource.addEventListener("chatAlarm-event", (event) => {
      const eventData = JSON.parse(event.data);
      console.log("Received event:", eventData);
    });

그래서 위와 같이 헤더에 토큰을 담아 보냈는데 서버에서 토큰을 받지 못하였다. 

 

EventSource는 Same-origin 정책과 CORS(Cross-Origin Resource Sharing)에 따라 동작하는데, Same-origin 정책은 웹 브라우저의 보안을 위해 도메인이나 프로토콜, 포트가 동일한 경우에만 리소스를 공유할 수 있도록 제한한다. 따라서 다른 도메인으로부터 리소스를 요청할 때는 CORS 정책을 따르게 되는데 브라우저에서 자동으로 처리되는 CORS 요청에는 미리 정의된 헤더만 허용되고, 따라서 EventSource의 헤더에 임의의 토큰을 추가하는 것은 지원되지 않는다고 한다.

 

 

해결방법: EventSource Polyfill 사용

EventSource에서 헤더에 토큰을 담아 보내기 위해서는 EventSource Polyfill을 사용해야 한다. EventSource Polyfill은  Fetch API를 사용하여 SSE 요청을 보낼 수 있도록 도와주게 된다. Fetch API는 브라우저의 보안 제약을 우회하고 추가적인 헤더를 포함한 요청을 보낼 수 있게 해주기 때문에 EventSource Polyfill을 사용하면 다음과 같이 헤더에 토큰을 담아 보낼 수 있다:

 

 const Access_key = sessionStorage.getItem("Access_key");
  const Refresh_key = sessionStorage.getItem("Refresh_key");

  const EventSource = EventSourcePolyfill;
  useEffect(() => {
    if (isLoggedIn) {
      try {
        const fetchSse = async () => {
          const eventSource = new EventSource(
            `https://moment-backend.shop/sse/chat/alarm/${userId}`,
            {
              headers: {
                "Content-Type": "text/event-stream",
                ACCESS_KEY: `${Access_key}`,
                REFRESH_KEY: `${Refresh_key}`,
              },
              withCredentials: true,
            }
          );
          eventSource.addEventListener("chatAlarm-event", (event) => {
            const eventData = JSON.parse(event.data);
            console.log("Received event:", eventData);
            setAlarmList((prevList) => [...prevList, eventData]);
          });
        };
        fetchSse();
      } catch (error) {
        throw error;
      }
    }
  }, [isLoggedIn]);

이를 통해 SSE 요청 시 토큰을 정상적으로 전달할 수 있게 되었다.

댓글