Vue Error Boundary

이대현·2024년 6월 19일
2

vue

목록 보기
4/4

errorCaptured: 이 훅을 사용하면 자식 컴포넌트에서 발생한 에러를 부모 컴포넌트에서 잡아낼 수 있다.

아래는 Vue 3에서 에러 바운더리 기능을 구현하는 예시입니다:

  1. 글로벌 에러 핸들러 설정:

    먼저, Vue 애플리케이션 전체에서 에러를 잡아내기 위한 글로벌 에러 핸들러를 설정해보겠습니다.

    // main.js
    import { createApp } from 'vue';
    import App from './App.vue';
    
    const app = createApp(App);
    
    app.config.errorHandler = (err, instance, info) => {
      console.error(`Captured in Vue.config.errorHandler:`, err);
      // 에러 로깅 서비스로 에러 전송 등 추가 작업
    };
    
    app.mount('#app');
  2. 컴포넌트 수준에서 오류 처리 - Setup 함수 내의 ErrorBoundary:

    컴포넌트 수준에서 에러를 처리하기 위해 setup 함수 내의 errorCaptured 훅을 사용할 수 있습니다. 다음은 그 예시입니다.

    <!-- ParentComponent.vue -->
    <template>
      <div>
        <h1>Parent Component</h1>
        <ChildComponent v-if="!hasError" />
        <div v-else>
          <p>{{ error.message }}</p>
          <button @click="resetError">Try again</button>
        </div>
      </div>
    </template>
    
    <script>
    import { ref } from 'vue';
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: {
        ChildComponent
      },
      setup() {
        const hasError = ref(false);
        const error = ref(null);
    
        const resetError = () => {
          hasError.value = false;
          error.value = null;
        };
    
        return {
          hasError,
          error,
          resetError
        };
      },
      errorCaptured(err, instance, info) {
        // 에러 핸들링 로직
        this.hasError = true;
        this.error = err;
        console.error(`Captured in errorCaptured hook:`, err);
    
        // 에러를 상위로 전파하지 않고 여기서 처리
        return false;
      }
    };
    </script>
  3. 에러를 발생시키는 자식 컴포넌트:

    <!-- ChildComponent.vue -->
    <template>
      <div>
        <h2>Child Component</h2>
      </div>
    </template>
    
    <script>
    export default {
      mounted() {
        throw new Error('This is a test error in ChildComponent');
      }
    };
    </script>

이 예시에서는 ParentComponentChildComponent를 포함하고 있습니다. ChildComponent에서 에러가 발생하면, ParentComponent에서 errorCaptured 훅을 통해 에러가 잡힙니다. 에러가 발생하면 ParentComponent에는 에러 메시지가 표시되고, "Try again" 버튼을 클릭하면 에러 상태가 초기화됩니다.

공통 컴포넌트로 관리

  1. 에러 바운더리 공통 컴포넌트:

    <!-- ErrorBoundary.vue -->
    <template>
      <div>
        <slot v-if="!hasError" />
        <div v-else>
          <p>{{ error.message }}</p>
          <button @click="resetError">Try again</button>
        </div>
      </div>
    </template>
    
    <script>
    import { ref, defineComponent } from 'vue';
    
    export default defineComponent({
      name: 'ErrorBoundary',
      setup(_, { expose }) {
        const hasError = ref(false);
        const error = ref(null);
    
        const resetError = () => {
          hasError.value = false;
          error.value = null;
        };
    
        const setError = (err) => {
          hasError.value = true;
          error.value = err;
        };
    
        expose({ setError });
    
        return {
          hasError,
          error,
          resetError
        };
      }
    });
    </script>
  2. 에러 바운더리 사용 예시:

    에러 바운더리 컴포넌트를 다양한 컴포넌트에서 사용할 수 있습니다.

    <!-- ParentComponent.vue -->
    <template>
      <ErrorBoundary ref="errorBoundary">
        <template v-slot:default>
          <ChildComponent />
        </template>
      </ErrorBoundary>
    </template>
    
    <script>
    import { defineComponent, onMounted, ref } from 'vue';
    import ErrorBoundary from './ErrorBoundary.vue';
    import ChildComponent from './ChildComponent.vue';
    
    export default defineComponent({
      components: {
        ErrorBoundary,
        ChildComponent
      },
      setup() {
        const errorBoundary = ref(null);
    
        onMounted(() => {
          // 접근하여 에러 설정 가능
          if (errorBoundary.value) {
            errorBoundary.value.setError(new Error('Initial error test'));
          }
        });
    
        return {
          errorBoundary
        };
      }
    });
    </script>
  3. 에러를 발생시키는 자식 컴포넌트:

    <!-- ChildComponent.vue -->
    <template>
      <div>
        <h2>Child Component</h2>
      </div>
    </template>
    
    <script>
    import { defineComponent, onMounted } from 'vue';
    
    export default defineComponent({
      name: 'ChildComponent',
      setup() {
        onMounted(() => {
          throw new Error('This is a test error in ChildComponent');
        });
    
        return {};
      }
    });
    </script>

이 예시에서는 ErrorBoundary.vue 컴포넌트를 공통 컴포넌트로 만들어, 다른 컴포넌트에서 에러 바운더리를 쉽게 재사용할 수 있습니다. ParentComponent.vue에서 ErrorBoundary를 이용해 ChildComponent를 감싸고 있습니다. ChildComponent에서 에러가 발생하면, ErrorBoundary가 이를 감지하여 에러 메시지를 표시합니다.

profile
Frontend Developer

0개의 댓글