ํฐ์คํ ๋ฆฌ ๋ทฐ
๐ Next.js์์ OpenTelemetry๋ก ๊ด์ธก์ฑ(Observability) ๊ตฌ์ถํ๊ธฐ
octo54 2025. 6. 4. 10:48
๐ Next.js์์ OpenTelemetry๋ก ๊ด์ธก์ฑ(Observability) ๊ตฌ์ถํ๊ธฐ
Next.js๋ ๊ธฐ๋ณธ์ ์ผ๋ก SSR๊ณผ ๋์ ๊ธฐ๋ฅ์ ์ง์ํ๊ธฐ ๋๋ฌธ์ ๋ณต์กํ ์๋น์ค ๊ตฌ์กฐ์์ ์ฑ๋ฅ ์ถ์ ๊ณผ ์ค๋ฅ ์ง๋จ์ด ํ์์ ๋๋ค. ์ด๋ ํ์คํ๋ ์คํ์์ค์ธ OpenTelemetry๋ฅผ ํ์ฉํ๋ฉด ๋ก๊ทธ, ๋ฉํธ๋ฆญ, ํธ๋ ์ด์ค๋ฅผ ํตํฉ์ ์ผ๋ก ์์งํ๊ณ ์๊ฐํํ ์ ์์ต๋๋ค.
โ OpenTelemetry๋?
OpenTelemetry(OTel)๋ ๋ค์ ์ธ ๊ฐ์ง๋ฅผ ํ๋๋ก ์ถ์ ํ ์ ์๋ ํ์ค ํ๋ ์์ํฌ์ ๋๋ค.
- ๐ ๋ฉํธ๋ฆญ (Metrics)
- ๐ ํธ๋ ์ด์ค (Traces)
- ๐ชต ๋ก๊ทธ (Logs)
์๋ฒ์ ํด๋ผ์ด์ธํธ์ ๊ฒฝ๊ณ๋ฅผ ๋๋๋๋ ์์ฒญ ํ๋ฆ์ ์ถ์ ํ ์ ์์ด ์ฑ๋ฅ ๋ณ๋ชฉ๊ณผ ์ค๋ฅ ๋ฐ์ ์ง์ ์ ๋น ๋ฅด๊ฒ ํ์ ํ ์ ์์ต๋๋ค.
โ ๊ธฐ๋ณธ ์ค์ ๋ฐฉ๋ฒ (@vercel/otel ์ฌ์ฉ)
1. ํจํค์ง ์ค์น
npm install @vercel/otel
2. ๋ฃจํธ ๋๋ ํ ๋ฆฌ์ instrumentation.ts ์์ฑ
import { registerOTel } from '@vercel/otel';
export function register() {
registerOTel({ serviceName: 'next-app' });
}
3. next.config.js ์ค์
module.exports = {
experimental: {
instrumentationHook: true,
},
};
instrumentation.ts๋ ๋ฐ๋์ ๋ฃจํธ์ ์์ด์ผ ํ๊ณ , Next.js 14+ ์ด์๋ถํฐ ์ง์๋ฉ๋๋ค.
โ ๊ณ ๊ธ ์ค์ (์๋ ์ค์ )
๋ ์ธ๋ถ์ ์ธ ํธ๋ ์ด์ฑ์ด๋ ์ธ๋ถ ์์ง ์๋ฒ ์ฐ๋์ด ํ์ํ ๊ฒฝ์ฐ ์๋ ์ค์ ์ด ํ์ํฉ๋๋ค.
์ค์น
npm install @opentelemetry/sdk-node \
@opentelemetry/exporter-trace-otlp-http \
@opentelemetry/resources \
@opentelemetry/semantic-conventions
์ค์ ์์
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
export function register() {
const sdk = new NodeSDK({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'next-app',
}),
traceExporter: new OTLPTraceExporter({
url: 'http://localhost:4318/v1/traces',
}),
});
sdk.start();
}
โ ์ฃผ์ ์คํฌ ๋ชฉ๋ก
Next.js์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑ๋๋ ์คํฌ ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- render route (app) /about
- fetch GET https://api.example.com
- getServerSideProps /dashboard
- executing api route /api/user
โ ์ฌ์ฉ์ ์ ์ ์คํฌ ์ถ๊ฐ
import { trace } from '@opentelemetry/api';
export default async function handler(req, res) {
const tracer = trace.getTracer('custom');
const span = tracer.startSpan('fetch-user-data');
try {
await fetchUser();
res.status(200).json({ ok: true });
} catch (e) {
span.recordException(e);
res.status(500).json({ error: 'fail' });
} finally {
span.end();
}
}
โ ์๋ ๊ณ์ธก
์๋์ผ๋ก fetch, fs, http ๋ฑ ์ฃผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ณ์ธกํ๋ ค๋ฉด ๋ค์ ์ค์ ์ ์ถ๊ฐํฉ๋๋ค.
npm install @opentelemetry/auto-instrumentations-node
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
const sdk = new NodeSDK({
instrumentations: [getNodeAutoInstrumentations()],
});
โ Vercel ํ๊ฒฝ์์์ ํ์ฉ
- @vercel/otel ์ฌ์ฉ ์, Vercel ํ๋ซํผ์์ ์์ฝ๊ฒ ํ์ฑํ ๊ฐ๋ฅ
- NEXT_OTEL_VERBOSE=1 ํ๊ฒฝ ๋ณ์๋ก ๋๋ฒ๊น ๋ก๊ทธ ํ์ฑํ ๊ฐ๋ฅ
โ ์์ฝ
ํญ๋ชฉ ๊ฐํธ ์ค์ (@vercel/otel) ์๋ ์ค์
์ค์ ๋์ด๋ | ๋งค์ฐ ์ฌ์ | ๋ค์ ๋ณต์ก |
Edge ์ง์ ์ฌ๋ถ | O | X |
์ธ๋ถ ์ ์ด ๊ฐ๋ฅ์ฑ | ์ ํ์ | ๋งค์ฐ ๋์ |
์๋ ๊ณ์ธก | ๊ธฐ๋ณธ ์ ๊ณต | ์ง์ ์ค์ ํ์ |
๋ฐฐํฌ ํ๋ซํผ | Vercel ์ต์ ํ | ์ด๋์๋ ์ฌ์ฉ ๊ฐ๋ฅ |
Next.js, OpenTelemetry, Observability, ๋ฉํธ๋ฆญ, ํธ๋ ์ด์ค, ์๋น์ค ๋ชจ๋ํฐ๋ง, ๋ก๊ทธ ๋ถ์, ์ฑ๋ฅ ์ต์ ํ, Vercel, Full Stack Observability
'framework > NextJS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
- Total
- Today
- Yesterday
- ๋ฅ๋ฌ๋
- CI/CD
- ์น๊ฐ๋ฐ
- nodejs
- SEO ์ต์ ํ
- App Router
- ๋ฐฑ์๋๊ฐ๋ฐ
- ํ๋ก ํธ์๋๋ฉด์
- llm
- Prisma
- Docker
- SEO์ต์ ํ
- rag
- NestJS
- fastapi
- ๊ฐ๋ฐ๋ธ๋ก๊ทธ
- kotlin
- Python
- ํ์ด์ฌ ์๊ณ ๋ฆฌ์ฆ
- gatsbyjs
- ํ๋ก ํธ์๋
- JAX
- Webpack
- Next.js
- seo ์ต์ ํ 10๊ฐ
- Ktor
- AI์ฑ๋ด
- PostgreSQL
- nextJS
- REACT
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |