
리액트는 렌더링 중 에러가 발생하면, 에러를 발생시킨 UI를 화면에서 없애버린다. (극단적이네..)
사용자 입장에서는 에러가 발생했다고 알려주는게 아니라 화면에서 해당 UI가 갑자기 사려져 버린것이니
무척 당황스러울 것이다.
에러를 발생시킨 UI가 사라지기보다는 그 위치에 어떤 에러가 발생했는지 에러메세지와같은 관련 정보를 보여주는 것이 더 나은 방향이다.
이렇게 등장한 것이 바로 오류경계 (Error Boundary) 이다.
| 오류 발생시, 발생한 부분에 오류 메세지와 같은 fallback UI를 제공하는 컴포넌트
자바스크립트에서는 에러 핸들링을 try...catch 를 활용하여 진행하였다.
리액트에서는 try...catch 문을 사용할 수 없기때문에 그 기능을 에러 바운더리가 하는 것이다.
그렇다면 ErrorBoundary 컴포넌트는 어떻게 생겼고 어떻게 사용하면 될까?
⚠️ 에러 바운더리는 클래스 컴포넌트로만 만들 수가 있고, 함수형에서는 만들 수가 없다.
그럼 함수형 컴포넌트에서는 에러가 발생해서 UI가 사라져도 속수무책인걸까? 그렇진않다!
클래스/함수형 컴포넌트로 나눠서 살펴보기전에 공통적으로 적용되는 내용이 있다.
1️⃣ 기본형태
// App 파일기준
<StrictMode>
<ErrorBoundary>
<App />
</ErrorBoundary>
</StrictMode>
위와 같은 형태로 적용시키면 App 컴포넌트 내에서 발생하는 오류는 에러 바운더리가 잡아낼 수 있다.
2️⃣ 중첩형태
다음과같이 ErrorBoundary 컴포넌트를 여러 개 중첩해서도 사용할 수 있다.
중첩하여 사용할 경우에는 ErrorBoundary 컴포넌트를 적용한 부분만 오류 발생시 대체UI로 렌더링되고, 나머지 컴포넌트 영역은 영향을 받지않도 정상작동할 수 있기때문에 필요한 경우 중첩하여 사용하기도 한다.
<Header />
<Main>
<ErrorBoundary FallbackComponent={SectionError}>
<Section />
</ErrorBoundary>
<ErrorBoundary FallbackComponent={WidgetError}>
<Widget />
</ErrorBoundary>
</Main>
<Footer />
자식 컴포넌트에서 발생한 오류를 감지한다.fallback)를 렌더링한다.렌더링 중 발생한 오류만 잡을 수 있다. 다음의 내용들은 에러 바운더리로 오류를 잡아낼 수 없다.⚠️ 에러 바운더리로 잡을 수 없는 오류
fetch,setTimeout등과 같은비동기 코드→try...catch문으로 해결해야한다.이벤트 핸들러에서 발생한 오류 →try...catch문으로 해결해야한다.- 서버 사이드 렌더링
- 자식 컴포넌트가 아닌 에러
경계에서 발생하는 오류
에러 바운더리를 클래스 컴포넌트와 함수형 컴포넌트의 경우로 나눠서 살펴보자.
클래스 컴포넌트에서 에러 바운더리를 만드는 형태는 다음과 같다.
// 클래스 컴포넌트 생성을 위한 Component import
import { Component } from 'react'
export default class ErrorBoundary extends Component {
state = {
hasError: false,
error: null,
info: null
}
// 오류에 대한 응답으로 오류 발생 시 state를 업데이트하여 사용자에게 보여줄 메시지부분
static getDerivedStateFromError(error) {
return { hasError: true, error }
}
// 오류 정보 기록 로직
componentDidCatch(error, info) {
this.setState({ info })
}
render() {
const { fallback: DisplayError, children } = this.props
const { hasError, error, info } = this.state
// 오류가 있으면 fallback UI 렌더링
if (hasError) {
return <DisplayError error={error} errorInfo={info} />
}
// 오류가 없으면 정상적으로 자식 컴포넌트 렌더링
return children
}
}
static getDerivedStateFromError 와 componentDidCatch 둘 중 하나 이상을 정의하여 에러 바운더리를 구현하는데, 둘 다 사용하는 것이 일반적이고 기능적으로 권장되는 바이다.
함수형으로는 에러 바운더리 컴포넌트를 만들 수 없다면 어떻게 사용할 수 있을까?
이런 상황에서 사용하라고 라이브러리가 있는게 아닐까!
1️⃣ 함수형 컴포넌트에서 에러 바운더리를 사용할 수 있는 첫 번째 방법은 react-error-boundary 라이브러리를 이용하는 것이다.
react-error-boundary 라이브러리를 사용하는 형태는 다음과같다.
import { ErrorBoundary } from 'react-error-boundary'
<StrictMode>
<ErrorBoundary>
<App />
</ErrorBoundary>
</StrictMode>
2️⃣ 라이브러리를 사용하지 않고도 함수형 컴포넌트에서 에러 바운더리를 구현하길 원한다면, 클래스 컴포넌트로 만든 에러 바운더리 를 만들어 함수형 컴포넌트를 감싸주는 방법이 있다.
두 가지 방법이 있긴하지만 아무래도 라이브러리를 이용하는 것이 편리한 방법이기때문에 꼭 클래스 컴포넌트로 에러 바운더리를 만들어야하는 상황이 아니라면 react-error-boundary 라이브러리를 이용하자! 😉
🔗 참고자료
https://ko.legacy.reactjs.org/docs/error-boundaries.html
https://ko.react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary