INP 프레젠테이션 지연: DOM 크기, 레이아웃 작업 및 렌더링 최적화

프레젠테이션 지연으로 인해 발생하는 INP 문제를 찾고 개선하는 방법을 알아보세요

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-04

프레젠테이션 지연으로 인해 발생하는 Interaction to Next Paint (INP) 문제

이 페이지는 Interaction to Next Paint (INP) 시리즈의 일부입니다. INP는 사용자 상호작용부터 다음 시각적 업데이트까지의 전체 시간을 측정합니다. 프레젠테이션 지연은 입력 지연(input delay)처리 시간(processing time)에 이어 INP의 세 번째이자 마지막 단계입니다. INP가 처음이시라면 먼저 INP 문제를 식별하고 해결하는 방법에 대한 가이드를 읽어보세요.

요약하자면: Interaction to Next Paint (INP)는 사용자가 페이지와 상호작용한 후 시각적 변화를 보기까지 걸리는 시간을 측정합니다. 이 INP 는 "입력 지연 (input delay)", "처리 시간 (processing time)", "프레젠테이션 지연(presentation delay)"이라는 3가지 구성 요소로 나눌 수 있습니다.

프레젠테이션 지연은 전체 INP에 가장 큰 영향을 미치는 요소로, 평균적으로 전체 INP 시간의 약 42%를 차지합니다. 렌더링 파이프라인을 최적화하고 HTML 구조를 단순화하는 것이 INP를 개선하기 위한 가장 큰 지렛대입니다.

프레젠테이션 지연: 버튼을 클릭하고 결과를 보는 데 왜 아주 짧은 순간이 더 걸렸는지 궁금했던 적이 있나요? 그것이 바로 Interaction to Next Paint (INP)가 작동하는 모습입니다. 프레젠테이션 지연은 상호작용 프로세스의 마지막 단계로, 클릭이 처리된 후 시각적 변화를 보기 전에 발생합니다.

프레젠테이션 지연 이해하기

프레젠테이션은 상호작용의 마지막 단계입니다. 프레젠테이션 지연은 상호작용에 따른 시각적 업데이트를 브라우저가 렌더링하는 데 걸리는 시간을 나타냅니다. 프레젠테이션 지연은 상호작용에 대한 이벤트 핸들러 실행이 완료되면 시작되어, 다음 프레임(시각적 변경 사항 포함)이 화면에 그려질 때(paint) 종료됩니다. 프레젠테이션 지연은 레이아웃의 복잡성, DOM의 크기, 필요한 렌더링 작업량 등 다양한 요인의 영향을 받을 수 있습니다.

inp 3 stage processing time highlighted

Interaction to Next Paint (INP)는 3가지 하위 부분인 "입력 지연(Input Delay)", "처리 시간(Processing Time)", "프레젠테이션 지연 (Presentation Delay)"으로 나눌 수 있습니다.

프레젠테이션 지연과 INP

프레젠테이션 지연은 INP의 마지막 단계입니다. 평균적으로 프레젠테이션 지연은 전체 INP 시간의 약 42%를 차지하여, 느린 상호작용을 유발하는 가장 큰 단일 요인이 됩니다.

inp distribution input delay highlighted

CoreDash에서는 매시간 수백만 개의 Core Web Vitals 데이터 포인트를 수집합니다. 이 데이터에 따르면, 프레젠테이션 지연은 Interaction to Next Paint의 42%를 차지합니다. 이는 처리 시간 (40%)보다 길고, 입력 지연 (18%)보다 훨씬 깁니다. 가장 큰 원인임에도 불구하고, 애플리케이션 코드가 아닌 브라우저의 렌더링 파이프라인과 관련되어 있기 때문에 최적화하기 가장 어려운 단계인 경우가 많습니다.

