본문으로 건너뛰기
개발 머꼬
개발 노트React
hohyeon.dev24

ErrorBoundary를 감쌌는데 버튼 클릭 에러는 못 잡은 이유

  • #Engineering Note
  • #Error Handling
  • #React

문제 발생

컴포넌트 트리를 ErrorBoundary로 감싸서 에러 발생 시 대체 UI를 보여주도록 만들었는데, 버튼 클릭 핸들러 안에서 발생한 에러는 전혀 잡히지 않고 콘솔에 처리되지 않은 에러로만 남았습니다.

<ErrorBoundary fallback={<ErrorMessage />}>
  <SubmitButton />
</ErrorBoundary>

function SubmitButton() {
  const handleClick = () => {
    throw new Error("실패"); // ErrorBoundary가 잡지 못함
  };
  return <button onClick={handleClick}>제출</button>;
}

원인 분석

React의 Error Boundary는 렌더링 과정에서 발생한 에러만 잡도록 설계되어 있습니다 — 컴포넌트 함수 본문이 실행되는 동안(즉 React가 그 컴포넌트를 화면에 그리려고 시도하는 동안) 던져진 에러를 감지합니다.

React 공식 문서는 Error Boundary가 잡지 못하는 경우를 명시적으로 나열합니다.

  1. 이벤트 핸들러(onClick, onChange 등) — 이건 렌더링 과정이 아니라 사용자 상호작용에 반응해 실행되는 별도의 코드 경로입니다.
  2. 비동기 코드(setTimeout, Promise 콜백, async 함수 안) — 에러가 발생하는 시점에 React의 렌더링 스택이 이미 끝나 있습니다.
  3. 서버 사이드 렌더링 중 발생한 에러
  4. Error Boundary 자기 자신의 코드에서 발생한 에러

이런 경우들은 React의 렌더링 트리 바깥에서 발생하므로, React가 "이 하위 트리에서 에러가 났으니 fallback을 보여줘야겠다"고 판단할 방법이 없습니다.

해결 방안

  1. 이벤트 핸들러/비동기 코드는 일반 JavaScript의 try/catch로 직접 처리합니다.
function SubmitButton() {
  const [error, setError] = useState<string | null>(null);
  const handleClick = async () => {
    try {
      await submit();
    } catch (e) {
      setError("제출에 실패했습니다"); // 상태로 관리해 UI에 반영
    }
  };
  return (
    <>
      <button onClick={handleClick}>제출</button>
      {error && <p role="alert">{error}</p>}
    </>
  );
}
  1. 이벤트 핸들러 안에서 잡은 에러를 렌더링 중 에러로 다시 전환하고 싶다면(즉 Error Boundary가 처리하게 만들고 싶다면), catch 블록에서 상태를 업데이트해 그 상태 변화가 다음 렌더링에서 실제로 throw되도록 만드는 패턴을 쓸 수 있습니다(예: 상태에 에러를 저장했다가 렌더링 함수 본문에서 그 상태가 있으면 throw).
  2. React 19+에서는 createRoot/hydrateRootonUncaughtError/onCaughtError 콜백으로 Error Boundary 밖의 처리되지 않은 에러까지 중앙에서 로깅할 수 있는 훅이 추가되었습니다 — Error Boundary가 못 잡는 에러를 완전히 대체하지는 않지만, 최소한 관측(로깅) 목적으로는 보완할 수 있습니다.
  3. 비동기 데이터 페칭에서 발생하는 에러를 UI 트리 차원에서 선언적으로 다루고 싶다면, Suspense + 에러를 던지는 방식으로 설계된 데이터 페칭 라이브러리(예: React Query의 useSuspenseQuery)와 Error Boundary를 조합하는 패턴도 있습니다 — 이 경우는 데이터 페칭이 렌더링 과정의 일부로 통합되어 있어 Error Boundary가 정상적으로 개입할 수 있습니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.