필요한 정보 모아보기
테크

Vercel Speed Insights FID 11월 1일 종료 — INP로 바뀌는 것과 web-vitals로 직접 재는 법

#Vercel#Core Web Vitals#INP#FID#web-vitals#웹 성능

Vercel Speed Insights가 FID(First Input Delay, 최초 입력 지연) 지표를 정리한다. Vercel 체인지로그(10월 1일 게시)에 따르면 Speed Insights는 2026년 11월 1일부터 FID의 새 측정값을 더 이상 기록하지 않는다. 반응성 지표는 이미 INP(Interaction to Next Paint)가 맡고 있어서, Vercel은 사용자 쪽에서 바꿀 것도 없고 점수에도 영향이 없으며 지금까지 쌓인 FID 데이터도 계속 볼 수 있다고 밝혔다.

한 줄로 요약하면 "할 일 없음"이다. 다만 체인지로그는 이 말이 어디까지 해당하는지 따로 밝히지 않았고, Drains로 FID를 외부에 내보내는 경우는 언급이 없다. 그런 파이프라인이 있다면 우리 판단으로는 한 번 들여다볼 만하다. Vercel과 별개로, 직접 심은 측정 코드가 아직 onFID()를 부르고 있다면 그것도 정리 대상이다. 이 글은 FID와 INP가 무엇이 다른지, 구글이 언제 어떻게 바꿨는지, Vercel에서 실제로 무엇이 남고 무엇이 끊기는지, 그리고 web-vitals 라이브러리로 INP를 직접 재는 방법까지 정리했다.

FID와 INP는 무엇을 재나

FID는 사용자가 페이지와 처음 상호작용한 순간(링크 클릭 등)부터 브라우저가 그 입력에 반응을 시작할 수 있게 될 때까지의 시간이다. 이름 그대로 '첫 입력'의 '지연'만 본다. web.dev 문서도 FID는 이벤트 처리의 지연 부분만 재고, 이벤트 핸들러가 도는 시간이나 화면이 갱신되는 시간은 재지 않는다고 설명한다.

INP는 범위가 훨씬 넓다. 방문하는 동안 일어난 클릭·탭·키보드 상호작용을 전부 지켜보고, 각 상호작용마다 입력 지연 → 이벤트 핸들러 실행 → 다음 프레임이 그려질 때까지를 한 덩어리로 잰다. 최종값은 이상치를 뺀 가장 긴 상호작용이다. 상호작용 50번마다 가장 긴 것 하나를 버리는 방식인데, 대부분의 방문은 50번을 넘지 않으니 사실상 "가장 느렸던 한 번"이 보고되는 경우가 많다.

구분FIDINP
보는 상호작용첫 번째 상호작용 하나방문 중 모든 클릭·탭·키 입력
재는 구간입력 지연만입력 지연 + 핸들러 처리 + 다음 프레임 표시
'좋음' 기준100ms 이하200ms 이하 (500ms 초과는 '나쁨')
Core Web Vitals 지위2024년 3월 12일 제외2024년 3월 12일부터 정식 지표

차이가 크다. 페이지를 열자마자 버튼을 누르는 순간만 빠르면 FID는 좋게 나온다. 반면 필터 하나 바꿀 때마다 화면이 0.5초씩 멈추는 페이지라도 그 사실은 FID에 잡히지 않는다. INP가 FID를 대체한 이유가 바로 이것이다.

구글은 2024년에 이미 바꿨다