프레젠테이션 지연의 예: 휴대전화로 이커머스 웹사이트에서 새 신발을 찾고 있다고 상상해 보세요. 제품 이미지를 탭하여 자세한 내용을 확인하려고 합니다. 하지만 휴대전화가 구형이라 처리하는 데 어려움을 겪습니다. 이미지를 탭합니다(상호작용). 휴대전화가 요청을 처리하고 화면을 업데이트하는 데 시간이 약간 걸립니다(처리 시간). 웹사이트는 더 큰 이미지와 세부 정보가 포함된 새 페이지를 렌더링해야 합니다. 마침내 화면에 새로운 제품 세부 정보와 이미지가 나타나는 데 눈에 띄게 긴 시간이 걸립니다(프레젠테이션 지연). INP의 이러한 지연은 사용자에게 실망감을 줄 수 있으므로 이를 해결하는 것이 중요합니다.

높은 프레젠테이션 지연의 원인은 무엇인가요?

프레젠테이션 지연은 이벤트 핸들러가 종료된 후 화면에 픽셀이 나타나기 전까지 브라우저가 수행하는 모든 작업을 포함합니다. 여기에는 스타일 재계산, 레이아웃 계산, 페인팅 및 합성이 포함됩니다. 다음과 같은 여러 요인이 높은 프레젠테이션 지연에 기여합니다.

큰 DOM 크기

크거나 깊게 중첩된 DOM은 높은 프레젠테이션 지연의 가장 흔한 원인 중 하나입니다. 상호작용 후 브라우저가 페이지의 시각적 상태를 업데이트해야 할 때마다, 스타일을 재계산하고 레이아웃을 계산하며 영향을 받는 요소들을 다시 칠해야(repaint) 합니다. 이러한 각 단계의 비용은 영향을 받는 DOM 노드의 수에 비례하여 증가합니다.

Google은 DOM 요소를 1,400개 미만으로, 최대 깊이는 32단계, 부모 노드당 자식 요소는 60개를 넘지 않도록 유지할 것을 권장합니다(Lighthouse DOM 크기 감사 참조). DOM이 이러한 임계값을 초과하면, 브라우저는 각 상호작용 후 스타일 재계산 및 레이아웃 계산에 훨씬 더 많은 시간을 소비합니다.

다음 시나리오를 고려해 보세요. 사용자가 컨테이너 요소에서 CSS 클래스를 토글하는 버튼을 클릭합니다. 해당 컨테이너에 5,000개의 하위 노드가 있는 경우, 브라우저는 시각적으로 변경되는 요소가 몇 개뿐이더라도 잠재적으로 모든 노드에 대해 스타일을 재계산해야 합니다. 이러한 스타일 재계산은 다음 페인트 전에 동기적으로 발생하여 프레젠테이션 지연을 직접적으로 증가시킵니다.

DOM을 줄이기 위한 구체적인 기술은 과도한 DOM 크기 수정에 대한 가이드를 읽어보세요.

과도한 레이아웃 작업

레이아웃("리플로우(reflow)"라고도 함)은 브라우저가 페이지의 모든 표시 가능한 요소의 위치와 크기를 계산하는 프로세스입니다. DOM을 수정하거나 기하학적 형태(너비, 높이, 여백, 패딩, 상단, 좌측)에 영향을 주는 CSS 속성을 변경하는 상호작용 후, 브라우저는 업데이트된 프레임을 페인트하기 전에 레이아웃을 수행해야 합니다.

두 가지 패턴이 프레젠테이션 지연에 특히 해롭습니다.

강제 동기 레이아웃(Forced synchronous layout)은 JavaScript가 레이아웃을 무효화하는 DOM 변경을 수행한 직후 레이아웃 속성(예: offsetHeight 또는 getBoundingClientRect())을 읽을 때 발생합니다. 브라우저는 정확한 값을 반환하기 위해 이벤트 핸들러 내에서 동기적으로 레이아웃을 수행해야 합니다. 이 레이아웃 작업은 처리 시간의 일부가 되지만, 이후의 추가적인 DOM 변경으로 인해 트리거되는 후속 레이아웃은 프레젠테이션 지연의 일부가 됩니다.

