/ 우리는 이렇게 합니다 / INP — 반응성 직접 느끼기
개발·인터랙션 · 성능을 맡은 사람

눌렀는데 멈칫하는 0.2초, 그게 INP입니다.

2024년 3월, 구글의 핵심 웹 바이탈에서 ‘반응성’ 지표가 바뀌었습니다. 오래된 FID가 빠지고 INP가 그 자리에 들어왔죠. 어렵게 들리지만, 사실은 아주 단순한 감각의 문제입니다. 눌렀을 때 곧바로 반응하느냐, 한 박자 늦느냐. 이 글은 읽는 글이 아니라 두 버튼을 직접 눌러보는 글입니다.

한 줄 직답

INP(Interaction to Next Paint)는 2024년 3월 12일 FID를 대체한 핵심 웹 바이탈로, 클릭·탭·키 입력 같은 모든 상호작용이 화면에 반영되기까지 걸리는 시간을 측정합니다. 표준 기준으로 75번째 백분위에서 200밀리초 이하면 ‘좋음’입니다. 메인스레드를 무거운 작업으로 막지 않는 것이 핵심이며, Findable은 긴 작업 쪼개기·디바운스로 클릭이 ‘멈칫’하지 않게 만듭니다.

요약

  • INP는 2024.03.12 FID를 대체한 ‘반응성’ 핵심 웹 바이탈이다 — 첫 입력만 보던 FID와 달리 모든 상호작용을 본다.
  • 좋은 INP는 75번째 백분위에서 200ms 이하(표준 기준). 즉 사용자 4명 중 3명이 0.2초 안에 반응을 받아야 한다.
  • 클릭이 ‘멈칫’하는 주범은 메인스레드를 길게 붙잡는 무거운 자바스크립트다.
  • 해법은 긴 작업 쪼개기(yield), 불필요한 계산 미루기, 입력 디바운스다.

예전에 한 고객사 사이트에서 ‘버튼이 가끔 안 눌린다’는 제보가 들어왔습니다. 코드를 봐도 버튼은 멀쩡했죠. 진짜 원인은 버튼이 아니라, 그 옆에서 돌던 무거운 계산이었습니다. 사용자가 누른 순간 브라우저가 그 계산을 처리하느라 화면을 못 그렸던 겁니다. 사용자에겐 ‘안 눌린 것’처럼 느껴졌고요. 그 ‘멈칫’의 정체를 숫자로 보여주는 지표가 바로 INP입니다.

그래서 INP가 뭔가요? FID와 뭐가 다르죠?

둘 다 ‘반응성’을 보는 지표입니다. 차이는 보는 범위입니다. 옛 지표 FID는 ‘첫 입력이 처리되기 시작할 때까지의 지연’만 쟀습니다. 처리에 걸리는 시간도, 화면에 그려지는 시간도 보지 않았죠. 그래서 ‘반응이 빠른 것처럼’ 보이는 착시가 있었습니다. INP는 페이지에서 일어난 모든 상호작용을, 입력 지연 + 처리 시간 + 다음 화면을 그리는 시간까지 통째로 봅니다. 그리고 대표값 하나를 내놓습니다. 더 정직한 지표입니다.

왜 2024년에 바뀐 건가요?

구글은 2024년 3월 12일 INP를 핵심 웹 바이탈로 정식 채택하고 FID를 대체했습니다(FID는 같은 해 9월 프로그램에서 제거). 이유는 단순합니다. 요즘 웹은 첫 클릭보다 ‘쓰는 내내’의 반응성이 더 중요하기 때문입니다. 메뉴 열기, 탭 전환, 필터 적용처럼 매 순간의 클릭이 빨라야 사람이 ‘쾌적하다’고 느낍니다. INP는 바로 그 ‘쓰는 내내’를 봅니다.

말로는 모릅니다 — 직접 눌러보세요

아래 두 버튼은 똑같이 생겼지만 속이 다릅니다. ‘가벼운 버튼’은 메인스레드를 거의 쓰지 않고, ‘무거운 버튼’은 누르는 순간 메인스레드를 잠깐 꽉 막습니다. 번갈아 눌러보고, 반응 시간 숫자를 비교해 보세요.

Live · INP / 반응성

두 버튼을 눌러 반응 속도를 비교

