Broadcastchannel API로 서로 다른 탭 사이에 통신하기
들어가며
개발을 진행하다보면 다른 탭 사이에 데이터를 전달해야 하는 경우가 있다. 예를들어 새로운 탭을 열고 해당 탭에 이전 탭에의 데이터를 전달하는 경우이다.
해결방법으로는 여려가지가 있을 수 있겠으나 그 중에서도 BroadcastChannel을 사용하면 다른 탭 사이의 데이터 전송을 손 쉽게 구현할 수 있다.
BroadcastChannel
BroadcastChannel은 동일한 Origin을 가진 서로 다른 브라우저 창, 탭, iframe 간 통신을 가능하게 해주는 브라우저 API이다.
이는 복잡한 메시지 전송 메커니즘을 단순화하여 다중 탭이나 창 간에 데이터를 손쉽게 주고받을 수 있도록 한다.
아래는 BroadcastChannel 객체를 생성하는 방법이다.
const broadcastChannel = new BroadcastChannel(CHANNEL_NAME);
CHANNEL_NAME
은 통신에 사용될 채널의 이름이며, 동일한 Origin에서는 동일한 이름의 BroadcastChannel이 공유된다. 따라서 중복된 이름으로 여러 BroadcastChannel을 생성하더라도 동일한 채널로 간주된다..
생성된 BroadcastChannel 객체는 postMessage 메서드를 통해 메시지를 전송할 수 있다.
이 메시지는 같은 이름의 BroadcastChannel을 리스닝하고 있는 모든 인스턴스에 전달된다.
const sendBroadcastChannel = new BroadcastChannel(CHANNEL_NAME);
sendBroadcastChannel.postMessage("new Message!");
전달된 메시지는 아래와 같이 동일한 CHANNEL_NAME
을 사용하는 다른 BroadcastChannel 객체에서 수신할 수 있으며, onmessage 이벤트를 통해 접근 가능하다.
const receiveBroadcastChannel = new BroadcastChannel(CHANNEL_NAME);
receiveBroadcastChannel.onmessage = (event) => {
console.log(event.data); // 'new Message!'
};
이처럼 BroadcastChannel은 간단한 API로 탭 간 통신을 손쉽게 구현할 수 있다.
브라우저에서 기본적으로 제공하는 API이므로 별도의 라이브러리 없이도 사용할 수 있다는 장점이 있다.
React에서 BroadcastChannel을 사용하는 Custom Hook 만들기
React 환경에서도 BroadcastChannel을 활용하여 다중 탭 간 통신을 구현할 수 있다.
아래는 React에서 사용할 수 있는 BroadcastChannel용 Custom Hook의 구현한 코드이다.
// hooks/useBroadCastChannel.jsx
import { useEffect, useRef, useState } from "react";
const CHANNEL_NAME = "newtab";
const useBroadCastChannel = () => {
const channel = useRef(null);
const [data, setData] = useState(null);
// 메시지를 보내는 함수
const postMessage = (message) => {
channel.current?.postMessage(message);
};
// 새로운 탭을 여는 함수
const openNewTab = () => {
window.open("/newtab", "_blank");
};
useEffect(() => {
channel.current = new BroadcastChannel(CHANNEL_NAME);
// 메시지 이벤트 리스너 등록
const messageHandler = (event) => {
setData(event.data);
};
channel.current.addEventListener("message", messageHandler);
return () => {
// 메시지 이벤트 리스너 해제
channel.current?.removeEventListener("message", messageHandler);
};
}, []);
return { postMessage, data, openNewTab };
};
export default useBroadCastChannel;
위 코드의 Custom Hook의 주요 기능을 정리하자면 다음과 같다
-
postMessage: 메시지를 지정된 BroadcastChannel로 전송한다.
-
data: 메시지 이벤트가 발생할 때 수신된 데이터를 상태로 저장한다.
-
openNewTab: 새로운 탭을 열어
/newtab
경로를 표시한다.
Custom Hook 사용 예제
아래는 위에서 정의한 useBroadCastChannel Hook을 활용하여 다중 탭 간 메시지를 송수신하는 예제이다.
Home 컴포넌트는 새로운 탭에서 보낸 메시지를 수신하여 화면에 표시한다.
// pages/Home.js
import useBroadCastChannel from "@/src/hooks/useBroadCastChannel";
export default function Home() {
const { data, openNewTab } = useBroadCastChannel();
return (
<div>
<div>Received Data: {data || "No data yet"}</div>
<button onClick={openNewTab}>Open New Tab</button>
</div>
);
}
newtab 컴포넌트는 메시지를 입력받아 기존 탭으로 전달한다.
// pages/newtab.jsx
import useBroadCastChannel from "@/src/hooks/useBroadCastChannel";
const NewTab = () => {
const { postMessage } = useBroadCastChannel();
const onSubmit = (e) => {
e.preventDefault();
const message = e.target.data.value;
postMessage(message);
};
return (
<form onSubmit={onSubmit}>
<input type="text" name="data" placeholder="Enter message" />
<button type="submit">Send</button>
</form>
);
};
export default NewTab;
위 코드가 동작하는 방법을 정리하자면 다음과 같다
-
Home에서 Open New Tab 버튼 클릭: 새로운 탭(/newtab)이 열린다.
-
새로운 탭에서 메시지 전송: 폼에 데이터를 입력하고 전송 버튼을 누르면 메시지가 BroadcastChannel을 통해 전달된다.
-
Home에서 메시지 수신: 전달된 메시지가 실시간으로 화면에 표시된다.