레이아웃 스래싱(Layout thrashing)은 루프 내에서 DOM에 쓰고 레이아웃 속성을 읽는 반복적인 패턴입니다. 읽을 때마다 브라우저는 레이아웃을 다시 계산해야 하며, 쓸 때마다 레이아웃이 다시 무효화됩니다. 이로 인해 상호작용당 수십 또는 수백 번의 불필요한 레이아웃 계산이 발생할 수 있습니다. 다음은 레이아웃 스래싱 및 이를 해결하는 방법의 예입니다.

// 나쁨: 루프 내 레이아웃 스래싱
function resizeItems() {
  const items = document.querySelectorAll('.item');
  items.forEach(item => {
    // 읽기 (레이아웃 강제)
    const parentWidth = item.parentElement.offsetWidth;
    // 쓰기 (레이아웃 무효화)
    item.style.width = parentWidth + 'px';
  });
}

// 좋음: 일괄 읽기 후 일괄 쓰기
function resizeItems() {
  const items = document.querySelectorAll('.item');
  // 먼저 모든 값을 읽음
  const widths = Array.from(items).map(
    item => item.parentElement.offsetWidth
  );
  // 그런 다음 모든 값을 씀
  items.forEach((item, i) => {
    item.style.width = widths[i] + 'px';
  });
}

Single Page Applications에서의 클라이언트 사이드 렌더링

HTML의 클라이언트 사이드 렌더링은 특히 Single Page Applications (SPA)에서 프레젠테이션 지연에 상당한 영향을 미칠 수 있습니다. 사용자 상호작용으로 인해 라우트 변경이나 큰 UI 업데이트가 트리거될 때 SPA 프레임워크는 다음을 수행해야 합니다.

  1. 가상 DOM(virtual DOM) 디핑(diffing) 알고리즘을 실행하여 무엇이 변경되었는지 결정합니다.
  2. 결과 DOM 변형(mutations)을 실제 DOM에 적용합니다.
  3. 영향을 받는 모든 요소에 대해 스타일 재계산 및 레이아웃을 트리거합니다.
  4. 업데이트된 프레임을 페인트합니다.

React 애플리케이션에서 가상 DOM 재조정(reconciliation) 프로세스는 처리 시간에 속하지만, 그로 인한 DOM 변형과 렌더링 비용은 프레젠테이션 지연에 해당합니다. 컴포넌트 트리가 생성하는 DOM 노드가 많을수록 재조정 및 후속 렌더링 작업 비용이 더 많이 듭니다.

React 및 Next.js 애플리케이션에서 이를 완화하는 방법은 다음과 같습니다.

  • 동일한 props를 받는 하위 컴포넌트의 불필요한 리렌더링을 방지하려면 React.memo()를 사용하세요.
  • 무거운 리렌더링을 트리거하는 값에 useDeferredValue()를 사용하여 React가 더 긴급한 업데이트의 우선순위를 지정할 수 있도록 하세요.
  • 컴포넌트 트리를 얕게 유지하세요. 깊게 중첩된 컴포넌트 계층은 깊게 중첩된 DOM을 생성하여 재조정 및 브라우저 렌더링 비용을 모두 증가시킵니다.
  • DOM에 표시되는 항목만 포함되도록 긴 목록에 가상화 라이브러리(예: react-window 또는 @tanstack/react-virtual)를 사용하세요.

프레젠테이션 지연 줄이기

DOM 크기 최소화

프레젠테이션 지연을 해결하는 가장 좋은 방법은 DOM을 작게 유지하는 것입니다.

  • 사용하지 않는 HTML 요소, 특히 깊게 중첩된 래퍼(wrapper) div를 제거하세요.
  • 긴 목록에 목록 가상화(표시되는 항목과 작은 버퍼만 렌더링)를 사용하세요.
  • 가능한 경우 깊게 중첩된 구조를 평탄화하세요.
  • 레이아웃에 중첩된 div 대신 CSS Grid와 Flexbox를 사용하세요.
// DOM 크기를 줄이기 위한 긴 목록 가상화
// 이전: DOM에 10,000개의 항목

<ul>
  {allItems.map(item => 
     <li key="{item.id}">{item.name}</li>)
   }
</ul>

