Shadow DOM
최근 크롬 익스텐션 개발을 하다가 Shadow DOM에 대해서 접하게 되었는데, 이에 대해 간단히 정리해보았다.
Shadow DOM?
Shadow DOM이란, 기존에 존재하는 DOM 트리와 독립된 DOM 트리를 생성해주는 기술이다. 캡슐화를 통해 마크업 구조, 스타일, 동작을 숨기고 페이지의 다른 코드들로부터의 분리하여 기존의 코드들과의 충돌을 방지하고 코드들이 깔끔하게 유지될 수 있게 한다.

사실 Shadow DOM은 사실 완전히 새로운 개념은 아니며 브라우저는 오랫동안 내장 요소(예: <video>
, <audio>
)의 내부 구조를 캡슐화하기 위해 Shadow DOM을 사용해왔다고 한다.
Shadow DOM의 구조
기본 사용법
Shadow DOM을 사용하려면 Element.attachShadow()
메서드를 사용하여 요소에 Shadow root를 부착이 필요하다.
// open 모드로 Shadow root 생성
const shadowRoot = element.attachShadow({ mode: "open" });
// closed 모드로 Shadow root 생성
const shadowRoot = element.attachShadow({ mode: "closed" });
여기서 mode 옵션에 따라 다음과 같은 차이가 있다.
open
: 외부 JavaScript에서 element.shadowRoot를 통해 Shadow DOM에 접근 가능closed
: 외부에서 Shadow DOM에 접근 불가
Shadow root가 생성되면 일반 DOM API를 사용하여 Shadow DOM 내부에 요소를 추가하고 조작이 가능해진다.
// Shadow DOM 내부에 요소 추가하기
const paragraph = document.createElement("p");
paragraph.textContent = "이것은 Shadow DOM 내부의 요소입니다!";
shadowRoot.appendChild(paragraph);
React에서 Shadow DOM 사용하기
React에서도 Shadow DOM을 활용할 있다. 다음은 React 컴포넌트에서 Shadow DOM을 사용하는 간단한 예제이다.
import { useRef } from "react";
import "./App.css";
function App() {
const shadowHostNodeRef = useRef<HTMLDivElement | null>(null);
const createShadowDom = () => {
if (!shadowHostNodeRef.current) return;
// 이미 Shadow DOM이 있는지 확인
const shadowRoot =
shadowHostNodeRef.current.shadowRoot ||
shadowHostNodeRef.current.attachShadow({ mode: "open" });
// Shadow DOM 내부에 요소 생성
const paragraph = document.createElement("p");
paragraph.textContent = "이것은 Shadow DOM 내부의 요소입니다!";
paragraph.style.color = "red";
paragraph.id = "shadow_content";
shadowRoot.appendChild(paragraph);
};
const checkHasShadowContent = () => {
console.log({ "shadow-dom": shadowHostNodeRef.current?.shadowRoot });
};
return (
<div className="flex flex-col items-center">
<div className="text-blue-500 bg-white p-12" ref={shadowHostNodeRef}>
Shadow Host Node
</div>
<div className="card">
<button onClick={createShadowDom}>Create Shadow dom</button>
</div>
<div className="card">
<button onClick={checkHasShadowContent}>
check has shadow dom content
</button>
</div>
</div>
);
}
export default App;
이 예제에서는 useRef를 사용하여 DOM 요소에 대한 참조를 얻고, 버튼 클릭 시 해당 요소에 Shadow DOM을 부착 및 하위 컨텐츠들을 생성하는 예제이다.



이렇게 Shadow DOM을 통해서 스타일링 및 DOM 경리로 인해 독립적인 UI 구현이 가능하다.
크롬 익스텐션 개발에서는, Content Script 를 통해서 해당 브라우저 내 DOM을 조작하는 경우가 있는데 (현재 새로 마이그레이션하고 있는 사내 익스텐션 또한 기존 브라우저 내 DOM을 직접 조작해야 하는 상황이다.) Shadow DOM을 활용하면 좀더 유용할 것이라 생각된다.
Reference
'Etc' 카테고리의 다른 글
Copy right 자동 생성용 플러그인 만들기 (Webpack) (1) | 2024.09.18 |
---|---|
Page Object Models - Playwright (0) | 2023.10.16 |
소스맵 정리 (0) | 2023.09.28 |
TTF, OTF 폰트별 특징 (0) | 2023.07.28 |
리액트와 함께하는 테스트 격리(번역) (0) | 2023.04.17 |