[React] 10. Shadow DOM (ft. 영역전개)

“접근 금지” – Shadow DOM, 주술회전 ‘영역 전개’

“내 스타일에 간섭하지 마세요. 여긴 Shadow 영역입니다.”


웹 개발을 하다 보면 이런 생각이 들 때가 있다.

“왜 내가 꾸민 스타일이 자꾸 깨지지…?

내 버튼은 분명히 예뻤는데…?”

(※ 정확히 말하자면 React 개념보단 웹 컴포넌트 쪽에 가까워요.
하지만 따로 섹션이 없으니 여기 React 영역에 올려두겠슴다 🙃)

스타일의 영역 전개 – Shadow DOM이란?

Shadow DOM은 말 그대로 DOM의 그림자 세계.

브라우저가 제공하는 웹 컴포넌트(Web Components) 기능 중 하나로,

외부 스타일이나 스크립트가 내부에 간섭하지 못하는 독립된 DOM 트리를 만드는 것.

마치 자신만의 세계를 펼치는 고죠 사토루의 ‘무량공처’처럼,

이 영역 안에서는 내가 정의한 룰만 작동한다.

예를 들어 버튼 하나를 만들었다고 해보자.

<button class="a">버튼</button>

근데 갑자기 다른 CSS에서 .pretty 클래스를 오버라이딩해버리면?

당신의 예쁜 버튼은 누군가의 !important 한 방에 무너질 수도 있다.

주술회전의 ‘영역 전개(領域展開)’처럼

이때 Shadow DOM을 사용하면 외부 스타일이 침범하지 못한다.

진짜 스타일 방어막이 생기는 셈이다.
(단, 주술회전에서 강력한 공격을 받으면 부서지는 것 처럼 자바스크립트 로직은 통과가 된다)

React에서도 Shadow DOM을 쓰나?

여기서 헷갈리기 쉬운 포인트 하나!

“React는 Shadow DOM을 쓴다면서요?”

실은 React는 Shadow DOM을 쓰지 않아.

우리가 흔히 말하는 React의 ’가상 DOM(Virtual DOM)’과 Shadow DOM은 완전히 다른 개념이야.

Shadow DOM|브라우저가 제공하는 진짜 DOM 캡슐화 기능 (스타일 독립)
Virtual DOM|React가 내부적으로 쓰는 JS 객체 (성능 최적화용)

그러니까 “React는 Shadow DOM 기반이다”라는 말은 틀린 말!

React는 Shadow DOM을 직접 사용하지 않지만, 커스텀 엘리먼트와 함께 쓸 수는 있어.

그럼 React에서 Shadow DOM을 쓰려면?

우리는 React에서도 attachShadow() API를 직접 써서 Shadow DOM을 붙일 수 있어.

하지만 좀 귀찮고 복잡하지.

그래서 보통은 외부 라이브러리를 써!

import ShadowDOM from 'react-shadow';

function MyComponent() {
  return (
    <ShadowDOM.div>
      <style>{`p { color: red; }`}</style>
      <p>이건 Shadow DOM 안에 있어요!</p>
    </ShadowDOM.div>
  );
}

이렇게 감싸주면 p 태그는 외부 CSS 영향을 받지 않고, 이 안에서 정의한 스타일만 적용돼.

실무 ?

솔직히 말하면 Shadow DOM을 직접 쓰는 일은 많지 않아.

하지만 다음과 같은 경우에 만나게 될 수도 있어:

  1. 메인보드급 독립 디자인

    • 헤더, 채팅 위젯, 버튼 등 절대 외부 스타일 간섭 받으면 안 되는 컴포넌트에 유용
  1. 외부 라이브러리 컴포넌트

    • 예: date-picker, modal, toast 같은 UI 라이브러리에서 스타일 충돌을 피하려고 Shadow DOM을 사용하는 경우 많음

정리해보자 – Shadow DOM 핵심 요약

  • Shadow DOM은 브라우저가 제공하는 독립된 DOM 캡슐화 공간이다.

  • 외부 스타일이 침범하지 못하며, 내부에서 정의한 룰만 적용된다.

  • React는 Shadow DOM을 기본적으로 사용하지 않는다.

  • 필요할 땐 react-shadow 같은 라이브러리를 통해 사용할 수 있다.

  • 강력한 스타일 보호막이 필요할 때 써보자!