// 이후: DOM에 표시되는 항목만 존재 (react-window 사용)
import { FixedSizeList } from 'react-window';
<fixedsizelist height="{600}" 
               itemcount="{allItems.length}" 
               itemsize="{50}" width="100%">  
  {({ index, style }) => (
    <div style="{style}">{allItems[index].name}</div>
  )}
</fixedsizelist>

content-visibility를 사용하여 화면 밖의 콘텐츠 지연 렌더링

CSS content-visibility 속성은 사용자가 해당 콘텐츠 근처로 스크롤할 때까지 브라우저에 화면 밖 콘텐츠의 렌더링을 건너뛰도록 지시합니다. 이는 스타일 재계산 및 레이아웃 범위를 페이지의 표시되는 부분으로 제한하여 상호작용 중 렌더링 작업량을 줄입니다.

/* 스크롤해야 보이는(below-the-fold) 섹션에 content-visibility 적용 */
.below-fold-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 500px;
}

/* 긴 목록의 개별 항목에 적용 */
.list-item {
  content-visibility: auto;
  contain-intrinsic-size: auto 80px;
}

contain-intrinsic-size 속성은 브라우저가 콘텐츠를 렌더링하지 않고도 스크롤바 크기를 올바르게 계산할 수 있도록 예상 높이를 제공합니다. 이는 사용자가 스크롤하여 콘텐츠가 표시될 때 레이아웃 시프트(layout shifts)를 방지합니다.

렌더링 비용을 줄이는 더 많은 CSS 최적화 전략을 보려면 사용하지 않는 CSS 제거에 대한 가이드를 참조하세요.

상호작용에 의해 트리거되는 레이아웃 작업 최소화

상호작용을 디자인할 때는 레이아웃을 트리거하지 않는 CSS 속성을 우선적으로 사용하세요. transformopacity와 같은 속성은 레이아웃이나 페인트를 트리거하지 않고 GPU 합성기(compositor)에서 처리할 수 있습니다. top, left, width 또는 height를 애니메이션하는 대신 transform: translate()transform: scale()을 사용하세요. 레이아웃을 트리거하는 전체 CSS 속성 목록은 web.dev 렌더링 성능 가이드를 참조하세요.

CSS will-change 속성을 사용하여 요소가 애니메이션될 것임을 브라우저에 힌트로 제공하세요. 이를 통해 브라우저는 해당 요소에 대해 별도의 합성기 레이어를 생성하여 페이지의 다른 부분과 격리하여 렌더링할 수 있습니다.

/* 요소를 자체 합성기 레이어로 승격 */
.animated-element {
  will-change: transform, opacity;
}

/* display 대신 opacity로 가시성 토글 */
.modal {
  opacity: 0;
  pointer-events: none;
  transform: translateY(10px);
  transition: opacity 0.2s, transform 0.2s;
}

