가상화의 기준

2025. 12. 3. 13:18개발/fe

반응형

 

1. 브라우저가 실제로 느려지는 기준(실제 현업 경험 기반)

아래는 Chrome·Safari·Firefox 공통적으로 널리 받아들여지는 DOM 규모 기준이다.

DOM 노드 개수 기준

DOM 노드 수 체감 성능 설명

0 ~ 1,500개 매우 빠름 거의 모든 상황에서 문제 없음
1,500 ~ 3,000개 대체로 빠름 스타일 복잡하면 느려질 수 있음
3,000 ~ 10,000개 주의 필요 스크롤 시 프레임 드랍 시작
10,000 ~ 50,000개 느려짐 레이아웃 계산과 페인트에 랙 발생
50,000개 이상 매우 느려짐 가상화 없이는 실사용 불가

※ “div 개수”가 아니라 “DOM 전체 노드” 기준임
(각 div 안에 span, text node 등이 있으면 실제 노드는 훨씬 많아짐)


2. 리스트/테이블 같은 반복 요소에서의 기준

리스트 렌더링의 경우에는 다음이 더 Practical한 기준이다.

스크롤 가능한 UI에서의 가상화 필요 기준

DOM 항목 수 가상화 필요 여부

0 ~ 200개 불필요
200 ~ 500개 조건부 필요. 애니메이션/반응형 레이아웃 사용 시 가상화 권장
500 ~ 2,000개 대부분 가상화 필요
2,000개 이상 무조건 가상화해야 함

React·Vue 기반 앱에서도 동일하며, React Window/Virtualized 등이 바로 이 기준을 근거로 만들어진 것.


3. 왜 느려지는가 (Chrome 기준 성능 병목 요소)

Chrome의 렌더링 파이프라인에서 느려지는 구간은 아래와 같다.

  1. 스타일 계산 (Style Recalc)
    • DOM 노드 수와 CSS 복잡도에 비례해 증가한다.
  2. 레이아웃(Layout / Reflow)
    • 부모-자식 전체 트리를 다시 계산해야 해서 트리 크기에 민감하다.
  3. 페인팅(Paint) + 컴포지팅
    • 영역이 많아지고 오버플로우/스크롤/섀도우 등이 많을수록 느려진다.

즉, 단순히 div 개수만 문제가 아니라:

  • CSS depth
  • flex / grid 사용 여부
  • shadowDom 여부
  • resize 발생 빈도
  • 스크롤 시 repaint 영역

등이 모두 영향을 준다.


4. “가상화 적용해야 하는 기준” 결론

가상화(virtual scrolling, windowing)를 적용해야 할 판단 기준을 요약하면 다음과 같다.

✔ 반드시 가상화해야 하는 상황

  • 리스트 항목이 500개 이상
  • DOM 노드가 총 10,000개 이상
  • “스크롤 시 렉”이 발생
  • 테이블 컬럼/로우가 동적으로 늘어나는 UI
  • 모바일 사양 고려해야 할 때

✔ 고려할 필요 없는 상황

  • 화면 전체 DOM이 1,500개 이하
  • 항상 고정된 UI(리스트 스크롤 없음)
  • 애니메이션, sticky header, infinite scroll 등 기능이 없는 단순 렌더링

5. 추천 실무 가이드라인

  1. 스크롤 되는 리스트라면
    100개 이하면 가상화 불필요,
    300개 넘어가면 무조건 가상화 고려
  2. DOM 전체 노드 수가
    3,000개 넘어가면 성능 점검,
    10,000개 넘어가면 반드시 최적화 필요
  3. Lighthouse 성능 점수 기준
    • “Large DOM” 경고가 뜨면 노드 수가 약 1,400개 이상이라는 의미

 

갯수 확인 방법

 

 

 

Chrome DevTools에서 DOM 노드 개수를 직접 확인하는 가장 신뢰성 높은 방법을 정리해준다. 실무에서 성능 체크할 때 흔히 쓰는 방식들이다.


1. Chrome DevTools → Performance 패널로 측정

가장 정확하고 권장되는 방법.

방법

  1. Chrome DevTools 열기 (F12)
  2. 상단 탭에서 Performance 선택
  3. Record 버튼 클릭
  4. 페이지를 스크롤하거나 문제 구간을 재현
  5. Record 중지
  6. 하단에 Summary → DOM Nodes 확인

장점

  • 전체 DOM 노드 수 확인 가능
  • GC 후 살아남은 노드 개수(Live DOM Nodes)도 확인 가능 → 메모리 누수 분석에 중요
  • 스크립트·레이아웃·페인트까지 트리거 원인을 종합 분석 가능

2. Memory 패널 → Heap Snapshot에서 확인

대규모 페이지 진단할 때 유용.

방법

  1. DevTools → Memory
  2. Take Heap Snapshot
  3. 생성된 Snapshot에서 Summary 뷰 선택
  4. HTMLDivElement / Node / Element 기반으로 개수 확인 가능

장점

  • div, span, li 등 개별 노드 타입별 개수 확인 가능
  • “Detached DOM Nodes”도 보여줘서 메모리 누수 감지 가능

