- 사용하려면 팀원 모두 이를 잘 알아야 할 것 같고, 프로젝트 복잡도가 높아질 수도 있기 때문에, 이는 추후에 다시 이야기하는 게 좋을 것 같습니다!
- 아직 기획이 완성된 것도 아니기 때문에, 만약 애플리케이션에서 특정 부분에서만 에러(fallback)를 보여주고 싶다면 그떄 추가해도 좋을 것 같아요 ☺️
- UI의 일부분에 존재하는 자바스크립트 에러가 전체 애플리케이션을 중단시켜서는 안 된다.
- React 사용자들이 겪는 이 문제를 해결하기 위해 React 16에서는 error boundary라는 새로운 개념이 도입되었다.
- 에러 경계는 하위 컴포넌트 트리의 어디에서든 자바스크립트 에러를 기록하며 깨진 컴포넌트 트리 대신 폴백 UI를 보여주는 React 컴포넌트다.
- 에러 경계는 렌더링 도중 생명주기 메서드 및 그 아래에 있는 전체 트리에서 에러를 잡아낸
- 에러 경계는 다음과 같은 에러는 포착하지 않는다.
- 이벤트 핸들러 (더 알아보기)
- 비동기적 코드 (예:
setTimeout
혹은requestAnimationFrame
콜백) - 서버 사이드 렌더링
- 자식에서가 아닌 에러 경계 자체에서 발생하는 에러.
- 직접 error boundary를 쓰려면 class를 extends 하는 방식으로 구현해야 함.
- 그렇게 해도 되지만, react-error-boundary 라이브러리를 쓰면 함수형 컴포넌트로 구현할 수 있긴 하다.
- 용량이 얼마나되나? 나쁘지 않네

