API 에러 처리는 catch 블록 하나로 끝나지 않습니다
프론트엔드에서 API 요청을 처리할 때 성공 응답만 기준으로 화면을 만들면 운영 환경에서 금방 문제가 드러납니다. 네트워크가 느리거나, 로그인이 만료되거나, 서버가 일시적으로 실패하거나, 데이터가 비어 있는 상황은 모두 다른 화면 처리가 필요합니다. 모든 실패를 “오류가 발생했습니다”로 보여주면 사용자는 무엇을 해야 하는지 알 수 없습니다.
좋은 API 에러 처리는 로딩, 성공, 빈 상태, 권한 오류, 네트워크 오류, 서버 오류를 구분합니다. 이 구분이 명확하면 사용자는 다시 시도할지, 로그인할지, 입력을 고칠지, 잠시 기다릴지 판단할 수 있습니다.
1. 빈 데이터는 오류가 아닙니다
검색 결과가 0개이거나, 아직 등록된 알림이 없거나, 사용자가 첫 프로젝트를 만들기 전이라면 이는 오류가 아니라 빈 상태입니다. 빈 상태 화면에는 다음 행동이 있어야 합니다. 예를 들어 “검색 결과가 없습니다”만 보여주는 것보다 “검색어를 줄이거나 필터를 초기화해 보세요”처럼 회복 방법을 함께 안내하는 편이 좋습니다.
- 목록 데이터가 빈 배열이면 빈 상태를 보여줍니다.
- 요청 자체가 실패하면 에러 상태를 보여줍니다.
- 권한이 없으면 로그인 또는 권한 요청 흐름으로 안내합니다.
2. HTTP 상태 코드별로 사용자 행동이 달라집니다
프론트엔드에서 모든 HTTP 오류를 같은 문구로 처리하면 중요한 단서를 잃습니다. 400번대 오류는 사용자의 입력, 권한, 인증 상태와 관련될 가능성이 높고, 500번대 오류는 서버 문제일 가능성이 큽니다. 401은 로그인 만료, 403은 권한 부족, 404는 리소스 없음, 429는 요청 과다로 나누어 생각할 수 있습니다.
function getErrorMessage(status) {
if (status === 401) return "로그인이 만료되었습니다. 다시 로그인해 주세요.";
if (status === 403) return "이 작업을 수행할 권한이 없습니다.";
if (status === 404) return "요청한 데이터를 찾을 수 없습니다.";
if (status === 429) return "요청이 많습니다. 잠시 후 다시 시도해 주세요.";
if (status >= 500) return "서버 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.";
return "요청을 처리하지 못했습니다.";
}
상태 코드별 문구를 중앙에서 관리하면 화면마다 다른 에러 메시지가 나오는 문제를 줄일 수 있습니다.
3. 재시도 버튼은 모든 오류에 넣지 않습니다
네트워크 오류나 일시적인 서버 오류에는 재시도 버튼이 도움이 됩니다. 하지만 권한이 없는 요청이나 잘못된 입력에는 재시도 버튼보다 로그인, 권한 요청, 입력 수정 안내가 필요합니다. 재시도 버튼을 넣을 때도 같은 요청이 중복 실행되지 않도록 pending 상태를 함께 관리해야 합니다.
function ErrorState({ message, onRetry, canRetry }) {
return (
<div role="alert">
<p>{message}</p>
{canRetry ? <button onClick={onRetry}>다시 시도</button> : null}
</div>
);
}
role="alert"를 사용하면 중요한 오류 메시지가 보조 기술에 더 명확하게 전달될 수 있습니다. 다만 너무 많은 영역에 alert를 남발하면 오히려 방해가 될 수 있으므로 핵심 오류에만 사용합니다.
4. 로딩 화면은 지연 시간에 따라 다르게 설계합니다
모든 요청에 큰 스피너를 보여줄 필요는 없습니다. 짧은 요청은 버튼 내부 로딩만으로 충분하고, 페이지 전체 데이터를 불러오는 요청은 스켈레톤이나 빈 프레임을 보여주는 편이 좋습니다. 기존 데이터가 이미 있는 상태에서 다시 요청하는 경우에는 화면 전체를 비우기보다 기존 데이터를 유지하고 작은 갱신 표시를 보여주는 것이 안정적입니다.
API 상태 모델 예시
const requestState = {
status: "idle", // idle | loading | success | empty | error
data: null,
error: null
};
상태 이름을 명확하게 두면 화면 조건문도 읽기 쉬워집니다. data === null인지, data.length === 0인지, error가 있는지를 뒤섞어 판단하면 빈 상태와 오류 상태가 쉽게 섞입니다.
실무 적용 체크리스트
- 빈 데이터와 요청 실패를 구분했는가?
- 401, 403, 404, 429, 500 오류에 서로 다른 안내가 있는가?
- 재시도 가능한 오류와 불가능한 오류를 구분했는가?
- 요청 중 버튼 중복 클릭이 막히는가?
- 기존 데이터가 있는 재요청에서 화면 전체가 깜빡이지 않는가?
- 오류 메시지가 사용자의 다음 행동을 알려주는가?
Frontend Note 실무 노트
API 에러 처리는 사용자가 실패를 만났을 때 서비스가 얼마나 신뢰할 만한지 보여주는 지점입니다. 실패 자체를 없앨 수는 없지만, 실패 후 무엇을 할 수 있는지 알려줄 수는 있습니다. 특히 콘텐츠 사이트, 관리자 도구, 커머스 화면은 오류 안내 방식이 전환율과 신뢰도에 직접 영향을 줍니다.
운영 중인 프로젝트에서는 에러 로그를 화면 단위로 묶어 보는 것이 좋습니다. 특정 페이지에서 404가 많다면 링크나 라우팅 문제일 수 있고, 401이 많다면 세션 만료 안내가 부족할 수 있습니다. 500 오류가 반복된다면 프론트엔드 메시지 개선과 함께 서버 로그 확인이 필요합니다.
참고 자료와 업데이트 기준
HTTP 상태 코드와 브라우저 네트워크 동작은 웹 표준과 서버 구현에 영향을 받습니다. 이 글은 프론트엔드 화면 설계 관점에서 에러 처리를 설명하며, 관련 문서나 브라우저 동작이 바뀌면 내용을 다시 점검합니다.
- MDN HTTP 상태 코드에서 상태 코드 의미를 확인합니다.
- MDN Fetch API에서 요청 처리 방식을 확인합니다.
- web.dev Accessibility에서 사용자에게 상태 변화를 전달하는 기준을 확인합니다.