[JS] documentFragment

Minyoung's Conference·2022년 10월 19일
0

JavaScript

목록 보기
28/28
post-thumbnail
처음 자바스크립트로 돔을 만들고 추가하는 방법을 배울 때 보통 
document.createElement()로 생성하고 
appendChild()를 이용해 바로 DOM에 등록하게 된다.

[코드 예시]
<body>
    <script>
      for (let i = 0; i < 10; i++) {
        let divEl = document.createElement("div");
        divEl.innerText = "Hello, this is" + i;
        document.body.appendChild(divEl);
      }
    </script>
</body>

// 화면에는 Hello, this is 1~10까지 나타나게 된다

**여기서 documentFragment 노드를 사용하면 오직 메모리상에만 존재하는 경량화된 DOM을 만들 수 있다.**

<body>
    <script>
      const docFrag = document.createDocumentFragment();
			// documentFragment를 for문 밖에 생성하고 

      for (let i = 0; i < 10; i++) {
        let divEl = document.createElement("div");
        divEl.innerText = "Hello, this is" + i;
        docFrag.appendChild(divEl);
				// for문 내에 docFrag에 divEl을 붙여주고
      }
      document.body.appendChild(docFrag);
			// body에 docFrag 노드를 붙여준다.
    </script>
  </body>

// 화면에는 똑같이 Hello, this is 1~10까지 나타나게 된다

**그럼 div요소를 하나 만들어 거기다 노드 트리를 만드는 것과 뭐가 다를까?**

<body>
    <script>
      const test = document.createElement("div");

      for (let i = 0; i < 10; i++) {
        let divEl = document.createElement("div");
        divEl.innerText = "Hello, this is" + i;
        test.appendChild(divEl);
      }
      document.body.appendChild(test);
    </script>
  </body>

// 화면에는 똑같이 Hello, this is 1~10까지 나타나게 된다
결과는 같다. 

**DocumentFragment의 특징**
1. DocumentFragment를 DOM노드에 추가한다고 해도 DocumentFragment 노드는 등록되지 않고 그 자식 노드들만 추가된다., 개발자도구에서 HTML을 확인하면 div 태그 내에 묶음으로 추가된 div 노드들이 있다.
하지만 DocumentFragment로 만든 노드는 각각의 div태그로 구성되어 독립적인 것을 볼 수 있다.

2. DocumentFragment를 DOM에 추가하면 DocumentFragment의 노드의 자식요소들은 더 이상 메모리 상에 존재하지 않는다.

자식요소를 확인해보자. (childNodes 속성이용)
console.log(docFrag.childNodes); // 등록 전
document.body.appendChild(docFrag); // body에 등록
console.log(docFrag.childNodes); // 등록 후

결과는 아래와 같다. 등록 전에는 자식 노드들이 뜨지만, 등록 후에는 뜨지 않는다.

이러한 특징 때문에 요소를 여러 개의 각기 다른 부모 요소에 집어넣을 때 더욱 깔끔한 코딩이 가능하다.

코드 예제를 통해 다시 한 번 비교해보자

**[일반적인 제작방식]**
<body>
    <div class="container"></div>
    <div class="container"></div>
    <div class="container"></div>
    <script>
      let element = [];
      for(let i =0; i <100; i++){
        const el = document.createElement("div");
        element.push(el);
      }

      const cont = document.querySelectorAll(".container");

      for(let i = 0; i< cont.length; i++){
        for(let j =0; j< element.length; j++){
          cont[i].appendChild(elements[j].cloneNode(true));
					// 배열은 참조타입이기 때문에 clone을 해줘야 한다.
        }
      }
    </script>
  </body>

**[DocumentFragment 사용] - 가상 돔처럼 fragment에 넣어 그것을 사용**

<body>
    <div class="container"></div>
    <div class="container"></div>
    <div class="container"></div>
    <script>
      const frag = document.createDocumentFragment();

      for (let i = 0; i < 100; i++) {
        const el = document.createElement("div");
        frag.appendChild(el);
      }

      const cont = document.querySelectorAll(".container");

      for (let i = 0; i < cont.length; i++) {
        cont[i].appendChild(frag.cloneNode(true));
      }
    </script>
  </body>

**[정리]**
- DocumentFragment 노드는 오직 메모리상에만 존재하는 경량화된 노드이다.
- DocumentFragment를 DOM에 추가한다고 해도 DocumentFragment노드는 추가되지 않고
	 그 자식노드만 추가된다.
- DocumentFragment를 DOM에 추가할 떄, DocumentFragment의 자식 노드는 더 이상 생성한 메모리상의 위치에 존재하지 않는다. 만약 이를 유지시키고 싶다면 cloneNode를 통해 복제하는 방법이 있다.
(cloneNode를 이용해 자식을 복사하면 frag.childNodes를 통해 자식을 확인할 수 있다.)

(인프런 "코딩인터뷰를 저격하는 JS 스나이퍼 양성학교" 참고)

profile
안녕하세요, FE 개발자 김민영입니다.

0개의 댓글