프론트엔드 개발에서 컴포넌트 기반 아키텍처가 중요해지면서, Shadow DOM의 중요성도 함께 커지고 있습니다. 이 글에서는 Shadow DOM의 개념부터 실제 사용 방법까지 자세히 알아보겠습니다.

이미지 출처 - https://www.ionos.com/digitalguide/websites/web-development/shadow-dom/
Shadow DOM은 웹 컴포넌트(Web Components)의 핵심 기술 중 하나로, DOM 캡슐화를 가능하게 해주는 기능입니다. 쉽게 말해, 컴포넌트 내부의 DOM과 스타일을 외부로부터 격리시키는 기술입니다.
<host-element>
#shadow-root (open)
<style>
p { color: red; }
</style>
<p>Hello Shadow DOM</p>
</host-element>
위 예시에서 볼 수 있듯이, Shadow DOM은 일반 DOM과 달리 Shadow Root를 가진 트리 구조를 가집니다. 이 구조를 통해 컴포넌트 내부의 스타일이 외부에 영향을 주지 않고, 외부 스타일도 컴포넌트에 영향을 주지 않게 됩니다.
class MyElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
p { color: blue; font-weight: bold; }
</style>
<p>This is inside Shadow DOM</p>
`;
}
}
customElements.define('my-element', MyElement);
<my-element></my-element>
attachShadow(): Shadow Root를 생성하는 메서드
const shadow = this.attachShadow({ mode: 'open' });
innerHTML: Shadow DOM에 직접 HTML 삽입
shadow.innerHTML = `<p>Content</p>`;
Shadow DOM은 두 가지 모드를 제공합니다:
| 모드 | 설명 | 접근성 |
|---|---|---|
| open | 외부에서 element.shadowRoot로 접근 가능 | element.shadowRoot로 접근 가능 |
| closed | 외부 접근 불가능 | shadowRoot는 null 반환 |
const shadow = this.attachShadow({ mode: 'closed' });
console.log(this.shadowRoot); // null
class CustomButton extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
button {
padding: 10px 20px;
border: none;
border-radius: 4px;
background: #007bff;
color: white;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
</style>
<button><slot></slot></button>
`;
}
}
customElements.define('custom-button', CustomButton);
class AdWidget extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'closed' });
shadow.innerHTML = `
<style>
.ad-container {
width: 300px;
height: 250px;
border: 1px solid #ccc;
}
</style>
<div class="ad-container">
<!-- 광고 콘텐츠 -->
</div>
`;
}
}
customElements.define('ad-widget', AdWidget);
Shadow DOM은 웹 컴포넌트 개발에서 필수적인 기술입니다. 특히 다음과 같은 상황에서 큰 장점을 발휘합니다:
React, Vue, Svelte 등에서는 Shadow DOM을 직접 사용하지 않지만, Web Components 기반 프레임워크나 Vanilla JS에서는 중요한 기술입니다. 특히 디자인 시스템을 구축하거나 외부 영향 없이 안정적인 UI를 만들고자 할 때 큰 도움이 됩니다.