ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DocumentFragment으로 DOM 조작하기
    FE 2025. 9. 8. 22:58

    👻 DOM 트리에 노드를 추가

    createElement 와 appendChild 를 사용해서 DOM 트리에 노드를 추가할 수 있습니다.

    const container = document.createElement('div'); // 노드를 생성
    const content = document.createElement('div');
    container.appendChild(content); // DOM 트리에 추가

    ⚠️ 문제점

    이렇게 직접 DOM에 접근하여 노드를 추가하게 되면 DOM에서 매번 reflow가 발생하여 문제가 발생합니다.

     

    📖 reflow

    요소의 너비, 높이, 위치 등이 변경되어 render tree가 재생성

    • 특정 요소에서 reflow가 발생하면 주변 요소(부모, 자식, 형제)에도 영향을 주게 됩니다.

     

    🔍 DocumentFragment

    DocumentFragment 객체는 DOM 요소를 메모리에 저장하는 임시 저장소입니다.

     

    DocumentFragment는 일반 DOM 처럼 요소를 추가하거나 조작할 수 있습니다.

    • 이 과정에서 웹 페이지에는 변화가 없습니다.

     

    이후, 여러개의 요소들을 저장한 후 하위 DOM 트리를 준비한 후 DOM에 하위 트리를 추가합니다.

    • 이때 DocumentFragment의 노드들이 모두 DOM으로 이동하고 빈 DocumentFragment만 남게됩니다.
    • 모든 노드가 한 번에 추가되기 때문에 리플로우도 한 번만 발생하게 됩니다.

     

    🖥️ 사용 예제

    const fragment = document.createDocumentFragment();
    
    for (let i = 0; i < 10; i++) {
      const text = document.createElement('p');
      fragment.appendChild(text);
    }
    
    document.body.appendChild(fragment);

     

    🏄‍♂️ 동작과정

     

    1️⃣ document.createDocumentFragment()로 메모리 상의 가상 DOM 컨테이너인 fragment를 생성

     

    2️⃣ 반복문을 돌며 <p> 요소 10개를 만들고 이 요소들을 fragment에만 추가합니다.

    • 이 시점까지는 브라우저의 실제 DOM 트리에 전혀 변화가 없음
    • → 리플로우(Reflow), 리페인트(Repaint) 없음

    3️⃣ 마지막에 fragment를 한 번에 실제 DOM에 추가해 화면에 표시됩니다.

    • <p> 요소 10개가 한 번의 DOM 업데이트로 추가됩니다.
    • 이때 reflow 한 번 발생

     

    🆚 createElement와 비교해보기

    const ELEMENT_COUNT = 10000;
    
    function clearBody() {
      while (document.body.firstChild) {
        document.body.removeChild(document.body.firstChild);
      }
    }
    
    // DocumentFragment 사용한 경우
    function testWithoutFragment() {
      clearBody();
      console.time('Without DocumentFragment');
    
      for (let i = 0; i < ELEMENT_COUNT; i++) {
        const p = document.createElement('p');
        p.textContent = `문단 ${i + 1}`;
        document.body.appendChild(p); // 매번 DOM 업데이트 발생
      }
    
      console.timeEnd('Without DocumentFragment');
    }
    
    // DocumentFragment 사용한 경우
    function testWithFragment() {
      clearBody();
      console.time('With DocumentFragment');
    
      const fragment = document.createDocumentFragment();
    
      for (let i = 0; i < ELEMENT_COUNT; i++) {
        const p = document.createElement('p');
        p.textContent = `문단 ${i + 1}`;
        fragment.appendChild(p); // 메모리 상에서만 작업
      }
    
      // 한 번에 DOM 업데이트
      document.body.appendChild(fragment);
    
      console.timeEnd('With DocumentFragment');
    }
    
    // 실행
    console.log(`테스트 시작: ${ELEMENT_COUNT.toLocaleString()}개의 <p> 태그 생성`);
    testWithoutFragment();
    testWithFragment();

     

     

    🖥️ 결과

    'FE' 카테고리의 다른 글

    프론트엔드 빌드, 번들러  (0) 2025.09.22
    History API 와 클라이언트 라우팅  (1) 2025.09.08
    프론트엔드 아키텍처 구조 - MVC, MVVM  (0) 2025.09.02

    댓글

Designed by Tistory.