๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ

 

Next.js ์•ฑ์—์„œ ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ์ ์— ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” ์ดˆ๊ธฐํ™” ๋กœ์ง์ด ํ•„์š”ํ–ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ, ์บ์‹œ ์„ค์ •, ์™ธ๋ถ€ ์„œ๋น„์Šค ์—ฐ๊ฒฐ ๊ฐ™์€ ๊ฒƒ๋“ค ๋ง์ด๋‹ค. ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๋ณด๋‹ˆ instrumentation.ts ํŒŒ์ผ์„ ๋งŒ๋“ค๋ฉด ์•ฑ ์‹œ์ž‘ ์‹œ์ ์— ํ•œ ๋ฒˆ ๋Œ์•„๊ฐ€๋Š” ๊ธฐ๋Šฅ์ด ์žˆ์—ˆ๊ณ  register ํ•จ์ˆ˜๋ฅผ exportํ•˜๋ฉด ๋œ๋‹ค๊ณ  ๋‚˜์™€์žˆ์—ˆ๋‹ค.

// instrumentation.ts
export async function register() {
  console.log('์„œ๋ฒ„ ์ดˆ๊ธฐํ™” ์ค‘...');
  // ์ดˆ๊ธฐํ™” ๋กœ์ง
}

๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” ์ž˜ ๋˜๋”๋ผ. npm run dev ํ•˜๋ฉด ์ฝ˜์†”์— ๋กœ๊ทธ๋„ ์ž˜ ์ฐํžˆ๊ณ , ์ดˆ๊ธฐํ™”๋„ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ ํ›„ ์‹คํ–‰ํ•˜๋‹ˆ๊นŒ ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋œ๋‹ค.

 

npm run build
npm start

์ฝ˜์†”์— ์•„๋ฌด๋Ÿฐ ๋กœ๊ทธ๋„ ์—†๊ณ , ์ดˆ๊ธฐํ™” ์ฝ”๋“œ๋„ ์‹คํ–‰๋˜์ง€ ์•Š์•˜๋‹ค. ๋ญ”๊ฐ€ ์ด์ƒํ•ด์„œ GitHub ์ด์Šˆ๋“ค์„ ์ฐพ์•„๋ดค๋”๋‹ˆ ๋‚˜๋งŒ ๊ฒช๋Š” ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ์—ˆ๋‹ค.

 

 

 

๋ฐœ๊ฒฌํ•œ ์ด์Šˆ๋“ค

Next.js ๊ณต์‹ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์—์„œ ๊ด€๋ จ ์ด์Šˆ๋“ค์„ ์—ฌ๋Ÿฌ ๊ฐœ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.

 

ํŠนํžˆ Next.js 14.0.5-canary.29์—์„œ ๋ฐœ๊ฒฌํ•œ ๊ฑด๋ฐ, ํ”„๋กœ๋•์…˜ ๋นŒ๋“œ ํ›„ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ register ํ•จ์ˆ˜๊ฐ€ ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ณ , ์ฒซ ๋ฒˆ์งธ ๋ผ์šฐํŠธ๋ฅผ ๋ฐฉ๋ฌธํ•ด์•ผ๋งŒ ์‹คํ–‰๋˜๋Š” ๋ฌธ์ œ์˜€๋‹ค. ํ•˜์ง€๋งŒ ๋‚˜๋Š” Next.js 15๋ฅผ ์‚ฌ์šฉํ–ˆ๊ณ , instrumentation ๊ธฐ๋Šฅ์ด ์ •์‹์œผ๋กœ ์•ˆ์ •ํ™”๋˜์–ด์„œ experimental.instrumentationHook ์„ค์ •์„ config์— ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

 

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

๋ฌธ์ œ๋Š” ์„œ๋ฒ„ ์‹œ์ž‘๊ณผ ๋™์‹œ์— ์‹คํ–‰๋˜์–ด์•ผ ํ•  ์ดˆ๊ธฐํ™” ๋กœ์ง์ด ์‚ฌ์šฉ์ž์˜ ์ฒซ ๋ฒˆ์งธ HTTP ์š”์ฒญ์— ์˜์กดํ•œ๋‹ค๋Š” ์ ์ด์—ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋˜์ž๋งˆ์ž ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด๋‚˜ ํ™˜๊ฒฝ ์„ค์ • ๊ฐ™์€ ๊ฑธ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋ˆ„๊ตฐ๊ฐ€ ์›น์‚ฌ์ดํŠธ์— ์ ‘์†ํ•ด์•ผ๋งŒ ๊ทธ ์ฝ”๋“œ๊ฐ€ ๋Œ์•„๊ฐ„๋‹ค๋‹ˆ... ๊ฒฐ๊ตญ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ํ–ˆ๋‹ค.

 

 

 

