pile·
프론트엔드·vercel-blogVercel Blog·

INP 완전 정복 — 상호작용 응답성 최적화 실전 가이드

Interaction to Next Paint(INP)는 사용자 입력에 200ms 이내로 반응하는지를 측정하는 Core Web Vitals 지표다. 이 글은 INP의 핵심 오해인 '페인트 = 시각적 변화 완료'를 정정하고, 실제 최적화 방법과 코드 수준의 해결 패턴을 제시한다.

핵심 포인트
  • INP에서 'Paint'는 브라우저가 페인트할 기회를 가졌다는 의미지, 시각 변화가 완료됐다는 뜻이 아니다
  • INP는 세 단계로 구성된다 — 다른 코드 간섭(서드파티 JS), 이벤트 핸들러 실행, 브라우저 렌더링
  • await interactionResponse() 패턴으로 비용이 큰 작업을 페인트 이후로 미뤄 INP를 즉시 개선할 수 있다
  • requestAnimationFrame + setTimeout 조합으로 약 8ms 지연 후 무거운 작업을 처리해 체감 성능을 유지한다
  • React의 startTransition으로 긴급하지 않은 상태 업데이트를 지연시키는 현대적 대안도 있다
상세 정리
  • INP 정의 정정: 200ms 기준은 입력 수신부터 브라우저가 '페인트할 기회를 얻는' 시점까지다. 실제 시각 변화 완료(예: 애니메이션)가 아니어도 된다.
  • 세 단계 병목: 1) 서드파티 JS가 메인 스레드를 선점해 이벤트 핸들러 실행을 막음, 2) 애플리케이션 로직의 이벤트 핸들러 실행, 3) DOM 변경을 픽셀로 변환하는 브라우저 렌더링.
  • 역설적 최적화: onClick에서 async fetch를 await하면 그 사이에 브라우저가 페인트 기회를 얻어 '완벽한 INP'가 나온다. 메인 스레드 블로킹 작업 전에 await 포인트 삽입이 핵심.
  • await-interaction-response 모듈: setSelected로 상태를 먼저 업데이트한 뒤 await interactionResponse()로 브라우저 페인트를 유도하고, 이후 비용이 큰 setLanguage를 실행. 8ms 지연으로 UX 영향 없음.
  • 구현 원리: requestAnimationFrame() 안에서 setTimeout()을 호출해 브라우저 페인트 사이클 이후 작업 실행을 보장.
  • React startTransition: 긴급하지 않은 상태 업데이트를 transition으로 감싸 React가 우선순위를 낮춰 처리하도록 지시 — 별도 라이브러리 없이 동일 효과.
  • DOM 크기와 CSS containment: DOM 노드 수가 많을수록 렌더 비용이 O(n)으로 증가. CSS contain 속성으로 레이아웃 재계산 범위를 격리해 비용 절감.
  • 리스트 가상화: 화면에 보이는 항목만 렌더링해 대규모 목록의 DOM 조작 비용 감소.
  • 실제 사례: Next.js 문서 언어 선택기가 전체 페이지 레이아웃을 재계산해 INP가 높게 나왔고, 아키텍처 변경으로 해결.
  • 서드파티 JS: 가장 제어하기 어려운 병목. 태그 매니저, 분석 스크립트 등이 메인 스레드를 선점하면 이벤트 응답이 지연된다.
왜 읽나Core Web Vitals INP 점수를 개선해야 하는 프론트엔드 엔지니어에게 원리부터 실전 코드 패턴까지 제공하는 참조 가이드.
vercel-blog
Vercel Blog 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·LINE EngineeringLINE Engineering·

    AI로 웹 엔지니어 없이 LINE 앱 안에서 그룹 영상 통화 서비스 만들기

    LINE Planet 팀의 PM과 Android 엔지니어 두 명이 웹 전문 엔지니어 없이 LINE 앱 내에서 그룹 영상 통화 서비스를 개발한 과정을 다룬다. LIFF(LINE Front-end Framework)와 LINE Planet SDK를 활용해 React/Vite 기반 웹 앱을 구성했고, Firebase Cloud Functions로 별도 서버 인프라 없이 구현을 완료했다.

    #react#webrtc#firebase+2