웹이나 API를 다루다 보면 200, 403, 404, 500 같은 숫자를 자주 만나게 된다.
처음에는
200 = 정상
404 = 페이지 없음
500 = 서버 오류
정도만 알고 있었는데, 실제로 API나 서버 문제를 확인하다 보니 상태코드만 봐도 어느 쪽부터 확인해야 하는지 어느 정도 감을 잡을 수 있었다.
특히 401과 403, 301과 302처럼 비슷해 보이는 코드들은 막상 만나면 헷갈린다.
이번에는 웹이나 API를 확인할 때 자주 보게 되는 HTTP 상태코드 위주로 정리해봤다.
HTTP 상태코드는 무엇일까?
클라이언트가 서버에 요청을 보내면 서버는 요청을 처리한 뒤 응답을 보낸다.
클라이언트
│
│ HTTP Request
▼
┌─────────┐
│ Server │
└─────────┘
│
│ HTTP Response
▼
클라이언트
이때 응답에는 상태를 나타내는 숫자가 포함된다.
예를 들어:
HTTP/1.1 200 OK
또는:
HTTP/1.1 404 Not Found
같은 식이다.
curl을 사용하면 이런 상태코드를 직접 확인할 수도 있다.
curl -i https://example.com/api/test
또는 좀 더 자세하게:
curl -v https://example.com/api/test
를 사용할 수 있다.
앞자리 숫자부터 보면 쉽다
HTTP 상태코드는 세 자리 숫자지만 우선 첫 번째 숫자를 보면 대략적인 의미를 알 수 있다.
| 범위 | 의미 |
| 1xx | 요청 처리 중의 정보성 응답 |
| 2xx | 요청 처리 성공 |
| 3xx | 리다이렉션 |
| 4xx | 요청을 처리할 수 없는 클라이언트 측 요청 관련 오류 |
| 5xx | 서버가 요청 처리 과정에서 실패 |
실제로 자주 만나게 되는 건 주로 2xx ~ 5xx였다.
200 OK — 요청 처리 성공
가장 익숙한 상태코드다.
HTTP/1.1 200 OK
서버가 요청을 정상적으로 처리했다는 의미다.
예를 들어 API를 호출해서:
{
"result": "success"
}
라는 데이터와 함께 200 OK가 왔다면 일반적으로 정상적인 응답이라고 볼 수 있다.
그런데 여기서 하나 주의할 점이 있다.
200이 나왔다고 무조건 모든 게 정상일까?
꼭 그렇지는 않다.
예전에 API를 확인하면서 이런 상황을 본 적이 있었다.
HTTP/1.1 200 OK
<data>
...
...
응답 헤더에는 분명 200 OK가 왔는데 데이터를 받는 도중 연결이 종료됐다.
즉:
요청
↓
200 OK
↓
응답 Body 전송
↓
연결 종료 ❌
가 된 것이다.
따라서 대용량 API나 파일 다운로드에서는 200을 받았는지뿐 아니라 응답 Body까지 정상적으로 수신했는지도 확인해야 한다.
301 Moved Permanently — 영구적인 이동
301은 요청한 리소스의 위치가 영구적으로 변경되었다는 의미다.
예를 들어:
http://example.com
으로 요청했는데 서버가 앞으로는:
https://example.com
을 사용하도록 구성했다면 301 응답과 함께 새로운 주소를 알려줄 수 있다.
응답은 대략 이런 형태다.
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
여기서 중요한 게 Location 헤더다.
기존 URL
↓
301
↓
Location
↓
새 URL
브라우저는 이 값을 보고 새로운 URL로 다시 요청한다.
302 Found — 임시적인 이동
302도 다른 URL로 이동시키는 상태코드다.
HTTP/1.1 302 Found
Location: https://example.com/login
301과 비슷해 보이지만 의미상 차이가 있다.
301
→ 리소스가 영구적으로 이동
302
→ 현재 요청을 다른 위치로 임시 이동
로그인하지 않은 사용자를 로그인 페이지로 보내는 것처럼 일시적인 이동에 302가 사용되는 경우가 있다.
301과 302를 비교하면
| 301 | 302 | |
| 의미 | 영구 이동 | 임시 이동 |
| Location | O | O |
| 핵심 | 앞으로 새 주소 사용 | 현재는 다른 주소로 이동 |
웹 서비스에서 HTTP를 HTTPS로 전환하거나 특정 URL을 다른 URL로 보내는 작업을 할 때 자주 만나게 된다.

