SSR 프레임워크에서 RUM 통합¶
RUM SDK는 브라우저 환경에서만 초기화할 수 있으며, 서버 사이드 렌더링 단계에서는 실행할 수 없습니다. 이 페이지에서는 Next.js 및 Nuxt의 공식 프레임워크 플러그인을 통한 통합 방법을 소개합니다.
| 단계 | 실행 환경 | RUM 초기화 여부 |
|---|---|---|
| SSR, Server Component 또는 Nitro 실행 단계 | Node.js | 아니오 |
| Hydration 및 클라이언트 라우팅 단계 | Browser | 예 |
프레임워크 플러그인은 브라우저 View, 리소스, 동작 및 클라이언트 오류를 수집합니다. 순수 서버 요청, Server Action, Nitro 처리 과정 및 클라이언트로 전달되지 않은 서버 오류는 서버 측 모니터링 솔루션을 사용해야 합니다.
버전 요구 사항
Next.js 및 Nuxt 프레임워크 플러그인은 RUM SDK 3.3.6부터 제공됩니다. RUM 메인 패키지 버전은 프레임워크 플러그인 버전보다 낮을 수 없습니다.
다음 예제는 공용 네트워크 OpenWay의 site 및 clientToken을 사용합니다. DataKit 직접 연결을 사용하는 경우 이 두 매개변수를 datakitOrigin으로 대체하고, 두 가지 보고 주소를 동시에 구성하지 마십시오.
Next.js¶
Next.js 플러그인은 Next.js 13 이상, React 18 이상, 그리고 App Router 및 Pages Router를 지원합니다.
설치¶
App Router: Next.js 15.3 이상¶
Next.js 15.3 이상은 instrumentation-client.js|ts를 지원합니다. 이 파일은 hydration 전에 실행되며, 브라우저 모니터링을 최대한 빨리 초기화하는 데 적합합니다.
instrumentation-client.ts를 생성합니다. 프로젝트가 src 디렉터리를 사용하는 경우 파일을 src/instrumentation-client.ts에 배치합니다:
import { datafluxRum } from "@cloudcare/browser-rum"
import {
nextjsPlugin,
onRouterTransitionStart,
} from "@cloudcare/browser-rum-nextjs"
export { onRouterTransitionStart }
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "web-nextjs",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
plugins: [nextjsPlugin()],
})
클라이언트 Router tracker를 생성합니다:
// app/rum-router-tracker.tsx
"use client"
import { RumNextjsAppRouter } from "@cloudcare/browser-rum-nextjs"
export function RumRouterTracker() {
return <RumNextjsAppRouter />
}
루트 layout에서 한 번 렌더링합니다:
// app/layout.tsx
import { RumRouterTracker } from "./rum-router-tracker"
export default function RootLayout({ children }) {
return (
<html lang="zh-CN">
<body>
<RumRouterTracker />
{children}
</body>
</html>
)
}
onRouterTransitionStart()는 탐색 대상을 기록하고, RumNextjsAppRouter는 새 pathname이 실제로 제출된 후에만 View를 생성합니다. 탐색이 취소되거나, 실패하거나, 렌더링이 제출되지 않은 경우 유효하지 않은 View가 생성되지 않습니다. 리디렉션이 성공적으로 발생한 경우 View는 최종 제출된 pathname을 사용합니다.
App Router: Next.js 13 ~ 15.2¶
이 버전에는 instrumentation-client가 없으므로, 루트 layout에 클라이언트 초기화 컴포넌트를 배치할 수 있습니다:
// app/rum-provider.tsx
"use client"
import { useEffect } from "react"
import { datafluxRum } from "@cloudcare/browser-rum"
import {
nextjsPlugin,
RumNextjsAppRouter,
} from "@cloudcare/browser-rum-nextjs"
let initialized = false
export function RumProvider() {
useEffect(() => {
if (initialized) return
initialized = true
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "web-nextjs",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
plugins: [nextjsPlugin()],
})
}, [])
return <RumNextjsAppRouter />
}
app/layout.tsx에서 <RumProvider />를 렌더링합니다. 이 방법은 성공적으로 제출된 App Router 라우트를 수집할 수 있지만, 초기화 시점이 instrumentation-client보다 늦습니다.
Pages Router¶
pages/_app.tsx에서 Pages Router tracker를 초기화하고 렌더링합니다:
import { useEffect } from "react"
import { datafluxRum } from "@cloudcare/browser-rum"
import {
nextjsPlugin,
RumNextjsPagesRouter,
} from "@cloudcare/browser-rum-nextjs"
let initialized = false
export default function App({ Component, pageProps }) {
useEffect(() => {
if (initialized) return
initialized = true
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "web-nextjs",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
plugins: [nextjsPlugin()],
})
}, [])
return (
<>
<RumNextjsPagesRouter />
<Component {...pageProps} />
</>
)
}
Pages Router는 router.pathname을 템플릿 이름으로 사용합니다. 예를 들어 실제 URL /users/42는 /users/[id]로 분류됩니다. routeChangeError, 취소된 탐색, 그리고 query 또는 hash만 변경된 경우에는 새 View가 생성되지 않습니다.
Next.js View 및 Error¶
App Router는 usePathname()과 useParams()를 기반으로 파일 라우트 템플릿을 생성합니다:
| 실제 URL | View 이름 |
|---|---|
/ |
/ |
/users/42 |
/users/[id] |
/docs/a/b |
/docs/[...slug] |
안정적인 이름을 자동으로 생성할 수 없는 경우, getViewName을 전달할 수 있습니다:
App Router의 error.tsx, global-error.tsx 또는 비즈니스 오류 처리기에서 addNextjsError()를 호출합니다:
"use client"
import { useEffect } from "react"
import { addNextjsError } from "@cloudcare/browser-rum-nextjs"
export default function ErrorPage({ error, reset }) {
useEffect(() => {
addNextjsError(error, undefined, {
route_boundary: "dashboard",
})
}, [error])
return <button onClick={reset}>재시도</button>
}
오류 객체에 Next.js digest가 포함된 경우, 플러그인은 이를 Error 컨텍스트에 기록하여 서버 로그와의 연관을 용이하게 합니다. 플러그인은 또한 클라이언트 React 하위 트리를 보호하는 데 사용할 수 있는 ErrorBoundary를 제공합니다.
Nuxt¶
Nuxt 플러그인은 Nuxt 3, 4, 그리고 Vue 3 및 Vue Router 4를 지원합니다.
설치¶
클라이언트 플러그인 생성¶
프로젝트 plugins 디렉터리에 rum.client.ts를 생성합니다. .client 접미사는 코드가 브라우저에서만 실행되도록 보장하며, enforce: "pre"는 RUM이 라우트 및 오류 리스너를 최대한 빨리 설치하도록 합니다.
import { datafluxRum } from "@cloudcare/browser-rum"
import { nuxtRumPlugin } from "@cloudcare/browser-rum-nuxt"
export default defineNuxtPlugin({
name: "dataflux-rum",
enforce: "pre",
setup(nuxtApp) {
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "web-nuxt",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
plugins: [
nuxtRumPlugin({
nuxtApp,
router: useRouter(),
}),
],
})
},
})
Nuxt는 plugins 디렉터리 최상위에 있는 플러그인을 자동으로 등록하므로 nuxt.config.ts에 추가로 작성할 필요가 없습니다. 동일한 애플리케이션에서 Nuxt 플러그인과 Vue 플러그인을 동시에 사용하여 동일한 Router를 추적하지 마십시오.
Nuxt View 및 Error¶
플러그인은 Vue Router 매개변수 경로를 Nuxt 파일 라우트 이름으로 변환합니다:
| Vue Router 경로 | RUM View 이름 |
|---|---|
/users/:id |
/users/[id] |
/users/:id? |
/users/[[id]] |
/docs/:slug(.*)* |
/docs/[...slug] |
성공적인 pathname 탐색 및 hash 라우트는 View를 생성합니다. query만 변경되거나 실패한 탐색은 View를 생성하지 않습니다. 사용자 정의 이름이 필요한 경우 nuxtRumPlugin()에 getViewName(route)를 전달합니다.
nuxtApp을 전달하면 플러그인이 Vue 컴포넌트 오류와 Nuxt app:error를 모두 처리합니다. 동일한 Error 객체가 한 번의 전파 중에 두 오류 체인에 동시에 진입하는 경우 한 번만 보고되며, 애플리케이션의 기존 Vue 오류 처리기는 유지됩니다.
비즈니스 로직에서 오류를 능동적으로 포착하는 경우 addNuxtError()를 호출합니다:
import { addNuxtError } from "@cloudcare/browser-rum-nuxt"
try {
await submitOrder()
} catch (error) {
addNuxtError(error, {
operation: "submit_order",
module: "checkout",
})
}
통합 확인¶
- 브라우저 개발자 도구를 열고 Network 탭에서
/v1/write/rum을 필터링합니다. - 페이지에 처음 진입했을 때
type=view가 나타나는지 확인합니다. - 동적 라우트로 이동했을 때 View가
/users/[id]와 같은 파일 라우트 템플릿을 사용하는지 확인합니다. - query만 변경했을 때 View가 중복 생성되지 않는지 확인합니다.
- 클라이언트 컴포넌트 오류를 트리거했을 때
type=error가 나타나고,context.framework = nextjs또는context.framework = nuxt가 포함되는지 확인합니다.
자주 묻는 질문¶
빌드 시 window is not defined 오류 발생¶
RUM 초기화가 서버 측 모듈로 진입했습니다. Next.js는 instrumentation-client.ts 또는 "use client"가 포함된 초기화 컴포넌트를 사용해야 합니다. Nuxt 플러그인 파일은 반드시 .client.ts 또는 .client.js 접미사를 사용해야 합니다.
오류는 있지만 프레임워크 View가 없음¶
Next.js는 현재 Router에 해당하는 tracker를 렌더링해야 합니다. Nuxt 플러그인은 router: useRouter()를 전달해야 합니다. 동일한 애플리케이션에서 여러 Router tracker를 혼용하지 마십시오.
한 번의 이동으로 여러 View 생성¶
애플리케이션 전체에 하나의 tracker만 배치하고, 동일한 탐색을 위해 datafluxRum.startView()를 추가로 호출하지 마십시오.