Node.js 애플리케이션 트레이싱 (Tracing Node.js Applications)
Node.js 애플리케이션에 Datadog SDK(dd-trace)를 설치하고 계측해 트레이스를 Datadog으로 보내는 방법이에요. 설치, 초기화, 번들링 관련 내용을 다룹니다.
출처: 문서
본문
호환성 요구사항 (Compatibility requirements)
최신 Node.js 트레이서는 Node.js >=18 버전을 지원해요. Datadog의 Node.js 버전·프레임워크 지원(레거시·유지보수 버전 포함) 전체 목록은 호환성 요구사항 페이지를 참고하세요.
시작하기 (Getting started)
시작하기 전에 Agent를 이미 설치·구성했는지 확인하세요. 그런 다음 다음 단계를 완료해 Node.js 애플리케이션에 Datadog SDK를 추가해 계측하세요.
Datadog SDK 설치하기
Node.js 18+에서 npm으로 Datadog SDK를 설치하려면:
npm install dd-trace
수명이 끝난 Node.js 16용 Datadog SDK(dd-trace 4.x)를 설치하려면:
npm install dd-trace@latest-node16
Datadog의 배포 태그와 Node.js 런타임 버전 지원에 대한 자세한 내용은 호환성 요구사항 페이지를 참고하세요. 라이브러리의 이전 메이저 버전(0.x, 1.x, 2.x, 3.x, 4.x)에서 다른 메이저 버전으로 업그레이드한다면 마이그레이션 가이드를 읽고 주요 변경 사항을 확인하세요.
Serverless 환경이나 Single-Step Instrumentation을 사용할 때는 라이브러리가 이미 사전 설치되어 있어 의존성으로 추가할 필요가 없어요. 대신 로컬에서 트레이싱하려면 dev dependency로 추가하세요: npm install dd-trace -D(대신 npm install dd-trace).
Datadog 공용 API 설치하기 (선택)
이 단계는 Serverless나 Single-Step Instrumentation에서 커스텀 계측을 할 때만 필요해요. 다른 커스텀 계측 사용 사례에서는 선택사항이에요. Datadog 공용 API를 언제 사용해야 하는지에 대한 정보는 Datadog API를 사용한 커스텀 계측을 참고하세요.
npm install dd-trace-api
커스텀 계측을 하는 코드에서는 dd-trace 대신 dd-trace-api를 import할 수 있어요.
트레이서 import·초기화
트레이서를 코드에서 또는 명령줄 인자로 import·초기화하세요. Node.js SDK는 다른 어떤 모듈보다 먼저 import·초기화되어야 해요.
Next.js, Nest.js 같은 프레임워크에서는 환경 변수를 제공하거나 추가 Node.js 플래그를 달아야 해요. 자세한 내용은 복잡한 프레임워크 사용을 참고하세요.
설정을 마쳤는데 URL 라우트 누락, 끊기거나 누락된 스팬 같은 완전한 트레이스를 받지 못한다면 SDK가 올바르게 import·초기화되었는지 확인하세요. 자동 계측을 위해 필요한 모든 라이브러리를 SDK가 제대로 패치하려면 SDK가 가장 먼저 초기화되어야 해요.
TypeScript, Webpack, Babel 같은 트랜스파일러를 사용한다면, 외부 파일에서 SDK를 import·초기화하고 애플리케이션을 빌드할 때 그 파일을 전체로 import하세요.
명령줄 인자로 SDK 추가하기
Node.js의 --require 옵션을 사용해 한 번에 SDK를 로드·초기화하세요.
node --require dd-trace/init app.js
위 방식은 SDK의 모든 구성을 환경 변수로 해야 해요. 프로그래매틱 구성을 사용해야 한다면 전용 파일에서 dd-trace를 초기화하고 그것을 require하세요.
node --require ./dd-trace.js app.js
파일에는 다음이 있어야 해요.
// ./dd-trace.js
require('dd-trace').init({
// programmatic config
})
CLI 인자를 제어할 수 없는 경우에는 환경 변수를 대신 사용할 수 있어요.
DD_TRACE_ENABLED는 기본적으로 true예요. 즉 초기화되기 전 import 시점에 일부 계측이 일어날 수 있어요. 계측을 완전히 비활성화하려면 다음 중 하나를 하세요.
- 모듈을 조건부로 import
DD_TRACE_ENABLED=false설정(예: 정적 또는 최상위 ESM import가 조건부 로드를 막는 경우)
ESM 애플리케이션만 해당: 로더 import
ECMAScript Modules(ESM) 애플리케이션은 추가 명령줄 인자가 필요해요. SDK를 어떻게 import·초기화하든 이 인자를 추가하세요.
- Node.js < v20.6:
--loader dd-trace/loader-hook.mjs - Node.js >= v20.6:
--import dd-trace/register.js
예를 들어 Node.js 22에서 위 옵션 1로 SDK를 초기화한다면 이렇게 시작해요.
node --import dd-trace/register.js app.js
이것은 --require dd-trace/init 명령줄 인자와 결합할 수도 있어요.
node --import dd-trace/register.js --require dd-trace/init app.js
Node.js v20.6 이상에서는 두 명령줄 인자를 결합하는 약식이 있어요.
node --import dd-trace/initialize.mjs app.js
번들링 (Bundling)
dd-trace는 Node.js 애플리케이션이 모듈을 로드할 때 하는 require() 호출을 가로채서 동작해요. 여기에는 파일시스템 접근용 fs 모듈처럼 Node.js에 내장된 모듈과 pg 데이터베이스 모듈처럼 NPM 레지스트리에서 설치한 모듈이 모두 포함돼요.
번들러는 애플리케이션이 디스크의 파일에 하는 모든 require() 호출을 탐색해요. require() 호출을 커스텀 코드로 바꾸고 결과 JavaScript를 하나의 "번들된" 파일로 결합해요. 내장 모듈(require('fs'))을 로드할 때는 그 호출이 결과 번들에서 그대로 유지될 수 있어요.
dd-trace 같은 APM 도구는 이 시점에서 동작을 멈춰요. 내장 모듈에 대한 호출은 계속 가로챌 수 있지만, 서드파티 라이브러리에 대한 호출은 가로채지 않아요. 이 말은 번들러로 dd-trace 앱을 번들하면 디스크 접근(fs 통해서)과 아웃바운드 HTTP 요청(http 통해서) 정보는 포착하지만 서드파티 라이브러리 호출은 빠뜨릴 가능성이 크다는 뜻이에요. 예를 들어:
express프레임워크의 들어오는 요청 라우트 정보 추출.mysql데이터베이스 클라이언트에서 실행되는 쿼리 표시.
일반적인 해결책은 APM이 계측해야 하는 모든 서드파티 모듈을 번들러에 대해 "external"로 취급하는 거예요. 이 설정으로 계측된 모듈은 디스크에 남아 계속 require()로 로드되고, 계측되지 않은 모듈만 번들돼요. 하지만 이렇게 하면 빌드에 불필요한 파일이 많아져 번들링의 목적이 무너지기 시작해요.
Datadog은 커스텀 빌드 번들러 플러그인을 권장해요. 이 플러그인은 번들러에게 동작 방식을 알려주고, 중간 코드를 주입하며, "변환된" require() 호출을 가로챌 수 있어요. 그 결과 더 많은 패키지가 번들된 JavaScript 파일에 포함돼요.
참고: 일부 애플리케이션은 모듈의 100%를 번들할 수 있지만, 네이티브 모듈은 여전히 번들 외부에 남아 있어야 해요.
esbuild로 번들링
이 라이브러리는 esbuild 플러그인 형태로 esbuild를 지원하며, 최소 Node.js v16.17 또는 v18.7이 필요해요. 플러그인을 사용하려면 dd-trace@3+가 설치되어 있는지 확인하고, 번들을 빌드할 때 dd-trace/esbuild 모듈을 require하세요.
esbuild로 dd-trace를 사용하는 예시:
const ddPlugin = require('dd-trace/esbuild')
const esbuild = require('esbuild')
esbuild.build({
entryPoints: ['app.js'],
bundle: true,
outfile: 'out.js',
plugins: [ddPlugin],
platform: 'node', // 내장 모듈을 require할 수 있게 함
target: ['node16'],
external: [
// 네이티브 메트릭을 사용한다면 필요
'@datadog/native-metrics',
// 프로파일링을 사용한다면 필요
'@datadog/pprof',
// Datadog 보안 기능을 사용한다면 필요
'@datadog/native-appsec',
'@datadog/native-iast-taint-tracking',
'@datadog/wasm-js-rewriter',
]
}).catch((err) => {
console.error(err)
process.exit(1)
})
Webpack으로 번들링
이 라이브러리는 Webpack 플러그인 형태로 실험적 Webpack 지원을 제공해요. 플러그인을 사용하려면 [email protected]+가 설치되어 있는지 확인하고, 번들을 빌드할 때 dd-trace/webpack 모듈을 require하세요.
Webpack으로 dd-trace를 사용하는 예시:
const path = require('path')
const webpack = require('webpack')
const DatadogWebpackPlugin = require('dd-trace/webpack')
const compiler = webpack({
entry: 'main.js',
target: 'node',
externalsType: 'commonjs',
output: {
filename: 'out.js',
path: __dirname,
hashFunction: 'sha256',
},
externals: [
// target: 'node'에 대한 Webpack 기본 목록에 없는 Node.js 내장 모듈
'diagnostics_channel',
// knex가 도입한 죽은 코드 경로
'pg',
'mysql2',
'better-sqlite3',
'sqlite3',
'mysql',
'oracledb',
'pg-query-stream',
'tedious',
'@yaacovcr/transform',
// 선택적 네이티브 dd-trace 모듈
'@datadog/native-appsec',
'@datadog/native-iast-taint-tracking',
'@datadog/native-metrics',
'@datadog/pprof',
'@datadog/libdatadog',
],
plugins: [
new DatadogWebpackPlugin(),
],
})
Next.js로 번들링
Next.js로 애플리케이션을 번들한다면 next.config.js 구성 파일 안에 Webpack용과 비슷한 선언을 추가하세요:
/** @type {import('next').NextConfig} */
const nextConfig = {
// ... 관련 없는 부분은 생략, 자신의 구성을 대신 넣으세요 ...
// Datadog 트레이싱이 동작하려면 이 커스텀 webpack 구성이 필요해요
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
) => {
const externals = [
// 네이티브 메트릭을 사용한다면 필요
'@datadog/native-metrics',
// 프로파일링을 사용한다면 필요
'@datadog/pprof',
// Datadog 보안 기능을 사용한다면 필요
'@datadog/native-appsec',
'@datadog/native-iast-taint-tracking',
'@datadog/wasm-js-rewriter',
];
config.externals.push(...externals);
return config;
},
};
export default nextConfig;
지원되지 않는 Datadog 기능
다음 기능은 Node.js 트레이서에서 기본적으로 꺼져 있어요. 번들링을 지원하지 않으므로 애플리케이션이 번들되면 사용할 수 없어요.
- APM: Dynamic Instrumentation
일반적인 번들링 참고 사항
참고: SDK에서 네이티브 모듈(보통 .node 파일 확장자로 끝나는 컴파일된 C++ 코드)을 사용하기 때문에 external 목록에 항목을 추가해야 해요. 현재 Node.js 트레이서에 사용되는 네이티브 모듈은 @datadog 접두사 패키지 안에 있어요. 또한 번들된 애플리케이션 옆에 node_modules/ 디렉터리를 함께 배포해야 해요. 번들에 포함되어야 하는 불필요한 패키지가 많이 들어 있을 수 있으므로 node_modules/ 디렉터리 전체를 배포할 필요는 없어요.
필요한 네이티브 모듈(및 해당 의존성)만 있는 더 작은 node_modules/ 디렉터리를 만들려면, 먼저 필요한 패키지 버전을 확인한 다음 임시 디렉터리를 만들어 설치하고 거기서 결과 node_modules/ 디렉터리를 복사하세요. 예를 들어:
cd path/to/project
npm ls @datadog/native-metrics
# [email protected] ./dd-trace-js
# └── @datadog/[email protected]
$ npm ls @datadog/pprof
# [email protected] ./dd-trace-js
# └── @datadog/[email protected]
mkdir temp && cd temp
npm init -y
npm install @datadog/[email protected] @datadog/[email protected]
cp -R ./node_modules path/to/bundle
참고: Next.js의 경우 path/to/bundle은 보통 앱의 .next/standalone 디렉터리예요.
이 단계에서 네이티브 모듈과 그 의존성을 담은 node_modules/ 디렉터리와 함께 번들(애플리케이션 코드와 대부분의 의존성)을 배포할 수 있어야 해요.
구성 (Configuration)
필요하다면 Unified Service Tagging 설정을 포함해 원하는 대로 애플리케이션 성능 텔레메트리 데이터를 보내도록 SDK를 구성하세요. 자세한 내용은 라이브러리 구성을 읽어보세요.
초기화 옵션 목록은 트레이서 설정을 읽어보세요.
더 알아보기 (Learn more)
도움이 되는 추가 문서, 링크, 글: