DevOps/Network

HTTP상태코드

꼰용 2026. 7. 7. 21:22

개발하다보면 한 번쯤 이런 화면이나 숫자를 본 적이 있으실 겁니다.

  • 웹페이지가 작동하지 않을 때 보이는 404 Not Found
  • 서버가 터졌을 때 개발자들이 외치는 500 Internal Server Error
  • API 통신 성공시 반갑게 맞이하는 200 OK

이 3자리 숫자들의 정체가 바로 HTTP 상태 코드(Status Code)입니다.

 

왜 텍스트(Sucess, Fail 등) 글자 대신 3자리 숫자를?

서버는 단순히 HTML이나 JSON 데이터만 보내는 것이 아니라, 클라이언트의 요청이 성공했는지 실패했는지에 대한 결과도 함께 전달해야 합니다. 물론 "성공했습니다" 또는 "오류가 발생했습니다"처럼 문장으로 표현할 수도 있겠지만, 인터넷 세상에는 수많은 언어와 시스템, 운영체제가 존재합니다. 한국어, 영어, 일본어 등 언어와 관계없이 전 세계의 모든 브라우저와 서버가 동일한 의미로 즉시 이해할 수 있도록 HTTP는 3자리 숫자 상태 코드라는 글로벌 약속을 사용합니다. 실제로 서버가 보내주는 HTTP 응답(Response) 메시지 데이터를 직접 들여다보면 다음과 같이 생겼습니다.

 

HTTP/1.1 200 OK      ← [HTTP Header: 3자리 상태 코드]
Content-Type: text/html

<html>              ← [HTTP Body: 응답 데이터]
  <body>Hello World!</body>
</html>

 

브라우저와 서버는 Header에 담긴 이 숫자 하나를 보고 요청이 성공했는지, 클라이언트의 요청에 문제가 있는지, 아니면 서버 내부에서 오류가 발생했는지를 즉시 판단합니다.

상태코드는 누가 정했을까?

HTTP 상태 코드는 인터넷 기술 표준화 기구인 IETF의 RFC(인터넷 표준 문서)를 통해 엄격하게 정의되어 있으며, IANA(Internet Assigned Numbers Authority)에서 정식 관리하고 있습니다. 덕분에 언어나 플랫폼에 상관없이 전 세계 기기가 동일한 의미로 해석합니다.

 

상태 코드(Status Code)와 응답 본문(Body)은 별개

많은 입문 개발자들이 실수하는 부분 중 하나가 "200 OK이면 무조건 데이터(Body)가 들어있고, 404/500 에러면 Body 데이터는 비어있을 것이다"라고 생각하는 점입니다. 하지만 HTTP 상태 코드는 Header의 영역이며, 응답 본문(Body)은 완전히 별개의 영역입니다.

  • 성공(200대) 이어도 데이터가 없을 수 있습니다.
    요청이 성공했다고 해서 항상 화면에 보여줄 데이터가 넘어오는 것은 아닙니다. 예를 들어 게시글 삭제 요청이 성공했을 때 서버는 204 No Content를 보내며, 이때 Body는 깨끗하게 비어 있습니다.
  • 에러(400/500대) 여도 JSON 데이터를 함께 내려줄 수 있습니다.
    404 Not Found나 500 Internal Server Error가 발생하더라도, 서버는 프론트엔드나 클라이언트가 에러 원인을 쉽게 파악할 수 있도록 JSON 형태의 에러 응답 객체(Body)를 얼마든지 함께 전달할 수 있습니다.
HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "status": 404,
  "code": "ARTICLE_NOT_FOUND",
  "message": "요청하신 105번 게시글을 찾을 수 없습니다."
}

이처럼 "상태 코드는 통신의 성공/실패 여부를 알려주는 껍데기(Header)이고, Body는 그 안에 담긴 내용물"이라는 점을 구분하는 것이 REST API를 제대로 이해하는 첫걸음입니다.

 

상태 코드 분류

상태 코드는 첫 번째 숫자에 따라 5가지 그룹(1xx ~ 5xx)으로 나뉩니다. 첫 번째 숫자만 봐도 상태의 대략적인 성격을 확인할 수 있습니다.

  • 1xx (Informational) : 요청을 받아 처리 중
  • 2xx (Successful)    : 성공! 요청을 처리
  • 3xx (Redirection)   : 주소가 변경, 다른 곳으로 이동
  • 4xx (Client Error)  : 클라이언트 요청에 문제
  • 5xx (Server Error)  : 서버 쪽 문제

🔵 1xx (Informational): 정보 전달

  • 요청을 받아 처리가 진행중임을 나타냅니다.
  • 101 Switching Protocols: HTTP에서 WebSocket 통신으로 프로토콜을 전환할 때 사용됩니다.

 🟢 2xx (Successful): 성공

  • 클라이언트의 요청이 성공적으로 처리되었음을 의미합니다.
  • 200 OK: 가장 대표적인 요청 성공
  • 201 Created: 요청이 성공하여 새로운 리소스가 생성됨 (회원가입 완료, 게시글 등록 등)
  • 204 No Content: 요청은 성공했으나 응답 Body에 전달할 데이터가 없음 (게시글 삭제 성공 등)
  • 206 Partial Content: 데이터의 일부(Range)만 응답함
    🎬 유튜브/넷플릭스 영상 스트리밍의 비밀
    몇십 GB가 넘는 대용량 동영상을 한 번에 전부 다운로드받으려면 시간이 오래 걸립니다. 따라서 브라우저는 Range: bytes=0-1024처럼 일부만 분할 요청하고, 서버는 206 Partial Content로 응답하며 데이터를 조각조각 스트리밍합니다. 동영상 타임라인을 클릭해 앞으로 빨리 감기 할 때 구동되는 핵심 상태 코드입니다.

