[React]
- [React] vite React설치
- Project initial setting
- Hooks && Library
- [React] Javascript 파일을 Typescript Import해보자
- [React] react-router-dom 알아보고 사용하자
- [React] child 컴포넌트에서 함수호출하기
- [React] useCallback
- [React] framer-motion 알아보고 사용하자
- [React] Context API
- [React] react lazy 지연로딩 예제
- [React] react에서 캐싱처리를 위한 react queryd와 indexDB 비교분석
- [React] 스타일 라이브러리 styled-components stitches 비교
- [React] 프론트 에러추적 도구 Sentry 사용해보기
- [React] React 19 주요 변경점
- [React] DOM이란 무엇이고? 가상 DOM이란 무엇인가?
- [React] preact 알아보기
- [React] Sentry 심층 가이드
- [React] stagewise 사용법
절약하면서도 스마트하게! Sentry 사용 가이드 🔍
아, 로그 찍는 건 좋은데… 왜 갑자기 요금이 청구되었지? 😱 이런 경험, 다들 한 번쯤 있으시죠? Sentry는 정말 유용한 에러 추적 도구지만, 주머니 사정도 생각해야 합니다!
간단사용법은 [React] 프론트 에러추적 도구 Sentry 사용해보기 적어두었으니 확인!
🚨 문제 발견! 로그가 넘쳐흐른다!
플랜 | 가격 | 대상 | 주요 기능 |
---|---|---|---|
Developer | 무료 | 소규모 프로젝트에서 일하는 개인 개발자 | • 사용자 1명 • 오류 모니터링 및 추적 • 이메일을 통한 알림 및 알림 |
Team | $26/월 | 협업하는 성장 중인 팀 | • 무제한 사용자 • Developer 기능 포함 • 서드파티 통합 • 메트릭 알림 • 인사이트(7일 룩백) • 추가 이벤트(가격 정책 참조) |
Business | $80/월 | 규모에서 운영되는 여러 팀 | • Team 기능 포함 • 인사이트(90일 룩백) • 커스텀 대시보드 • 고급 할당량 관리 • 추가 이벤트(가격 정책 참조) |
Enterprise | 커스텀 가격 | 고급 요구사항을 가진 조직 | • Business 기능 포함 • 기술 계정 관리자 • 전담 고객 지원 |
Sentry 오류 가격 정책
오류 볼륨 | Team 예약 가격 | Team PAYG 가격 | Business 예약 가격 | Business PAYG 가격 |
---|---|---|---|---|
>50k-100k | $0.0002900 | $0.0003625 | $0.0008900 | $0.0011125 |
>100k-500k | $0.0001750 | $0.0002188 | $0.0005000 | $0.0006250 |
>500k-10M | $0.0001500 | $0.0001875 | $0.0003000 | $0.0003750 |
>10M-20M | $0.0001300 | $0.0001625 | $0.0002600 | $0.0003250 |
>20M | $0.0001200 | $0.0001500 | $0.0002400 | $0.0003000 |
- 모든 유료 플랜은 기본적으로 매월 50,000개의 오류를 포함합니다.
- 예약 볼륨을 초과할 경우, PAYG(Pay-as-you-go) 예산을 사용해 추가 데이터를 처리할 수 있습니다.
- 예약 볼륨과 PAYG 예산을 모두 소진한 경우 데이터는 더 이상 처리되지 않으며, 해당 청구 주기의 나머지 기간 동안 모니터링이 중단됩니다.
- 미사용된 예약 볼륨은 매월 청구 주기 말에 만료됩니다.
물론 돈을 추가 하여 사용량을 추가하는 방법도 있지만 필요없는 로그에 수집 등등 절약하기 위하여 개선방안을 작성
💡 현명한 해결책: 샘플링과 필터링!
1. 🎯 샘플링: “다 볼 필요 없어, 대표만 보자!”
1
2
// 이렇게 하면 전체 오류의 25%만 수집해요! 👇
Sentry.init({ sampleRate: 0.25 });
생각해보세요. 같은 에러가 100번 발생했다면, 사실 25번만 알아도 충분하지 않나요? 이것만으로도 비용을 1/4로 줄일 수 있어요!
더 스마트하게 샘플링하기 🧠
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Sentry.init({
tracesSampler: ({ name }) => {
// 헬스체크는 별로 중요하지 않으니 무시!
if (name.includes("healthcheck")) return 0;
// 결제 관련은 매우 중요하니 100% 수집!
if (name.includes("payment")) return 1;
// 댓글 관련은 그냥 1%만 볼게요~
if (name.includes("comment")) return 0.01;
// 나머지는 절반만 수집
return 0.5;
},
});
이런 방식으로 중요한 건 놓치지 않고, 덜 중요한 건 적게 수집하면 비용도 절약하고 중요한 정보도 놓치지 않을 수 있어요! 👍
2. ✂️ 필터링: “이건 필요없어, 버려!”
특정 에러 무시하기
1
2
3
4
Sentry.init({
// 이 에러들은 이제 Sentry에 보내지 않아요!
ignoreErrors: ["나중에 볼게요...", /^이건 별로 중요하지 않아요$/],
});
원하는 데이터만 골라서 보내기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Sentry.init({
beforeSend(event) {
// 사용자 개인정보는 제거하고 보내요 (개인정보 보호도 챙기고!)
if (event.user && event.user.email) {
delete event.user.email;
}
// "테스트" 환경에서 발생한 에러는 보내지 않을래요
if (event.tags && event.tags.environment === "test") {
return null; // null 반환하면 이 이벤트는 전송되지 않아요!
}
return event;
},
});
특정 URL에서 발생한 에러만 수집하기
1
2
3
4
Sentry.init({
// 우리 사이트 도메인에서 발생한 에러만 수집할게요!
allowUrls: [/https?:\/\/(www\.)?mysite\.com/],
});
써드파티 라이브러리에서 발생하는 에러 필터링하기
1
2
3
4
5
6
7
8
9
10
Sentry.init({
integrations: [
Sentry.thirdPartyErrorFilterIntegration({
// 우리 코드에만 "my-app-key" 태그를 붙여두고
filterKeys: ["my-app-key"],
// 외부 라이브러리 에러는 수집하지 않아요! 그들의 문제니까요~
behaviour: "drop-error-if-contains-third-party-frames",
}),
],
});
3. 🎭 실전 활용 팁!
- 개발 초기: 모든 에러를 수집하세요 (
sampleRate: 1
) - 안정화 후: 샘플링 비율을 낮추세요 (
sampleRate: 0.2
~0.5
) - 특정 기능 출시 후: 해당 기능 관련 에러는 더 많이 수집하고, 안정된 기능은 적게!
- 중요한 사용자: VIP 고객의 에러는 100% 수집하고, 일반 사용자는 샘플링하세요!
이렇게 Sentry를 똑똑하게 사용하면, 비용은 줄이면서도 중요한 에러는 놓치지 않을 수 있어요! 월 50,000개 제한에도 여유롭게 대처할 수 있겠죠? 😎
팁: 샘플링과 필터링은 동시에 적용 가능해요! 샘플링으로 전체 양을 줄이고, 필터링으로 중요한 것만 걸러내면 완벽해요!
🔍 에러 수색의 달인되기: Sentry Tags 활용법!
에러가 발생했는데 찾을 수가 없다면? 그건 마치 바늘을 찾는 건초더미 같은 경험이죠! 🧐
🚫 전통적인 방법의 한계
기존에 우리가 Sentry에 에러를 보낼 때는 이렇게 했었죠:
1
2
3
4
5
6
7
8
9
10
11
12
Sentry.captureException(
new Error(
`${bridgeName} 에러 발생 :: ${error instanceof Error ? error.message : ""}`
),
{
extra: {
memberSeq: localStorage.getItem("memberSeq"), // 👈 여기에 주목!
bridgeName,
error,
},
}
);
이런 방식의 문제점은 뭘까요? 검색이 안 된다는 것! 😱
데이터는 Additional Data에 잘 보이는데… 만약 “특정 사용자에게 발생한 에러를 모두 찾아줘!”라고 요청받는다면? 아휴… 일일이 다 열어봐야 하나요? 😓
✨ 태그로 변신! 검색의 마법 부리기
해결책은 간단합니다! extra
대신 tags
를 활용하세요:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Sentry.captureException(
new Error(
`${bridgeName} 에러 발생 :: ${error instanceof Error ? error.message : ""}`
),
{
tags: {
// 🌟 tags를 사용하면 검색 가능!
memberSeq: localStorage.getItem("memberSeq"),
bridgeName,
},
extra: {
error, // 객체는 여전히 extra에 넣어요
},
}
);
🎉 태그의 마법으로 얻는 혜택
이렇게 태그를 사용하면:
- 초고속 검색 🚀 - “memberSeq:12345”로 검색하면 해당 사용자의 모든 에러가 바로!
- 필터링의 달인 🔎 - 여러 태그를 조합해서 “이 기능에서, 이 사용자에게, 이런 에러가…” 식으로 복합 검색 가능!
- 고객 응대 레벨 업 💯 - “죄송합니다만 회원번호 좀 알려주시겠어요?” → 즉시 해당 회원의 에러 이력 파악!
- 트렌드 분석 📊 - 특정 기능(bridgeName)에서 에러가 많이 발생하는지 한눈에!
💡 프로 팁: 태그 활용법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Sentry.captureException(error, {
tags: {
// 사용자 관련
memberSeq: user.id,
userType: user.type, // "premium", "free" 등
// 기능 관련
feature: "bluemeter",
action: "connect",
// 디바이스 관련
device: deviceInfo.model,
os: deviceInfo.os,
// 비즈니스 관련
priority: error.message.includes("payment") ? "high" : "normal",
impactLevel: calculateImpact(error),
},
});
🎯 실전 검색 예시
1
2
3
4
5
6
7
8
# 프리미엄 사용자의 결제 관련 에러만 보기
is:unresolved userType:premium feature:payment
# 특정 디바이스에서 발생하는 블루미터 연결 문제
device:"Galaxy S21" feature:bluemeter action:connect
# 우선순위가 높은 해결되지 않은 이슈
is:unresolved priority:high
🚀 태그 사용 시 주의사항
- 너무 많은 태그는 금물! - 정말 검색이 필요한 것만 태그로!
- 민감한 정보 주의! - 이메일, 전화번호 등은 필터링하거나 해싱하세요
- 일관성 유지! - 팀 내에서 태그 네이밍 규칙을 정하고 통일하세요
- 태그값 제한! - 엄청 긴 텍스트나 JSON 등은
extra
에 넣어주세요
이렇게 태그를 활용하면 에러 추적이 마치 구글 검색처럼 쉬워집니다! 사용자 경험도 개선되고, 개발자 경험도 개선되는 일석이조의 효과를 얻을 수 있어요! 🎊