BroadcastChannel API를 사용하면 동일 출처 스크립트가 다른 탐색 컨텍스트에 메시지를 보낼 수 있습니다. 윈도우/탭, iframe, 웹 워커 및 서비스 워커 간에 Pub/Sub 의미 체계를 허용하는 간단한 메시지 버스로 생각할 수 있습니다.
API 기본사항
Broadcast Channel API는 브라우징 컨텍스트 간에 더 쉽게 통신할 수 있도록 하는 간단한 API입니다. 즉, 창/탭, iframe, 웹 워커 및 서비스 워커 간에 통신합니다. 지정된 채널에 게시된 메시지는 해당 채널의 모든 리스너에게 전달됩니다.
BroadcastChannel
생성자는 단일 매개변수(채널 이름)를 사용합니다.
이름은 채널을 식별하는 데 사용되며 전체 탐색 환경에서 사용됩니다.
// Connect to the channel named "my_bus".
const channel = new BroadcastChannel('my_bus');
// Send a message on "my_bus".
channel.postMessage('This is a test message.');
// Listen for messages on "my_bus".
channel.onmessage = function(e) {
console.log('Received', e.data);
};
// Close the channel when you're done.
channel.close();
메시지 전송
메시지는 문자열이거나 구조화된 클론 알고리즘에서 지원하는 모든 항목일 수 있습니다 (문자열, 객체, 배열, Blob, ArrayBuffer, 맵).
예 - Blob 또는 파일 전송
channel.postMessage(new Blob(['foo', 'bar'], {type: 'plain/text'}));
채널은 자신에게 방송되지 않습니다. 따라서 onmessage
리스너가 있고
동일한 채널의 postMessage()
와 같은 페이지에서 message
이벤트
실행되지 않습니다.
다른 기법과의 차이점
이 시점에서 이것이 WebSockets, SharedWorkers, MessageChannel
API, window.postMessage()
와 같은 메시지 전달의 다른 기술과 어떤 관련이 있는지 궁금할 수 있습니다. Broadcast Channel API는 이러한 API를 대체하지 않습니다. 각각 목적이 있습니다. Broadcast Channel API는 같은 출처에 있는 스크립트 간의 간편한 일대다 통신을 위한 것입니다.
방송 채널의 몇 가지 사용 사례는 다음과 같습니다.
- 다른 탭에서 사용자 작업 감지
- 사용자가 다른 창/탭에서 계정에 로그인할 때 알림을 받습니다.
- 작업자가 백그라운드 작업을 수행하도록 지시합니다.
- 서비스가 특정 작업 수행을 완료한 시점을 파악합니다.
- 사용자가 한 창에 사진을 업로드하면 열려 있는 다른 페이지로 전달합니다.
예 - 같은 사이트의 다른 열린 탭에서도 사용자가 로그아웃할 때 이를 알 수 있는 페이지
<button id="logout">Logout</button>
<script>
function doLogout() {
// update the UI login state for this page.
}
const authChannel = new BroadcastChannel('auth');
const button = document.querySelector('#logout');
button.addEventListener('click', e => {
// A channel won't broadcast to itself so we invoke doLogout()
// manually on this page.
doLogout();
authChannel.postMessage({cmd: 'logout', user: 'Eric Bidelman'});
});
authChannel.onmessage = function(e) {
if (e.data.cmd === 'logout') {
doLogout();
}
};
</script>
또 다른 예로, 서비스 워커에 인코더-디코더 아키텍처를
사용자가 '오프라인 저장공간 설정'을 변경한 후 캐시된 콘텐츠가 캐시되는 경우 확인할 수 있습니다.
window.caches
를 사용하여 캐시를 삭제할 수 있지만 서비스 워커는
이 작업을 수행하는 유틸리티가 이미 포함되어 있습니다. Broadcast Channel API를 사용하여
코드를 재사용하세요. Broadcast Channel API가 없으면 서비스 워커에서 모든 클라이언트로 통신하려면 self.clients.matchAll()
의 결과를 루프하고 각 클라이언트에서 postMessage()
를 호출해야 합니다 (이 작업을 수행하는 실제 코드). 방송 채널을 사용하면 O(N)
가 아닌 O(1)
가 됩니다.
예 - 내부 유틸리티 메서드를 재사용하여 서비스 워커에 캐시를 삭제하도록 지시합니다.
index.html
const channel = new BroadcastChannel('app-channel');
channel.onmessage = function(e) {
if (e.data.action === 'clearcache') {
console.log('Cache removed:', e.data.removed);
}
};
const messageChannel = new MessageChannel();
// Send the service worker a message to clear the cache.
// We can't use a BroadcastChannel for this because the
// service worker may need to be woken up. MessageChannels do that.
navigator.serviceWorker.controller.postMessage({
action: 'clearcache',
cacheName: 'v1-cache'
}, [messageChannel.port2]);
sw.js
function nukeCache(cacheName) {
return caches.delete(cacheName).then(removed => {
// ...do more stuff (internal) to this service worker...
return removed;
});
}
self.onmessage = function(e) {
const action = e.data.action;
const cacheName = e.data.cacheName;
if (action === 'clearcache') {
nukeCache(cacheName).then(removed => {
// Send the main page a response via the BroadcastChannel API.
// We could also use e.ports[0].postMessage(), but the benefit
// of responding with the BroadcastChannel API is that other
// subscribers may be listening.
const channel = new BroadcastChannel('app-channel');
channel.postMessage({action, removed});
});
}
};
postMessage()
와의 차이
postMessage()
와 달리 iframe 또는 worker와 통신하기 위해 더 이상 iframe 또는 worker 참조를 유지할 필요가 없습니다.
// Don't have to save references to window objects.
const popup = window.open('https://another-origin.com', ...);
popup.postMessage('Sup popup!', 'https://another-origin.com');
window.postMessage()
를 사용하면 출처 간 커뮤니케이션도 가능합니다. Broadcast Channel API는 동일한 출처입니다. 메시지의 출처가 동일함을 보장하므로 window.postMessage()
에서와 같이 메시지를 검증할 필요는 없습니다.
// Don't have to validate the origin of a message.
const iframe = document.querySelector('iframe');
iframe.contentWindow.onmessage = function(e) {
if (e.origin !== 'https://expected-origin.com') {
return;
}
e.source.postMessage('Ack!', e.origin);
};
'구독' 안전하고 양방향 통신을 할 수 있습니다.
SharedWorkers와의 차이점
잠재적으로 여러 창/탭 또는 작업자에게 메시지를 보내야 하는 간단한 경우에는 BroadcastChannel
를 사용합니다.
잠금 관리, 공유 상태 관리, 서버와 여러 클라이언트 간 리소스 동기화 또는 원격 호스트와 WebSocket 연결 공유와 같은 고급 사용 사례의 경우 공유 작업자가 가장 적합한 솔루션입니다.
MessageChannel API와의 차이점
Channel Messaging API와 BroadcastChannel
의 주요 차이점은 후자가 메시지를 여러 리스너 (일대다)에 전달하는 수단이라는 것입니다. MessageChannel
는 스크립트 간의 직접 일대일 통신을 위한 것입니다. 또한 포트가 양 끝에 있는 채널을 설정해야 하므로 더 복잡합니다.
기능 감지 및 브라우저 지원
현재 Chrome 54, Firefox 38, Opera 41은 Broadcast Channel API를 지원합니다.
if ('BroadcastChannel' in self) {
// BroadcastChannel API supported!
}
폴리필의 경우 몇 가지가 있습니다.
- https://gist.github.com/alexis89x/041a8e20a9193f3c47fb
- https://gist.github.com/inexorabletash/52f437d1451d12145264
이러한 기능을 사용해 보지 않았으므로 사용 방법은 다를 수 있습니다.