Language/Javascript

Shadow DOM이란? + Shadow DOM 활용 예시

둉이 2024. 8. 6. 13:40

Shadow DOM이란?

Shadow DOM은 독립적인 DOM 트리를 생성할 수 있게 해주는 웹 표준이자, 웹 컴포넌트의 핵심적인 기술 중 하나이다.

 

캡슐화를 통해 마크업 구조, 스타일, 로직을 숨기고 페이지 내 다른 코드로부터 분리되어 코드 충돌이 없게 만들어준다.

 

 

input[type=text] 요소를 예시로 들어 보자.

 

좌측 코드처럼 input 태그의 placeholder 가상 요소에 color 스타일을 주면 placeholder의 글자 색을 바꿀 수 있다.

 

화면에 렌더링된 input 태그를 확인해 봐도 글자 색이 보라색으로 잘 변경이 된 것을 확인할 수 있지만, 개발자 탭에서는 placeholder 요소에 적용한 스타일이 보이지 않는다.

개발자 탭에서는 input 요소의 내부가 보이지 않음

 

 

이유는 바로 input 태그 안에 있는 placeholder가 Shadow DOM 내에 있기 때문이다.

 

그럼 Shadow DOM은 어떻게 확인할 수 있을까?

 

 

Shadow DOM 확인 방법

Shadow DOM을 확인하기 위해서는 (크롬 기준) 개발자 도구 - 설정에서 Show user agent shadow dom 옵션을 체크해주면 된다.

Shadow DOM 조회 가능하도록 설정 변경

 

이제 개발자 도구에서 Shadow DOM 조회가 가능해졌다.

 

<input> 태그 외에도 화면을 만들 때 유용하게 사용할 수 있는 <progress>, <video> 태그도 Shadow DOM을 사용한 대표적인 예시이다.

 

 

모드

Shadow DOM은 외부 JavaScript에서의 shadowRoot 접근 가능 여부에 따라 열린(open) 모드와 닫힌(closed) 모드로 나뉜다.

 

열린 모드에서는 shadowRoot를 통해 Shadow DOM 요소 내부에 접근이 가능하다.

 

innerHTML, querySelector를 호출하여 내부 요소의 정보를 가져올 수도 있고, append를 호출하여 요소 추가 및 삭제도 가능하다.

 

닫힌 모드에서는 shadowRoot 접근이 되지 않으므로 내부 요소 접근이 불가능하다.

 

크롤링 등 외부 접근을 막고 싶다면 닫힌 모드를 사용하는 것이 좋다.

 

 

구조

shadow DOM의 구조 및 구성 요소를 그림으로 표현하면 다음과 같다.

shadow DOM의 구조

 

Shadow HostShadow DOM이 부착되는 일반 DOM의 요소를 말한다.

 

Shadow TreeShadow DOM 내부의 DOM 트리를 말한다.

 

Shadow BoundaryShadow DOM과 일반 DOM을 구분하는 경계이다.

 

Shadow RootShadow Tree의 루트 노드를 의미한다.

 

 

장점

Shadow DOM은 크게 두 가지의 장점을 갖는다.

 

 

독립적인 스코프

Shadow DOM은 외부 환경과는 독립적인 스코프를 갖기 때문에 외부 자바스크립트, CSS의 영향을 받지 않는다.

 

해당 요소에서만 사용되는 독립된 기능 구현이나 스타일 추가시 유용하다.

 

HTML / CSS / Javascript를 하나의 Shadow DOM 내에 관리하게 되면 코드 관리에도 용이하다.

 

불필요한 리렌더링 방지

브라우저가 Shadow DOM을 별도로 처리하여 렌더링 성능이 향상될 수 있다.

 

메인 DOM의 변경이 Shadow DOM에 영향을 주지 않으므로 불필요한 리렌더링을 방지하기 때문이다.

 

 

예제 코드

예제를 통해 Shadow DOM을 생성하고, 내부에 요소를 추가하는 방법을 알아보자.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Shadow DOM without createElement</title>
  </head>
  <body>
    <div id="wrap"></div>

    <script>
      // 1. Shadow DOM을 호스트할 요소 선택
      const host = document.getElementById("wrap");

      // 2. Shadow DOM 생성
      const shadow = host.attachShadow({ mode: "open" });

      // 3. Shadow DOM 내에 콘텐츠 추가
      shadow.innerHTML = `
            <style>
                .blue {
                    color: blue;
                }
                .red {
                    color: red;
                }
            </style>
            <p class="blue">Hello, Shadow DOM!</p>
            <div id="container"></div>
        `;

      // 4. Shadow DOM 내부의 container 요소 선택
      const container = shadow.getElementById("container");

      // 5. container 요소를 통해 추가 콘텐츠 삽입
      container.insertAdjacentHTML(
        "beforeend",
        '<p class="red">Hello, Container!</p>'
      );
    </script>
  </body>
</html>

 

먼저, Shadow DOM을 부착하기 위한 Shadow Host를 선택한다.

 

attachShadow 메소드를 호출하여 Shadow Host 내부에 Shadow DOM을 생성할 수 있다.

 

예제 코드에서는 mode의 인자로 'open'을 넘겨서 열린 모드의 Shadow DOM을 선언했는데, 닫힌 모드로 만들고 싶다면 'closed'를 넘겨주면 된다.

 

