(fetch 등 API) 함수 선언을 분리해뒀는데, 이 함수 내부가 아니라
함수를 호출하는 컴포넌트에서 try catch문을 사용해 에러처리를 따로 하는 것이
통상적이다!!!
s3 이미지 처리를 위해 기존 API 통신 함수들을 수정하기 시작.
참고한 코드에는 try catch문이 제거되어 있었다.
javascript// 서비스 함수에서는 에러를 던지고
const uploadToS3 = async () => {
if (!response.ok) {
throw new Error('업로드 실패'); // 에러를 던짐
}
}
// 컴포넌트에서 try-catch로 처리
const handleSubmit = async () => {
try {
await uploadToS3();
} catch (error) {
// 여기서 UI에 맞는 에러 처리 (토스트, 알림 등)
}
}
결론: 서비스 함수는 에러를 던지고, UI 컴포넌트에서 try-catch로 사용자에게 적절한 피드백을 주는 것이 일반적인 패턴입니다.
일반적인 패턴이라는 게, fetch를 사용하는 경우만 가리키는 거야 아니면 일반적인 트라이 캐치문이 사용되는 장소가 호출되는 것이라는 얘기야?편집일반적인 try-catch 사용 패턴 전체를 말하는 겁니다. fetch만이 아니라요.
기본 원칙:
낮은 레벨 함수(유틸리티, 서비스): 에러를 던짐 (throw)
높은 레벨 함수(컴포넌트, 컨트롤러): 에러를 잡음 (try-catch)
예시들:
javascript// 1. 데이터베이스 함수
const getUserById = (id) => {
if (!user) throw new Error('유저 없음'); // 에러 던짐
}
// 2. 파일 읽기 함수
const readFile = (path) => {
if (!exists) throw new Error('파일 없음'); // 에러 던짐
}
// 3. API 호출 함수
const fetchUser = async () => {
if (!response.ok) throw new Error('API 실패'); // 에러 던짐
}
// 4. 컴포넌트에서 사용
const UserProfile = () => {
try {
const user = getUserById(1); // 여기서 catch
const data = readFile('user.json'); // 여기서 catch
const apiData = await fetchUser(); // 여기서 catch
} catch (error) {
// UI에 에러 표시
}
}
왜 이렇게 하나요?
재사용성: 같은 서비스 함수를 다른 곳에서 다르게 에러 처리 가능
책임 분리: 비즈니스 로직과 UI 처리 분리
유연성: 컴포넌트마다 다른 에러 UI 가능
그래서 fetch뿐만 아니라 모든 종류의 함수에서 이 패턴을 씁니다.
그니까 종합하면, 트라이 캐치뿐 아니라 에러 처리를 함수 내부에서 안 하는 게 더 유연하다는 말도 맞아?편집네, 정확합니다!
에러 처리를 함수 내부에서 안 하고 호출하는 쪽에 위임하는 게 더 유연합니다.
함수 내부에서 에러 처리 시 문제점:
javascript// ❌ 유연하지 않음
const fetchUser = async () => {
try {
const response = await fetch('/api/user');
if (!response.ok) {
alert('에러 발생!'); // 항상 alert만 나옴
return null;
}
return response.json();
} catch (error) {
console.log('에러'); // 항상 콘솔에만 찍힘
return null;
}
}
호출하는 쪽에서 에러 처리 시 장점:
javascript// ✅ 유연함
const fetchUser = async () => {
const response = await fetch('/api/user');
if (!response.ok) throw new Error('API 실패');
return response.json();
}
// 사용하는 곳마다 다르게 처리 가능
// 페이지 A
try {
const user = await fetchUser();
} catch (error) {
showToast(error.message); // 토스트로 표시
}
// 페이지 B
try {
const user = await fetchUser();
} catch (error) {
setErrorModal(true); // 모달로 표시
}
// 페이지 C
try {
const user = await fetchUser();
} catch (error) {
redirectToErrorPage(); // 에러 페이지로 이동
}
결론: 에러 처리를 호출부에 위임하면 같은 함수를 여러 상황에서 다르게 활용할 수 있어서 더 유연합니다.
➡️ 상기 특별 케이스 (비중은 모르겠지만) 외에는 에러 처리 자체를 함수 호출 컴포넌트에서!