3. 콘솔에서 JavaScript로 직접 DOM 노드 수 계산

빠르게 보는 간단한 방법.

방법 A) 전체 노드 수(모든 element)

document.getElementsByTagName('*').length

방법 B) 특정 태그만

document.querySelectorAll('div').length

방법 C) Text node 포함한 전체 노드 수

(function count(node) {
  let total = 1;
  node.childNodes.forEach(n => total += count(n));
  return total;
})(document.body)

장점

  • 가장 빠르고 단순
  • 특정 섹션별 DOM 수 확인 가능
  • 스크롤 이벤트 중에 실시간 측정도 가능

4. Chrome DevTools → Elements → “DOM Breakpoints” 사용

직접 개수를 보여주진 않지만, 노드 추가/삭제를 추적할 수 있어 DOM 증가 패턴 분석에 유용.

사용법

  1. Elements 패널에서 body 또는 특정 컨테이너 선택
  2. 우클릭 → Break on → Subtree modifications
  3. 변경 시점에서 call stack 추적 가능

장점

  • 의도치 않은 DOM 폭증 문제 디버깅에 적합
  • 프레임워크 이슈(React useEffect 중복 실행 등) 찾는 데 좋음

5. Lighthouse 성능 점검

"Avoid large DOM size" 경고로 DOM 노드 수(대략 1,400개 이상임)를 알려줌.

방법

  1. DevTools → Lighthouse
  2. Performance → Generate Report
  3. Avoid large DOM size 항목 확인

추천 실무 팁

  • 2000개 이상이면 성능 점검 필요
  • 5000~10000개는 레이아웃 리플로우에 영향
  • 10000개 이상은 가상화(Windowing) 고려 필수

 

 

 

 


DOM 크기가 커질 때 발생하는 주요 성능 문제

DOM이 커질수록 다음 작업 비용이 증가한다:

1) 스타일 계산(style recalc)

CSS 선택자가 깊어질수록 재계산 비용 증가
특히 div div div input[type="checkbox"] 같은 깊은 selector 사용 시 더 악화됨

2) 레이아웃(Reflow)

부모 → 자식 트리를 전체 순회하므로, 트리 깊이가 성능에 직접 영향

3) 페인트(Paint)

요소 수가 많거나 clipping/scroll 영역이 많으면 paint 시간이 증가

4) 메모리 증가

DOM 객체 자체가 일정 메모리를 사용


3. DOM 크기 최적화 전략 (실제 적용 가능한 항목 위주)

✔ 1) DOM 깊이 완화: Nesting 줄이기

현재 깊이 21은 웹 페이지 기준으로 꽤 깊다.

개선 방향

  • 불필요한 <div> 래퍼 제거
  • 스타일링 목적의 중첩 div → CSS Grid/Flexbox 로 구조 간소화
  • 의미 없는 wrapper 요소 제거 (예: .container > .inner > .wrapper 구조)

체크 예시

문제 있는 패턴:

<div>
  <div>
    <div>
      <input ... >
    </div>
  </div>
</div>

개선:

<div class="input-wrapper">
  <input ...>
</div>

✔ 2) Scroll 영역 내 DOM 최적화

가장 많은 자식을 가진 요소가
DIV.c-topnav-navcontainer-scroll 이라면, 스크롤 영역 가상화 고려 가능

적용 기준

  • 자식 50~200개: 문제 없을 가능성 큼
  • 300개 이상: 스크롤 시 랙 발생 가능 → virtual scroll 검토

현재 자식 수 22개는 문제 없음.
그러나 확장될 가능성이 있다면 구조 미리 설계하는 것이 좋다.


✔ 3) CSS 선택자 최적화

DOM 깊이가 깊다면 CSS selector 계산 비용도 증가한다.

지양:

.header .nav .menu .item input[type="checkbox"] { ... }

권장:

.chk-all { ... }

✔ 4) 불필요한 DOM 제거

다음 패턴은 성능을 악화시키는 공통 요소:

  • 숨겨진 영역을 DOM에 미리 렌더링 해둔 경우
  • 탭/모달을 display: none 상태로 쌓아 둔 경우
  • 리스트 항목 템플릿을 화면에 미리 복제한 경우

IntersectionObserver 를 이용한 lazy render 도 가능


✔ 5) 이벤트 위임 사용

많은 input/checkbox가 존재한다면 각 요소에 직접 handler를 붙이지 말고 상위에서 event delegation 처리.

document.querySelector('.table').addEventListener('click', e => {
  if (e.target.matches('input[type="checkbox"]')) {
    // 처리
  }
})

✔ 6) 너무 많은 SVG 아이콘 inline 삽입 금지

Inline SVG가 늘어나면 DOM 수 폭증
→ sprite sheet, symbol, img 태그로 대체 가능

 

 

 

반응형

'개발 > fe' 카테고리의 다른 글

Turborepo 개념 정리  (0) 2025.12.10
console.log와 성능  (1) 2025.12.03
AI 로 프런트 디자인 하는 방법  (0) 2025.08.18
"data-toggle"  (0) 2023.05.18
컴포넌트 만들시  (0) 2023.04.25