-
브라우저 탭 사이의 통신 (chrome postMessage, BroadcastChannel API 사용해보기)웹 개발 2024. 7. 14. 19:40
SPA가 대중적으로 많이 퍼지면서 여러 브라우저를 오가며 복잡한 작업을 하는 경우는 적어진 것 같다.
하지만, 여전히 다양한 이유로 여러 탭을 사용하여 오가는 웹 앱이 필요하고, 그 때 탭간의 데이터 통신을 위해서 사용할 수 있는 API들이 있다.
그 API들 중에서 이번엔 postMessage와 BroadcastChannel을 사용하는 방법에 대해서 간단하게 알아보았다.
일단 window. postMessage를 사용해보자.
postMessage를 통해서 새로 띄워진 창에 메세지를 전달할 수 있다.
일단, window.open 메서드로 새로운 창을 띄운다.
const newWindow = window.open("https://www.naver.com");그럼 새로운 네이버 탭이 열린다.
이 탭의 콘솔창을 열어 이벤트를 연결해두자.
function receiveMessage(event) { if (event.origin !== "https://www.naver.com") return; console.log(event) } window.addEventListener("message", receiveMessage, false);+ event.origin을 검사하는 건 보안적으로 좋은 습관이지만, event.source를 같이 확인하는 게 더 안전하다.
같은 origin이라도, 악성 코드가 메시지를 보낼 가능성이 있기 때문이다 👻function receiveMessage(event) { if (event.origin !== "https://www.naver.com") return; if (event.source !== trustedWindow) return; // 신뢰할 수 있는 창인지 확인 console.log(event); }이제 이벤트를 직접 보내면, 새로 열린 탭에서 데이터를 전달받을 수 있다.
newWindow.postMessage("GOOOOOOOOOOOOOOOOOOD", "https://www.naver.com")+ postMessage를 사용할 때, 새 창이 완전히 로드되지 않은 상태에서 메시지를 보내면 무시될 수 있다.
때문에, onload를 사용해 시점을 잡아주는 것이 좋다.
const newWindow = window.open("https://www.naver.com"); newWindow.onload = () => { newWindow.postMessage("GOOOOOOOOOOOOOOOOOOD", "https://www.naver.com"); };새로 열렸던 창의 콘솔창을 확인해보면,

메세지가 전달된 것을 확인할 수 있다.
다만, 새로 열린 창을 사용해야 하는 불편함이 있다.
대신, 다른 origin 도메인과도 통신할 수 있다.
이번에는 BroadcastChannel을 사용해보자.
BroadcastChannel API는 same-origin이고, 동일한 출처로부터 온것을 보장하기에 위와 같이 event.origin을 검사할 필요가 없다.
직접 사용해보면, 일단 다음과 네이버 두 탭을 띄우자.

그리고 두 탭에 각각 채널을 생성해준다. (동일한 채널이름)
const channel = new BroadcastChannel('test');그리고 다음 탭에 onmessage 이벤트를 설정한다.
channel.onmessage = function(e) { console.log('Received', e.data); };그리고 네이버 탭에서 메세지를 보내면,
channel.postMessage('This is a test message.');반응이 없을 것이다. 😅
same-origin이 아니기에 데이터를 받을 수 없었다.
+ BroadcastChannel을 사용할 때, 사용이 끝나면 반드시 close()를 호출해야 한다. 안 그러면 메모리 누수가 발생할 수 있다.
const channel = new BroadcastChannel("test"); channel.onmessage = (e) => { console.log("Received", e.data); }; // 사용이 끝났다면 반드시 닫기! channel.close();다시 네이버 탭을 띄우고, 채널을 설정한 뒤 onmessage 이벤트를 설정하면 정상 작동함을 확인할 수 있다.

메세지 수신 성공 요약하자면, 다음과 같다.
// BroadcastChannel 인스턴스 생성 const channel = new BroadcastChannel('test'); // 메시지 수신 설정 channel.onmessage = function(e) { console.log('Received', e.data); }; // 메시지 보내기 channel.postMessage('This is a test message.');origin이 같은 모든 탭에 데이터를 보내기에, 각 탭에서 id를 설정해서 원하는 탭에서만 데이터를 받을 수 있도록 설정할 수도 있다.
const channel = new BroadcastChannel("test"); const myTabId = Math.random().toString(36).substr(2, 9); // 각 탭의 고유 ID 생성 channel.onmessage = (e) => { if (e.data.targetId && e.data.targetId !== myTabId) return; // 특정 탭이 아니면 무시 console.log("Received", e.data.message); }; // 특정 탭으로 메시지 보내기 function sendMessageToTab(targetId, message) { channel.postMessage({ targetId, message }); }(id 설정 후 해당 id를 포함해서 데이터가 올 때에만 데이터 수신하도록 onmessage를 설정할 수 있다)
🍇 참고 자료
https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage
Window.postMessage() - Web API | MDN
window.postMessage() 메소드는 Window 오브젝트 사이에서 안전하게 cross-origin 통신을 할 수 있게 합니다. 예시로, 페이지와 생성된 팝업 간의 통신이나, 페이지와 페이지 안의 iframe 간의 통신에 사용할
developer.mozilla.org
https://developer.chrome.com/blog/broadcastchannel?hl=ko
BroadcastChannel API - 웹용 메시지 버스 | Blog | Chrome for Developers
BroadcastChannel API는 창, 탭, iframe 또는 작업자 간의 간단한 Pub/Sub에 사용할 수 있습니다.
developer.chrome.com
+ 2025.03.20 내용 보완
'웹 개발' 카테고리의 다른 글
resize Event와 ResizeObserver 비교해보기 🙌 (0) 2024.10.18 requestIdleCallback 알아보기 (브라우저가 idle할 때, 콜백함수를 대기열에 👍) (0) 2024.09.05 commonJS, ESM 둘 다 지원하는 package.json 설정법 (feat. rollup) (0) 2024.08.18 프론트엔드 개발 생태계에서 Rust 개발 툴들 (1) 2024.07.02 Biome.js 사용 후기 (prettier + eslint) (0) 2024.06.24