innerHTML, insertAdjacentHTML 등의 메소드를 통해 style, html 요소 등 내부 컨텐츠를 추가할 수 있다.

 

 

 

Shadow DOM 활용 예시

Shadow DOM의 캡슐화, 모듈화 특성은 다양한 곳에서 유용하게 사용될 수 있다.

 

예시를 알아보자.

 

 

HTML Template과 웹 컴포넌트

HTML Template이란 재사용 가능한 HTML 마크업을 정의할 수 있는 기술이다.

 

<template> 태그를 사용하여 템플릿을 선언하고, 내부에 <slot> 요소를 추가하여 외부에서 템플릿 내부로 동적 컨텐츠를 삽입할 수 있다.

 

HTML Template은 주로 Shadow DOM과 함께 웹 컴포넌트 구현에 사용된다.

 

웹 컴포넌트에 대한 자세한 설명은 아래 링크에 잘 정리되어 있다.

 

웹 컴포넌트 - Web API | MDN

웹 컴포넌트는 그 기능을 나머지 코드로부터 캡슐화하여 재사용 가능한 커스텀 엘리먼트를 생성하고 웹 앱에서 활용할 수 있도록 해주는 다양한 기술들의 모음입니다.

developer.mozilla.org

 

 

 

크롤링 막기

사이트를 운영하다 보면 크롤러로 인해 몸살을 앓을 때가 많다.

 

특히 이커머스 사이트는 크롤러가 가격 정보나 검색 결과를 긁어가는 경우가 많으며, 최근 지마켓에서는 과도한 악성 크롤링 봇으로 인해 서버가 다운되는 이슈도 있었다.

 

Gmarket Mobile Web Vip 악성 봇 대침투 사건

Gmarket Mobile Web Vip 악성 봇 대침투 사건안녕하세요 저는 VI Engineering 팀 김윤제입니다.Gmarket Mobile Web Vip(View Item Page = 상품 상세)를 담당하고 있는 Backend Engineer 입니다. 올해 1월 6일부터 Gmarket Mobile

dev.gmarket.com

 

이러한 악성 크롤링 봇을 퇴치하는 방법은 여러 가지가 있지만, 프론트엔드에서도 간단하게 Shadow DOM을 이용하여 크롤링을 막을 수 있다.

 

닫힌(closed) 모드의 Shadow DOM은 내부 요소 접근이 불가능하기 때문에 HTML 파싱 방식의 크롤링이 불가하다.

 

이러한 특징을 이용하면 아래처럼 크롤링이 불가능한 상품 영역 구현이 가능하다.

See the Pen shadow dom test by MiJeong Kim (@sap03110) on CodePen.

 

물론 OCR 방식의 크롤러까지는 막을 수 없긴 하지만, 대부분의 케이스는 막을 수 있다.

 

 

 

사용시 주의사항

Shadow DOM을 사용하기 전에 고려해야 할 사항은 다음과 같다.

 

 

브라우저 호환성

Shadow DOM은 Firefox (63 이상), Chrome, Opera, Safari에서 기본으로 지원한다.

 

새로운 Chromium 기반의 Edge (79 이상) 또한 Shadow DOM을 지원하나, 구버전 Edge를 포함한 IE에서는 지원되지 않는다.

 

자세한 호환 정보는 아래 링크를 통해 확인이 가능하다.

 

 

Shadow DOM (V1) | Can I use... Support tables for HTML5, CSS3, etc

Method of establishing and maintaining functional boundaries between DOM trees and how these trees interact with each other within a document, thus enabling better functional encapsulation within the DOM & CSS.

caniuse.com

 

 

이벤트 전파

Shadow DOM 내에서 일어나는 load, unload 등의 일부 이벤트는 Shadow DOM 내에서만 제한되며, 외부로 전파되지 않는다.

 

하지만 focus, 키보드 및 마우스 이벤트는 Shadow DOM 외부로 전파(= 버블링)되기 때문에 이벤트 핸들링할 때 주의해야 한다.

외부로 전파되는 이벤트 외부로 전파되지 않는 이벤트
blur, focus, focusin, focusout
click, dblclick
mousedown, mouseup, mousemove, mouseout, mouseover
wheel
beforeinput, input, keydown, keyup
load, unload, abort, error
mouseenter, mouseleave
select, slotchange

 

 

 

참고 링크

 

웹 컴포넌트(3) - 쉐도우 돔(#Shadow DOM)

이 글은 웹 컴포넌트 소개 연재로 그중 세 번째인 쉐도우 돔에 대한 글이다. 아마도 이전 글의 커스텀 엘리먼트 글을 읽고 온 분은 여러 스펙, API, 기억해 두어야 할 것들로 질렸을지도 모르겠다.

ui.toast.com

 

Shadow DOM and events

 

ko.javascript.info

 

shadow DOM 사용하기 - Web API | MDN

웹 컴포넌트의 중요한 측면은 캡슐화입니다. 캡슐화를 통해 마크업 구조, 스타일, 동작을 숨기고 페이지의 다른 코드로부터의 분리하여 각기 다른 부분들이 충돌하지 않게 하고, 코드가 깔끔하

developer.mozilla.org