Vercel의 이번 결정은 새 소식이라기보다 2년 전 구글 결정의 뒷정리에 가깝다. web.dev 공식 블로그 기준으로 흐름을 정리하면 이렇다.

  1. 2022년 5월 — 크롬 팀이 INP를 실험적 지표로 공개했다.
  2. 2023년 — INP가 '대기(pending)' 지표가 됐고, 2024년 3월 정식 승격이 예고됐다.
  3. 2024년 3월 12일 — INP가 정식 Core Web Vital이 되며 FID를 대체했다. 구글은 이날 Search Console에서 FID를 바로 빼고, PageSpeed Insights·CrUX 같은 나머지 도구에는 6개월 유예를 두겠다고 예고했다. PageSpeed Insights의 Core Web Vitals 평가도 이날부터 FID 대신 INP로 판정한다.
  4. 2024년 9월 9일 — 크롬 도구의 FID 지원이 끝났다. CrUX·PageSpeed Insights API에서 FID를 읽던 애플리케이션은 이날까지 INP로 옮겨야 했고, 구글은 이것이 메이저 버전 번호 변경 없는 호환성 깨짐(breaking change)이라고 미리 못 박았다.
  5. 2025년 5월 7일 — 구글의 web-vitals 라이브러리 v5.0.0이 이미 deprecated 처리돼 있던 onFID() 함수를 아예 지웠다.

그러니 2026년 11월 1일은 FID 측정이 남아 있던 마지막 축 중 하나가 정리되는 날이다. 구글 도구에서 FID가 사라진 지 2년 넘게 지났다.

Vercel에서 실제로 남는 것과 끊기는 것

공식 안내 자체는 짧다. FID 새 측정 중단, 기존 데이터 열람 가능, 점수 영향 없음 — 이 세 가지다. 나머지는 Speed Insights 문서와 맞춰 보면 그림이 그려진다.

점수(RES)는 그대로다. Real Experience Score는 지표별 점수의 가중 평균인데, 문서의 가중치 표에 들어 있는 건 FCP 15%, LCP 30%, INP 30%, CLS 25%다. FID는 애초에 계산식에 없다. "점수에 영향 없다"는 말이 정확한 이유다.

상호작용 시점의 FID 데이터 포인트가 빠진다. 문서상 한 방문에서 최대 6개 데이터 포인트를 모으는데, 그중 '상호작용 시점'에 보내는 것이 FID와 LCP다. 새 FID 측정이 멈추면 FID 데이터 포인트는 더 이상 쌓이지 않고, 같은 시점의 LCP는 그대로 남는다. 과금이나 사용량에 미치는 영향은 Vercel이 따로 밝히지 않았다.

Drains 스키마에는 아직 FID가 있다. Speed Insights Drains 문서의 metricType 값은 CLS, LCP, FID, FCP, TTFB, INP 여섯 가지다. 새 FID 측정이 멈추면 Drains로 들어오는 FID 레코드도 끊긴다고 보는 게 자연스럽다. Drains에 대한 별도 안내는 체인지로그에 없다. 외부 대시보드나 알림이 FID 기준으로 걸려 있다면 11월 이후 "데이터 없음" 상태로 조용히 멈출 수 있다는 점이 실무에서 가장 놓치기 쉽다.

CLI는 이미 INP 중심이다. vercel metrics 문서가 안내하는 Speed Insights 값 지표는 lcp_ms, inp_ms, cls(Core Web Vitals)와 fcp_ms, ttfb_ms다. FID 항목은 목록에 없다. 기기 유형별 INP p75를 보려면 문서 예시처럼 이렇게 조회한다.

vercel metrics vercel.speed_insights.inp_ms --aggregation p75 \
  --group-by deviceType --since 7d --order-by count \
  --project project-name --prod

HTML 요소별 원인 분석(Selectors 보기, Speed Insights Plus 필요)은 INP·FID·CLS·LCP에서 지원된다. 느린 상호작용이 어느 버튼에서 나는지 보던 화면이라면, 이제 INP 탭만 보면 된다.

web-vitals로 INP 직접 재 보기

Speed Insights를 쓰지 않거나, Vercel 밖에서도 같은 기준으로 재고 싶다면 구글의 web-vitals 라이브러리가 표준이다. 2026-10-09에 npm view web-vitals version으로 확인한 최신 버전은 6.2.3이었다(10월 5일 배포, Apache-2.0, 런타임 의존성 없음).