메인스레드를 막으면 클릭이 '멈칫'합니다. 핵심 지표 INP를 직접 느껴보세요.

버튼을 눌러 반응 시간을 측정해 보세요.

차이가 느껴지시나요? ‘무거운 버튼’을 누르면 눌린 모양이 한 박자 늦게 따라옵니다. 이게 INP가 나쁜 상태의 감각입니다. 실제 사이트에서는 이 ‘무거운 작업’이 광고 스크립트, 거대한 목록 렌더링, 잘못 짠 스크롤 핸들러 같은 모습으로 숨어 있습니다.

그럼 ‘좋은 INP’는 얼마인가요?

표준 기준으로는 실사용자 데이터의 75번째 백분위에서 200밀리초 이하면 ‘좋음’입니다. 200~500ms는 ‘개선 필요’, 500ms 초과는 ‘나쁨’입니다. 풀어 말하면, 사용자 4명 중 적어도 3명이 클릭 후 0.2초 안에 화면 반응을 받아야 한다는 뜻입니다. 0.2초는 사람이 ‘즉시’라고 느끼는 경계선에 가깝습니다. 그 선을 넘기면 ‘느린 사이트’라는 인상이 남습니다. (임계값은 표준 기준이며 기기·네트워크 환경에 따라 다르게 측정될 수 있습니다.)

그래서 어떻게 고치나요? — 메인스레드를 양보하기

핵심은 하나입니다. 클릭 직후 메인스레드를 오래 붙잡지 마라. 제가 현장에서 실제로 쓰는 방법은 이렇습니다.

① 긴 작업 쪼개기. 한 번에 수십 밀리초씩 걸리는 작업을 작은 조각으로 나누고, 조각 사이에 메인스레드를 잠깐 양보합니다. 그러면 브라우저가 그 틈에 화면을 그리고 다음 입력을 받습니다. 위의 ‘무거운 버튼’도 작업을 쪼개기만 하면 ‘가벼운 버튼’처럼 즉시 반응하게 만들 수 있습니다.

② 화면에 안 보이는 일은 뒤로. 클릭 직후 정말 필요한 건 ‘눌린 표시’와 ‘다음 화면’뿐입니다. 분석 전송, 무거운 계산 같은 건 화면을 먼저 그린 뒤로 미룹니다. 사용자는 먼저 반응을 받고, 나머지는 뒤에서 조용히 처리됩니다.

③ 입력 디바운스. 검색창 타이핑처럼 입력이 빗발치는 곳에서는 매 글자마다 무거운 작업을 돌리지 않습니다. 입력이 잠깐 멈춘 뒤 한 번만 처리하도록 묶습니다(디바운스). 처리 횟수 자체가 줄어드니 메인스레드가 한가해집니다.

제가 현장에서 실제로 쓰는 두 조각입니다. 하나는 긴 작업을 쪼개 메인스레드를 양보하는 코드, 하나는 INP가 어디서 나빠지는지 직접 재보는 코드입니다.

JS · 긴 작업 쪼개기 + 반응성 측정
// 1) 긴 작업을 조각내고 사이사이 메인스레드를 양보(yield)
async function processChunks(items, handle) {
  for (let i = 0; i < items.length; i++) {
    handle(items[i]);
    if (i % 50 === 0) {
      // 브라우저가 그 틈에 화면을 그리고 다음 입력을 받게 함
      await (scheduler?.yield?.() ?? new Promise(r => setTimeout(r)));
    }
  }
}

// 2) 느린 상호작용만 골라 INP 원인 추적
new PerformanceObserver((list) => {
  for (const e of list.getEntries()) {
    if (e.duration > 200) {            // 200ms 초과 = '개선 필요'
      console.warn("느린 상호작용:", e.name, Math.round(e.duration) + "ms");
    }
  }
}).observe({ type: "event", durationThreshold: 200, buffered: true });

두 번째 조각이 콘솔에 찍어주는 ‘느린 상호작용’ 목록이, 위의 무거운 버튼 같은 범인을 실제 사이트에서 찾아내는 출발점입니다.

항목블로킹 코드분할 처리(쪼개기·디바운스)
클릭 반응성한 박자 늦게 멈칫즉시 눌린 표시
INP200ms 초과 위험200ms 이하 ‘좋음’ 지향
사용자 이탈‘느린 사이트’로 이탈↑행동을 끝까지 완료↑

