framework/NextJS

๐Ÿ” Next.js Instrumentation ๊ฐ€์ด๋“œ: ์„œ๋ฒ„ ๋ฐ ํด๋ผ์ด์–ธํŠธ ๊ด€์ธก์„ฑ ์„ค์ •

octo54 2025. 5. 20. 11:00
๋ฐ˜์‘ํ˜•

๐Ÿ” Next.js Instrumentation ๊ฐ€์ด๋“œ: ์„œ๋ฒ„ ๋ฐ ํด๋ผ์ด์–ธํŠธ ๊ด€์ธก์„ฑ ์„ค์ •

Next.js์˜ Instrumentation ๊ธฐ๋Šฅ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง, ์˜ค๋ฅ˜ ์ถ”์ , ๋กœ๊น… ๋“ฑ์„ ์œ„ํ•œ ๊ด€์ธก์„ฑ ๋„๊ตฌ๋ฅผ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ๋ฅผ ์ถ”์ ํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ“ ํŒŒ์ผ ๊ตฌ์„ฑ ๋ฐ ์œ„์น˜

1. instrumentation.ts ๋˜๋Š” instrumentation.js

  • ์œ„์น˜: ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ ๋˜๋Š” src/ ํด๋” ๋‚ด๋ถ€
  • ์šฉ๋„: ์„œ๋ฒ„ ์ธก ๊ด€์ธก์„ฑ ๋„๊ตฌ ์ดˆ๊ธฐํ™” ๋ฐ ์„ค์ •
  • ํ•„์ˆ˜ ํ•จ์ˆ˜: register ํ•จ์ˆ˜
// instrumentation.ts
import { registerOTel } from '@vercel/otel';

export function register() {
  registerOTel('next-app');
}

์ฐธ๊ณ :
instrumentation ํŒŒ์ผ์€ app/ ๋˜๋Š” pages/ ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด๋ถ€๊ฐ€ ์•„๋‹Œ ๋ฃจํŠธ์— ์œ„์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
src/ ํด๋”๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ํด๋” ๋‚ด์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.


2. instrumentation-client.ts ๋˜๋Š” instrumentation-client.js

  • ์œ„์น˜: ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ ๋˜๋Š” src/ ํด๋” ๋‚ด๋ถ€
  • ์šฉ๋„: ํด๋ผ์ด์–ธํŠธ ์ธก ๊ด€์ธก์„ฑ ๋„๊ตฌ ์ดˆ๊ธฐํ™” ๋ฐ ์„ค์ •
  • ํŠน์ง•: ํŠน์ • ํ•จ์ˆ˜์˜ export ์—†์ด ์ฝ”๋“œ ์‹คํ–‰
// instrumentation-client.ts
console.log('ํด๋ผ์ด์–ธํŠธ ์ธก ๊ด€์ธก์„ฑ ๋„๊ตฌ ์ดˆ๊ธฐํ™”');

// ์˜ค๋ฅ˜ ์ถ”์  ์„ค์ •
window.addEventListener('error', (event) => {
  console.error('์˜ค๋ฅ˜ ๋ฐœ์ƒ:', event.error);
});

์ฐธ๊ณ :
์ด ํŒŒ์ผ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ๋กœ๋“œ๋˜๋ฏ€๋กœ, ์ดˆ๊ธฐํ™” ์ฝ”๋“œ๋‚˜ ๊ธ€๋กœ๋ฒŒ ์„ค์ •์„ ๋ฐฐ์น˜ํ•˜๊ธฐ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.


โš™๏ธ ๋™์ž‘ ์›๋ฆฌ ๋ฐ ์„ค์ •

๋ฐ˜์‘ํ˜•

์„œ๋ฒ„ ์ธก: register ํ•จ์ˆ˜

  • ํ˜ธ์ถœ ์‹œ์ : ์ƒˆ๋กœ์šด Next.js ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ํ•œ ๋ฒˆ ํ˜ธ์ถœ
  • ๋น„๋™๊ธฐ ์ง€์›: async ํ•จ์ˆ˜๋กœ ์ •์˜ ๊ฐ€๋Šฅ
export async function register() {
  await import('some-observability-tool');
}

์ฃผ์˜:
register ํ•จ์ˆ˜๋Š” ๋ชจ๋“  ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ์—์„œ ํ˜ธ์ถœ๋˜๋ฏ€๋กœ, ํŠน์ • ํ™˜๊ฒฝ(Node.js ๋˜๋Š” Edge)์—๋งŒ ํ•„์š”ํ•œ ์ฝ”๋“œ๋Š” ์กฐ๊ฑด๋ถ€๋กœ ๋กœ๋“œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('./instrumentation-node');
  } else if (process.env.NEXT_RUNTIME === 'edge') {
    await import('./instrumentation-edge');
  }
}