- 보면 좋을 글 링크들!
- error boundaries (https://ko.legacy.reactjs.org/docs/error-boundaries.html)
- 포착되지 않은 오류에 대한 새로운 동작 (https://legacy.reactjs.org/blog/2017/07/26/error-handling-in-react-16.html#new-behavior-for-uncaught-errors)
- error boundary로 렌더링 오류 잡기 (https://react.dev/reference/react/Component#componentdidcatch)
아래부터는 브랜든 데일(brandon dail) 씨의 블로그 내용 요약 (https://www.brandondail.com/posts/fault-tolerance-react)
- 네트워크 장애 같은 이유로 다른 모듈을 로드에 실패할 경우 에러를 발생.
- Error Boundaries를 이용하여 사용자의 경험과 복구 관리를 처리할 수 있다.
- Error Boundary를 만들고 lazy 컴포넌트로 감싸면 네트워크 장애가 발생했을 때 에러 표시할 수 있다.
- 앱에 error boundary 설정하는 건 쉽다. 까다로운 부분은 그것을 어디에 두느냐다...
- 골디락스 원칙에 따라 딱 맞게 error boundary를 구현하고 싶지만 어떻게 할 수 있을까??
error boundary가 충분하지 않음
애플리케이션 최 상단에 error boundary가 있는 경우
// react-error-boundary를 사용 import ErrorBoundary from "react-error-boundary"; import App from "./App.js"; ReactDOM.render( <ErrorBoundary> <App /> </ErrorBoundary>, document.getElementById("root") );
- 이것은 아마도 대부분의 사람들이 하는 일과 비슷할 것.
- 이는 서버에서 렌더링된 애플리케이션이 실패할 때 발생하는 것과 본질적으로 동일.
- 그것은 끔찍한 경험도 아니고 우리가 할 수 있는 최선이 아닐 뿐.
- 문제는 한 가지가 실패하면 다른 모든 것도 실패한다.
- 이 접근 방식은 응용 프로그램의 어느 부분에서든 오류가 발생하여 전체를 사용할 수 없게 되는 경우에 적합
- 물론 그런 경우도 있지만 일반적인 경우는 아닌 것 같다.
- 내결함성은 장애가 발생하더라도 시스템이 계속해서 제대로 작동할 수 있도록 하는 속성
- 단일 오류로 인해 전체 애플리케이션이 다운되기 때문에 단일 error boundary가 실제로 내결함성을 제공하지 않는다는 것을 알 수 있다.
error boundary가 너무 많음
- 모든 컴포넌트를 error boundary 로 감싸려고 시도할 수 도 있다.
- 이 접근 방식의 문제점은 더 미묘하므로 이것이 단일 error boundary보다 더 나쁠 수 있는 이유를 알아보기 위해 더 자세한 예가 필요하다.
function CheckoutForm(props) { return ( <form> <CartDescription items={props.items} /> <CreditCardInput /> <CheckoutButton cartId={props.id} /> </form> ); }
... // Everyone gets an error boundary! <form> <ErrorBoundary> <CartDescription items={props.items} /> </ErrorBoundary> <ErrorBoundary> <CreditCardInput /> </ErrorBoundary> <ErrorBoundary> <CheckoutButton cartId={props.id} /> </ErrorBoundary> </form>
- 처음에는 이것이 좋은 생각처럼 보일 수도 있다.
- error boundary 가 더 세분화될수록 단일 오류가 애플리케이션 전체에 미치는 영향이 줄어든다.
- 오, 그러면 내결함성이 보장되는 것 아닌가?
- 문제는 오류의 영향을 최소화하는 것이 내결함성과 동일하지 않다는 것이다 .
<form> <ErrorBoundary> <CartDescription items={props.items} /> </ErrorBoundary> <ErrorBoundary> {/* Uh oh! Something broke in here 😢 */} <CreditCardInput /> </ErrorBoundary> <ErrorBoundary> <CheckoutButton cartId={props.id} /> </ErrorBoundary> </form>
반쯤 망가진 UI는 완전 망가진 UX
- 자체 error boundary 가 있으므로
CreditCardInput
오류는 나머지CheckoutForm
컴포넌트 로 전파되지 않지만CheckoutForm
컴포넌트는CreditCardInput
컴포넌트 없이는 동작할 수 없다.
CheckoutButton
,CardDescription
컴포넌트가 여전히 마운트되어 사용자가 항목을 보고 결제를 시도할 수 있지만 신용 카드 정보 입력이 완료되지 않은 경우에는 어떻게 될까?- 충돌이 발생하기 전에 신용 카드를 입력 했다면 해당 상태가 유지되나??
- 결제를 시도하면 어떻게 되나??
Generic Error Boundary, Generic Fallback
- 이것이 실망스럽고 혼란스러운 정도는 fallback으로 무엇을 렌더링하느냐에 따라 달라진다 .
- 컴포넌트가 경고 없이 화면에서 갑자기 튀어나온다면 그것은 거의 모든 사람에게 정말 혼란스럽다.
- 그렇지 않다면 아마도 공유 대체 UI를 사용하고 있을 것이다.
- 어쩌면 오류에 대한 유용한 정보를 슬픈 표정으로 표현하는 것일 수도 있다.
- 아무것도 없는 것보다는 낫지만 이 error boundary의 모든 컴포넌트를 래핑하는 경우 이 폴백은 가능한 모든 UI 요소 에 대해 올바르게 렌더링되어야 함을 의미한다.
- 컴포넌트마다 레이아웃 요구 사항이 다르기 때문에 이를 올바르게 수행하는 것은 거의 불가능하다.
- 헤더와 같은 페이지 수준 섹션에 적합한 폴백은 작은 아이콘 버튼에는 적합하지 않으며 그 반대의 경우도 마찬가지다.
- 모든 컴포넌트를 error boundary로 래핑하면 혼란스럽고 중단된 사용자 경험을 초래할 수 있다 .
- 이는 종종 사용자를 좌절시키고 혼란스럽게 할 수 있는 일관되지 않은 상태로 애플리케이션을 배치한다.
- "손상된 상태"를 피하는 것이 실제로 error boundary가 애초에 존재하는 주요 이유 중 하나
적절한 양의 error boundary
- 요약하자면, error boundary가 충분하지 않으면 오류로 인해 필요한 것보다 더 많은 애플리케이션이 중단되고, error boundary가 너무 많으면 UI 상태가 손상될 수 있다.
- 그렇다면 error boundary의 적절한 양은 얼마냐 ?
- 응용 프로그램에 따라 다르기 때문에 "적절한 양"이라고 가리키고 말할 수 있는 단일 숫자는 없다.
- 내가 찾은 최선의 접근 방식은 애플리케이션의 feature를 식별하고 거기에 error boundary를 두는 것이다 .
특징 찾기
- 임의의 앱을 살펴보고 그 boundary를 식별하는 데 사용할 수 있는 "feature"에 대한 보편적인 정의는 없다.
- 지침으로 사용할 수 있는 몇 가지 일반적인 패턴이 있다.
- 대부분의 애플리케이션은 함께 구성된 개별 섹션으로 구성된다.
- 머리글, 탐색, 기본 콘텐츠, 사이드바, 바닥글 등.
- 각각은 전체적으로 사용자 경험에 기여하지만 일정 수준의 독립성을 유지한다.
ex) 트위터

- 페이지에 별개의 섹션과 기능이 있다는 것이 즉시 분명해진다.
- 트윗의 기본 타임라인, 팔로어 추천, 트렌드 섹션 및 탐색 모음.
- 이러한 섹션의 레이아웃과 스타일은 (정말 좋은 출발점이 되는) 섹션 사이의 구분이 있음을 나타낸다.
- 시각적으로 독립적인 섹션은 error boundary를 원하는 정확한 위치에 있는 독립적인 feature일 가능성이 높다 .
- 이러한 섹션 중 하나의 컴포넌트에서 오류가 발생하면 다른 섹션도 충돌해서는 안 된다고 말하는 것이 맞아 보인다.
- 예를 들어 팔로어 추천 섹션의 팔로우 버튼이 충돌하는 경우, 기본 타임라인도 중단되어서는 안 된다.
재귀적인 질문 라인
- UI는 종종 재귀적 이다.
- 페이지 수준에는 사이드바 및 타임라인과 같은 큰 섹션이 있지만 해당 섹션 내부에는 다른 섹션 등을 포함하는 헤더 및 목록과 같은 하위 섹션 도 있다.
- error boundary의 올바른 위치를 식별할 때 스스로에게 물어볼 좋은 질문은 "이 컴포넌트의 오류가 형제 항목에 어떤 영향을 미치나?" 이다.
- 이
<CheckoutForm />
예에서 이것을 고민해보자.CreditCardInput
실패하면CheckoutButton
,CardDescription
컴포넌트에 어떻게 영향을 끼치나? - 이 질문을 구성 요소 트리에 반복적으로 적용하면 feature boundary가 어디에 있는지 빠르게 식별하고 그 주위에 error boundary를 배치할 수 있다.
Twitter deep dive: 페이지
- 트위터를 다시 예로 들어 이것이 어떻게 작동하는지 살펴보자.
- 맨 위에서 시작한 다음 팔로어 추천 섹션을 보자.

- 상단부터 홈 , 트렌드 , 팔로우할 사람 등 세 가지 주요 콘텐츠 섹션을 식별할 수 있다 .
- 팔로우할 사람 섹션을 자세히 살펴보자 .
- 스스로에게 다음과 같이 질문하는 것으로 시작한다.
이 컴포넌트의 오류는 형제 요소에 어떤 영향을 미치나?
- 이 질문을 다음과 같이 바꾸어 표현하면 좀 더 구체적으로 만들 수 있다.
이 컴포넌트가 충돌하면 형제도 충돌해야 하나?
- 따라서 팔로우할 사람을 고려할 때 다음과 같이 질문한다.
- 팔로우할 사람 섹션 이 충돌 하면 홈 및 트렌드 섹션도 충돌해야 하나? .
- 나는 이것이 해서는 안되는 분명한 사례라고 생각한다 .
- 다른 섹션은 서로 의존하지 않는 것 같아서 error boundary를 설정하기에 좋은 곳이다.
Twitter deep dive: 팔로우할 사람
- 이제 우리는 Who to Follow 섹션에도 이와 동일한 질문을 적용한다.

- 팔로우할 사람 에 초점을 맞추면 제목, 팔로우할 사용자 목록, 더보기 버튼이라는 세 가지 분명한 섹션이 있다.
- 사용자 목록을 자세히 살펴보면서 우리는 다시 같은 질문을 스스로에게 던져야 한다.
- 팔로어 목록이 충돌하면 제목과 "더 보기" 버튼도 충돌해야 할까?
- 이 경우에는 조금 덜 분명하지만 아마도 그렇게해서는 안된다고 생각한다.
- 제목을 그대로 유지해도 아무런 문제가 없으며 "더 보기" 버튼은 자체적으로 작동할 수 있는 다른 페이지로 연결된다.
Twitter deep dive: 팔로어 추천

- 사용자의 이름과 핸들이 충돌하는 경우 팔로우 버튼도 충돌해야 하며 그 반대의 경우도 마찬가지인가?
- 이 경우 대답은 '예'다!
- 사용자의 이름과 핸들이 사라지면 우리는 우리가 누구를 팔로우하고 있는지 알 수 없다.
- 팔로우 버튼이 사라진 경우 아무런 조치도 취하지 않고 추천을 받는 것이 답답할 수 있다.
내결함성 테스트
- 애플리케이션의 내결함성을 테스트하기 위해 찾은 가장 쉽고 간편한 방법은 직접 들어가서 수동으로 문제를 해결하는 것 이다 .
function CreditCardInput(props) { // What happens if I messed up here? Let's find out! throw new Error("oops, I made a mistake!"); return <input className="credit-card" />; }
- 이것은 내가 추가하는 모든 새로운 구성 요소에 대해 시작했던 작업이며 우리 애플리케이션이 오류를 처리하는 방법을 보는 것이 정말 도움이 되었다.
요약
따라서 이것은 대부분 다음과 같이 해야 한다고 말하는 방법입니다.
- 상단에 단일 error boundary만 두지 말자.
- 이것이 실패를 처리하는 가장 좋은 방법인 경우는 드물다.
- error boundary를 과도하게 사용하지 말자.
- 이로 인해 사용자 경험이 저하되고 잠재적으로 성능이 저하될 수 있다.
- 앱의 feature boundary를 식별하고 거기에 error boundary를 둬라.
- React 앱은 트리로 구조화되어 있으므로 위에서부터 시작하여 아래로 내려가는 것이 좋은 접근 방식이다.
- "이 컴포넌트가 충돌하면 형제도 충돌해야 하는가?"라고 스스로에게 재귀적으로 질문해 보자.
- feature boundaries를 찾는 데 좋은 경험적 방법이다.
- 오류 상태에 맞게 앱을 의도적으로 디자인하자.
- feature boundary에 error boundary를 추가하면 보기에 좋고 사용자에게 문제가 발생했음을 알리는 사용자 지정 대체 UI를 만드는 것이 훨씬 쉽다.
- 사용자가 전체 페이지를 새로 고치지 않고도 해당 섹션을 새로 고칠 수 있도록 기능별 재시도 논리를 구현할 수도 있다.
- 무슨 일이 일어나는지 확인하기 위해 의도적으로 일을 중단해라.