사용자 동작을 나열하며 간략히 공부해보자.

 

>>> 사용자 동작 시작

1. https://okayoon.tistory.com/ 를 검색한다.

 

2. DNS(Domain Name System)에서 주소를 검색, 해당 ip 주소를 찾아서 사용자가 입력한 URL과 함께 전달한다.

- 이때 캐싱된 DNS 기록이 있는지 먼저 확인한다.

 

3. 전달받은 ip 주소를 이용하여 웹 브라우저는 웹 서버에게 해당 웹 사이트의 리소스를 요청하고 해상 웹 서버는 리소스를 전달한다.

 

>>>> 전달받은 리소스를 통해 브라우저 렌더링 과정 시작

Main flow 예시 (출처: http://taligarsiel.com/Projects/howbrowserswork1.htm)

4. DOM Tree 구축을 위해 HTML을 파싱한다.

- DOM Tree는 문서 객체 모델로 모든 요소, 속성, 텍스트 등 (문서노드, 요소노드, 속성노드, 텍스트노드)을 트리 구조로 표현한 것.

- 중간에 외부 스타일 로드를 만나게되면 DOM Tree 생성을 중단하고 CSS 파싱을 시작한다.

- Style Sheets를 통해 CSSOM Tree를 생성한다.

- CSSOM Tree는 스타일 노드들을 트리 구조로 표현한 것. 

 

5. Render Tree 생성 

- DOM Tree와 CSSOM Tree를 통해 Render Tree를 생성한다.

- Render Tree는 최종적으로 실제 브라우저에 표현되어야하는 노드들로만 구성하여 트리 구조로 표현한 것.

(ex: <head> 태그나 display: none;와 같이 브라우저에 그려지지 않는 것들은 포함되지 않는다.)

- 만약 과정 중에 JS 코드를 만나게 된다면 JS 파싱을 위해 렌더링이 잠시 중단되고, JS 파싱이 끝난 후 재개된다.)

 

6. Layout (레이아웃)

- Render Tree와 viewport를 통해 노드들의 화면상 위치와 크기를 계산한다. 

(ex: 1em -> 16px)

 

7. Paint (그리기)

- Layout 단계에서 계산한 레이아웃을 각 레이어에 px 단위로 그린다. (이 단계에서 Layer 생성)

- Layout에 포함안된 속성들도 그린다. (ex: 색상, 그림자효과 등)

- Update Layer Tree: 렌더링에 사용될 최종 레이어들을 계산하여 생성하며 생성조건은 root object, css filter, position, transform, overflow, canvas, video....

- 사용자 경험을 위해 렌더링 엔진은 모든 파싱을 기다리지 않고 동시에 일부를 그리기 시작한다.

 

8. Composite (합성)

- Update Layer Tree에서 생성한 레이어들을 합성하여 한장의 비트맵으로 만들어 실제 화면에 나타낸다.

- 별도의 합성 스레드를 두어 합성 과정만 별도로 분리해서 진행한다.

 

Q. 만약 Re-rendering이 될 경우에는?

Reflow (리플로우)

- Layout 단계의 변화가 있을때 발생한다.

- Layout 계산부터 다시한다 (Layout -> Paint -> Composite)

Repaint (리페인트)

- Paint 단계의 변화가 있을때 발생한다.

- 재 결합된 Render Tree를 기반으로 다시 그린다. 

- Repaint는 Reflow가 발생하지 않고도 발생할 수 있다. (Paint -> Composite)

 

Q. <scrpt> 태그를 만나서 HTML 파싱이 중단되는 문제를 해결할 수는 없나?

script 태그에 async와 defer 속성을 사용할 수 있다. (둘 다 사용 시 우선순위는 async)

- async: 비동기

- defer: html 파싱이 끝나고 진행하는 속성

 

 


더 깊은 내용에 대해 알고 싶거나, 참고한 글을 확인하고 싶다면!

https://d2.naver.com/helloworld/59361

http://taligarsiel.com/Projects/howbrowserswork1.htm

 

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

 

 

+ Recent posts