실제로 v6에 FID가 남아 있는지도 확인했다. 패키지 tarball을 내려받아(npm pack, 설치 아님) Node 22.16.0(macOS)에서 ES 모듈을 불러와 내보내는 이름을 찍어 본 결과는 이렇다.

[ 'CLSThresholds', 'FCPThresholds', 'INPThresholds', 'LCPThresholds',
  'TTFBThresholds', 'onCLS', 'onFCP', 'onINP', 'onLCP', 'onTTFB' ]
INP [ 200, 500 ]  LCP [ 2500, 4000 ]  CLS [ 0.1, 0.25 ]

onFID는 없다. 함께 들어 있는 INPThresholds가 [200, 500]이니 web.dev의 '좋음/나쁨' 경계와 같다. 4.x 이하에서 onFID를 import하던 코드는 v5 이상으로 올리는 순간 빌드가 깨진다는 뜻이기도 하다.

아래는 attribution 빌드로 INP와 그 원인 정보를 함께 보내는 예시다. README의 사용법과 v6 타입 정의(INPAttribution)에 있는 필드만 썼다. 브라우저에서 실제 사용자 데이터로 돌려 본 것은 아니니 수집 주소(/analytics)는 각자 환경에 맞게 바꾼다.

import {onINP, onLCP, onCLS} from 'web-vitals/attribution';

function send(metric) {
  const body = {
    name: metric.name,        // 'INP' | 'LCP' | 'CLS'
    value: metric.value,
    rating: metric.rating,    // 'good' | 'needs-improvement' | 'poor'
    id: metric.id,
    page: location.pathname,
  };
  if (metric.name === 'INP') {
    const a = metric.attribution;
    body.target = a.interactionTarget;        // 느렸던 요소의 선택자
    body.inputDelay = a.inputDelay;           // 핸들러 시작까지 기다린 시간
    body.processing = a.processingDuration;   // 핸들러 실행 시간
    body.presentation = a.presentationDelay;  // 다음 프레임 표시까지
    body.loadState = a.loadState;
  }
  const json = JSON.stringify(body);
  (navigator.sendBeacon && navigator.sendBeacon('/analytics', json)) ||
    fetch('/analytics', {body: json, method: 'POST', keepalive: true});
}

onINP(send);
onLCP(send);
onCLS(send);

몇 가지 동작은 알고 쓰는 게 좋다. 사용자가 한 번도 상호작용하지 않으면 INP는 아예 보고되지 않는다. 탭이 숨겨질 때마다 다시 보고될 수 있어 같은 id로 여러 번 들어올 수 있다. 그리고 onINP() 같은 함수는 페이지당 한 번만 부른다 — 부를 때마다 PerformanceObserver가 새로 생긴다. attribution 빌드는 표준 빌드보다 조금 크다. 직접 gzip으로 재 보니 web-vitals.js 3,344바이트, web-vitals.attribution.js 5,595바이트였다.

v6에서 새로 생긴 소프트 내비게이션(SPA 화면 전환) 측정은 reportSoftNavs: true 옵션으로 켠다. README 기준 크롬 151부터 지원하는 기능이고, 켜면 INP가 화면 전환마다 새로 측정된다.

INP를 줄이는 순서

INP는 세 구간의 합이라 어느 구간이 긴지부터 봐야 한다. 위 코드의 inputDelay·processing·presentation이 바로 그 세 구간이다. web.dev의 INP 최적화 가이드를 바탕으로 우리 기준의 점검 순서를 정리하면 이렇다.

  1. 실사용 데이터부터 본다. 구글 기준 '좋음'은 페이지 로드의 75퍼센타일이 200ms 이하인 상태다. Speed Insights의 INP p75나 위 코드의 수집값으로 현재 위치를 확인한다.
  2. 느린 요소를 특정한다. interactionTarget이나 Speed Insights Selectors에서 자주 걸리는 버튼·입력창을 찾고, 크롬 개발자도구 Performance 패널에서 그 상호작용을 재현한다.
  3. 입력 지연이 길면 페이지 로드 중 메인 스레드를 오래 잡는 스크립트를 의심한다. 긴 작업(long task)을 쪼개고, 지금 필요 없는 스크립트는 미룬다.
  4. 처리 시간이 길면 이벤트 핸들러에서 하는 일을 줄인다. 화면에 바로 보여야 하는 갱신만 먼저 하고, 저장·집계 같은 나머지는 다음 작업으로 넘긴다(requestAnimationFrame 안에서 setTimeout으로 미루는 패턴이 web.dev 예시다).
  5. 표시 지연이 길면 DOM 크기와 레이아웃을 본다. 스타일을 바꾼 직후 같은 작업 안에서 다시 읽는 레이아웃 스래싱을 없애고, 화면 밖 요소는 CSS content-visibility로 늦게 그리는 방법을 검토한다.

