feat(WEB): 에러 리포팅 시스템 및 ErrorBoundary 개선
- 에러 리포팅 유틸리티 및 API route 추가 - ErrorBoundary(error.tsx) 에러 리포팅 연동 - providers 컴포넌트 구조 추가 - layout에 provider 적용 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
68
src/components/providers/ChunkErrorHandler.tsx
Normal file
68
src/components/providers/ChunkErrorHandler.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { reportErrorToSlack } from '@/lib/error-reporting';
|
||||
|
||||
/**
|
||||
* ChunkLoadError 전역 감지 컴포넌트
|
||||
*
|
||||
* 배포 후 캐시된 구버전 JS 청크 로딩 실패를 감지하여 Slack으로 전송
|
||||
* - window 'error' 이벤트: <script> 태그 로딩 실패
|
||||
* - window 'unhandledrejection': dynamic import() 실패
|
||||
*/
|
||||
|
||||
const CHUNK_ERROR_PATTERNS = [
|
||||
'Loading chunk',
|
||||
'ChunkLoadError',
|
||||
'Failed to fetch dynamically imported module',
|
||||
'error loading dynamically imported module',
|
||||
];
|
||||
|
||||
function isChunkError(message: string): boolean {
|
||||
return CHUNK_ERROR_PATTERNS.some((pattern) =>
|
||||
message.toLowerCase().includes(pattern.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
function sendReport(message: string, stack?: string) {
|
||||
reportErrorToSlack({
|
||||
errorType: 'CHUNK_LOAD_ERROR',
|
||||
message,
|
||||
pageUrl: window.location.href,
|
||||
timestamp: new Date().toISOString(),
|
||||
stack: stack?.slice(0, 500),
|
||||
userAgent: navigator.userAgent,
|
||||
});
|
||||
}
|
||||
|
||||
export function ChunkErrorHandler() {
|
||||
useEffect(() => {
|
||||
function handleError(event: ErrorEvent) {
|
||||
if (event.message && isChunkError(event.message)) {
|
||||
sendReport(event.message, event.error?.stack);
|
||||
}
|
||||
}
|
||||
|
||||
function handleRejection(event: PromiseRejectionEvent) {
|
||||
const reason = event.reason;
|
||||
const message =
|
||||
reason instanceof Error ? reason.message : String(reason ?? '');
|
||||
if (isChunkError(message)) {
|
||||
sendReport(
|
||||
message,
|
||||
reason instanceof Error ? reason.stack?.slice(0, 500) : undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('error', handleError);
|
||||
window.addEventListener('unhandledrejection', handleRejection);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('error', handleError);
|
||||
window.removeEventListener('unhandledrejection', handleRejection);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user