ํ•ด๊ฒฐ์ฑ… ์ฐพ๊ธฐ

instrumentation ๊ธฐ๋Šฅ ์ž์ฒด๊ฐ€ ๋ถˆ์•ˆ์ •ํ•˜๊ณ , next ํŒ€์—์„œ๋„ ๋™์ž‘ ๋ฐฉ์‹์„ ๋ธ”๋ž™ ๋ฐ•์Šค๋กœ ์ˆจ๊ฒจ๋†“์œผ๋‹ˆ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์จ์•ผ๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์„ ์‹œ๋„ํ•ด๋ดค๋Š”๋ฐ, ๊ฐ๊ฐ ์žฅ๋‹จ์ ์ด ์žˆ์—ˆ๋‹ค.

 

 

 

1. Next.js ์ปค์Šคํ…€ ์„œ๋ฒ„

๊ฐ€์žฅ ํ™•์‹คํ•œ ๋ฐฉ๋ฒ•์€ Next.js ๋‚ด์žฅ ์ปค์Šคํ…€ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

// server.js
const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

async function initialize() {
  console.log('๐Ÿš€ ์„œ๋ฒ„ ์ดˆ๊ธฐํ™” ์ค‘...');

  // ์—ฌ๊ธฐ์— ์ดˆ๊ธฐํ™” ๋กœ์ง ์ž‘์„ฑ
  // await connectDatabase();
  // await setupCache();

  console.log('โœ… ์ดˆ๊ธฐํ™” ์™„๋ฃŒ');
}

app.prepare().then(async () => {
  await initialize();

  createServer((req, res) => {
    const parsedUrl = parse(req.url, true);
    handle(req, res, parsedUrl);
  }).listen(3000, () => {
    console.log('> Ready on http://localhost:3000');
  });
});

package.json์—์„œ start ์Šคํฌ๋ฆฝํŠธ๋„ ๋ฐ”๊ฟ”์ค€๋‹ค:

{
  "scripts": {
    "start": "node server.js"
  }
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Next.js ์„œ๋ฒ„๊ฐ€ ์ค€๋น„๋œ ์งํ›„์— ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๊ฐ€ ํ™•์‹คํžˆ ์‹คํ–‰๋œ๋‹ค.

 

 

 

2. ๋ชจ๋“ˆ ๋ ˆ๋ฒจ์—์„œ ์‹คํ–‰

์ข€ ๋” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค. Next.js ์•ฑ ๋‚ด์—์„œ ๋ชจ๋“ˆ์ด ์ฒ˜์Œ ๋กœ๋“œ๋  ๋•Œ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

// lib/server-init.ts
let initialized = false;

async function initializeApp() {
  if (initialized) return;

  console.log('๐Ÿš€ ์•ฑ ์ดˆ๊ธฐํ™” ์ค‘...');

  // ์ดˆ๊ธฐํ™” ๋กœ์ง

  initialized = true;
  console.log('โœ… ์•ฑ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ');
}

// ์„œ๋ฒ„์—์„œ๋งŒ ์‹คํ–‰
if (typeof window === 'undefined') {
  initializeApp();
}

 

๊ทธ๋ฆฌ๊ณ  app/layout.tsx์—์„œ ์ด ๋ชจ๋“ˆ์„ import๋งŒ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

 

 

// app/layout.tsx
import '@/lib/server-init'; // ์ด๊ฒƒ๋งŒ ์ถ”๊ฐ€

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html>
      <body>{children}</body>
    </html>
  );
}

 

 

 

3. ์ข€ ๋” ์ •๊ตํ•œ ์กฐ๊ฑด ์ฒ˜๋ฆฌ

๋นŒ๋“œ ํƒ€์ž„๊ณผ ๋Ÿฐํƒ€์ž„์„ ํ™•์‹คํžˆ ๊ตฌ๋ถ„ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ด๋Ÿฐ ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.

