--- id: wiki-2026-0508-interaction-to-next-paint-inp title: Interaction to Next Paint (INP) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [INP, Interaction to Next Paint, web vital, FID replacement] duplicate_of: none source_trust_level: A confidence_score: 0.95 verification_status: applied tags: [web-vitals, inp, performance, frontend, core-web-vitals] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: JavaScript / TypeScript framework: web-vitals --- # Interaction to Next Paint (INP) ## 매 한 줄 > **"매 user input → 매 next visible paint 의 latency"**. 2024-03 의 의 의 FID 의 replace. 매 Core Web Vitals member. 매 < 200ms 'good', < 500ms 'needs improvement'. ## 매 핵심 ### 매 measurement - 매 매 page session 의 of 의 모든 interaction 의 worst (P98). - 매 input delay + processing + presentation delay. ### 매 응용 - SEO (Google ranking). - UX. - Form / button responsiveness. ## 💻 패턴 ### Measure ```javascript import { onINP } from 'web-vitals'; onINP(({ value, rating }) => { analytics.track('INP', { value, rating }); // 매 rating: 'good' | 'needs-improvement' | 'poor' }); ``` ### Optimize: yield to main thread ```javascript button.addEventListener('click', async () => { await scheduler.yield(); // 매 modern API // 매 매 chunk 의 의 의 yield for (let i = 0; i < items.length; i++) { if (i % 100 === 0) await scheduler.yield(); process(items[i]); } }); ``` ### Web Worker (heavy work) ```javascript const worker = new Worker('heavy.js'); button.addEventListener('click', () => { worker.postMessage(data); }); worker.onmessage = e => updateUI(e.data); ``` ### Debounce / throttle ```javascript function debounce(fn, ms) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), ms); }; } input.addEventListener('input', debounce(handleSearch, 300)); ``` ### React 18 useDeferredValue ```jsx function Search({ query }) { const deferredQuery = useDeferredValue(query); const results = expensiveCompute(deferredQuery); return ; } ``` ### Long Animation Frames API (debug) ```javascript new PerformanceObserver(list => { for (const entry of list.getEntries()) { if (entry.duration > 50) { console.warn('Long task', entry); } } }).observe({ type: 'long-animation-frame', buffered: true }); ``` ### Code splitting ```javascript const HeavyComponent = lazy(() => import('./HeavyComponent')); // 매 only loaded on demand ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Heavy compute | Worker | | Long task | scheduler.yield | | Search input | Debounce + useDeferredValue | | Initial bundle | Code split | **기본값**: 매 measure with web-vitals + 매 yield + 매 worker for heavy + 매 < 200ms target. ## 🔗 Graph - 부모: [[Core Web Vitals Optimization (INP, LCP, CLS)|Core-Web-Vitals]] · [[Google-Page-Experience-2025-Update]] - 응용: [[GPU Acceleration (Compositing)]] · [[E-commerce-Optimization]] - Adjacent: [[Core Web Vitals Optimization (INP, LCP, CLS)|First Input Delay (FID)]] ## 🤖 LLM 활용 **언제**: 매 web product. 매 SEO. **언제 X**: 매 backend. ## ❌ 안티패턴 - **Synchronous heavy work on main thread**: 매 INP 폭발. - **No measurement**: 매 invisible. - **setTimeout(0) only**: 매 still on main. ## 🧪 검증 / 중복 - Verified (web.dev, web-vitals.js docs). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — INP + 매 yield / worker / debounce / React code |