본문 바로가기

개발/API

HTTP 상태코드 200, 301, 302, 400, 401, 403, 404, 500 차이 정리

웹이나 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로 보내는 작업을 할 때 자주 만나게 된다.

curl에서 HTTP 302 응답과 Location 헤더를 확인한 화면


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로 최종 응답까지 확인하는 식이다.

curl을 이용해 HTTP 200 302 404 상태코드를 확인한 화면


정리

HTTP 상태코드는 전부 외우려고 하기보다 먼저 앞자리부터 기억하면 편하다.

2xx
→ 성공

3xx
→ 이동

4xx
→ 요청·인증·권한·리소스 등을 확인

5xx
→ 서버 또는 서버 간 처리 과정 확인

그다음 자주 만나는 코드부터 익히면 된다.

200 → OK
301 → 영구 이동
302 → 임시 이동

400 → 잘못된 요청
401 → 인증 필요
403 → 접근 거부
404 → 찾을 수 없음

500 → 서버 내부 오류
502 → Gateway 문제
503 → 현재 서비스 이용 불가

무엇보다 상태코드 하나만 보고 원인을 단정하기보다는 “어디를 먼저 확인해야 할지 알려주는 힌트”로 사용하는 게 가장 이해하기 쉬웠다.