본문 바로가기

읽고 요약/pages

[아티클 프로젝트 009] shadowDOM

shadowDOM

 

HTML, CSS, JS 전반적 특성 때문에 생기는 웹앨 빌드의 취약성을 제거한다.

id나 class가 중복되어도 충돌되는지에 대한 여부를 알려주지 않기때문에 버그가 많았다.

스타일이 쌓이고 쌓이다가.. 도저히 안될때면 !important를 통해 스타일을 해결하기도 했다.

 

shadowDOM은 CSS및 DOM을 수정한다.

vanilla 자바스크립트에서 CSS를 마크업과 번들로 묶고 세부정보를 숨겨 자체포함 구성요소로 작성할 수 있다.

 

구성요소

  • HTML Templates

  • Shadow DOM

  • Custom elements

  • HTML Imports

CSS범위, DOM 캡슐화 등이 shadowDOM으로 인해 재사용가능하기 때문에 

shadowDOM을 사용하면 웹 컴포넌트로 만들 필요가 없다.

 

  • 자체적으로 DOM이 포함되어있다.

  • document.querySelector 컴포넌트의 shadowDOM에서 노드를 반환하지 않음

  • CSS의 범위가 정해져있음

  • id, class 충돌에 대해 걱정하지 않아도됨

 

호스트에 shadow DOM을 붙이기 위해, attachShadow() 메서드를 사용한다.

주로 상호 작용하는 특정 요소들은 shadow host가 될 수 없기 때문에,

단순히 <a> 요소를 shadow host로 사용할 수 없다.

 

새로운 shadow tree를 만들기 위해 콘텐츠를 생성해야 한다.

shadow tree는 DOM tree와 비슷하지만 일반 DOM 대신 shadow DOM을 사용한다.

 

예시

-코드 출처 : https://wit.nts-corp.com/2019/03/27/5552

HTML

<div class="shadow-host"></div>

JS로 엘리먼트 삽입

// 호스트에 shadowDOM을 붙임
const shadowEl = document.querySelector(".shadow-host");
const shadow = shadowEl.attachShadow({mode: 'open'});
 
// 내부에 삽입할 엘리먼트 생성
const link = document.createElement("a");
link.href = shadowEl.querySelector("a").href;
link.innerHTML = `
    <span aria-label="Twitter icon"></span>
    ${shadowEl.querySelector("a").textContent}
`;
 
// shadowDOM에 삽입
shadow.appendChild(link);

JS로 CSS삽입

// shadowDOM에 추가할 스타일 태그 생성
const styles = document.createElement("style");
 
// 내부에 삽입할 스타일 생성
styles.textContent = `
a, span {
  vertical-align: top;
  display: inline-block;
  box-sizing: border-box;
}
a {
    height: 20px;
    padding: 1px 8px 1px 6px;
    background-color: #1b95e0;
    color: #fff;
    border-radius: 3px;
    font-weight: 500;
    font-size: 11px;
    font-family:'Helvetica Neue', Arial, sans-serif;
    line-height: 18px;
    text-decoration: none;
}
a:hover {  background-color: #0c7abf; }
span {
    position: relative;
    top: 2px;
    width: 14px;
    height: 14px;
    margin-right: 3px;
    background: transparent 0 0 no-repeat;
    background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2072%2072%22%3E%3Cpath%20fill%3D%22none%22%20d%3D%22M0%200h72v72H0z%22%2F%3E%3Cpath%20class%3D%22icon%22%20fill%3D%22%23fff%22%20d%3D%22M68.812%2015.14c-2.348%201.04-4.87%201.744-7.52%202.06%202.704-1.62%204.78-4.186%205.757-7.243-2.53%201.5-5.33%202.592-8.314%203.176C56.35%2010.59%2052.948%209%2049.182%209c-7.23%200-13.092%205.86-13.092%2013.093%200%201.026.118%202.02.338%202.98C25.543%2024.527%2015.9%2019.318%209.44%2011.396c-1.125%201.936-1.77%204.184-1.77%206.58%200%204.543%202.312%208.552%205.824%2010.9-2.146-.07-4.165-.658-5.93-1.64-.002.056-.002.11-.002.163%200%206.345%204.513%2011.638%2010.504%2012.84-1.1.298-2.256.457-3.45.457-.845%200-1.666-.078-2.464-.23%201.667%205.2%206.5%208.985%2012.23%209.09-4.482%203.51-10.13%205.605-16.26%205.605-1.055%200-2.096-.06-3.122-.184%205.794%203.717%2012.676%205.882%2020.067%205.882%2024.083%200%2037.25-19.95%2037.25-37.25%200-.565-.013-1.133-.038-1.693%202.558-1.847%204.778-4.15%206.532-6.774z%22%2F%3E%3C%2Fsvg%3E);
}다
`;
 
// shadowDOM에 삽입
shadow.appendChild(styles);

일반적인 방법과 동일하게 appendChild() 메서드를 사용하여 shadow DOM에 새로운 요소를 추가합니다.

shadowDOM을 하나의 페이지로 보지않고 각각의 컴포넌트 덩어리로 생각하면 편하다.

원본 글 캡쳐
원본 글 캡쳐
원본 글 캡쳐

shadow-root, html template를 확인할 수 있다.

 

원본 글 캡쳐


<slot> 태그 내부에 html template의 내용이 삽입된다.

만약 <slot> 비어있다면 슬롯이 대체 컨텐츠를 렌더링한다.

 

그외에 호스팅태그 접근, 상위태그접근 등 어떻게 사용하면되는지에 대해 자세하게 적혀있다.

 

역사관련 작성된 부분에서 말하듯 지난 2년동안 chrome 35+/opera가 한동안 shadowDOM을 제공했다고한다.

아티클 프로젝트를 하면서 내가 얼마나 최신 트렌드에 무뎠는지를 알게되는 경우가 많다.(최신도 아니지..)

 

shadowDOM v1은 chrome53, Opera 40, Safari 10 및 Firefox 63으로 제공됩니다. Edge 는 개발을 시작했다고하니.
IE 하위를 맞춰야하는것이 아니라면 <iframe> 대신에 써볼만 할 것같다.

iframe과는 다른 것으로 shadowDOM은 경량화된, 감춰진 DOM 트리로 보면된다.

보안을 원하면 iframe을 사용하도록...

 


원본 글

https://developers.google.com/web/fundamentals/web-components/shadowdom

그 외 참고

https://wit.nts-corp.com/2019/03/27/5552

https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow