errorCaptured: 이 훅을 사용하면 자식 컴포넌트에서 발생한 에러를 부모 컴포넌트에서 잡아낼 수 있다.
아래는 Vue 3에서 에러 바운더리 기능을 구현하는 예시입니다:
글로벌 에러 핸들러 설정:
먼저, 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');
컴포넌트 수준에서 오류 처리 - 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>
에러를 발생시키는 자식 컴포넌트:
<!-- 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>
이 예시에서는 ParentComponent
가 ChildComponent
를 포함하고 있습니다. ChildComponent
에서 에러가 발생하면, ParentComponent
에서 errorCaptured
훅을 통해 에러가 잡힙니다. 에러가 발생하면 ParentComponent
에는 에러 메시지가 표시되고, "Try again" 버튼을 클릭하면 에러 상태가 초기화됩니다.
에러 바운더리 공통 컴포넌트:
<!-- 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>
에러 바운더리 사용 예시:
에러 바운더리 컴포넌트를 다양한 컴포넌트에서 사용할 수 있습니다.
<!-- 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>
에러를 발생시키는 자식 컴포넌트:
<!-- 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
가 이를 감지하여 에러 메시지를 표시합니다.