서론
리액트에서는 예외 발생 시 예외를 발생한 컴포넌트만 언마운트 되지 않는다.
예외 발생 시 모든 컴포넌트가 언마운트 된다.
이는 잘못된 정보를 사용자에게 보여 주는 것보다는 아무것도 보여주지 않는 것이 낫기 때문이다.
하지만, 아무것도 보여주지 않는 것은 잘못된 정보를 제공하지 않았을 뿐이지 나쁜 사용자 경험을 제공하게 된다.
이러한 문제점을 해결하기 위해 등장한 것이 Error Boundary 이다.
Error Boundary는 하위 컴포넌트에서 발생한 예외를 catch(try-catch 와는 다름)하여 Fallback UI를 보여주는 등의 처리를 해주는 컴포넌트이다.
웹 페이지를 이용하다가 갑자기 흰 화면만 덩그러니 나오는 것보다는 현재 상태가 어떤 지 표시해주는 게 훨씬 좋은 사용자 경험을 제공하지 않을까?
Error Boundary
다음은 리액트 공식 홈페이지에서 제공하는 Error Boundary 코드에서 fallBack UI 부분만 수정한 코드이다.
두 개의 라이프사이클 메서드를 사용한다.
- getDerivedStateFromError
- componentDidCatch
hook에서는 아직 위의 라이프사이클에 대한 핸들링을 지원하지 않는다.
아직은 hook이 클래스형에서 지원하는 라이프사이클을 모두 대체하고 있지는 못하다.
그렇기에 Error Boundary가 클래스형 컴포넌트로 이루어져 있는 것이다.
Error Boundary Usage
Error Boundary를 사용하는 기본적인 구조는 다음과 같다.
<ErrorBoundary>
<SomeComponent />
</ErrorBoundary>
Error Boundary 하위에 존재하는 컴포넌트 즉, SomeCmponent 내부에서 예외가 발생하면 Error Boundary에 의해 catch 된다.
Error Boundary의 배치
그럼 Error Boundary는 어디에 배치해야 할까?
Error Boundary 는 반드시 최상위 컴포넌트에 위치하지 않아도 된다.
다음과 같이 쓸 수 있다는 의미이다.
<Header />
<ErrorBoundary>
<CouldBeError />
</ErrorBoundary>
<Footer />
위와 같은 구조에서는 CouldBeError 컴포넌트에서 발생한 예외만 처리가 가능함을 명심해야 한다.
Header, Footer에서 발생하는 예외는 처리할 수 없다.
결과적으로, 개발자의 의도에 따라 Error Boundary를 배치할 수 있다는 것.
Error Boundary 예제
버튼을 클릭하면 state error가 true로 바뀌고 effect에 의하여 에러를 throw 한다.
ErrorBoundary 로 <Test /> 를 감싸지 않은 채로 버튼을 클릭하면 그저 흰 화면과 함께 모두 언마운트 된다.
ErrorBoundary에 의해 Test에서 발생한 예외를 처리하여 Fallback UI 를 렌더링할 수 있게 된다.
이 예제는 Error Boundary가 처리하지 않는 예외를 나타내고 있다.
우선 에러 만들기 버튼을 클릭하면 onClick이라는 이벤트 핸들러에 의해 throwError 함수가 실행된다.
하지만, Fallback UI는 나타나지 않는다.
이벤트 핸들러에 의해 발생한 예외는 Error Boundary에서 처리하지 않기 때문이다.
( = 이벤트 핸들러는 렌더링 중에 발생하지 않기 때문이다. )
Error Boundary는 렌더링 중에 발생하는 예외에 대해 처리한다.
즉, 렌더링 중에 일어나는 라이프 사이클 메서드와 하위 컴포넌트에게서 발생하는 예외만 처리한다는 것이다.
이와 관련해 리액트는 다음의 상황에서 발생한 예외는 Error Boundary가 처리하지 않는다고 명시했다.
- 이벤트 핸들러
- 비동기적 코드 (setTimeout 등)
- 서버사이드 렌더링
- 자식이 아닌 Error Boundary 자체에서 발생한 예외
그럼 이벤트 핸들러에서 발생한 예외는 어떻게 처리할까?
const throwError = () => {
try {
throw new Error("Boom!");
} catch (err) {
console.error(err);
}
};
다들 익히 알고 있는 try-catch 문을 사용하면 된다.
마치며
- Fallback UI를 통해 사용자 경험을 개선할 수 있다.
- 배포 단계에서 발생한 예상치 못한 예외를 핸들링을 할 수 있다.
뿐 만 아니라 componentDidCatch 메서드를 사용하면 예외에 대해 서버에 기록(log)을 남길 수 있다.
이는 미처 핸들링하지 못한 예외를 빠르게 인식하고 수정할 수 있음을 의미하기도 한다.
이상, Error Boundary에 대해 알아보았다.
틀린 부분이 있다면 지적 바랍니다.
'유연해지기 > React.js' 카테고리의 다른 글
간단한 리액트 커스텀 훅 만들어보기. (React custom hook) (0) | 2021.11.04 |
---|---|
리액트 절대경로 설정 및 모듈/경로 별명 짓기 with CRA (absolute path, path alias) (0) | 2021.10.21 |
[React.js] useEffect, cleanUp, deps, unMount에 대하여 (0) | 2021.09.29 |
[React.js] useRef와 useState의 용도와 차이 (0) | 2021.09.07 |
[React.js] crypto-js를 이용한 패스워드 암호화 (0) | 2021.04.22 |