docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거

Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
This commit is contained in:
Antigravity Agent
2026-07-05 00:33:48 +09:00
parent 1cfd3bbb56
commit 9148c358d0
6455 changed files with 1 additions and 86875 deletions
@@ -0,0 +1,362 @@
---
id: web-broadcastchannel-sharedworker
title: BroadcastChannel / SharedWorker — tab 간 통신
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [web, worker, vibe-coding]
tech_stack: { language: "TS", applicable_to: ["Frontend"] }
applied_in: []
aliases: [BroadcastChannel, SharedWorker, MessageChannel, postMessage, tab sync, cross-tab]
---
# BroadcastChannel / SharedWorker
> Tab / iframe / worker 간 message passing. **BroadcastChannel (simple), SharedWorker (logic 공유), MessageChannel (port pair)**. Same-origin 만.
## 📖 핵심 개념
- 같은 origin 의 다른 tab.
- BroadcastChannel: pub/sub.
- SharedWorker: 공유 worker.
- MessageChannel: 1-1 port.
## 💻 코드 패턴
### BroadcastChannel
```ts
const channel = new BroadcastChannel('updates');
// Sender (tab A)
channel.postMessage({ type: 'config-changed', value: 'dark' });
// Receiver (tab B)
channel.onmessage = (e) => {
console.log(e.data); // { type: 'config-changed', value: 'dark' }
};
// Cleanup
channel.close();
```
→ Same-origin 의 모든 tab 가 receive.
### Use case
```
- Theme toggle: 1 tab 에서 바꾸면 모든 tab.
- Logout: 1 tab 에서 logout = 모두.
- Cache invalidation: data 변경 알림.
- Real-time sync: collaborative edit.
```
### SharedWorker
```ts
// shared-worker.ts (worker file)
const ports: MessagePort[] = [];
self.onconnect = (e) => {
const port = e.ports[0];
ports.push(port);
port.onmessage = (e) => {
// 모든 tab 에 broadcast
ports.forEach(p => p.postMessage(e.data));
};
};
```
```ts
// main thread
const worker = new SharedWorker('shared-worker.ts', { type: 'module' });
worker.port.start();
worker.port.postMessage({ type: 'hello' });
worker.port.onmessage = (e) => console.log(e.data);
```
→ 모든 tab 가 1 worker instance 공유.
### vs BroadcastChannel
```
BroadcastChannel:
- Simple.
- 매 tab 가 자체 logic.
SharedWorker:
- 공유 state (1 instance).
- Logic 가 worker 안.
- WebSocket / DB connection 가 1 곳.
```
### MessageChannel (port pair)
```ts
const channel = new MessageChannel();
const { port1, port2 } = channel;
port1.onmessage = (e) => console.log('p1:', e.data);
port2.onmessage = (e) => console.log('p2:', e.data);
port1.postMessage('hello');
// → p2: hello
port2.postMessage('world');
// → p1: world
port1.start();
port2.start();
```
→ 1-1 통신. iframe / worker 친화.
### iframe 와 통신
```ts
// Parent
const iframe = document.querySelector('iframe')!;
const channel = new MessageChannel();
iframe.contentWindow!.postMessage({ port: channel.port2 }, '*', [channel.port2]);
channel.port1.postMessage('hello');
channel.port1.onmessage = (e) => console.log(e.data);
```
```ts
// iframe
window.addEventListener('message', (e) => {
const port = e.data.port;
port.onmessage = (e) => console.log('parent:', e.data);
port.postMessage('hi from iframe');
});
```
→ Parent ↔ iframe 의 secure channel.
### Use case 비교
```
BroadcastChannel:
- 매 tab 가 같은 logic.
- 알림 / sync.
SharedWorker:
- 공유 connection (WebSocket).
- 공유 cache.
- 공유 computation.
MessageChannel:
- iframe 와 통신.
- Worker 와 sub-channel.
Web Locks:
- Tab 간 mutex.
```
### SharedWorker 의 함정
```
- iOS Safari 가 안 (no support).
- Chrome incognito 가 안 (privacy).
- Firefox 가 OK.
→ 가벼운 use case 만.
대부분 = BroadcastChannel + Web Locks.
```
→ [[Web_Web_Locks_API]].
### Single WebSocket pattern
```ts
// SharedWorker 가 1 WS.
self.onconnect = (e) => {
const port = e.ports[0];
if (!ws) {
ws = new WebSocket('wss://...');
ws.onmessage = (msg) => {
// 모든 connected tab 에 broadcast
ports.forEach(p => p.postMessage({ type: 'message', data: msg.data }));
};
}
ports.push(port);
port.onmessage = (e) => ws.send(e.data.payload);
};
```
→ N tab → 1 WS connection.
### postMessage (window)
```ts
// Parent → iframe
iframe.contentWindow.postMessage({ type: 'init' }, 'https://child.com');
// iframe
window.addEventListener('message', (e) => {
if (e.origin !== 'https://parent.com') return; // 검증
console.log(e.data);
});
```
→ Cross-origin (BroadcastChannel 가 안 됨).
### postMessage 의 함정
```
- Origin 검증 필수 (모든 origin = 위험).
- Object 가 structured clone (function 안 됨).
- 큰 object = 느림 → transferable.
```
### Transferable
```ts
const buf = new ArrayBuffer(1_000_000);
worker.postMessage({ buf }, [buf]);
// → buf 가 worker 로 transfer (main thread 에서 사용 X).
```
→ Zero-copy.
### MessageChannel 의 transferable port
```ts
const { port1, port2 } = new MessageChannel();
worker.postMessage({ port: port2 }, [port2]);
// → port2 가 worker 로 transfer.
```
### React 통합
```tsx
// Theme sync across tab
useEffect(() => {
const ch = new BroadcastChannel('theme');
ch.onmessage = (e) => setTheme(e.data);
return () => ch.close();
}, []);
const updateTheme = (t: Theme) => {
setTheme(t);
new BroadcastChannel('theme').postMessage(t);
};
```
### Service Worker + BroadcastChannel
```ts
// Service worker
self.addEventListener('fetch', async (event) => {
// ...
const ch = new BroadcastChannel('cache');
ch.postMessage({ type: 'fetched', url: event.request.url });
});
// Page
const ch = new BroadcastChannel('cache');
ch.onmessage = (e) => console.log(e.data);
```
### Browser support
```
BroadcastChannel: 모든 modern (Safari 15.4+).
SharedWorker: Chrome / FF / Edge. Safari iOS 안.
MessageChannel: 모든.
postMessage: 모든.
```
### Polyfill (BroadcastChannel)
```ts
// localStorage 식 (옛 browser)
window.addEventListener('storage', (e) => {
if (e.key === 'channel:updates') {
const data = JSON.parse(e.newValue!);
// ...
}
});
localStorage.setItem('channel:updates', JSON.stringify({ ... }));
localStorage.removeItem('channel:updates');
```
→ 옛 hack. Modern = native.
### When 안 사용?
```
- Cross-origin: postMessage + origin check.
- Same-tab worker: regular worker.
- Server → multi-tab: SSE / WebSocket + BroadcastChannel.
- Persistent: IndexedDB.
```
### 함정
```
- BroadcastChannel 가 same origin 만.
- Worker close 시 message lost.
- iOS Safari 가 SharedWorker X.
- 큰 object = serialize cost.
- Origin 검증 안 함: XSS.
```
### Use case 패턴
```
1. Tab sync:
BroadcastChannel.
2. Single WS:
SharedWorker (Chrome/FF) + BroadcastChannel fallback.
3. iframe widget:
MessageChannel.
4. Service worker:
BroadcastChannel.
5. Cross-origin:
postMessage + origin.
```
### Performance
```
BroadcastChannel: ms latency.
SharedWorker: 비슷.
MessageChannel: 가장 빠름 (port).
postMessage cross-origin: 비슷.
→ 모두 빠름. 큰 object 가 cost.
```
### Tab 의 visibility
```ts
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
// Refetch state via BroadcastChannel
bc.postMessage({ type: 'request-state' });
}
});
```
→ Tab 가 hidden = sync 가 throttle.
## 🤔 의사결정 기준
| 작업 | 추천 |
|---|---|
| Tab sync | BroadcastChannel |
| Shared logic | SharedWorker |
| iframe 통신 | MessageChannel + postMessage |
| Cross-origin | postMessage + origin check |
| Mutex | Web Locks |
| 1 WS / N tab | SharedWorker |
| Service worker | BroadcastChannel |
## ❌ 안티패턴
- **Cross-origin 가 BroadcastChannel**: 안 됨.
- **Origin 검증 X**: XSS.
- **iOS Safari + SharedWorker**: 깨짐.
- **큰 object 자주 broadcast**: 느림.
- **Channel close X**: leak.
- **모든 tab 가 자체 WS**: 비효율.
## 🤖 LLM 활용 힌트
- BroadcastChannel = simple cross-tab.
- SharedWorker = 공유 logic (Safari iOS X).
- MessageChannel = iframe / worker.
- Origin check 가 cross-origin 의 보안.
## 🔗 관련 문서
- [[Web_OffMain_WebWorker]]
- [[Web_Web_Locks_API]]
- [[Web_Service_Worker_Patterns]]