에러 바운더리 (Error Boundaries)

* 간단하게 적는 도입 이유
: 가장 상단에서 페이지에 진입하게 되면, api를 여러 개 호출하는데
한가지의 api 관련 에러 때문에 페이지 전체가 보이지 않는 에러가 생겼다.
이 api는 하나의 작은 버튼만을 표출하는 역할을 하는데,
이 오류 하나로 페이지가 표출되지 않는다면 너무 큰 문제기 때문에 에러 바운더리를 도입하게 되었다.
🗂️ 에러 바운더리 (Error Boundaries)
UI의 일부분에 존재하는 자바스크립트 에러가 전체 애플리케이션을 중단시켜서는 안 된다.
→ 그래서 등장한 것이 에러 바운더리
React 16부터는 에러 경계에서 포착되지 않은 에러로 인해 전체 React 컴포넌트 트리의 마운트가 해제 됨.
→ 손상된 UI를 완전히 제거하는 것보다 그대로 남겨두는 것이 더 좋기 때문
전체 컴포넌트 트리의 마운트를 해제하는 대신, 깨진 UI를 교체하는 방식으로 오류를 처리하여 애플리케이션의 일부 UI가 여전히 사용자에게 표시될 수 있도록 함.
- 역할
React 컴포넌트 트리 내에서 발생하는 JavaScript 오류를 포착하고, 오류가 발생한 부분을 완전히 제거하는 대신 fallback UI를 렌더링하여 애플리케이션이 멈추지 않게 함.
에러 바운더리 하위 컴포넌트 트리의 자바스크립트 에러를 기록
- 작동 방식
렌더링 도중 발생한 에러와 생명주기 메서드에서 발생한 오류를 잡을 수 있음.
getDerivedStateFromError()와 componentDidCatch() 메서드를 사용하여 오류 발생 후 폴백 UI를 렌더링하거나, 오류 로그를 기록
- 에러 바운더리가 잡지 않는 오류
1. 이벤트 핸들러에서 발생하는 오류
이유 : 이벤트 핸들러는 렌더링 중에 발생하지 않기 때문에, 이벤트 핸들러가 에러를 던져도 React는 여전히 화면에 무엇을 표시해야 할지 알고 있음.
ex. 버튼 클릭시 발생하는 오류
-> 이러한 오류를 처리하려면? 이벤트 핸들러 내에서 발생한 에러는 일반 자바스크립트의 try/catch 구문을 사용
2. 비동기 코드에서 발생하는 오류
이유 : 비동기 작업이 렌더링 주기 외부에서 발생하기 때문
ex. setTimeout이나 API 호출 등 비동기 작업에서 발생하는 오류
-> 이러한 오류를 처리하려면? useSuspenseQuery를 사용 + try/catch 구문을 비동기 코드에 적용
3. 서버 사이드 렌더링(SSR)
이유 : 클라이언트 사이드에서와 같은 방식으로 에러 바운더리가 작동하지 않음.
React가 서버에서 HTML을 렌더링할 때는 클라이언트의 라이프 사이클과 다르게 동작하기 때문.
ex. SSR 환경에서 API 호출 중 오류 발생
-> 이러한 오류를 처리하려면? SSR에서는 별도의 에러 처리 로직이나 서버 측 오류 경계를 구현
4. 자식 컴포넌트가 아닌 에러 바운더리 자체에서 발생하는 오류
이유 : React는 상위 컴포넌트에서 발생한 오류만 처리할 수 있기 때문
에러 바운더리 내에서 발생하는 오류는 자체적으로 처리되지 않음.
-> 이러한 오류를 처리하려면? 예방하기 위한 로직을 별도로 추가
- 에러 바운더리 사용법
클래스 컴포넌트에서 에러 바운더리를 사용
-> 생명주기 메서드인 static getDerivedStateFromError()와 componentDidCatch()를 정의하기
- 에러 발생 후 폴백 UI를 렌더링 : getDerivedStateFromError()
- 에러 정보를 기록 : componentDidCatch()
- 리액트 공식 문서에 나온 예시
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// 다음 렌더링에서 폴백 UI가 보이도록 상태를 업데이트 합니다.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 에러 리포팅 서비스에 에러를 기록할 수도 있습니다.
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// 폴백 UI를 커스텀하여 렌더링할 수 있습니다.
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
작성하고, 부모에서 적용
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
해주면, <MyWidget />의 내부에서 발생한 에러는 잡힘.
* 참고
https://ko.legacy.reactjs.org/docs/error-boundaries.html
에러 경계(Error Boundaries) – React
A JavaScript library for building user interfaces
ko.legacy.reactjs.org
- 함수형 컴포넌트에서 에러 바운더리 사용법
react-error-boundary 라이브러리를 활용
* 참고
https://www.npmjs.com/package/react-error-boundary
react-error-boundary
Simple reusable React error boundary component. Latest version: 4.1.2, last published: 2 months ago. Start using react-error-boundary in your project by running `npm i react-error-boundary`. There are 1400 other projects in the npm registry using react-err
www.npmjs.com