🟡 3xx (Redirection): 리다이렉션

  • 요청을 완료하기 위해 위치 이동 등의 추가 동작이 필요함을 알립니다.
  • 301 Moved Permanently: 리소스의 위치가 영구적으로 이동함 (http → https 전환 시 필수 사용, SEO 승계)
  • 302 Found: 리소스의 위치가 임시로 이동함
  • 304 Not Modified: 이전 요청 결과와 비교해 변경사항이 없으니, 클라이언트의 브라우저 캐시(Cache) 데이터를 그대로 재사용하라는 신호 (네트워크 대역폭 절약)
  • 307 Temporary / 308 Permanent: 최근 REST API나 현대적 웹 환경에서 302 / 301의 대체로 많이 쓰이는 코드입니다. 리다이렉트 시 클라이언트가 요청했던 HTTP Method(GET, POST 등)와 본문(Body)을 변경하지 않고 그대로 유지해 준다는 안전성이 있습니다

🟠 4xx (Client Error): 클라이언트 오류

  • 클라이언트의 요청 방식이나 데이터에 문제가 있을 때 발생합니다. (사용자/개발자 책임)
  • 400 Bad Request: 잘못된 요청 syntax, JSON 파라미터 규격 불일치
  • 401 Unauthorized: 인증되지 않음 (로그인이 안 된 상태)
  • 403 Forbidden: 권한 없음 (로그인은 되었으나 관리자 전용 페이지 접근 등)
  • 404 Not Found: 단순히 URL 주소가 틀렸다는 뜻을 넘어, 서버에 요청한 '리소스(Resource)'가 존재하지 않는다는 의미입니다
    • 존재하지 않는 URL 경로 접근
    • 이미 삭제된 게시글이나 삭제된 이미지 파일 조회
    • 서버에 구현되지 않은 API Endpoint 호출
  • 405 Method Not Allowed: POST 전용 API에 GET으로 접근했을 때
  • 429 Too Many Requests: 짧은 시간에 너무 많은 요청을 보냄 (Rate Limit 제한, 디도스 방지)

🔴  5xx (Server Error): 서버 오류

  • 클라이언트의 요청은 정상이나, 서버 내부에서 예외나 장애가 발생한 상태입니다. (서버 개발자/운영자 책임)
  • 500 Internal Server Error: 서버 내부 예외 발생. 백엔드 개발 시 가장 많이 마주하는 코드로, 코드 내부에서 예상치 못한 예외(Exception)가 발생했을 때 반환됩니다.
    • 백엔드(Spring, Node.js 등) 개발자 통곡의 원인
    • NullPointerException (객체 참조 오류)
    • SQLException / DataAccessException (DB 쿼리/연결 에러)
    • RuntimeException (처리되지 않은 언체크 예외)
  • 502 Bad Gateway: 앞단의 Nginx/Apache 프록시 서버가 뒷단의 애플리케이션 서버(Tomcat, Spring Boot 등)로부터 응답을 받지 못함 (뒷단 서버 다운)
  • 503 Service Unavailable: 서버 점검 중이거나 일시적인 과부하 상태
  • 504 Gateway Timeout: 뒷단 서버가 응답을 주지 않아 프록시 서버에서 타임아웃(Timeout)이 터짐

 

자주 보는 에러 

  • 404 Not Foud 발생 시
    1. Request URL 및 URI 오탈자 확인
    2. 백엔드 Controller / Router의 매핑 경로(@GetMapping 등) 확인
    3. 앞단 Reverse Proxy(Nginx, Apache)의 proxy_pass 경로 설정 확인
    4. DB에 실제 해당 데이터/리소스 ID가 존재(삭제 여부)하는지 확인
  • 500 Internal Server Error 발생 시
    1. 서버 Application 로그(Log) 파일 확인
    2. Stack Trace의 맨 처음 발생한 Exception 위치(Line) 추적
    3. DB Connection Pool 고갈 또는 SQL 쿼리 예외 발생 여부 점검

401과 403의 차이

  • 401 Unauthorized (인증 X): "누구세요?" → 신원 미확인 (로그인 유도)
  • 403 Forbidden (권한 X): "누군지는 알겠는데, 들어올 수는 없습니다."  → 신원 확인됨, 권한 부족

 

 

마치며
HTTP 상태 코드는 클라이언트와 서버가 서로의 상태를 가정 명확하게 전달하는 글로벌 공용 언어입니다. 
상태코드가 필요한 이유를 정확히 이해하고 있다면 웹 서비스 및 API를 개발할 때 훨씬 더 깔끔하고 견고한 시스템을 구축할 수 있습니다.
도움이 되시길 바랍니다!
감사합니다 :)

 

 

'DevOps > Network' 카테고리의 다른 글

HTTP/HTTS  (0) 2026.07.06
Well-Known Port  (0) 2026.07.02
Port  (0) 2026.07.01
포트포워딩 없이 Cloudflare Tunnel로 내부 Tomcat 서버 외부로 공개  (0) 2026.06.29
가비아 도메인 구매부터 Cloudflare 네임서버 이관  (1) 2026.06.29