400 Bad Request — 요청 자체에 문제가 있다
400은 서버가 클라이언트의 요청을 정상적으로 처리하기 어려운 경우 반환될 수 있다.
HTTP/1.1 400 Bad Request
예를 들어 API에서 필수 파라미터가 잘못됐거나 요청 형식이 서버가 기대하는 형태와 맞지 않는 경우가 있을 수 있다.
/api/user?id=
처럼 필수 값이 빠졌거나 JSON 형식이 잘못된 경우 등이 대표적인 예다.
다만 어떤 경우에 400을 반환할지는 API 구현에 따라 달라질 수 있다.
그래서 400을 만나면 먼저:
요청 URL
Query Parameter
Request Body
Content-Type
등 요청 내용을 확인해보는 편이 좋다.
401 Unauthorized — 인증이 필요하다
이름 때문에 조금 헷갈리는 코드다.
401 Unauthorized는 주로 인증 정보가 없거나 유효하지 않은 상황에서 사용된다.
예를 들어 인증 토큰이 필요한 API인데:
curl https://example.com/api/user
처럼 인증정보 없이 호출했다면:
HTTP/1.1 401 Unauthorized
가 반환될 수 있다.
정상적인 토큰을 추가해야 요청을 처리할 수 있는 식이다.
curl \
-H "Authorization: Bearer ********" \
https://example.com/api/user
쉽게 기억하면:
401 → 너 누구야? 인증부터 해줘.
정도로 생각하면 편하다.
403 Forbidden — 인증과 별개로 접근이 거부됨
403은 서버가 요청을 이해했지만 해당 요청에 대한 접근을 허용하지 않는 경우다.
HTTP/1.1 403 Forbidden
401과 가장 많이 헷갈리는 부분이다.
간단하게 비교하면:
401
→ 인증이 필요하거나 인증정보에 문제가 있음
403
→ 서버가 요청을 거부함
다만 실제 서비스에서 어떤 상황에 401과 403을 반환하는지는 인증·인가 구현에 따라 차이가 있을 수 있다.
예를 들어 접근 가능한 IP가 제한되어 있거나 사용자에게 해당 리소스에 대한 권한이 없을 때 403을 반환하도록 구성할 수 있다.
예전에 외부에서 서버에 접근했을 때 403이 발생해서 처음에는 포트포워딩이나 네트워크 문제를 의심했지만, 실제로는 서버 쪽 제한과 관련된 문제였던 적도 있었다.
즉 403이라고 해서 무조건 네트워크가 막힌 것이라고 볼 수는 없다.
404 Not Found — 요청한 리소스를 찾을 수 없음
가장 익숙한 오류 중 하나다.
HTTP/1.1 404 Not Found
요청한 URL에 해당하는 리소스를 서버가 찾지 못했다는 의미다.
예를 들어:
https://example.com/api/users
가 정상 URL인데:
https://example.com/api/userzzz
로 요청했다면 404가 발생할 수 있다.
API 작업 중 404가 나오면 먼저:
URL 오타
Context Path
API Endpoint
Controller Mapping
등을 확인해볼 수 있다.
500 Internal Server Error — 서버 내부 오류
API 개발이나 운영에서 만나면 반갑지 않은 코드다.
HTTP/1.1 500 Internal Server Error
서버가 요청을 처리하는 과정에서 예상하지 못한 문제가 발생했다는 의미다.
예를 들어 서버 애플리케이션에서 예외가 발생했다면 500으로 응답할 수 있다.
클라이언트 요청
↓
Controller
↓
Service
↓
DB 조회
↓
Exception 발생
↓
500 Internal Server Error
이 경우에는 클라이언트에서 요청만 계속 바꿔보기보다 서버 로그를 확인해야 할 가능성이 높다.
tail -f application.log
같은 방식으로 요청 시점에 어떤 예외가 발생했는지 확인하는 것이다.
502와 503도 같이 알아두면 좋다
웹 서버나 프록시가 앞에 있는 환경에서는 502, 503도 볼 수 있다.
502 Bad Gateway
클라이언트
↓
Web / Proxy
↓
WAS
이런 구조에서 중간 서버가 뒤쪽 서버로부터 정상적인 응답을 받지 못했을 때 나타날 수 있다.
HTTP/1.1 502 Bad Gateway
예를 들어 Reverse Proxy 뒤의 WAS가 정상적으로 응답하지 못하는 상황 등을 생각할 수 있다.
503 Service Unavailable
서버가 현재 요청을 처리할 수 없는 상태임을 나타낸다.
HTTP/1.1 503 Service Unavailable
서버 과부하나 일시적인 서비스 중단 등의 상황에서 사용할 수 있다.
다만 500·502·503 모두 실제 원인은 시스템 구성과 로그를 같이 봐야 한다.
상태코드만 보고:
502니까 무조건 WAS가 죽었다.
라고 단정하면 안 된다.
자주 보는 상태코드만 한 번에 정리
| 코드 | 이름 | 먼저 확인해볼 것 |
| 200 | OK | 응답 Body까지 정상 수신됐는지 |
| 301 | Moved Permanently | Location 헤더 |
| 302 | Found | 어디로 리다이렉트되는지 |
| 400 | Bad Request | 파라미터·Body·요청 형식 |
| 401 | Unauthorized | 인증정보·토큰 |
| 403 | Forbidden | 권한·접근 정책 |
| 404 | Not Found | URL·경로·Mapping |
| 500 | Internal Server Error | 애플리케이션 서버 로그 |
| 502 | Bad Gateway | Proxy ↔ Backend 통신 |
| 503 | Service Unavailable | 서비스 상태·과부하 등 |
이 표 정도는 서버/API 문제를 볼 때 옆에 두고 봐도 괜찮다.
상태코드는 원인을 알려주는 답안지가 아니다
상태코드를 처음 배울 때는:
403 = 권한 문제
500 = 서버 문제
처럼 외우기 쉽다.
그런데 실제 장애를 확인해보면 상태코드는 원인을 확정하는 정보라기보다 어디부터 확인할지 알려주는 단서에 가깝다.
예를 들어 200 OK여도 응답이 중간에 끊길 수 있고, 403도 애플리케이션 권한뿐 아니라 서버의 접근 제한 정책 등 다양한 이유로 발생할 수 있다.
그래서 실제 문제를 볼 때는:
상태코드 확인
↓
응답 헤더 확인
↓
요청/응답 내용 확인
↓
curl 등으로 재현
↓
서버 로그 확인
처럼 범위를 좁혀가는 게 좋았다.
curl로 상태코드 확인하기
앞에서 정리한 curl을 사용하면 상태코드를 쉽게 확인할 수 있다.
응답 헤더와 본문을 같이 보려면:
curl -i https://example.com/api/test
통신 과정까지 자세하게 보려면:
curl -v https://example.com/api/test
리다이렉트를 따라가고 싶다면:
curl -L https://example.com
반대로 리다이렉트가 발생하는지 조사할 때는 바로 -L을 붙이기보다 먼저 원래 응답의 상태코드와 Location을 보는 것도 좋다.
curl -i http://example.com
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
그 다음 필요하면 -L로 최종 응답까지 확인하는 식이다.

정리
HTTP 상태코드는 전부 외우려고 하기보다 먼저 앞자리부터 기억하면 편하다.
2xx
→ 성공
3xx
→ 이동
4xx
→ 요청·인증·권한·리소스 등을 확인
5xx
→ 서버 또는 서버 간 처리 과정 확인
그다음 자주 만나는 코드부터 익히면 된다.
200 → OK
301 → 영구 이동
302 → 임시 이동
400 → 잘못된 요청
401 → 인증 필요
403 → 접근 거부
404 → 찾을 수 없음
500 → 서버 내부 오류
502 → Gateway 문제
503 → 현재 서비스 이용 불가
무엇보다 상태코드 하나만 보고 원인을 단정하기보다는 “어디를 먼저 확인해야 할지 알려주는 힌트”로 사용하는 게 가장 이해하기 쉬웠다.
'개발 > API' 카테고리의 다른 글
| curl로 API 테스트하는 방법, 자주 쓰는 옵션만 정리해봤다 (0) | 2026.09.23 |
|---|---|
| HTTP에서는 끊기는데 HTTPS에서는 정상이다... 같은 API인데 왜 다를까? (0) | 2026.09.18 |