폴리이엔엠 디지털 미디어 연구

쉐도우 돔 가이드: 캡슐화부터 SSR까지 45

최신 프론트엔드 생태계에서 '독립적이고 재사용 가능한 컴포넌트'를 만드는 것은 모든 개발자의 목표입니다. 웹 컴포넌트 기술의 핵심 축을 담당하는 쉐도우 돔(Shadow DOM)은 마크업 구조와 스타일, 동작을 페이지의 다른 코드와 충돌하지 않도록 숨기고 분리하는 완벽한 캡슐화를 제공합니다.

하지만 쉐도우 돔을 실무에 도입하다 보면 이벤트 처리, CSS 스타일링, 접근성, 그리고 서버 사이드 렌더링(SSR) 등에서 예상치 못한 장벽에 부딪히게 됩니다. 이 글에서는 쉐도우 돔의 기본 개념과 렌더링 원리, 그리고 최신 웹 표준이 이러한 문제들을 어떻게 해결해 나가고 있는지 깊이 있게 살펴보겠습니다.

1. Open vs Closed: 쉐도우 돔의 모드 선택

쉐도우 돔을 생성할 때(attachShadow), 개발자는 modeopen 또는 closed로 지정해야 합니다. 이 두 모드의 차이는 외부 자바스크립트가 컴포넌트 내부에 접근할 수 있는지 여부를 결정합니다.

일반적으로는 보안이나 극단적인 격리가 필요한 특수한 상황(예: 서드파티 스크립트의 간섭 방지)이 아니라면 Open 모드의 사용이 권장됩니다. Closed 모드는 완벽한 캡슐화를 제공하는 것처럼 보이지만, 브라우저 개발자 도구에서의 디버깅을 어렵게 만들고 내부 구조 확장을 가로막는 등 유연성을 떨어뜨리기 때문입니다.

2. 캡슐화의 부작용: 이벤트 리타겟팅(Event Retargeting)

쉐도우 돔 내부에서 발생한 이벤트가 외부(Light DOM)로 전파될 때, 브라우저는 캡슐화를 유지하기 위해 이벤트의 진원지를 숨깁니다. 이를 이벤트 리타겟팅이라고 합니다.

예를 들어 쉐도우 돔 내부에 있는 <button>을 클릭했을 때, 외부의 문서 레벨에서 이벤트를 감지하면 이벤트의 대상(target)은 실제 버튼이 아니라 쉐도우 돔을 품고 있는 호스트 요소(Host Element)로 나타납니다. 이는 쉐도우 돔 내부의 복잡한 구현 디테일을 외부로 노출하지 않으려는 브라우저의 의도적인 설계입니다. 1

3. 그림자 속 스타일링: CSS 통제권 뚫어보기

쉐도우 돔의 가장 큰 장점은 글로벌 CSS가 컴포넌트 내부로 스며들지 않는다는 점입니다. 하지만 디자인 시스템을 구축하다 보면 외부에서 컴포넌트의 테마나 스타일을 부분적으로 커스터마이징해야 할 때가 많습니다. 이때 사용할 수 있는 3가지 주요 전략이 있습니다.

  1. CSS 사용자 지정 속성(Variables): 쉐도우 돔의 경계는 CSS 변수(--var)의 상속을 막지 않습니다. 컴포넌트 내부에서 --btn-color와 같은 변수를 사용하도록 설계하면, 외부에서 변수 값을 재정의하는 것만으로 안전하게 테마를 변경할 수 있습니다.
  2. ::part() 의사 요소: 컴포넌트 개발자가 내부 특정 요소에 part="label"과 같이 이름을 부여해 두면, 외부 CSS에서 custom-element::part(label) 선택자를 사용해 해당 요소에만 직접 스타일을 주입할 수 있습니다.
  3. ::slotted() 의사 클래스: <slot>을 통해 외부에서 주입된 Light DOM 콘텐츠를 쉐도우 돔 내부에서 스타일링할 때 사용합니다. 단, 삽입된 최상위 요소에만 적용되며 그 자식 요소로는 CSS가 타고 내려가지 않는다는 제약이 있습니다.