ํด๋ผ์ด์–ธํŠธ ์ธก: ์ดˆ๊ธฐํ™” ์ฝ”๋“œ

  • ์‹คํ–‰ ์‹œ์ : ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ๋กœ๋“œ
  • ์šฉ๋„: ํผํฌ๋จผ์Šค ๋ชจ๋‹ˆํ„ฐ๋ง, ์˜ค๋ฅ˜ ์ถ”์ , ๋ถ„์„ ๋„๊ตฌ ์ดˆ๊ธฐํ™” ๋“ฑ
// instrumentation-client.ts
performance.mark('app-init');

// ๋ถ„์„ ๋„๊ตฌ ์ดˆ๊ธฐํ™”
console.log('๋ถ„์„ ๋„๊ตฌ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ');

๐Ÿ”Œ OpenTelemetry ํ†ตํ•ฉ ์˜ˆ์‹œ

Next.js๋Š” OpenTelemetry๋ฅผ ํ†ตํ•œ ๊ด€์ธก์„ฑ ๋„๊ตฌ ํ†ตํ•ฉ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
@vercel/otel ํŒจํ‚ค์ง€๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค์น˜

npm install @vercel/otel @opentelemetry/sdk-logs @opentelemetry/api-logs @opentelemetry/instrumentation

์„ค์ •

// instrumentation.ts
import { registerOTel } from '@vercel/otel';

export function register() {
  registerOTel('next-app');
}

๐Ÿงช ํ…Œ์ŠคํŠธ ๋ฐ ๋””๋ฒ„๊น…

  • ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํ™•์ธ: process.env.NEXT_RUNTIME์„ ํ†ตํ•ด ํ˜„์žฌ ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ(Node.js ๋˜๋Š” Edge)์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์—๋Ÿฌ ์ฒ˜๋ฆฌ: onRequestError ํ•จ์ˆ˜๋ฅผ instrumentation.ts ํŒŒ์ผ์— ์ •์˜ํ•˜์—ฌ ์„œ๋ฒ„ ์ธก ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
export function onRequestError(error: Error) {
  console.error('์„œ๋ฒ„ ์—๋Ÿฌ ๋ฐœ์ƒ:', error);
}

โœ… ํ™œ์šฉ ๋ฐฉ์•ˆ

  1. ์„œ๋ฒ„ ๋กœ๊น… ๋ฐ ์ถ”์ 
    • instrumentation.ts์— ์„œ๋ฒ„ ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ ์„ค์ •
    • console.log๋ฅผ ํ†ตํ•œ ์‹ค์‹œ๊ฐ„ ์ƒํƒœ ํ™•์ธ
  2. ํด๋ผ์ด์–ธํŠธ ๋ถ„์„ ๋„๊ตฌ ํ†ตํ•ฉ
    • Google Analytics ๋˜๋Š” Sentry ์ดˆ๊ธฐํ™” ์ฝ”๋“œ ์ถ”๊ฐ€
    • ์„ฑ๋Šฅ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘์„ ์œ„ํ•œ Web Vitals ํ™œ์šฉ
  3. ์—๋Ÿฌ ์ถ”์ 
    • onRequestError ํ•จ์ˆ˜๋กœ ์„œ๋ฒ„ ์—๋Ÿฌ๋ฅผ ๊ด€๋ฆฌ
    • ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ๋Š” window.addEventListener('error')๋กœ ์˜ค๋ฅ˜ ํฌ์ฐฉ

โœ… ์š”์•ฝ

๊ตฌ์„ฑ ์š”์†Œ ์„ค๋ช…

instrumentation.ts ์„œ๋ฒ„ ์ธก ๊ด€์ธก์„ฑ ๋„๊ตฌ ์ดˆ๊ธฐํ™” ๋ฐ ์„ค์ •
instrumentation-client.ts ํด๋ผ์ด์–ธํŠธ ์ธก ๊ด€์ธก์„ฑ ๋„๊ตฌ ์ดˆ๊ธฐํ™” ๋ฐ ์„ค์ •
register ํ•จ์ˆ˜ ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค ์‹œ์ž‘ ์‹œ ํ˜ธ์ถœ๋˜์–ด ์ดˆ๊ธฐํ™” ์ž‘์—… ์ˆ˜ํ–‰
onRequestError ํ•จ์ˆ˜ ์„œ๋ฒ„ ์ธก ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ํ˜ธ์ถœ๋˜์–ด ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์ˆ˜ํ–‰
๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ process.env.NEXT_RUNTIME์„ ํ†ตํ•ด ํ™•์ธ
OpenTelemetry ํ†ตํ•ฉ @vercel/otel ํŒจํ‚ค์ง€๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฐ„๋‹จ ์„ค์ •

 

Next.js, Instrumentation, ๊ด€์ธก์„ฑ, OpenTelemetry, ์„œ๋ฒ„ ๋ชจ๋‹ˆํ„ฐ๋ง, ํด๋ผ์ด์–ธํŠธ ๋ชจ๋‹ˆํ„ฐ๋ง, ํผํฌ๋จผ์Šค ์ถ”์ , ์—๋Ÿฌ ์ถ”์ , ๋กœ๊น…, ๋ถ„์„ ๋„๊ตฌ, ์„œ๋ฒ„ ์ดˆ๊ธฐํ™”, ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”