Sentry 알림을 열었는데 TypeError 한 줄과 압축된 스택트레이스만 있으면 당최 어디서부터 봐야 할지 막막하다. 누가 어디서 겪었는지 모르면 재현부터 어렵다. 이벤트에 무엇을 붙여야 할까. 어디까지 보내도 될까.
2026-10-23 기준 npm @sentry/browser 최신은 11.8.0이다. v11에서 sendDefaultPii가 사라지고 dataCollection이 들어왔다. 마이그레이션 가이드에 따르면 v10은 옵션을 비워 두면 제한적으로 모았지만 v11은 비워 두면 전부 모은다. v10 기본값에 기대던 프로젝트는 업그레이드만 해도 쿠키와 요청 본문까지 모으게 된다.
남길 정보와 API
| 검색할 값 | setTag | 태그 | 키·값 각 200자 |
| 읽기만 할 데이터 | setContext | 이슈 화면 | 검색 안 됨, 키 type 금지 |
| 누가 겪었나 | setUser | 사용자 항목 | 이메일 대신 내부 id |
| 직전 동작 | 브레드크럼, 로그 | 브레드크럼, Logs | 개인정보를 적지 않는다 |
| 묶는 기준 | setFingerprint | 이슈 그룹 | 같은 지문은 한 이슈 |
| 파일 | addAttachment | 첨부 | 압축 40MB, 비압축 200MB |
| 원본 코드 줄 | 소스맵 | 스택트레이스 | 빌드 때 업로드 |
태그는 책의 색인, 컨텍스트는 본문이라고 보면 된다. 찾을 값만 태그로 올리자.

이벤트에 맥락 붙이기
릴리스와 환경은 init에 넣는다. 나머지는 set 계열로 붙인다.
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
release: "my-app@1.4.2", // 릴리스 이름
environment: "staging", // 공백·슬래시 없이 64자 이내
});
Sentry.setContext("cart", { itemCount: 3 }); // 읽기용
Sentry.setUser({ id: "u_1029" }); // 내부 id만. 로그아웃 때 null
한 요청에만 붙이기
특정 호출에만 붙일 값은 withScope 안에서 넣는다. 같은 스택이라도 경로별로 이슈를 나누려면 지문을 직접 준다.
try {
await fetch(path, { method });
} catch (err) {
Sentry.withScope((scope) => {
scope.setTag("api.path", path); // 이 콜백 안에서만
scope.setFingerprint(["{{ default }}", method, path]); // 경로별로 묶는다
Sentry.captureException(err); // Error 객체를 넘긴다
});
}
captureMessage의 기본 레벨은 info다. v11은 메시지에도 합성 스택트레이스가 붙고 세션이 errored로 잡힌다. 단순 기록은 로그가 낫다.
브레드크럼보다 로그
브라우저 SDK는 클릭·키 입력, fetch/XHR, console, 주소 변경을 브레드크럼으로 자동 기록한다. 문서는 이제 구조화 로그를 권한다. 10.71.0 이상은 로그가 기본으로 켜진다.
// 10.71.0 미만은 enableLogs: true 필요
Sentry.logger.info("Order created", { orderId: "order_456" }); // 둘째 인자는 검색 가능
Sentry.logger.warn(Sentry.logger.fmt`Retry ${attempt}`); // 값이 속성으로 뽑힌다
모든 로그에 붙일 값은 setAttribute(10.61.0 이상)로 넣자.
보내기 전에 지우기
문서가 꼽는 금지 대상은 이름·이메일 같은 개인정보와 인증 정보다. 막는 자리는 셋이다.
- SDK : beforeSend(에러·메시지)와 beforeSendLog(로그). 바꾸면 재배포해야 한다
- 서버 : Sentry 화면의 스크러빙 설정. 새 이벤트부터 바로 적용된다
- Relay : 내 서버에 둔 Relay가 중간에서 거른다
Sentry는 auth나 token, password처럼 생긴 키의 값을 가린다. 키 이름으로만 맞추므로 엉뚱한 이름의 토큰은 그대로 간다. setUser로 직접 넣은 값은 수집 설정과 상관없이 항상 전송된다. SDK 쪽은 이렇게 막는다.
Sentry.init({
// dsn 등은 생략
dataCollection: { userInfo: false, cookies: false, httpBodies: [] }, // v10 기준선 일부
beforeSend(event) {
if (event.user) delete event.user.email; // 이메일은 내보내지 않는다
return event; // null이면 이벤트를 버린다
},
beforeBreadcrumb(crumb) {
return crumb.category === "ui.click" ? null : crumb; // 클릭 기록은 버린다
},
});
beforeSend가 돌 때는 스코프 데이터가 이미 들어가 있어 태그·컨텍스트 값까지 여기서 지울 수 있다. 유출 사고 때 운영자 의무는 개정 개인정보보호법 정리에 따로 적어 뒀다. 토큰이 엉뚱한 곳에 남는 다른 예는 Dockerfile ARG 글에서 다뤘다.
압축된 스택트레이스 풀기
소스맵을 올려야 원본 코드 줄이 보인다. 쉬운 길은 npx @sentry/wizard@latest -i sourcemaps 마법사다.
하나만 먼저 한다면 소스맵이다. 태그를 아무리 붙여도 스택이 압축된 한 줄이면 고칠 곳을 모른다.
참고
- Sentry Docs APIs https://docs.sentry.io/platforms/javascript/configuration/apis/
- Sentry Docs Migrate from 10.x to 11.x https://docs.sentry.io/platforms/javascript/migration/v10-to-v11/
- Sentry Docs Options https://docs.sentry.io/platforms/javascript/configuration/options/
- Sentry Docs Scrubbing Sensitive Data https://docs.sentry.io/platforms/javascript/data-management/sensitive-data/
- Sentry Docs Logs https://docs.sentry.io/platforms/javascript/logs/
'개발 > 프론트엔드' 카테고리의 다른 글
| ⚡ Next.js prefetch false 언제 쓰나 · 기본값과 서버 부하 (0) | 2026.10.23 |
|---|---|
| ⚛️ React 19.3 출시, ViewTransition canary 없이 쓴다 (0) | 2026.09.16 |
| 📱 Shopify가 React Native 버리고 네이티브로 돌아간 이유 (0) | 2026.09.11 |