다른 담당자와의 연결

반응성은 혼자 있는 지표가 아닙니다. 페이지가 그려지는 속도, 자원이 불러와지는 순서와 한 몸으로 움직입니다. 반응성 설계의 전체 그림은 성능 담당자의 노트에서, 성능의 기본 개념은 웹 성능 기본기에서, 그리고 첫 화면이 빠르게 뜨게 만드는 로딩 설계는 로딩 담당자의 노트에서 이어집니다. 같은 팀이 같은 태도로 다룹니다.

INP를 진지하게 보는 사람이, 사이트 전체를 만듭니다

INP는 결국 ‘사용자를 기다리게 하지 않겠다’는 약속입니다. 클릭 한 번의 0.2초를 지키려고 작업을 쪼개고 미루고 묶는 사람이라면, 로딩도 폼도 같은 태도로 다룹니다. Findable에서는 이런 반응성 설계가 기본값입니다. 당신의 사이트, 어디서 멈칫하고 있을까요?

INP가 FID를 대체했다는 게 무슨 뜻인가요?
INP(Interaction to Next Paint)는 2024년 3월 12일 핵심 웹 바이탈에서 FID(First Input Delay)를 정식으로 대체했습니다. FID는 ‘첫 입력의 지연 시간’만 봤지만, INP는 페이지에서 일어난 모든 상호작용의 반응 속도를 측정해 대표값 하나로 보여줍니다. 클릭을 처리하고 화면에 결과를 그려주기까지 전체가 INP에 포함됩니다.
좋은 INP 점수는 얼마인가요?
표준 기준으로는 75번째 백분위에서 200밀리초 이하면 ‘좋음’, 200~500밀리초는 ‘개선 필요’, 500밀리초 초과는 ‘나쁨’으로 봅니다. 즉 실사용자 4명 중 3명이 클릭 후 0.2초 안에 화면 반응을 받아야 좋은 수준입니다. 임계값은 표준 기준이며 측정 환경에 따라 달라질 수 있습니다.
왜 클릭이 가끔 ‘멈칫’하나요?
브라우저의 메인스레드는 한 번에 한 가지 일만 합니다. 클릭 직후 무거운 자바스크립트가 메인스레드를 길게 붙잡고 있으면, 브라우저는 그 일이 끝날 때까지 화면을 다시 그리지 못합니다. 그 사이 사용자는 ‘눌렀는데 반응이 없다’고 느낍니다. 이것이 반응성이 나빠지는 가장 흔한 원인입니다.
긴 작업을 쪼갠다는 건 어떻게 하나요?
한 번에 수십 밀리초 이상 걸리는 작업을 작은 조각으로 나누고, 조각 사이에 메인스레드를 잠깐 양보(yield)합니다. 그러면 브라우저가 그 틈에 화면을 그리고 다음 입력을 받을 수 있습니다. 화면에 꼭 필요하지 않은 계산은 뒤로 미루고, 입력 이벤트는 디바운스로 묶어 처리 횟수를 줄입니다.
INP를 좋게 만들면 검색 순위가 오르나요?
INP는 핵심 웹 바이탈의 한 축으로 페이지 경험 신호에 포함됩니다. 다만 검색 순위는 콘텐츠 적합성 등 수많은 요소로 결정되며, INP 하나만으로 순위를 보장하지는 않습니다. 그보다 더 확실한 효과는 사용자가 ‘버벅이지 않는다’고 느껴 이탈이 줄고 행동을 끝까지 마친다는 점입니다.

당신의 사이트, 어디서 멈칫하나요

반응성까지 이렇게 다루는 팀이 당신의 홈페이지를 만들면 어떨까요. 무료 진단으로 시작하세요.

무료 진단 받기

이 글의 두 버튼은 이 페이지에서 실제로 동작하는 코드입니다(외부 라이브러리 0). INP의 임계값(75번째 백분위 200ms 등)은 핵심 웹 바이탈의 표준 기준이며, 측정 환경에 따라 다르게 나타날 수 있습니다. 검색 순위·전환 수치는 일반 원칙이며 특정 성과를 보장하지 않습니다. 날조된 사례·수치는 사용하지 않았습니다.