.modal.active {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

긴 프레젠테이션 지연 식별하기

긴 프레젠테이션 지연을 식별하려면 Chrome의 성능 프로파일러를 사용할 수 있습니다. DevTools(Ctrl+Shift+I)를 열고 Performance 탭으로 이동하여 녹화를 누른 다음 페이지와 상호작용합니다.

그런 다음 상호작용의 타임라인을 분석하고 프레젠테이션 지연을 포함한 다양한 단계를 시각화할 수 있습니다. 이벤트 핸들러가 완료된 후 발생하는 렌더링 업데이트를 조사하면, 긴 프레젠테이션 지연의 원인이 되는 병목 현상을 정확히 파악할 수 있습니다. 타임라인에서 큰 "Recalculate Style", "Layout", "Paint" 항목을 찾아보세요. 이것들은 브라우저가 프레젠테이션 지연 단계에서 수행하는 작업을 나타냅니다.

inp presentation delay devtools

RUM 데이터로 프레젠테이션 지연 식별하기

Real User Monitoring (RUM)은 Interaction to Next Paint 및 프레젠테이션 지연을 포함한 하위 구성 요소와 같은 중요한 Core Web Vitals 관련 지표에 대한 실시간 업데이트를 제공합니다. CoreDash와 같은 RUM 도구는 각 INP 상호작용을 세 단계로 분류하여, 특정 페이지 및 사용자 세그먼트에서 프레젠테이션 지연이 병목인지 확인할 수 있게 해줍니다.

Long Animation Frames (LoAF)로 프레젠테이션 지연 측정하기

Long Animation Frames (LoAF) API는 사용자 상호작용 중 렌더링 지연의 정확한 원인을 보여줍니다. API는 처리 시간(processing time)과 프레젠테이션 지연을 분리하고 어떤 스크립트가 렌더링을 늦추는지 파악할 수 있는 타이밍 데이터를 제공합니다.

프레젠테이션 지연을 이해하기 위한 주요 LoAF 속성은 다음과 같습니다.

  • renderStart: 브라우저가 렌더링 단계(스타일 재계산, 레이아웃, 페인트)를 시작한 시간
  • styleAndLayoutStart: 스타일 및 레이아웃 계산이 시작된 시간
  • duration: 긴 애니메이션 프레임(long animation frame)의 총 지속 시간
  • blockingDuration: 스크립트에 의해 프레임이 차단된 시간

LoAF는 현재 Chromium(Chrome 123+)에서만 사용할 수 있습니다. 다른 브라우저의 경우 Chrome DevTools Performance 패널 추적(traces)을 사용하여 렌더링 작업을 분석하세요.

스크립트 실행의 끝과 프레임 끝 사이의 차이는 순수한 렌더링 비용을 나타내며, 이것이 프레젠테이션 지연입니다. 이 데이터를 관찰하고 기록하는 방법은 다음과 같습니다.

// LoAF API를 사용하여 프레젠테이션 지연 측정
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.duration > 50) {
      const scriptEnd = Math.max(
        ...entry.scripts.map(s => s.startTime + s.duration)
      );
      const presentationDelay = (
        entry.startTime + entry.duration
      ) - Math.max(scriptEnd, entry.renderStart);

      console.log('Presentation delay breakdown:', {
        totalDuration: entry.duration,
        renderStart: entry.renderStart,
        styleAndLayoutStart: entry.styleAndLayoutStart,
        estimatedPresentationDelay: presentationDelay,
        scriptCount: entry.scripts.length
      });
    }
  }
});

observer.observe({
  type: 'long-animation-frame',
  buffered: true
});

CoreDash와 같은 RUM 도구는 LoAF 데이터를 통합하여 어떤 스크립트와 DOM 변경이 렌더링 지연을 유발하는지 전체 스크립트 속성(attribution)과 함께 보여줍니다.

다른 INP 단계 살펴보기

INP를 관리하려면 다른 두 단계도 해결해야 합니다.

  • 입력 지연(Input Delay): 이벤트 핸들러가 실행되기 시작할 때까지의 대기 시간을 최소화하세요. 입력 지연은 일반적으로 가장 짧은 단계이지만 메인 스레드가 바쁜 페이지 시작 시에 급증합니다.
  • 처리 시간(Processing Time): 상호작용 중에 실행되는 이벤트 핸들러 코드를 최적화하세요. 대부분의 페이지에서 이 부분에 최적화 노력을 기울일 때 가장 큰 효과를 봅니다.

완전한 진단 워크플로우를 보려면 INP 문제를 찾고 해결하는 방법에 대한 가이드를 참조하세요. 추가 렌더링 최적화 전략을 보려면 과도한 DOM 크기 수정사용하지 않는 CSS 제거 가이드를 살펴보세요. 전체 개요를 보려면 INP 허브 페이지로 돌아가세요.

보고서 말고 코드를 씁니다.

1~2 스프린트 동안 팀에 합류해서 모니터링까지 세팅해둡니다. 제가 빠진 뒤에도 지표가 계속 초록으로 유지되도록.

연락 주세요
INP 프레젠테이션 지연: DOM 크기, 레이아웃 작업 및 렌더링 최적화Core Web Vitals INP 프레젠테이션 지연: DOM 크기, 레이아웃 작업 및 렌더링 최적화