웹 애플리케이션을 개발하고 서비스를 설계할 때 REST API는 시스템 간 통신을 위한 글로벌 표준으로 자리 잡았습니다. 대다수의 개발자가 RESTful한 API를 만들기 위해 노력하지만, 실무에서 의외로 가장 많이 놓치는 부분이 바로 HTTP 상태 코드(HTTP Status Code)의 올바른 활용입니다. 상태 코드를 명확하게 정의하지 않으면 API를 소비하는 클라이언트 측 개발자는 응답 본문(Response Body)을 매번 파싱하여 별도의 커스텀 에러 코드를 확인해야 하는 번거로움이 발생합니다. 이는 개발 생산성을 떨어뜨리고 유지보수를 어렵게 만드는 주된 원인이 됩니다. 본 글에서는 REST API에서 HTTP 상태 코드를 표준에 맞게 제대로 사용하는 구체적인 기준과 실무적인 팁을 상세히 살펴보겠습니다.
01. HTTP 상태 코드의 핵심 분류체계
성공과 실패의 기준을 명확히 나누는 세 자리 숫자의 약속입니다.
✓ 상태 코드의 대분류 기준
HTTP 상태 코드는 백의 자리 숫자에 따라 그 역할과 의미가 완전히 달라집니다. API 설계 시 가장 많이 사용하는 200번대부터 500번대까지의 핵심 체계를 먼저 이해해야 합니다.
2xx (Success): 클라이언트가 요청한 작업이 성공적으로 접수되고 처리되었음을 의미합니다.
3xx (Redirection): 요청을 완료하기 위해 클라이언트 프로그램의 추가적인 조치가 필요함을 나타냅니다.
4xx (Client Error): 클라이언트의 요청에 잘못된 문법이 있거나 요청을 수행할 수 없는 원인이 클라이언트 측에 있음을 의미합니다.
5xx (Server Error): 서버가 유효한 요청을 처리하는 과정에서 서버 자체적인 오류가 발생했음을 나타냅니다.
02. 2xx 성공 응답의 명확한 구별 방법
단순히 모든 성공에 200 OK를 반환하는 관행에서 벗어나야 합니다.
✓ 상황별 성공 코드 선택 기준
많은 개발 팀에서 생성, 수정, 삭제 등의 모든 성공적인 요청에 일률적으로 200 OK를 반환하곤 합니다. 하지만 요청의 성격에 따라 세부 코드를 나누어 주면 클라이언트 측에서 불필요한 데이터 확인 과정을 줄일 수 있습니다.
200 OK: 주로 데이터를 조회(GET)하거나 기존 데이터를 수정(PUT/PATCH)하여 그 결과물을 응답 본문에 담아 전달할 때 사용합니다.
201 Created: 자원을 새롭게 생성(POST)하는 요청이 성공했을 때 사용합니다. 이때 응답 헤더의
Location필드에 생성된 자원의 URI를 함께 적어주는 것이 표준 관례입니다.202 Accepted: 요청이 접수되었으나 배치가 돌고 있거나 비동기 처리가 진행 중이어서 작업이 아직 완료되지 않았을 때 반환합니다.
204 No Content: 요청은 성공적으로 처리되었으나 클라이언트에게 돌려줄 응답 본문 데이터가 완전히 없을 때 사용합니다. 주로 자원을 삭제(DELETE)하는 요청에 적합합니다.
| 상태 코드 | 권장되는 HTTP 메서드 | 응답 본문(Body) 존재 여부 |
| 200 OK | GET, PUT, PATCH | 필수 또는 권장 |
| 201 Created | POST | 권장 (생성된 객체 정보) |
| 204 No Content | DELETE | 없음 (Body 포함 불가) |
03. 4xx 클라이언트 오류의 올바른 세부 설계
클라이언트의 잘못을 정확히 지적해 주어야 빠른 디버깅이 가능합니다.
✓ 가장 흔하게 혼동하는 401과 403의 차이점
API 설계 과정에서 가장 잦은 혼선이 생기는 지점은 바로 401 Unauthorized와 403 Forbidden의 구분입니다. 용어의 사전적 의미 때문에 헷갈리기 쉽지만, 기술적인 정의는 명확합니다.
401 Unauthorized (인증 오류): 사용자가 누구인지 아직 모르는 상태이거나, 로그인이 필요한 API에 토큰 없이 접근했을 때 발생합니다. 즉, '신원 증명'이 실패한 경우입니다.
403 Forbidden (인가 오류): 사용자가 누구인지는 서버가 알고 있으나(로그인은 성공했으나), 해당 사용자가 접근하려는 자원에 대한 관리자 권한 등 '접근 권한'이 없을 때 사용합니다.
✓ 그 외 실무 핵심 4xx 코드
400 Bad Request: 클라이언트가 보낸 JSON 파라미터의 규격이 맞지 않거나 필수 값이 누락되었을 때의 범용적인 오류 코드입니다.
404 Not Found: 요청한 URI에 해당하는 자원이 존재하지 않을 때 반환합니다.
409 Conflict: 현재 서버의 데이터 상태와 클라이언트의 요청이 충돌할 때 사용합니다. 예를 들어 중복된 아이디로 회원가입을 시도하는 경우에 적합합니다.
04. 5xx 서버 오류와 프론트엔드 대응
서버 내부의 결함은 절대 클라이언트의 책임으로 전가해서는 안 됩니다.
✓ 500 에러의 최소화와 예외 처리
서버 소스 코드 내부에서 NullPointerException 등의 가공되지 않은 런타임 예외가 발생하면 웹 서버는 기본적으로 500 Internal Server Error를 반환합니다. 비즈니스 로직 상의 데이터 검증 실패(예: 잔액 부족, 입력 유효성 실패)는 결코 500 에러로 처리해서는 안 되며, 이는 400 Bad Request나 422 Unprocessable Entity로 처리해야 마땅합니다.
500 Internal Server Error: 데이터베이스 연결 장애나 알 수 없는 서버 내부 시스템 로직 오류일 때만 제한적으로 발생해야 합니다.
503 Service Unavailable: 서버가 일시적인 과부하 상태이거나 정기 점검 등으로 인해 현재 요청을 처리할 수 없는 상태임을 나타냅니다.
05. 자주 묻는 질문 (FAQ)
Q. 데이터 조회 결과가 빈 리스트( [ ] )일 때는 200인가요, 404인가요?
A. 데이터 조회 요청 자체는 정상적으로 수행되었고 시스템에 오류가 없으므로 200 OK를 반환하는 것이 맞습니다. 빈 배열을 본문에 담아 응답하시면 됩니다. 404 Not Found는 해당 자원을 식별하는 URI 경로 자체가 존재하지 않거나 도메인 규칙상 완전한 부재를 뜻할 때 사용합니다.
Q. API 에러 메시지를 상태 코드만으로 다 표현하기 어려울 때는 어떻게 하나요?
A. HTTP 상태 코드는 대략적인 오류의 성격을 규정하는 물리적 통로 역할을 합니다. 세부적인 비즈니스 에러 원인은 응답 본문(Response Body)에 JSON 형태로 상세한 커스텀 에러 코드와 한글 설명 메시지를 포함하여 내려주는 것이 모범 사례입니다.
Q. 데이터 수정 요청 시 PUT과 PATCH의 상태 코드 활용은 어떻게 달라지나요?
A. 두 메서드 모두 성공 시 일반적으로 200 OK를 반환합니다. 다만 수정된 자원의 전체 모습을 그대로 반환할 때는 200을 사용하고, 수정 행동 자체의 완료만 알리고 응답 데이터를 비워두고 싶다면 204 No Content를 선택할 수 있습니다.