INP 해결하기: React 앱이 느리게 느껴지는 현상 방지하기
대시보드가 느리게 느껴집니다. API는 빠릅니다. Lighthouse 점수는 초록색입니다. 하지만 클릭할 때마다 지연이 발생합니다.
이것은 INP 문제입니다.
Interaction to Next Paint (INP)는 페이지가 사용자의 입력에 반응하는 데 걸리는 시간을 측정합니다. 2024년 3월에 First Input Delay (FID)를 대체했습니다. FID는 첫 번째 클릭만 확인했지만, INP는 모든 상호작용을 모니터링합니다.
INP 점수가 200ms 미만이면 빠르게 느껴집니다. 500ms를 넘어가면 느릿하게 느껴집니다.
INP를 해결하려면 다음 세 가지 단계로 나누어 접근해야 합니다.
- Input Delay (입력 지연) – 클릭과 코드가 실행되기 시작하는 시점 사이의 간격입니다. 메인 스레드가 바쁠 때 발생합니다.
- Processing Time (처리 시간) – 함수와 React 상태 업데이트가 실행되는 시간입니다.
- Presentation Delay (표시 지연) – 코드 실행이 완료된 시점과 브라우저가 화면을 그리는(paint) 시점 사이의 간격입니다.
Input Delay 해결하기
긴 작업(Long tasks)은 메인 스레드를 차단합니다. 작업이 50ms 이상 실행되면 클릭 동작이 멈춥니다. scheduler.yield()를 호출하여 긴 작업을 더 작은 단위로 나누면, 브라우저가 작업 사이사이에 클릭을 처리할 수 있습니다.
Processing Time 해결하기
UI의 반응성을 유지하기 위해 React의 transition API를 사용하세요.
startTransition– 긴급하지 않은 업데이트를 감쌉니다. React는 새로운 클릭을 처리하기 위해 무거운 업데이트를 일시 중지할 수 있습니다.useDeferredValue– 즉각적인 업데이트가 필요하지 않은 값을 지연시킵니다.
이 API들은 코드 자체를 빠르게 만드는 것이 아니라, 코드를 중단 가능한(interruptible) 상태로 만들어 INP를 낮춰줍니다.
Presentation Delay 해결하기
DOM 요소가 너무 많으면 화면을 그리는 속도가 느려집니다.
- CSS에
content-visibility: auto를 적용하여 화면 밖에 있는 요소의 렌더링을 건너뜁니다. - 레이아웃 스래싱(layout thrashing)을 방지하세요. 동일한 루프 내에서 스타일을 읽고 바로 쓰는 작업을 반복하지 마세요. 대신 읽기와 쓰기 작업을 일괄 처리(batch)해야 합니다.
- 긴 리스트는 가상화(Virtualize)하세요.
측정 방법
Lighthouse는 실험실 환경(lab)에서 실행되므로 실제 사용자처럼 버튼을 클릭할 수 없습니다. web-vitals 라이브러리를 설치하여 실제 사용자의 데이터를 수집하세요.
