Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sentry를 이용한 에러 추적기, React의 선언적 에러 처리

kakao
December 08, 2022

Sentry를 이용한 에러 추적기, React의 선언적 에러 처리

#React #Sentry #선언적에러처리

카카오페이 프론트엔드에서 선언적 에러처리를 통한 사용자경험과 개발자경험 증대 및 Sentry를 통한 웹뷰환경에서의 에러 추적, 장애 대응, 사용자 경험 개선기 (axios interceptor와 에러바운더리를 이용해 에러핸들링을 개선해 나가고, sentry를 통해 에러데이터를 쌓아 사용자 경험을 개선해나간 스토리로 풀어볼 예정입니다.)

발표자 : chloe.ykim
사용자 경험을 소중하게 생각하는 카카오페이 FE개발팀의 클로이, 나나입니다.

nana.na
사용자 경험을 소중하게 생각하는 카카오페이 FE개발팀의 클로이, 나나입니다.

kakao

December 08, 2022
Tweet

More Decks by kakao

Other Decks in Programming

Transcript

  1. Sentryܳ ੉ਊೠ ী۞ ୶੸ӝ, React੄ ࢶ঱੸ ী۞ ୊ܻ 김윤선 Chloe.ykm,

    나유리 Nana.na 카카오페이 Copyright 2022. Kakao Corp. All rights reserved. Redistribution or public display is not permitted without written permission from Kakao. if(kakao)2022
  2. 들어가며 기존의 에러 처리 Error Boundaries 라이브러리와 Error Boundaries 선언적

    에러 처리 선언적 에러 처리의 장단점 Sentry를 이용한 데이터 수집 Severity 기준설정과 모니터링 에러 데이터 분석 개선 후, 이런 점이 좋아졌어요
  3. 우리가 겪어야 했던 상황들 PM @FE 운영환경에서 pdf 파일 버튼

    클릭 시 반응이 없어요! 빠르게 확인 부탁드려요! FE @BE 운영환경 디버깅이 불가해서 그런데 혹시 /v1/api/pdf 이 API응답이 어떻게 오는지 알 수 있을까요? BE @FE 해당 API 응답을 확인해보니 빈 배열로 내려가는 경우가 있는 것 같습니다.
  4. 우리가 겪어야 했던 상황들 FE @BE 운영환경 디버깅이 불가해서 그런데

    혹시 /v1/api/pdf 이 API응답이 어떻게 오는지 알 수 있을까요? BE @FE 해당 API 응답을 확인해보니 빈 배열로 내려가는 경우가 있는 것 같습니다. PM @FE 운영환경에서 pdf 파일 버튼 클릭 시 반응이 없어요! 빠르게 확인 부탁드려요!
  5. 우리가 겪어야 했던 상황들 FE @BE 운영환경 디버깅이 불가해서 그런데

    혹시 /v1/api/pdf 이 API응답이 어떻게 오는지 알 수 있을까요? BE @FE 해당 API 응답을 확인해보니 빈 배열로 내려가는 경우가 있는 것 같습니다. PM @FE 운영환경에서 pdf 파일 버튼 클릭 시 반응이 없어요! 빠르게 확인 부탁드려요!
  6. PM @FE 운영환경에서 pdf 파일 버튼 클릭 시 반응이 없어요!

    빠르게 확인 부탁드려요! 우리가 겪어야 했던 상황들 FE @BE 운영환경 디버깅이 불가해서 그런데 혹시 /v1/api/pdf 이 API응답이 어떻게 오는지 알 수 있을까요? BE @FE 해당 API 응답을 확인해보니 빈 배열로 내려가는 경우가 있는 것 같습니다. 이슈 감지, 원인 파악, 해결까지 약 4시간 소요
  7. 에러 데이터 쌓기 Severity 기준설정 및 모니터링 에러 데이터 


    분석 분석 결과에 따른 개선 에러 추적을 개선해보자!
  8. 에러 데이터 쌓기 Severity 기준설정 및 모니터링 에러 데이터 


    분석 분석 결과에 따른 개선 에러 추적을 개선해보자!
  9. Sentry는 실시간 로그 취합 및 분석 도구이자 모니터링 플랫폼입니다. Sentry

    로그에 대한 다양한 정보를 제공하고 시각화 도구를 통해 발생한 이벤트들을 쉽게 분석할 수 있도록 도와줍니다. 다양한 플랫폼을 지원합니다.
  10. 에러 데이터 쌓기 captureException과 captureMessage 두 가지 API를 이용하여 에러

    데이터를 전송할 수 있습니다. import * as Sentry from '@sentry/react'; try { fetchAccountInfoApi(); } catch (error) { Sentry.captureException(error); } captureException로 에러 데이터 전송 import * as Sentry from '@sentry/react'; Sentry.captureMessage(‘API ࢲߡ ী۞о ߊࢤೞ৓णפ׮!'); captureMessage로 에러 데이터 전송
  11. 에러 데이터 쌓기 captureException과 captureMessage 두 가지 API를 이용하여 에러

    데이터를 전송할 수 있습니다. import * as Sentry from '@sentry/react'; try { fetchAccountInfoApi(); } catch (error) { Sentry.captureException(error); } captureException로 에러 데이터 전송 import * as Sentry from '@sentry/react'; Sentry.captureMessage(‘API ࢲߡ ী۞о ߊࢤೞ৓णפ׮!'); captureMessage로 에러 데이터 전송 에러 데이터는 쌓았는데 검색도 어렵고, 구분하기도 어렵고…
  12. import * as Sentry from '@sentry/react'; Sentry.withScope((scope) => { scope.setTag('type',

    'api'); scope.setLevel(Sentry.Severity.Error); Sentry.captureException( new Error('API Internal Server Error')); }); withScope로 해당 에러의 상세정보 전송 import * as Sentry from '@sentry/react'; Sentry.configureScope((scope) => { scope.setUser({ accountId: 2022, email: '[email protected]', }); scope.setTag({ webviewType: 'WEB' }); }); con fi gureScope로 사용자 정보 전송 에러 데이터 풍부하게 쌓기 - Scope con fi gureScope로는 공통 정보를 withScope로는 각 에러 상황 시 추가 정보를 전송합니다.
  13. 에러 데이터 풍부하게 쌓기 - Context 이벤트에 임의의 데이터를 연결할

    수 있는 context를 이용해 추가 정보를 전송합니다. 검색은 할 수 없고 해당 이벤트가 발생한 이벤트 로그에서 확인할 수 있습니다. // axios੄ errorё୓ const { method, url, params, data, headers } = error.config; const { data, status } = error.response; Sentry.setContext('API Request Detail', { method, url, params, data, headers, }); Sentry.setContext('API Response Detail', { status, data, });
  14. import * as Sentry from '@sentry/react'; 
 
 // withScopeܳ

    ੉ਊೞৈ ౠ੿ ੉߮౟ী tagܳ ࢸ੿ Sentry.withScope((scope) => { scope.setTag('type', 'api'); scope.setTag('api', 'general'); scope.setLevel(Sentry.Severity.Warning); Sentry.captureException(new Error('API Internal Server Error’)); }); 에러 데이터 풍부하게 쌓기 - Customized Tags tag는 키와 값이 쌍으로 이루어진 문자열입니다. tag는 인덱싱이 되는 요소이기 때문에 이슈 검색 및 트래킹을 신속하게 진행할 수 있습니다.
  15. 에러 데이터 풍부하게 쌓기 - Level 이벤트마다 level을 설정하여 이벤트의

    중요도를 식별할 수 있습니다. fetal, error, warning, log, info, debug, critical로 severity를 설정할 수 있습니다. import * as Sentry from '@sentry/react'; 
 Sentry.withScope((scope) => { scope.setTag('type', 'api'); scope.setTag('api', 'general'); scope.setLevel(Sentry.Severity.Error); // error level۽ ࢸ੿ Sentry.captureException(new Error('API Internal Server Error’)); }); Sentry.withScope((scope) => { scope.setTag('type', 'api'); scope.setTag('api', 'timeout'); scope.setLevel(Sentry.Severity.Warning); // warning level۽ ࢸ੿ Sentry.captureException(new ApiError('API Timeout Error’)); });
  16. 에러 데이터 풍부하게 쌓기 - Issue Grouping 모든 이벤트는 fi

    ngerprint를 가지고 있습니다. fi ngerprint가 동일한 이벤트는 하나의 이슈로 그룹화되며 재설정 할 수 있습니다. import * as Sentry from '@sentry/react'; // axios੄ errorё୓ const { method, url } = error.config; const { status } = error.response; // withScopeܳ ੉ਊೞৈ fingerprintܳ ੤ࢸ੿ Sentry.withScope((scope) => { scope.setTag(‘type', 'api'); scope.setTag(‘api’, 'general'); scope.setFingerprint([method, status, url]); Sentry.captureException(new Error('API Internal Server Error’)); }); 같은 API에 대한 에러가 fi ngerprint 설정에 의해 grouping
  17. 에러 데이터 쌓기 Severity 기준설정 및 모니터링 에러 데이터 


    분석 분석 결과에 따른 개선 에러 추적을 개선해보자!
  18. 알람 조건 설정하기 처음 보는 이슈가 생길 경우 해결된 이슈가

    다시 발생할 경우 무시하고 있던 이슈가 해제될 경우 이벤트의 Level이 조건에 맞는 경우 이벤트의 Attribute가 조건에 맞는 경우 이벤트의 Tag가 조건에 맞는 경우 이슈가 N번 중복 발생할 경우 원하는 레벨의 이벤트가 N번 발생할 경우 slack kakaowork jira When If Then
  19. 알람 조건 설정하기 처음 보는 이슈가 생길 경우 해결된 이슈가

    다시 발생할 경우 무시하고 있던 이슈가 해제될 경우 이벤트의 Level이 조건에 맞는 경우 이벤트의 Attribute가 조건에 맞는 경우 이벤트의 Tag가 조건에 맞는 경우 이슈가 N번 중복 발생할 경우 원하는 레벨의 이벤트가 N번 발생할 경우 When If Then slack kakaowork jira
  20. 에러 데이터 쌓기 Severity 기준 설정 및 모니터링 에러 데이터

    
 분석 분석 결과에 따른 개선 에러 추적을 개선해보자!
  21. 에러 데이터 수집 전 세웠던 가설 QA 과정을 거치기 때문에

    화면 영역에서 발생하는 에러는 많지 않을 것이다. 가설1 데이터 영역에서 발생하는 API에 대한 에러가 대부분일 것이다. 가설2 특정 기기나 브라우저 에서 발생하는 에러가 있을 것이다. (크로스 브라우징 이슈) 가설3
  22. 수집한 에러 데이터 분석 ApiNotFoundError 2% 2% 2% 7% 12%

    28% 47% ApiNotFoundError TypeError ReferenceError 카카오페이 펀드 서비스 에러 데이터 분석 ApiInternalServerError ApiTimeoutError ChunkLoadError
  23. 에러 데이터 쌓기 Severity 기준설정 및 모니터링 에러 데이터 


    분석 분석 결과에 따른 개선 에러 추적을 개선해보자!
  24. 유의미한 데이터를 수집하자 chunk load 에러나 network 에러는 수집 제외

    (timeout 에러는 수집) 분석하고자 하는 API의 http status를 구분하여 수집 (4xx 에러는 부분적 수집 제외) 에러 데이터뿐만 아니라 디버깅과 분석에 필요한 추가적인 정보 수집
  25. 서버와의 로그 분석 정합성 높이기 서버와 약속된 custom header를 추가하여

    API를 요청합니다. 이는 에러 상황 시 서버 로그와 프론트엔드에 남은 데이터를 서로 대조하여 분석의 정합성을 높일 수 있습니다. custom header를 추가하여 api를 요청한 서버 로그 검색이 되는 요소인 tag를 이용하여 custom header를 수집
  26. 에러 추적 개선 후, 이런 점이 좋아졌어요 브라우저 버전 문제나

    빌드 설정과 같은 문제로 발생한 예상하지 못 했던 에러들을 발견하여 사용자 경험을 개선시킬 수 있었습니다. 장애 탐지 시간, 원인 파악, 해결까지의 시간이 줄었습니다. CS 인입 시 사용자의 환경에서 재현하지 않아도 에러 원인을 파악하고 이전보다 정확하게 안내할 수 있게 되었습니다. 개발자 경험이 좋아졌습니다. import 'core-js/features/object/entries'; import 'core-js/features/object/values'; 사용자의 웹뷰 브라우저 버전을 확인하고 대응하기 위하여 poly fi ll 추가
  27. 에러 추적 개선 후, 이런 점이 좋아졌어요 브라우저 버전 문제나

    빌드 설정과 같은 문제로 발생한 예상하지 못 했던 에러들을 발견하여 사용자 경험을 개선시킬 수 있었습니다. 장애 탐지 시간, 원인 파악, 해결까지의 시간이 줄었습니다. CS 인입 시 사용자의 환경에서 재현하지 않아도 에러 원인을 파악하고 이전보다 정확하게 안내할 수 있게 되었습니다. 개발자 경험이 좋아졌습니다. 설정한 threshold 및 알람 조건 기준에 따라 알람 메시지를 통해 이슈 또는 장애 파악
  28. 에러 추적 개선 후, 이런 점이 좋아졌어요 브라우저 버전 문제나

    빌드 설정과 같은 문제로 발생한 예상하지 못 했던 에러들을 발견하여 사용자 경험을 개선시킬 수 있었습니다. 장애 탐지 시간, 원인 파악, 해결까지의 시간이 줄었습니다. CS 인입 시 사용자의 환경에서 재현하지 않아도 에러 원인을 파악하고 이전보다 정확하게 안내할 수 있게 되었습니다. 개발자 경험이 좋아졌습니다. CS 
 담당자 안드로이드 XXX 버전에서 해당 서비스에 접속이 안된다는 CS가 인입되었습니다. 확인 부탁드립니다. 안드로이드 XXX 버전에서 사용하는 웹 브라우저 버전에서 해당 서비스를 지원하지 못하는 현상이 있습니다. 브라우저 업데이트로 안내부탁드리며, 
 해당 이슈는 빠르게 수정하겠습니다. FE
  29. 에러 추적 개선 후, 이런 점이 좋아졌어요 브라우저 버전 문제나

    빌드 설정과 같은 문제로 발생한 예상하지 못 했던 에러들을 발견하여 사용자 경험을 개선시킬 수 있었습니다. 장애 탐지 시간, 원인 파악, 해결까지의 시간이 줄었습니다. CS 인입 시 사용자의 환경에서 재현하지 않아도 에러 원인을 파악하고 이전보다 정확하게 안내할 수 있게 되었습니다. 개발자 경험이 좋아졌습니다.
  30. axios interceptor 기존의 에러 처리는 axios interceptor의 reject callback으로 처리했습니다.

    axios.interceptors.response.use(_, onResponseRejected); function onResponseRejected(error: Error) { return new Promise((_, reject) => { /** ઺ۚ */ if (checkIsAxiosNetworkError(error)) { setTimeout(() => handleNetworkError(error, reject), 200); return; } if (checkIsAxiosTimeoutError(error)) { return handleTimeoutError(error, reject); } const errorCode = error.response?.data?.errorCode; const status = error.response?.status; if (errorCode) { switch (errorCode) { case KPAY_COMMON_ERROR_CODES.҅੿੉࢚: return handleKickOutError(error); /** ઺ۚ */ } } }); } 네트워크 에러 체크 타임아웃 에러 체크 계정이상 에러 체크
  31. axios interceptor 기존의 에러 처리는 axios interceptor의 reject callback으로 처리했습니다.

    axios.interceptors.response.use(_, onResponseRejected); function onResponseRejected(error: Error) { return new Promise((_, reject) => { /** ઺ۚ */ if (checkIsAxiosNetworkError(error)) { setTimeout(() => handleNetworkError(error, reject), 200); return; } if (checkIsAxiosTimeoutError(error)) { return handleTimeoutError(error, reject); } const errorCode = error.response?.data?.errorCode; const status = error.response?.status; if (errorCode) { switch (errorCode) { case KPAY_COMMON_ERROR_CODES.҅੿੉࢚: return handleKickOutError(error); /** ઺ۚ */ } } }); } 네트워크 에러 체크 타임아웃 에러 체크 계정이상 에러 체크 axios interceptor에서 예외 케이스는 어떻게 처리하지? 전역에서 처리하는 흐름이 과연 맞을까?
  32. axios interceptor, 이런 점이 불편했어요 에러 화면을 보여주려면 라우트 이동으로

    처리해야만 하는 불편함이 있었습니다. history.push(‘/error’);
  33. axios interceptor, 이런 점이 불편했어요 전역 에러를 처리하는 것은 수월하나

    화면의 일부만 에러 상태로 대응하는 것은 어렵습니다. 부분적 에러 처리
  34. ErrorBoundaries React 16에서 도입된 에러 경계 (error boundaries)를 활용하여 하위

    컴포넌트 트리의 자바스크립트 에러를 포착하고 Fallback UI를 보여줄 수 있습니다. 에러 바운더리를 통해 선언적 에러 처리가 가능합니다.
  35. 명령형 에러 처리 선언형 에러 처리 const ComponentWithPossiblyError = ()

    => { const { error: err1 } = useSomeQuery(); const { error: err2 } = useAnotherQuery(); if (err1 || err2) { return <ErrorFallback />; } return <NormalComponent />; }; const ComponentWithPossiblyError = () => { return ( <ApiErrorBoundary> <NormalComponent /> </ApiErrorBoundary> ); }; Error Boundaries
  36. ErrorBoundaries의 구조 class ErrorBoundary extends React.Component { constructor(props) { super(props);

    this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { logException(error, errorInfo); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } 다음 렌더링에서 fallback UI가 보이도록 상태 업데이트 에러 리포팅 서비스에 에러 기록 커스텀한 fallback UI 렌더링
  37. react - error - boundary Error Boundaries의 Fallback Component를 직관적으로

    작성할 수 있도록 도와주는 라이브러리입니다. import { ReactErrorBoundary } from 'react-error-boundary'; const FallbackComponent = () => { return ( <div>ী۞ಕ੉૑</div> ); } export const App = () => { return ( <ReactErrorBoundary fallback={<FallbackComponent />}> <Routes> {/* ઺ۚ */} </Routes> </ReactErrorBoundary> ) } 서비스 성격이나 에러 상황에 적절한 fallback component 구현 가능
  38. react - query와 Error Boundaries React의 Error Boundaries는 본래 이벤트

    핸들러의 에러를 포착하지 않습니다. react - query에서는 useErrorBoundary 옵션을 제공하여, API에서 에러가 발생하면 이를 Error Boundaries가 캐치할 수 있습니다. • useErrorBoundary: undefined | boolean | (error: TError, query: Query) => boolean ◦ Defaults to the global query config's useErrorBoundary value, which is undefined ◦ Set this to true if you want errors to be thrown in the render phase and propagate to the nearest error boundary ◦ Set this to false to disable suspense's default behavior of throwing errors to the error boundary. ◦ If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (true) or return the error as state (false)
  39. 선언적 에러 처리를 적용해보자! Error 
 Boundaries의 
 관심사 분리

    axios 
 interceptor 
 코드 줄이기 Error 
 Boundaries 및 
 Fallback Component 작성
  40. axios 
 interceptor 
 코드 줄이기 Error 
 Boundaries의 


    관심사 분리 Error 
 Boundaries 및 
 Fallback Component 작성 선언적 에러 처리를 적용해보자!
  41. if (isNetworkError(error)) { setTimeout(() => handleNetworkError(error, reject) , 200); return;

    } if (isTimeoutError(error)) { return handleTimeoutError(error, reject); } const errorCode = error.response?.data?.errorCode; const status = error.response?.status; if (errorCode) { /** ઺ۚ */ axios interceptor에서 처리하는 코드 줄이기 기존 axios interceptor
  42. if (isNetworkError(error)) { setTimeout(() => handleNetworkError(error, reject) , 200); return;

    } if (isTimeoutError(error)) { return handleTimeoutError(error, reject); } const errorCode = error.response?.data?.errorCode; const status = error.response?.status; if (errorCode) { /** ઺ۚ */ axios interceptor에서 처리하는 코드 줄이기 기존 axios interceptor if (isAxiosError(error) && isNetworkError(error)) { setTimeout(() => reject(error), 200); } else { reject(error); } 변경한 axios interceptor
  43. axios 
 interceptor 
 코드 줄이기 Error 
 Boundaries의 


    관심사 분리 선언적 에러 처리를 적용해보자! Error 
 Boundaries 및 
 Fallback Component 작성
  44. Error Boundaries의 관심사 분리 Error Boundaries를 관심사별로 분리하기 위해 중첩으로

    구성하였습니다. import { Outlet } from 'react-router-dom'; import { ApiErrorBoundary, RootErrorBoundary } from '~/shared/components'; export const AppLayout = () => { return ( <RootErrorBoundary> <ApiErrorBoundary> <Outlet /> </ApiErrorBoundary> </RootErrorBoundary> ); }; 그 외 Frontend Error api에서 발생하는 Error
  45. axios 
 interceptor 
 코드 줄이기 Error 
 Boundaries의 


    관심사 분리 Error 
 Boundaries 및 
 Fallback Component 작성 선언적 에러 처리를 적용해보자!
  46. const ApiErrorBoundary = ({ children }) => { const {

    reset } = useQueryErrorResetBoundary(); const { key } = useLocation(); return ( <ReactErrorBoundary FallbackComponent={FallbackComponent} onReset={reset} resetKeys={[key]} > {children} </ReactErrorBoundary> ); }; Fallback Component 작성 API 에러를 처리하는 Error Boundaries (Root Level) react - query에서 query를 reset하는 custom hook location 객체의 key를 기반으로 reset 트리거
  47. Fallback Component 작성 function FallbackComponent({ error, resetErrorBoundary }) { useEffect(()

    => { captureApiError(props.error); }, []); if (!isAxiosError(error)) { throw error; } /** ઺ۚ */ // 500 Error & ӝఋ ੌ߈ Api Error return ( <CommonErrorHandler resetErrorBoundary={resetErrorBoundary} />; ); }; 상위 Error Boundaries인 Global Error Boundaries로 에러 위임 API Error Boundaries의 Fallback Component Sentry와 같은 에러 모니터링 서비스에 에러 데이터 전송 가능
  48. const ProductList = () => { return ( <> <Container>

    <Banners /> <Title /> <FundCompareButton /> <LocalApiErrorBoundary height={300}> <AllProductList /> </LocalApiErrorBoundary> </Container> <Footer /> </> ); }; Local (Block) Error Boundaries Local Error Boundaries가 적용된 컴포넌트
  49. const ProductList = () => { return ( <> <Container>

    <Banners /> <Title /> <FundCompareButton /> <LocalApiErrorBoundary height={300}> <AllProductList /> </LocalApiErrorBoundary> </Container> <Footer /> </> ); }; Local (Block) Error Boundaries Local Error Boundaries가 적용된 컴포넌트
  50. Local (Block) Error Boundaries const FallbackComponent = (props) => {

    if (isApiRequiredError(props.error)) { throw props.error; } else { return <RetryErrorFallback {...props} />; } }; const LocalApiErrorBoundary = ({ children }) => { return ( <ErrorBoundary FallbackComponent={FallbackComponent}> {children} </ErrorBoundary> ); }; Local Error Boundaries와 Fallback Component 공통 에러 처리가 필요한 에러들은 상위로 위임
  51. 공통 에러 처리가 필요한 경우 iOS에서 unload event가 발생하면 axios에서

    호출 중이던 API에서 Network Error가 발생합니다. 이때 발생한 에러는 Error Boundaries가 포착하면 안 됩니다. function onResponseRejected(error: Error) { return new Promise((_resolve, reject) => { if (checkIsAxiosError(error) && checkIsNetworkError(error)) { setTimeout(() => reject(error), 200); } else { reject(error); } }); } iOS의 location 이동으로 인한 Network Error 방지를 위해 지연시킴
  52. 에러 처리 개선 후, 이런 점이 좋아졌어요 비즈니스 로직에 집중한

    에러 처리가 가능합니다. UI 일부에서 발생하는 에러를 전역으로 전파시키지 않고 처리할 수 있습니다. const ComponentWithPossiblyError = () => { const { error: err1 } = useSomeQuery(); const { error: err2 } = useAnotherQuery(); if (err1 || err2) { return <ErrorFallback />; } return <NormalComponent />; }; 명령형 에러 처리
  53. 에러 처리 개선 후, 이런 점이 좋아졌어요 비즈니스 로직에 집중한

    에러 처리가 가능합니다. UI 일부에서 발생하는 에러를 전역으로 전파시키지 않고 처리할 수 있습니다. const ComponentWithPossiblyError = () => { const { error: err1 } = useSomeQuery(); const { error: err2 } = useAnotherQuery(); if (err1 || err2) { return <ErrorFallback />; } return <NormalComponent />; }; 명령형 에러 처리 const ComponentWithPossiblyError = () => { return ( <ApiErrorBoundary> <NormalComponent /> </ApiErrorBoundary> ); }; 선언형 에러 처리
  54. 에러 처리 개선 후, 이런 점이 좋아졌어요 비즈니스 로직에 집중한

    에러 처리가 가능합니다. UI 일부에서 발생하는 에러를 전역으로 전파시키지 않고 처리할 수 있습니다. const Parent = () => { return ( <ErrorBoundary FallbackComponent={ErrorFallback}> <ComponentWithPossiblyError /> </ErrorBoundary> ); }; const ComponentWithPossiblyError = () => { const { data } = useSomeQuery({ useErrorBoundary: true, }); return <NormalComponent />; }; 이 컴포넌트 상위로 
 에러가 전파되지 않음
  55. 선언적 에러 처리를 고민해야 하는 부분도 존재합니다 전역에서 처리되어야 하는

    에러를 구분해야 합니다. export function FallbackComponent({ error, resetErrorBoundary }) { if (!isAxiosError(error)) { throw error; } // ઺ۚ... }; export function FallbackComponent({ error, resetErrorBoundary }) { if (!isAxiosError(error)) { return <ExceptionSection onClickButton={resetErrorBoundary} />; } if (isRootApiError(error)) { throw error; } // ઺ۚ... }; PayAxiosError가 아니라면 상위 Error Boundaries로 위임 ApiErrorBoundary에서 처리해야 하는 에러라면 위임
  56. Wrap - up 데이터 영역에서의 에러 화면 영역에서의 에러 외부요인에

    의한 에러 런타임에 의한 에러 Scopes Add Context Breadcurmbs Transaction Name Customized Tags Issue Grouping Level 에러 데이터 분석 모니터링 사용자와 개발자 경험 향상
  57. Wrap - up react - error - boundary Block Error

    Boundaries Error Boundaries Fallback Component 선언적 에러 처리 중첩 Error Boundaries