C.W.K.
Stream
Lesson 01 of 07 · published

DOM Tools 개관 — Real-world toolkit

~10 min · dom, overview, tooling, concepts

Level 0Extension 입덕
0 XP0/54 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"첫 여섯 track 이 cooperative page 의 skeleton 만듬. Track 7 이 반격하는 page — heavy framework, dynamic re-render, handler attach 보다 빠르게 content swap 하는 SPA — 의 prosthetic. Lesson 1 이 toolkit map, 다음 여섯 lesson 이 각 도구 sharpen."

DOM 도구가 뭐냐

Track 3 의 기본 너머 content script 와 page 의 실제 구조 잇는 모든 것. 도구가 세 가족으로 split:

  • Extraction — messy markup 에서 깔끔하고 structured 한 데이터 뽑기. Readability, schema.org parsing, OpenGraph, custom CSS-selector library.
  • Capture — user 가 지금 보고 있는 것 기록. Selection 텍스트, screenshot, scroll 위치, viewport 크기.
  • Mutation — user 위해 page 수정. Input 채우기, synthetic event dispatch, overlay inject, scroll into view.

ClipDeck v1 이 extraction (큰 clip 용 article body) 과 capture (selection + screenshot) 에 의존. v2 가 mutation (저장된 snippet 을 page 에 다시 auto-fill) 추가. Track 7 이 세 가족 모두 cover — 근육이 같아서.

'Real-world' 조정

도구가 textbook DOM 작업과 다른 이유는 real-world page 가 test 코드가 안 그러는 방식으로 extension 에 적대적이라서:

  • Framework 불투명성. React, Vue, Svelte 가 DOM 소유. state 변경에 component re-render, inject 한 어떤 overlay 든 demolish.
  • Synthetic event 추적. Framework form input 이 setter 통해 자체 state 추적; input.value 직접 설정해도 framework 의 input idea update 안 됨.
  • Lazy loading. Article 이미지 / 댓글 / related post 가 user scroll 함에 따라 load. DOMContentLoaded 에서 read 하는 코드는 그 순간 후 모든 거 놓침.
  • CSP 와 CSS-isolation. 많은 site 의 strict CSP 가 extension stylesheet 거부 — constructable stylesheet 통해 adopted stylesheet 로 inject 안 하면.
  • Shadow DOM. Open shadow root 는 query 가능; closed 는 아님. Site 가 component 위해 점점 더 사용, querySelector 가 아무것도 반환 안 함.

'User 신뢰' 조정

Page 가 user 공간. 만드는 어떤 mutation 도 존중해야:

  • Commit 전 preview. 하려는 거 보여 주고, user 가 confirm 이나 back out 하게. Track 7 Lesson 6 가 깊이 다룸.
  • Window 안 undo. Destructive action (clip 삭제, form 채우기) 가 5 초 undo 얻음. 그 너머는 finalize.
  • Visible 귀속. Form input 을 mutate 하면 작은 marker (border tint, side label) 남겨 user 가 ClipDeck 가 했음을 기억.
  • 놀라게 안 함. Auto-fill 없음, auto-save 없음, user 가 시작 안 한 자동 그 어떤 것도 없음.

Bundle 질문

일부 도구 (Readability) 가 third-party library 에서 옴. 가져오는 세 방법:

  • Vendor — source file 을 extension 에 drop, commit. 단순, auditable, vanilla JS library 엔 build step 필요 없음.
  • npm + bundler — 현대 setup. esbuild / Rollup / Vite 가 single bundled content.js 생산. ES module import 가진 것엔 필수.
  • Dynamic import — Chrome 96+ 가 type: 'module' field 통해 content script 의 ES module import 지원. 단순 케이스에 bundler 건너뛰게.

ClipDeck v1 이 single Readability.js 파일 vendor 하고 bundler 건너뜀. Track 8 (packaging) 이 one-file 접근 넘어 자랄 때의 bundler 경로 다룸.

이 track 이 추가하는 것

