sessionStorage에 데이터를 탭에서도 공유할 수 있는 방법 찾기 🔍

·2024년 11월 1일

더취페이 프로젝트

목록 보기
12/37

유저 기능이 다 끝난 줄 알고 다른 기능을 구현하던 도중에 브라우저 탭 간에 데이터 공유가 되질 않고 있어서 자동로그인 API가 호출되고 있다는 걸 알게 되었다. 탭 간에 데이터를 공유할 필요가 있을까? 하는 의견이 있었지만, 해당 부분을 신경쓰지 않는다면 자동로그인을 선택해서 로그인한 사용자는 2개 이상에 탭으로 접속하면 access가 계속 만료되게 되는 불필요한 상황이 발생할 것 같아서 탭 간에 데이터를 공유하도록 해주기로 했다.

sessionCookie가 같은 브라우저 탭끼리는 공유된다고 해서 sessionStorage도 당연히 탭끼리는 공유된다고 생각했었는데, sessionStorage는 공유되지 않고 탭끼리 공유하기 위해서는 localStorage를 사용했어야 했다. 하지만, 자동로그인을 원하지 않는 사용자는 나의 정보가 storage에 남지 않기를 바란 것일 것 같아 local에 남기는 것은 좋지 않다고 생각했다.
자동로그인을 원하는 사용자는 local에 원하지 않는 사용자는 session에 저장하는 건 어떨까 싶었는데 로그인 정보는 redux에 저장되어 있는 거였고, redux-persist로 session에 저장하고 있는 거였다. 가능하다라는 글을 보긴 했지만, 나중에 useSelector로 불러올 수 있는 방법에 의문이 조금 들어서 다른 방법을 생각해보고자 했다. 그래서 알게 된 방법이 storage 이벤트를 통해 데이터를 전달하는 것이다.

sessionStorage 탭 간 데이터 전송 이 게시글을 참고해 구현했다.
1번 탭과 2번 탭이 존재하고 1번 탭에서 로그인되어 있을 때를 가정해서 간단하게 구현 방식에 대해 정리를 하면,

  1. 2번 탭에서 페이지가 최초 렌더링 될 때 session에 access 값이 존재하지 않는다면, localStorage에 "sync-request"을 set해주고 remove 해준다.
  2. 방금 set에 의해 1번 탭에 storage 이벤트가 발생된다. 이 때, access가 1번 탭에 존재한다면 localStorage에 "sync-response"에 로그인 정보를 set해주고 remove 해준다.
  3. 방금 set에 의해 2번 탭에 storage 이벤트가 발생된다. event.key가 "sync-response"라면, 받은 로그인 정보를 session에 저장해준다.

즉, 일시적으로 set/remove를 해서 다른 탭에서 trigger 될 수 있게 해주어서 데이터를 요청하고 받을 수 있게 되는 것이다. storage 이벤트는 다른 탭에서의 이벤트만 받을 수 있고 같은 탭에서는 발생하지 않는다고 하니 sessionStorage에 데이터를 탭끼리도 공유할 수 있을 것 같았다.

하지만, stackoverflow를 보던 중 아래 댓글을 발견했다.간단하게 요약하면, local에 데이터 올릴거면 session 왜 쓰냐 가치가 있냐? 였다. 내가 생각한 부분도 local에서 거의 바로 삭제가 되긴 하지만, local에 등록되지 않길 바라는 데이터가 local에 저장되는 게 맞긴할까? 싶었다. 그래서 찾아본 결과 BroadcastChannel이라는 API를 사용하면 방금과 같은 방식을 조금 더 의미있게 진행할 수 있을 것 같았다.

BroadcastChannel API

브라우징 컨텍스트 간의 통신을 보다 쉽게 해주는 간단한 API로 윈도우/탭, iframe, 웹 워커 및 서비스 워커 간에 Pub/Sub 의미 체계를 허용하는 간단한 메시지 버스로 생각할 수 있다.
지정된 채널에 게시된 메시지는 해당 채널의 모든 청취자에게 전달된다. Broadcast Channel API는 같은 출처에 있는 스크립트 간의 간편한 일대다 통신을 위한 것이다.
단, 자신이 포스팅한 메세지는 자신이 받아볼 수 없다. 즉 포스팅을 한 페이지한테는 message이벤트가 실행되지 않는다.

BroadcastChannel은 다음과 같은 상황에서 사용할 수 있다.

  1. 다른 탭에서 사용자 작업 감지
  2. 사용자가 다른 창/탭에서 계정에 로그인할 때 알림을 받습니다.
  3. 작업자가 백그라운드 작업을 수행하도록 지시합니다.
  4. 서비스가 특정 작업 수행을 완료한 시점을 파악합니다.
  5. 사용자가 한 창에 사진을 업로드하면 열려 있는 다른 페이지로 전달합니다.
const channel = new BroadcastChannel('my_bus');

channel.postMessage('This is a test message.');

channel.onmessage = function(e) {
    console.log('Received', e.data);
};

channel.close();

이전에 사용했던 postMessage와 뭐가 다를까? broadcastchannel은 same origin만 지원하지만 window.postMessage는 그렇지 않다. 그리고 window.postMessage는 타켓 윈도우의 참조도 알고 있어야 하는 반면 broadcastchannel은 채널 이름으로 구독하고 양방향 소통이 가능해서 사용이 훨씬 쉽다.

참고 자료

browser sessionStorage. share between tabs?
BroadcastChannel API - 웹용 메시지 버스
[JavaScript] BroadcastChannel API란?

profile
Frontend🍓

0개의 댓글