1. 기존 문제점
사용자들이 무언가 에러가 발생했을 때, ‘빨간 에러가 떠요’라고만 이야기해줄 뿐, 어떤 에러인 지는 명확히 알려주지 않는 경우가 많았다. 에러 메시지가 화면에 떠서, 그 메시지를 보내주면 매우 고맙겠지만, 만약 그렇다 하더라도, 동일한 휴대폰과 환경에서 다시 재연하기란 불가능에 가까웠다. 그래서, 에러를 추적하는 방법을 생각해보았다.
2. 에러를 추적하는 방법
1. Next.js 서버 에러
-
Next.js 서버를 띄운 환경에서 확인이 가능하다.
-
vercel로 배포했을 경우, Logs탭에서 확인할 수 있다.
2. Next.js 클라이언트 에러
- 오류가 발생한 클라이언트 장비에 원격 접속해 직접 웹 브라우저를 확인한다
- 서비스 이용 중인 고객에게 직접 ‘웹 브라우저의 개발다 도구를 열고 > 콘솔에 찍힌 오류내용을 캡쳐해주세요’ 요구한다
너무 번거로운 일이다. 그리고, 이러한 에러 대응은 즉각적인 대응이 어렵다. 이러한 클라이언트에서 발생한 에러 트래킹을 도와주는 서비스가 바로 Sentry이다.
3. Sentry
: 실시간 로그 취합 및 분석 도구이자 모니터링 플랫폼
- 로그에 대해 다양한 정보를 제공하고 이벤트별, 타임라인으로 얼마나 많은 이벤트가 발생하는지 알 수 있고 설정에 따라 알림을 받을 수 있다
- 로그를 수집하는데서 그치지 않고 발생한 로그들을 시각화 도구로 쉽게 분석할 수 있도록 도와주며 다양한 플랫폼을 지원한다
1. 특징
- 이벤트 로그에 대한 다양한 정보를 제공한다.
- Exception & Message : 이벤트 로그 메시지 및 코드 라인 정보
- Device : 이벤트 발생 장비 정보
- e.g. name, family, model, memory
- Browser : 이벤트 발생 브라우저 정보
- e.g. name, version
- OS : 이벤트 발생 OS 쩡보
- Breadcrumbs : 이벤트 발생 과정
- 다양한 알림 채널을 지원한다
- Slack, Teams, Jira, Github
- 다양한 플랫폼을 지원한다
- .net, android, apple, Go, Java, Next, React, Python, Kotlin
-
종류
-
클라우드 버전 (구독형) : 인프라와 솔루션을 한 번에 제공
- 유지 보수 및 운영에 신경쓰지 않아도 된다.
-
프레미스 버전 (설치형)
- 정보 유출 방지
- 비용 절감 : Develop는 무료
4. Sentry을 적용해보자
1. 설치
npm install --save @Sentry/react @Sentry/tracing
💡
npm install —-save?
1. 에러 출력하기
export default function App(){
this.myCodeIsPerfect();
return <div> </div>
}
위와 같이 에러가 발생할만한 상황을 만들어보았다.
어느 기기, 어떤 환경에서, 그리고 어떤 코드에서 발생했는 지 모든 것을 알려준다. 정말 친절하다.
2. api 에러 출력하기
const queryClient = new QueryClient({
defaultOptions: {
// ..
},
logger: {
log: (message) => {
Sentry.captureMessage(message);
},
warn: (message) => {
Sentry.captureMessage(message);
},
error: (error) => {
Sentry.captureException(error);
},
},
});
QueryProvider의 logger객체로 Sentry.captureMeesage를 실행하였다.
export const getGroups = (page: number) => {
return privateApi.get<GroupsResponse>(`/groupsr?size=10&page=${page}`);
};
이를 테스트하기 위해 일부러, api 엔드포인트에 오타를 내서 에러를 만들어보았다.
출력한 에러이다. 그나저나,
3. 에러를 실시간으로 알림 받기
Integrations에서 Slack알림을 연동할 수 있다. 대신, 월 $29 이상의 요금을 결제해야한다.
연결을 하면, 위와 같이 에러가 발생했을 때 Sentry에서 Slack으로 알림을 보내준다.
4. 유저의 정보도 담아서 에러 출력하기
-
Sentry.setUser,Sentry.setTag,Sentry.setLevel을 이용하여 에러 상황 시 추가 정보를 전송할 수 있다. -
Sentry.setUser({ email: "john.doe@example.com" });
5. ErrorBoundary로 에러 명시적으로 처리하기
interface LocalApiAsyncBoundaryProps {}
export default function LocalApiAsyncBoundary({
children,
}: StrictPropsWithChildren<LocalApiAsyncBoundaryProps>) {
return (
<ErrorBoundary fallbackRender={Fallback}>
<Suspense fallback={<Loading />}>{children}</Suspense>
</ErrorBoundary>
);
}
Suspense는 Promise로 데이터 패칭에 대한 상태를 관리하는데, 에러가 발생하면 에러를 throw하여, 이를 ErrorBoundary가 받는다. 그래서 에러가 발생하면 ErrorBoundary의 fallbackRender로 넘긴 Fallback을 보여준다.
export function Fallback({ error, resetErrorBoundary }: PropsWithChildren<FallbackProps>) {
useEffect(() => {
captureException(new Error('LocalApiAsyncBoundary'));
}, []);
return (
<BaseError
error={error}
reset={useCallback(() => resetErrorBoundary(), [resetErrorBoundary])}
/>
);
}
Fallback에서는 ErrorBoundary에서 props로 넘겨준 error와 resetErrorBoundary로 에러를 보여주고, 새로고침을 실행할 수 있다.