여섯 lesson 안 여섯 도구:

  • Lesson 2 — article body 추출 위한 Readability.js.
  • Lesson 3 — Selection 과 Range API deep dive (toString 너머).
  • Lesson 4 — selection screenshot 위한 chrome.tabs.captureVisibleTab + canvas crop.
  • Lesson 5 — React-friendly input-fill trick.
  • Lesson 6 — Preview-and-confirm 패턴.
  • Lesson 7 — inline edit 와 undo 가진 ClipDeck CRUD-U 와 CRUD-D.

끝나면 ClipDeck 이 user 가 New York Times article 읽고, 세 문단 highlight 하고, Ctrl+Shift+K 누르고, 저장될 거의 preview 보고, confirm 하고, 다음 side panel 에서 clip title 편집하고 이전 중복 삭제 — page 자리 안 잃고 — 하는 현실적 케이스 처리.

Real-world page 가 반격. Framework 가 DOM 소유, lazy-load content, shadow root 에 숨김. Track 7 toolkit 이 그 적대성 살아남는 move set — 깔끔하게 extract, 정직하게 capture, visibly mutate, 우아하게 undo.
이 track 에 일부러 없는 것. Full-page 렌더링 (PDF, MHTML), accessibility tree walking, web-component slot mapping, 복잡한 form submission orchestration. 각자 자체 track 가능; ClipDeck 이 v1 엔 필요 없음. 패턴: feature 가 working ClipDeck 진척에 payback 없이 30 분 lesson 강제하면 defer.

Code

content.js — Track 7 도구들 위한 dispatcher 패턴·javascript
// content.js — 나중 lesson 의 도구 wire 하는 작은 dispatcher
const CD_TOOLS = {
  readability: null, // Lesson 2 가 할당
  selection: null,    // Lesson 3
  screenshot: null,   // Lesson 4 (SW 에 살아, 메시지 통해 호출)
  fillInput: null,    // Lesson 5
};

// 각 도구가 module load 시 자체 등록.
// content.js 가 얇은 coordinator 유지; 실제 logic 이 bundler (Track 8) 통해
// import 된 per-tool file 이나 옆 vendor 된 곳에 살아.

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message?.type === "tool") {
    const tool = CD_TOOLS[message.name];
    if (!tool) {
      sendResponse({ ok: false, reason: "unknown-tool" });
      return;
    }
    (async () => {
      try {
        const result = await tool(message.args);
        sendResponse({ ok: true, result });
      } catch (err) {
        sendResponse({ ok: false, reason: err.message });
      }
    })();
    return true;
  }
});

// 도구는 이렇게 자체 등록:
//   CD_TOOLS.selection = async (args) => { ... };
// Dispatcher 가 이름으로 route 하고 uniform 응답 shape 반환.

External links

Exercise

Code block 의 dispatcher skeleton 을 clipdeck/content.js 에 추가. Extension reload. Wikipedia article 열기, DevTools 열기, console 을 ClipDeck context 로 전환, chrome.runtime.sendMessage({type:'tool', name:'selection'}) 시도 — 아직 도구 등록 안 됐으니 {ok: false, reason: 'unknown-tool'} 얻어야 함. 이 track 의 Lesson 2–6 진행하면서 각자 CD_TOOLS.<name> 등록 추가. Dispatcher 의 목적은 content.js 작게 유지하고 기존 메시지 라우팅 안 만지고 새 도구 도착 가능하게.
Hint
메시지가 SDK error Receiving end does not exist 와 함께 돌아오면 content script 가 이 page 에 load 안 됨 — content_scripts.matches 가 URL 포함하는지 확인 (또는 narrow 했으면 chrome://extensions → ClipDeck → Site access). Dispatcher 가 async 도구가 sendResponse 부르게 listener 에서 true 반환 — 실제로 async 가 아닌 도구 추가할 때 그거 마음에. Sync handler 에 true 반환은 slot 낭비지만 깨뜨리진 않음.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.