리액트/예제
리액트 앱에서 에러 처리 및 예외 처리 구현하기
lamarcK
2025. 4. 10. 21:08
try catch error문을 통한 에러 관리 구현해보기
기본 구조
try {
// 에러가 발생할 수 있는 코드
const response = await fetch(`http://localhost:3001/videos?page=${currentPage}&limit=${limit}`);
// HTTP 에러 체크
if (!response.ok) {
throw new Error(/* 에러 메시지 */);
}
// 정상적인 데이터 처리
const result = await response.json();
} catch (error) {
// 에러 발생시 실행되는 코드
setError(error.message);
console.error('비디오 데이터 로딩 에러:', error);
// 특정 타입의 에러 처리
if (error.name === 'TypeError') {
setError('네트워크 연결을 확인해주세요.');
}
} finally {
// 성공/실패 상관없이 항상 실행되는 코드
setLoading(false);
}
1. 에러 상태 관리
const [error, setError] = useState(null); // 에러 상태 초기값은 null
2. 에러 초기
setError(null); // 새로운 데이터 요청 시작할 때 기존 에러 초기화
3. 에러 발생 처리
try {
// API 요청 코드...
if (!response.ok) {
throw new Error(
response.status === 404
? '더 이상 비디오를 찾을 수 없습니다.'
: `서버 오류가 발생했습니다. (${response.status})`
);
}
} catch (error) {
setError(error.message); // 에러 메시지를 상태에 저장
console.error('비디오 데이터 로딩 에러:', error);
// 네트워크 에러 특별 처리
if (error.name === 'TypeError') {
setError('네트워크 연결을 확인해주세요.');
}
}
4. 에러 표시 컴포넌트
const ErrorAlert = ({ message, onClose }) => (
<div className="error-alert">
<p>{message}</p>
<button onClick={onClose}>닫기</button>
</div>
);
- message: 표시할 에러 메시지
- onClose: 에러 알림을 닫을 때 실행할 함수
- 사용자에게 시각적으로 에러를 알리는 UI 컴포넌트
에러 처리 시스템은
- HTTP 응답 오류 (404 등)
- 네트워크 오류
- 서버 오류
등 다양한 종류의 에러를 처리하고 사용자에게 적절한 메시지를 표시할 수 있습니다.
function VideoList() {
const [videoData, setVideoData] = useState([]); // 비디오 데이터 목록
const [currentPage, setCurrentPage] = useState(1); // 현재 페이지 번호 (1부터 시작)
const [loading, setLoading] = useState(false); // 데이터 로딩 중 상태
const [hasMore, setHasMore] = useState(true); // 더 로드할 데이터가 있는지 여부
const limit = PAGE_CONFIG.ITEMS_PER_PAGE;; // 페이지당 불러올 비디오 개수
const observerTarget = useRef(null); // 📌 감시할 타겟 요소 Ref
const mountedRef = useRef(false); // 추가: 마운트 상태 추적을 위한 ref
const { isNavExpanded } = useContext(NavContext); // 이제 정상 작동
const [error, setError] = useState(null); //에러 처리
// ✨ 비디오 데이터를 로드하는 함수 (페이지네이션 적용)
const loadVideos = useCallback(async () => {
// 로딩 중이거나 더 이상 데이터가 없으면 실행 중지
if (loading || !hasMore) return;
setLoading(true);
setError(null); // 새로운 요청 시작 시 에러 초기화
try {
// 📌 API 요청 URL 변경: `offset` 대신 `page`와 `limit` 사용
const response = await fetch(`http://localhost:3001/videos?page=${currentPage}&limit=${limit}`);
if (!response.ok) { // HTTP 응답 상태 확인
throw new Error(
response.status === 404
? '더 이상 비디오를 찾을 수 없습니다.'
: `서버 오류가 발생했습니다. (${response.status})`
);
}
// 📌 API 응답 구조 변경에 따른 처리
// - 백엔드가 { data: [...], pagination: {...} } 형태로 응답
const result = await response.json();
const newVideos = result.data; // 실제 비디오 데이터 배열
const pagination = result.pagination; // 페이지네이션 정보
console.log(`[Frontend] Loaded page ${pagination.currentPage}/${pagination.totalPages}, Videos: ${newVideos.length}`);
// 받아온 비디오 데이터가 있으면 기존 목록에 추가
if (newVideos.length > 0) {
setVideoData(prev => [...prev, ...newVideos]);
}
// 📌 더 로드할 데이터가 있는지 판단 (hasMore 상태 업데이트)
// - 현재 페이지가 총 페이지 수보다 크거나 같으면 더 이상 데이터가 없음
if (pagination.currentPage >= pagination.totalPages) {
setHasMore(false);
console.log("[Frontend] No more videos to load.");
} else {
// 다음 페이지 로드를 위해 현재 페이지 번호 증가 (다음번 loadVideos 호출 시 사용됨)
setCurrentPage(prevPage => prevPage + 1);
}
} catch (error) {
setError(error.message);
console.error('비디오 데이터 로딩 에러:', error);
// 네트워크 오류의 경우 재시도 로직 추가
if (error.name === 'TypeError') {
setError('네트워크 연결을 확인해주세요.');
}
} finally {
// 로딩 상태 해제 (성공/실패 여부와 관계없이 실행)
setLoading(false);
}
}, [currentPage, hasMore, loading, limit]); // useCallback 의존성 배열 업데이트
// 에러 알림 컴포넌트트
const ErrorAlert = ({ message, onClose }) => (
<div className="error-alert">
<p>{message}</p>
<button onClick={onClose}>닫기</button>
</div>
);