// ๋Ÿฐํƒ€์ž„์—์„œ๋งŒ ์‹คํ–‰ (๋นŒ๋“œ ํƒ€์ž„ ์ œ์™ธ)
if (
  typeof window === "undefined" && 
  process.env.NEXT_PHASE !== "phase-production-build" &&
  process.env.NEXT_PHASE !== "phase-export" &&
  !process.env.NEXT_BUILD_ID
) {
  process.nextTick(() => {
    initializeApp().catch((error) => {
      console.error("์•ฑ ์ดˆ๊ธฐํ™” ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:", error);
    });
  });
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Next.js๊ฐ€ ๋นŒ๋“œ ์ค‘์ผ ๋•Œ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๊ณ , ์‹ค์ œ ์„œ๋ฒ„๊ฐ€ ๋Œ์•„๊ฐˆ ๋•Œ๋งŒ ์‹คํ–‰๋œ๋‹ค.

 

 

์ด ๋ฐฉ๋ฒ•์ด ์ตœ์ดˆ 1๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” ์ด์œ ๋Š” Node.js์˜ ๋ชจ๋“ˆ ์บ์‹ฑ ์‹œ์Šคํ…œ ๋•Œ๋ฌธ์ด๋‹ค. Node.js๋Š” ํ•œ ๋ฒˆ ๋กœ๋“œ๋œ ๋ชจ๋“ˆ์„ ๋ฉ”๋ชจ๋ฆฌ์— ์บ์‹œํ•ด๋‘๊ณ , ๊ฐ™์€ ๋ชจ๋“ˆ์„ ๋‹ค์‹œ importํ•  ๋•Œ๋Š” ์ƒˆ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ์บ์‹œ๋œ ๊ฒฐ๊ณผ๋ฅผ ์žฌ์‚ฌ์šฉํ•œ๋‹ค. ๋”ฐ๋ผ์„œ lib/server-init.ts ํŒŒ์ผ์ด ์ฒ˜์Œ import๋  ๋•Œ๋งŒ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์˜ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ณ , ๊ทธ ์ดํ›„์—๋Š” ์•„๋ฌด๋ฆฌ ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ด ๋ชจ๋“ˆ์„ importํ•ด๋„ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ๋Š” ๋‹ค์‹œ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.

์ด๋Š” RSC(React Server Components)์™€๋Š” ์ง์ ‘์ ์ธ ๊ด€๋ จ์ด ์—†๋Š”, Node.js ์ž์ฒด์˜ ๊ธฐ๋ณธ ๋™์ž‘์ด๋‹ค. ๋‹ค๋งŒ Next.js App Router ํ™˜๊ฒฝ์—์„œ๋Š” layout.tsx์—์„œ ๋ชจ๋“ˆ์„ importํ•  ๋•Œ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋˜๋ฉด์„œ ์ดˆ๊ธฐํ™”๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ๋ฟ์ด๋‹ค. ์—ฌ๊ธฐ์— initialized ํ”Œ๋ž˜๊ทธ๋ฅผ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉํ•ด์„œ ํ˜น์‹œ ๋ชจ๋ฅผ ์ค‘๋ณต ์‹คํ–‰๋„ ๋ฐฉ์ง€ํ•˜๊ณ , typeof window === 'undefined' ์ฒดํฌ๋กœ ์„œ๋ฒ„ ํ™˜๊ฒฝ์—์„œ๋งŒ ์‹คํ–‰๋˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ์ด์ค‘ ์•ˆ์ „์žฅ์น˜๋ฅผ ๋งˆ๋ จํ•œ ์…ˆ์ด๋‹ค.

 

 

๊ฒฐ๋ก 

Next.js 15์—์„œ instrumentation.ts๋Š” ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” ์ž˜ ๋˜์ง€๋งŒ ํ”„๋กœ๋•์…˜์—์„œ๋Š” ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋‹ค. ํŠนํžˆ standalone ๋นŒ๋“œ๋‚˜ Docker ํ™˜๊ฒฝ์—์„œ๋Š” ๋”๋”์šฑ ๊ทธ๋ ‡๋‹ค. ๋‹น๋ถ„๊ฐ„์€ ์ปค์Šคํ…€ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋ชจ๋“ˆ ๋ ˆ๋ฒจ์—์„œ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ์‹์„ ์“ฐ๋Š” ๊ฒŒ ์ข‹๊ฒ ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์ปค์Šคํ…€ ์„œ๋ฒ„ ๋ฐฉ์‹์„ ์ถ”์ฒœํ•œ๋‹ค. ์ข€ ๋” ๋ช…์‹œ์ ์ด๊ณ  ์ œ์–ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์–ด์ฐจํ”ผ ํ”„๋กœ๋•์…˜์—์„œ๋Š” ํ™•์‹คํ•œ ๊ฒŒ ์ตœ๊ณ ๋‹ค.

๋ฐ˜์‘ํ˜•