--- id: P-REINFORCE-AUTO-7669FA category: "10_Wiki/πŸ’‘ Topics/Programming & Language" confidence_score: 0.90 tags: [auto-reinforced] last_reinforced: 2026-04-20 github_commit: "[P-Reinforce] Continuous Worker - μ›Ή μ›Œμ»€ 이벀트 ν¬μ›Œλ”© Event Forwarding" --- # [[α„‹α…°α†Έ 워ᄏα…₯ 아벤트 포워당 Event Forwarding|μ›Ή μ›Œμ»€ 이벀트 ν¬μ›Œλ”© Event Forwarding]] ## πŸ“Œ ν•œ 쀄 톡찰 (The Karpathy Summary) > μ›Ή μ›Œμ»€(Web Worker)λŠ” DOM API에 직접 μ ‘κ·Όν•  수 μ—†κΈ° λ•Œλ¬Έμ—, 메인 μŠ€λ ˆλ“œμ˜ μΊ”λ²„μŠ€μ—μ„œ λ°œμƒν•œ 마우슀 및 ν„°μΉ˜ 이벀트λ₯Ό μΊ‘μ²˜ν•˜μ—¬ ν•„μš”ν•œ μ’Œν‘œμ™€ μƒνƒœ λ°μ΄ν„°λ§Œ μΆ”μΆœν•œ λ’€ `postMessage`λ₯Ό 톡해 μ›Œμ»€ μŠ€λ ˆλ“œλ‘œ 전달(Forwarding)ν•˜μ—¬ μƒν˜Έμž‘μš©μ„ λŒ€λ¦¬ μ²˜λ¦¬ν•˜λŠ” κΈ°λ²•μž…λ‹ˆλ‹€. ## πŸ“– κ΅¬μ‘°ν™”λœ 지식 (Synthesized Content) **1. 이벀트 ν¬μ›Œλ”©μ˜ ν•„μš”μ„±** OffscreenCanvas 등을 ν™œμš©ν•΄ 무거운 λ Œλ”λ§μ΄λ‚˜ 연산을 μ›Ή μ›Œμ»€λ‘œ λΆ„λ¦¬ν•˜λ©΄, μ›Œμ»€ λ‚΄λΆ€μ—μ„œλŠ” DOM이 μ‘΄μž¬ν•˜μ§€ μ•Šμ•„ μ‚¬μš©μžμ˜ 이벀트(`mousedown`, `mousemove` λ“±)λ₯Ό 직접 μˆ˜μ‹ ν•  수 μ—†μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 메인 μŠ€λ ˆλ“œμ—μ„œ μ‚¬μš©μžμ˜ μž…λ ₯ 이벀트λ₯Ό μΊ‘μ²˜ν•œ λ’€ μ›Œμ»€λ‘œ μ „λ‹¬ν•˜λŠ” λŒ€λ¦¬ μΈν„°λž™μ…˜(Proxy Interaction) μ‹œμŠ€ν…œμ„ ꡬ좕해야 ν•©λ‹ˆλ‹€. **2. 데이터 직렬화 및 ν•„μˆ˜ 속성 μΆ”μΆœ** λΈŒλΌμš°μ €μ˜ 원본 DOM 이벀트 객체 μžμ²΄λŠ” λ‚΄λΆ€μ μœΌλ‘œ λ‹€μ–‘ν•œ DOM λ…Έλ“œ μ°Έμ‘° 및 λ©”μ„œλ“œλ₯Ό ν¬ν•¨ν•˜κ³  μžˆμ–΄ `postMessage`둜 전달 μ‹œ κ΅¬μ‘°ν™”λœ 볡제(Structured Clone) μ•Œκ³ λ¦¬μ¦˜μ— μ˜ν•΄ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. λ”°λΌμ„œ μ›Œμ»€μ—μ„œ μƒν˜Έμž‘μš© 계산에 ν•„μš”ν•œ ν•„μˆ˜ 데이터(예: `clientX`, `clientY`, `type`, `button` λ“±)만 μΆ”μΆœν•˜μ—¬ κ°€λ²Όμš΄ 일반 객체 νŽ˜μ΄λ‘œλ“œλ‘œ μž¬κ΅¬μ„±ν•œ λ’€ 전솑해야 ν•©λ‹ˆλ‹€. **3. 메인 μŠ€λ ˆλ“œ κ΅¬ν˜„ 방식 (이벀트 캑처 및 전솑)** 메인 μŠ€λ ˆλ“œμ—μ„œλŠ” 좔적할 이벀트 이름듀을 λ°°μ—΄λ‘œ μ •μ˜ν•œ λ’€, μΊ”λ²„μŠ€ μš”μ†Œμ— 이벀트 λ¦¬μŠ€λ„ˆλ₯Ό 달아 μ›Œμ»€λ‘œ λ©”μ‹œμ§€λ₯Ό ν¬μ›Œλ”©ν•©λ‹ˆλ‹€. ``` // 메인 μŠ€λ ˆλ“œ μΈ‘ const events = ['mousedown', 'mouseup', 'mousemove', 'touchstart', 'touchend', 'touchmove']; events.forEach((eventName) => { canvas.addEventListener(eventName, (event) => { worker.postMessage({ eventName, event: { clientX: event.clientX, clientY: event.clientY, type: event.type, button: event.button } }); }); }); ``` λ˜ν•œ 더 μ›ν™œν•œ μƒν˜Έμž‘μš©(Interop)을 보μž₯ν•˜κΈ° μœ„ν•΄ 클릭, μ»¨ν…μŠ€νŠΈ 메뉴 같은 λΉ„μˆ˜λ™μ (non-passive) μ΄λ²€νŠΈμ— λŒ€ν•΄ `preventDefault()`λ₯Ό ν˜ΈμΆœν•˜κ±°λ‚˜, 포인터 이벀트의 캑처 및 ν•΄μ œ(`pointerdown` μ‹œ 캑처, `pointerup` μ‹œ ν•΄μ œ)λ₯Ό 관리해 슀크둀 λ“± κΈ°λ³Έ λ™μž‘κ³Ό μΆ©λŒν•˜μ§€ μ•Šλ„λ‘ μ²˜λ¦¬ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. **4. μ›Œμ»€ μŠ€λ ˆλ“œ κ΅¬ν˜„ 방식 (μˆ˜μ‹  및 μ—”μ§„ μ—°κ²°)** μ›Œμ»€ λ‚΄λΆ€μ—μ„œλŠ” `onmessage` ν•Έλ“€λŸ¬λ₯Ό 톡해 전달받은 이벀트λ₯Ό λΆ„μ„ν•˜κ³ , 3D μ”¬μ˜ μƒν˜Έμž‘μš©(예: Three.js의 Raycasting)μ΄λ‚˜ 2D μΊ”λ²„μŠ€ μ—”μ§„μ˜ 처리 둜직으둜 μ—°κ²°ν•©λ‹ˆλ‹€. ``` // μ›Œμ»€ μŠ€λ ˆλ“œ μΈ‘ self.onmessage = function (evt) { if (evt.data.eventName) { // 전달받은 이벀트λͺ…κ³Ό μ’Œν‘œ 데이터λ₯Ό λ°”νƒ•μœΌλ‘œ μ—”μ§„ λ‚΄λΆ€μ˜ 이벀트 μ‹œμŠ€ν…œ 호좜 // (ν•„μš” μ‹œ mouse 이벀트λ₯Ό pointer 이벀트둜 μΉ˜ν™˜ν•˜μ—¬ 톡합 처리) const event = evt.data.eventName.replace('mouse', 'pointer'); stage['_' + event](evt.data.event); } }; ``` ## ⚠️ λͺ¨μˆœ 및 μ—…λ°μ΄νŠΈ (Contradictions & RL Update) - **κ³Όκ±° λ°μ΄ν„°μ™€μ˜ 좩돌:** μžλ™ν™” 엔진에 μ˜ν•΄ λ§€ν•‘λœ μ§€μ‹μœΌλ‘œ, μΆ”ν›„ μ •λ°€ 검증 ν•„μš”. - **μ •μ±… λ³€ν™”:** Programming & Language λΆ„μ•Όμ˜ μžλ™ μžμ‚°ν™” μˆ˜ν–‰. ## πŸ”— 지식 μ—°κ²° (Graph) - **Related Topics:** [[OffscreenCanvas|OffscreenCanvas]], Web Worker postMessage 동기화, λŒ€λ¦¬ μΈν„°λž™μ…˜ (Proxy Interaction), Raycasting을 ν†΅ν•œ 3D 객체 선택 - **Projects/Contexts:** Konva의 Offscreen Canvas 및 이벀트 ν¬μ›Œλ”© κ΅¬ν˜„, react-three-offscreen 기반 DOM 이벀트 패치 - **Contradictions/Notes:** 이벀트 ν¬μ›Œλ”© 방식은 메인 μŠ€λ ˆλ“œμ™€ μ›Œμ»€ κ°„μ˜ ν†΅μ‹ μ΄λ―€λ‘œ 직렬화 및 λ©”μ‹œμ§€ νŒ¨μ‹±μ— λ”°λ₯Έ μ§€μ—°(μ•½κ°„μ˜ μ˜€λ²„ν—€λ“œ)이 λ°œμƒν•©λ‹ˆλ‹€. λ§ˆμš°μŠ€λ‚˜ ν„°μΉ˜ 이벀트 λ°œμƒ λΉˆλ„ μ •λ„λŠ” 일반적으둜 μ„±λŠ₯ μ €ν•˜λ₯Ό μΌμœΌν‚€μ§€ μ•ŠμœΌλ‚˜, κ³Όλ„ν•˜κ²Œ λ§Žμ€ 이벀트 데이터(예: 수천 번의 `mousemove`)κ°€ λ°œμƒν•  경우 μŠ€λ‘œν‹€λ§(Throttling) 기법을 ν•¨κ»˜ μ μš©ν•˜μ—¬ λ©”μ‹œμ§€ 큐의 병λͺ©μ„ λ§‰λŠ” 것이 μ•ˆμ „ν•©λ‹ˆλ‹€. --- _Last updated: 2026-04-14_ - Raw Source: 00_Raw/2026-04-20/μ›Ή μ›Œμ»€ 이벀트 ν¬μ›Œλ”© Event Forwarding.md ---