Skip to Content
Documentation고급 가이드

고급 가이드

명령형 스타일 플러그인

defineElement가 권장되지만, 직접 DOM을 조작하는 방식도 여전히 지원됩니다.

직접 DOM 조작

// @id my-legacy-plugin if (dmn.window.type !== "overlay") return; // 요소 생성 및 추가 const panel = document.createElement("div"); panel.className = "my-panel"; panel.innerHTML = `<h1>Hello</h1>`; document.body.appendChild(panel); // 클린업 등록 dmn.plugin.registerCleanup(() => { panel.remove(); });

직접 DOM 조작 시 반드시 dmn.plugin.registerCleanup으로 요소를 정리해야 합니다.

스타일 시트 직접 주입

// @id style-injection if (dmn.window.type !== "overlay") return; const style = document.createElement("style"); style.textContent = ` .my-panel { background: rgba(0, 0, 0, 0.8); padding: 16px; border-radius: 8px; } `; document.head.appendChild(style); dmn.plugin.registerCleanup(() => { style.remove(); });

이벤트 버스 활용

키 입력에 반응하는 로우 레벨 이벤트 처리가 필요할 때:

// @id event-bus-example // onKeyState - 등록된 키만 const unsub1 = dmn.keys.onKeyState(({ key, state }) => { if (state === "DOWN") { console.log(`Key ${key} pressed`); } }); // onRawInput - 모든 입력 (키보드 + 마우스) const unsub2 = dmn.keys.onRawInput(({ device, label, state }) => { console.log(`[${device}] ${label} ${state}`); }); dmn.plugin.registerCleanup(() => { unsub1(); unsub2(); });

디버깅 팁

DevTools 열기

// 모든 윈도우의 DevTools 열기 dmn.window.openDevtoolsAll();

상태 검사

// 현재 윈도우 타입 console.log("윈도우 타입:", dmn.window.type); // 현재 설정 dmn.settings.get().then((s) => console.log("설정:", s)); // 키 매핑 dmn.keys.get().then((k) => console.log("키:", k)); // 스토리지 키 목록 dmn.plugin.storage.keys().then((keys) => console.log("저장된 키:", keys));

에러 추적

// 전역 에러 핸들러 window.addEventListener("error", (e) => { console.error("Plugin error:", e.error); }); window.addEventListener("unhandledrejection", (e) => { console.error("Unhandled promise:", e.reason); });

보안 고려사항

샌드박싱 없음

플러그인은 앱과 동일한 권한으로 실행됩니다:

  • 모든 dmn.* API에 접근 가능
  • DOM 전체에 접근 가능
  • 외부 네트워크 요청 가능

신뢰할 수 없는 코드를 실행하지 마세요. 플러그인 코드는 항상 직접 검토 후 사용하세요.

외부 요청

// 일반 fetch 예시 (서버 CORS 정책에 따라 실패할 수 있음) const response = await fetch("https://api.example.com/data", { headers: { "Content-Type": "application/json" }, }); const data = await response.json();

성능 최적화

상태 업데이트 최적화

defineElement에서 상태 업데이트 시 setState를 사용합니다:

dmn.plugin.defineElement({ name: "Optimized Panel", template: (state, settings, { html }) => html` <div>Count: ${state.count ?? 0}</div> `, onMount: ({ setState }) => { // 여러 값을 한 번에 업데이트 setState({ count: 0, history: [], lastUpdate: Date.now(), }); }, });

불필요한 렌더링 방지

상태가 실제로 변경될 때만 setState를 호출하세요:

onMount: ({ setState, getSettings }) => { let lastKps = 0; const interval = setInterval(() => { const newKps = calculateKps(); // 값이 변경되었을 때만 업데이트 if (newKps !== lastKps) { lastKps = newKps; setState({ kps: newKps }); } }, 100); return () => clearInterval(interval); };

멀티 윈도우 패턴

메인에서 오버레이 제어

// 메인 윈도우에서 if (dmn.window.type === "main") { dmn.bridge.sendTo("overlay", "UPDATE_OVERLAY_VALUE", { value: 42 }); } // 오버레이에서 if (dmn.window.type === "overlay") { const node = document.createElement("div"); node.style.cssText = "position: absolute; left: 8px; top: 8px; padding: 8px 12px; border-radius: 8px; background: rgba(0,0,0,0.7); color: white;"; node.textContent = "Value: 0"; document.body.appendChild(node); const unsub = dmn.bridge.on("UPDATE_OVERLAY_VALUE", ({ value }) => { node.textContent = `Value: ${value}`; }); dmn.plugin.registerCleanup(() => { unsub(); node.remove(); }); }

양방향 동기화

const SYNC_KEY = "shared-state"; // 상태 변경 시 브로드캐스트 function updateShared(newState) { dmn.bridge.send(SYNC_KEY, newState); // 로컬도 업데이트 localState = newState; } // 수신 시 로컬 업데이트 dmn.bridge.on(SYNC_KEY, (state) => { localState = state; render(); });

제한사항

제한설명
Web Workers미지원
ES Modules동적 import 제한적 지원
LocalStoragedmn.plugin.storage 사용 권장
외부 라이브러리CDN에서 직접 로드 필요

외부 라이브러리 로드

async function loadScript(src) { return new Promise((resolve, reject) => { const script = document.createElement("script"); script.src = src; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); } // 사용 await loadScript("https://unpkg.com/lodash@4.17.21/lodash.min.js"); const result = _.chunk([1, 2, 3, 4], 2);