Sentry는 Vue 애플리케이션에서 오류와 성능 이슈를 실시간으로 감지하고 보고하는 강력한 도구입니다. 본 문서에서는 최신 버전의 Sentry(v21.8.x)를 기준으로 Vue 프로젝트에 Sentry를 효과적으로 통합하는 방법을 단계별로 설명합니다.
시작하기
Sentry SDK는 자동으로 예외와 오류를 캡처하여 개발자가 문제를 신속하게 파악할 수 있도록 지원합니다.
설치
프로젝트 루트 디렉터리에서 다음 명령어를 사용해 필요한 패키지를 설치하세요:
# npm 사용
npm install --save @sentry/vue @sentry/tracing
# yarn 사용
yarn add @sentry/vue @sentry/tracing
기본 설정
애플리케이션 초기화 시점에 Sentry를 구성해야 합니다. 아래 예제는 Vue 2와 Vue 3 환경에서 각각 어떻게 적용하는지를 보여줍니다.
Vue 2
import Vue from 'vue';
import Router from 'vue-router';
import * as Sentry from '@sentry/vue';
import { Integrations } from '@sentry/tracing';
Vue.use(Router);
const router = new Router({
// 라우팅 설정
});
Sentry.init({
Vue,
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
integrations: [
new Integrations.BrowserTracing({
routingInstrumentation: Sentry.vueRouterInstrumentation(router),
tracingOrigins: ['localhost', 'my-site-url.com', /^\//],
}),
],
tracesSampleRate: 1.0, // 운영 환경에서는 낮은 값으로 조정 권장
});
new Vue({
router,
render: h => h(App),
}).$mount('#app');
Vue 3
import { createApp } from 'vue';
import { createRouter } from 'vue-router';
import * as Sentry from '@sentry/vue';
import { Integrations } from '@sentry/tracing';
const app = createApp({});
const router = createRouter({});
Sentry.init({
app,
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
integrations: [
new Integrations.BrowserTracing({
routingInstrumentation: Sentry.vueRouterInstrumentation(router),
tracingOrigins: ['localhost', 'my-site-url.com', /^\//],
}),
],
tracesSampleRate: 1.0,
});
app.use(router);
app.mount('#app');
다중 앱 인스턴스 (Vue 3)
하나의 Sentry 인스턴스로 여러 Vue 앱을 동시에 모니터링할 수 있습니다:
const appOne = createApp(AppA);
const appTwo = createApp(AppB);
Sentry.init({
app: [appOne, appTwo],
});
수동 초기화
특정 앱만 선택적으로 Sentry를 연결하고자 할 때 사용합니다:
const app = createApp(App);
Sentry.init({ app });
const miscApp = createApp(MiscApp);
miscApp.mixin(Sentry.createTracingMixins({ trackComponents: true }));
Sentry.attachErrorHandler(miscApp, { logErrors: true });
검증 테스트
설정 후 오류가 정상적으로 전송되는지 확인하세요. 아래 코드를 컴포넌트에 추가하고 버튼을 클릭해보세요:
<template>
<button @click="triggerError">오류 발생</button>
</template>
<script>
export default {
methods: {
triggerError() {
throw new Error('테스트 오류: Sentry 작동 확인');
}
}
}
</script>
핵심 설정 옵션
Sentry는 다양한 설정 옵션을 제공하여 데이터 수집 방식을 세밀하게 제어할 수 있습니다.
공통 옵션
- dsn: Sentry 프로젝트 식별 정보. 환경 변수
SENTRY_DSN에서도 읽을 수 있음. - debug: 디버그 모드 활성화 여부. 기본값은
false. - release: 배포 버전명. CI/CD 파이프라인과 연동해 자동 설정 가능.
- environment: 현재 환경 (예: staging, production).
- sampleRate: 오류 이벤트 샘플링 비율 (0.0 ~ 1.0). 기본값은 1.0.
- tracesSampleRate: 트랜잭션 추적 샘플링 비율.
- maxBreadcrumbs: 저장할 브레드크럼 최대 개수. 기본값은 100.
- attachStacktrace: 메시지에 스택 트레이스 포함 여부.
훅 기반 설정
컴포넌트 생명주기 이벤트를 추적할 수 있습니다:
Sentry.init({
app,
dsn: '...',
trackComponents: true,
hooks: ['mount', 'update', 'destroy'],
timeout: 3000,
});
이벤트 필터링
불필요한 오류를 제외하거나 특정 조건에 따라 데이터를 조작할 수 있습니다.
beforeSend 사용
이벤트 전송 직전에 커스터마이징할 수 있습니다:
Sentry.init({
beforeSend(event, hint) {
const error = hint.originalException;
if (error && error.message.includes('database')) {
event.fingerprint = ['db-connection-error'];
}
return event;
}
});
도메인 기반 필터링
특정 출처의 오류만 허용하거나 차단합니다:
Sentry.init({
allowUrls: [/https?:\/\/(www\.)?my-domain\.com/],
denyUrls: [/graph\.facebook\.com/, /extensions\//]
});
소스맵(Source Maps) 통합
압축된 코드에서도 원본 소스 위치를 정확히 파악하기 위해 소스맵을 업로드해야 합니다.
Webpack 플러그인 사용
const SentryWebpackPlugin = require('@sentry/webpack-plugin');
module.exports = {
devtool: 'source-map',
plugins: [
new SentryWebpackPlugin({
authToken: process.env.SENTRY_AUTH_TOKEN,
org: 'your-org',
project: 'your-project',
release: process.env.SENTRY_RELEASE,
include: './dist',
ignore: ['node_modules']
})
]
};
수동 업로드 (sentry-cli)
- 릴리스 생성:
sentry-cli releases new "v1.0.0" - 아티팩트 업로드:
sentry-cli releases files v1.0.0 upload-sourcemaps ./dist - 완료 처리:
sentry-cli releases finalize v1.0.0
성능 추적 및 리소스 관리
트랜잭션 샘플링
과도한 데이터 전송을 방지하기 위해 동적 샘플링을 구현할 수 있습니다:
Sentry.init({
tracesSampler(context) {
if (context.transactionContext.name.startsWith('/admin')) {
return 0.5; // 관리자 경로는 절반만 추적
} else if (context.transactionContext.op === 'pageload') {
return 0.1; // 페이지 로드는 10%만 추적
}
return 0.01;
}
});
세션 추적
사용자 세션 상태를 기록하여 충돌률 등을 분석할 수 있습니다:
Sentry.init({
autoSessionTracking: true,
initialScope: {
user: { id: '123', email: 'user@example.com' }
}
});
고급 기능
rrweb을 이용한 세션 재생
사용자 행동을 녹화하여 문제 재현이 용이합니다:
npm install --save @sentry/rrweb rrweb
import * as Sentry from '@sentry/browser';
import SentryRRWeb from '@sentry/rrweb';
Sentry.init({
integrations: [new SentryRRWeb()],
tracesSampleRate: 0.2
});
광고 차단기 우회
클라이언트 측에서 요청이 차단되는 경우, 백엔드를 통해 프록시 요청을 보냅니다:
Sentry.init({
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
tunnel: '/sentry-tunnel'
});
서버 측에서 /sentry-tunnel 엔드포인트를 구현하여 실제 Sentry API로 포워딩해야 합니다.
문제 해결 팁
- CORS 문제: 외부 도메인에서 로드하는 스크립트에는
crossorigin="anonymous"속성을 추가하고 서버에Access-Control-Allow-Origin: *헤더를 설정하세요. - 소스맵 검증: sourcemaps.io를 사용해 로컬에서 소스맵 변환 결과를 미리 확인하세요.
- 브라우저 호환성: IE11 이하 지원을 위해서는
Promise,Object.assign등의 폴리필이 필요합니다.