개인적으로는 4번을 가장 먼저 의심한다. 입력 하나에 상태 갱신이 연쇄로 일어나는 화면이라면 핸들러 처리 시간이 길어지기 쉽고, 이건 코드만 고치면 바로 줄어드는 구간이기도 하다.

11월 1일 전에 손볼 곳

대시보드만 보는 팀이라면 정말로 할 일이 없다. RES 계산식에 FID가 없었고, INP는 이미 들어가 있었다. 손이 가는 건 FID를 '밖으로' 꺼내 쓰던 경우다.

  • Speed Insights Drains를 받는 쪽에서 metricType === 'FID'로 거르는 쿼리·대시보드·알림이 있는지 찾아 INP로 바꾼다. 체인지로그에 Drains 안내는 없지만, 새 측정이 멈추는 이상 FID 레코드도 끊길 가능성이 높다고 본다. 미리 바꿔 두면 11월 이후 그래프가 비더라도 헷갈릴 일이 없다.
  • 직접 심은 측정 코드에서 onFID를 검색한다. web-vitals 4.x 이하에 묶여 있다면 6.x로 올리면서 함께 걷어 낸다.
  • 성능 리포트나 사내 문서에 'FID 100ms 이하' 같은 목표가 남아 있다면 'INP p75 200ms 이하'로 바꾼다.

보안 쪽은 패키지별로 나눠 짚었다. 먼저 Vercel 쪽이다. Vercel은 2026년 4월 외부 AI 도구(Context.ai) 침해에서 시작된 내부 시스템 무단 접근 사고를 공개했고, 보안 공지에서 GitHub·Microsoft·npm·Socket과 함께 확인한 결과 Vercel이 배포한 npm 패키지는 침해되지 않았다고 밝혔다. Speed Insights 수집용 @vercel/speed-insights가 이 범위에 들어간다(공지 시점 기준).

web-vitals는 구글 크롬 팀이 배포하는 패키지라 위 공지의 대상이 아니다. 그래서 따로 확인했다 — Snyk 취약점 DB에는 이 패키지(최신 6.2.3)에 등록된 직접 취약점이 없다. 의존성 취약점은 이 결과에 포함되지 않는다는 게 Snyk의 단서인데, 6.2.3은 런타임 의존성 자체가 없다.

FID가 사라지는 건 아쉬울 게 없는 변화다. 첫 클릭 한 번만 보던 지표가 빠지고, 실제로 사용자가 답답해하는 순간을 잡는 지표만 남는다.

출처 vercel.com/…/speed-insights-deprecates-first-input-delay-on-november-firstvercel.com/…/metricsvercel.com/…/using-speed-insightsvercel.com/…/speed-insightsvercel.com/…/accessing-metrics-with-vercel-cliweb.dev/…/inp-cwv-launchweb.dev/…/inp-cwv-march-12web.dev/…/inpweb.dev/…/fidweb.dev/…/optimize-inpgithub.com/…/web-vitalsgithub.com/…/CHANGELOG.mdnpmjs.comvercel.com/…/vercel-april-2026-security-incidentsecurity.snyk.io

내용이 틀렸나요? 정정 요청

관련 글