4. 접근성의 단절과 ElementInternals

쉐도우 돔이 지닌 가장 까다로운 맹점 중 하나는 웹 접근성 훼손입니다. 쉐도우 돔의 경계는 aria-labelledby, aria-controls 등 ID 참조(IDREF)를 기반으로 하는 ARIA 속성들의 연결 고리를 끊어버립니다. 즉, 외부에 있는 <label id="my-label">을 쉐도우 돔 내부의 <input aria-labelledby="my-label">이 참조할 수 없게 되어 스크린 리더가 이를 올바르게 읽어내지 못합니다.

이 문제를 해결하기 위해 등장한 것이 바로 접근성 객체 모델(AOM)과 ElementInternals API입니다. 컴포넌트는 내부적으로 HTML 마크업의 속성을 억지로 조작하는 대신, ElementInternals 객체를 통해 브라우저 엔진에 직접 "나는 이런 역할(Role)과 상태를 가진 요소다"라고 기본 의미론(Default Semantics)을 선언할 수 있게 되었습니다. 2

5. 서버 사이드 렌더링(SSR)의 구원자: 선언적 쉐도우 돔(DSD)

전통적으로 쉐도우 돔은 자바스크립트의 attachShadow() 메서드를 통해서만 생성할 수 있었습니다. 이는 자바스크립트가 실행되기 전까지 화면이 렌더링되지 않거나 스타일이 깨진 채로 나타나는 현상(FOUC)을 유발하여 서버 사이드 렌더링(SSR) 생태계에서 웹 컴포넌트가 외면받는 결정적인 원인이 되었습니다.

웹 표준 위원회는 이 문제를 해결하기 위해 선언적 쉐도우 돔(Declarative Shadow DOM, DSD)을 도입했습니다. 이제 자바스크립트 없이 HTML 마크업만으로도 쉐도우 루트를 정의할 수 있습니다. 3

<custom-card>
  <template shadowrootmode="open">
    <style>
     .card-body { padding: 16px; border: 1px solid #ccc; }
    </style>
    <div class="card-body">
      <slot></slot>
    </div>
  </template>
  <h2>이 콘텐츠는 Light DOM입니다.</h2>
</custom-card>

HTML 파서가 shadowrootmode 속성을 가진 <template> 태그를 만나면, 즉시 이를 파싱하여 부모 요소의 쉐도우 돔으로 승격시킵니다. 이 기능은 2024년 8월을 기점으로 모든 주요 브라우저 엔진에서 완벽하게 지원하는 'Baseline' 기능으로 자리 잡았습니다. 덕분에 렌더링 속도와 검색엔진 최적화(SEO) 제약을 벗어던진 웹 컴포넌트는 완벽한 엔터프라이즈급 UI 기술로 거듭나고 있습니다.

결론

쉐도우 돔은 웹 생태계에 강력한 캡슐화 패러다임을 가져왔습니다. 엄격한 DOM 분리 원칙 때문에 스타일링이나 접근성 측면에서 한때 많은 불편함을 겪었던 것이 사실입니다. 그러나 ElementInternals의 도입과 선언적 쉐도우 돔(DSD)의 표준화 과정을 거치며, 브라우저 네이티브 기술의 아키텍처는 과거의 맹점들을 훌륭하게 극복해 냈습니다. 프레임워크의 유행에 흔들리지 않는 견고한 디자인 시스템을 구축하고 싶다면, 한층 더 성숙해진 쉐도우 돔과 웹 컴포넌트 표준에 다시 한번 주목해 볼 때입니다.

참고 자료

  1. ^ W3C. (2026-03-15). Shadow DOM and Events. DOM Standard. https://dom.spec.whatwg.org/#shadow-trees
  2. ^ MDN Web Docs. (2025-05-02). ElementInternals. Mozilla. https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals
  3. ^ Miller, J., Freed, M. (2024-08-13). Declarative Shadow DOM. web.dev. https://web.dev/articles/declarative-shadow-dom