HTTP 상태코드

구름코딩·2021년 1월 11일
2

HTTP 웹 _ 정리

목록 보기
6/8

상태코드

클라이언트가 서버로 요청을 보내면 해당 요청이 잘 처리가 되었는지, 문제가 있는지 http 응답 메시지가 올때 알려주는 기능이다

  • 1xx (Informational) : 요청이 수신되어 처리중
    • 거의 사용되지 않는다
  • 2xx (Successful) : 요청 정상 처리
  • 3xx (Redirection) : 요청을 완료하려면 추가 행동이 필요
  • 4xx (Client Error) : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없는 경우
  • 5xx (Server Error) : 서버 오류, 서버가 정상 요청을 처리하지 못한 경우

만약 모르는 상태 코드가 전달 되면?

Q. 클라이언트가 인식할 수 없는 상태코드를 서버가 반환한다면?
A. 클라이언트는 상위 상태코드로 해석해서 처리하면 된다

  • 미래에 새로운 상태코드가 추가되어도 클라이언트를 변경하지 않아도 된다
  • 아래와 같은 상황
    • 299 (정의되지 않음) -> 2xx (Successful) 로 인지
    • 451 (``) -> 4xx (Client Error)로 인지
    • 599 (``) -> 5xx (Server Error)로 인지

1xx (Informational)

  • 요청이 수신되어 처리중

거의 사용되지 않는다


2xx (Successful)

  • 200 OK
  • 201 Created (리소스 생성, POST로 등록 등의 경우)
  • 202 Accepted
  • 203 No Content

200 OK

클라에서 보낸 요청이 성공했다

GET /members/100 을 조회 요청 -> 클라 응답으로 정보 반환 & 200 OK

201 Created

요청 성공해서 새로운 리소스가 생성 되었다

POST /members + html body 로 등록 요청 -> 클라 응답으로 해당 리소스 URI 설정해서 등록하고 & 201 Created

html 응답 헤더에 Location을 추가해서 반환 (생성된 리소스 URI)

202 Accepted

요청이 접수는 되었지만 처리는 완료되지 않았다

  • 배치 처리 같은 곳에서 사용한다
    • 요청 접수후 한시간 뒤에 배치 프로세스가 요청을 처리하는 경우

204 No Content

서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없는 경우

  • 예) 웹 문서 편집기에서 save 버튼
    • 웹에서 문서를 작성하다 save를 누른다고 서버의 응답을 통해 데이터를 받아서 처릴 할 것은 없다, 내가 원하는 것은 정상적으로 저장이 된건지에 대한 여부일 뿐이다
  • save 버튼의 결과로 아무 내용이 없어도 된다
  • save 버튼을 눌러도 같은 화면을 유지해야 한다
  • 결과 내용이 없어도 204 메시지(2xx)만으로 성공을 인식할 수 있다

꼭 많은 종류의 상태 코드를 사용한다고 좋은것이 아니다. 200번과 201번만 사용하는 등 팀간의 약속을 통해서 맞춰서 사용하는 것이 좋다


3xx (Redirection)

요청을 완료하기 위해 유저 에이전트(클라이언트 프로그램 ex 웹브라우저)의 추가 조치 필요한 것

  • 300 Multiple Choices (사용 X)
  • 301 Moved Permanently
  • 302 Found
  • 303 See Other
  • 304 Not Modified
  • 307 Temporary Redirect
  • 308 Permanent Redirect

리다이렉션 이해

웹브라우저는 3xx 응답의 결과에 Location 헤더가 있으면 Location위치로 자동 이동한다 (리 다이렉트)

자동 리다이렉트 흐름

클라이언트가 url을 통해 GET /event HTTP/1.1 Host: localhost:8080으로 이벤트 페이지를 요청 했다고 하자

이때, event사이트가 new-envet라는 새로운 uri를 가진 곳으로 변경 되었다고 하면 이전 uri로 접근하는 클라이언트들에게 HTTP/1.1 301 Moved Permanently Location:/new-event의 응답메시지를 전달하게 된다

해당 응답 메시지를 받은 웹브라우저는 응답 결과에 Location이 헤더에 포함된 것을 인지하고 해당 위치로 다시 이동하게 된다 (자동 리다이렉트) 이때 웹이 알아서 GET /new-event HTTP/1.1 Host:localhost:8080을 새로운 uri에 요청하게 되고 정상적으로 연결이 되면 해당 서버에서 HTTP/1.1 200 OK를 응답 메시지로 주게된다

종류

  • 영구 리다이렉션 - 특정 리소스의 URI가 영구적으로(permanently) 이동

    • /members -> /users
    • /event -> /new-event
  • 일시 리다이렉션 - 일시적인 변경

    • 주문 완료 후 주문 내역 화면으로 일시적으로 이동
    • PRG : Post/Redirect/Get
  • 특수 리다이렉션

    • 결과 대신 캐시를 사용
    • 다시 서버한테서 다운 받지 말고 브라우저에 있는 캐시를 써라

영구 리다이렉션 301, 308

  • 리소스의 URI가 영구적으로 이동
  • 원래의 URI를 사용 X, 검색 엔진 등에서도 변경을 인지
  • 301 Moved Permanently
    • 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있다
    • 무언가를 작성한 데이터를 전송하는 경우였다면(post), GET으로 변하면서 해당 데이터는 날라가고 다시 작성해야 된다
  • 308 Permanent Redirect
    • 301과 기능은 같다
    • 리다이렉트시 요청 메서드와 본문을 유지한다
    • 처음부터 POST로 보냈고 데이터가 body에 있을 때, 리다이렉트때도 똑같이 POST로 보내고 body에 있는 데이터 유지

영구 리다이렉션 - 301

  1. 클라이언트에서 POST 메서드로 작성한 데이터와 함께 요청 메시지를 전송 POST /event HTTP/1.1 name=hello&age=20 (변경되기 전 uri로)

  2. 서버에서 응답메시지로 HTTP/1.1 301 Moved Permanentrly Location:/new-event를 전달 (기존 uri가 변경된 경우)

  3. 응답 메시지를 받은 웹 브라우저가 Location을 확인하고 리다이렉트 후 GET /new-event HTTP/1.1을 요청 (POST => GET으로 변경, 이때 갖고있던 데이터는 날라갈수 있다)

  4. GET 요청 메시지를 받은 서버가 해당 new-envet 창을 띄어주고 응답 메시지를 보내준다 HTTP/1.1 200 OK

즉, 전달 한 데이터가 사라지고 다시 리다이렉트 받은 웹페이지에서 다시 데이터를 작성 후 전달해야 한다


영구 리다이렉션 - 308

  1. 클라이언트에서 POST 메서드로 작성한 데이터와 함께 요청 메시지를 전송 POST /event HTTP/1.1 name=hello&age=20 (변경되기 전 uri로)

  2. 서버에서 응답메시지로 HTTP/1.1 301 Moved Permanentrly Location:/new-event를 전달 (기존 uri가 변경된 경우)

  3. 응답 메시지를 받은 웹 브라우저가 Location을 확인하고 리다이렉트 후 POST /new-event HTTP/1.1을 요청 (기존의 POST를 유지하고 body도 유지해준다, 데이터 손실이 없다)

  4. GET 요청 메시지를 받은 서버가 해당 new-envet 창을 띄어주고 응답 메시지를 보내준다 HTTP/1.1 200 OK

즉, 전달한 데이터가 없어지지 않고 메시지 바디에 유지된채로 리다이렉트 된 웹페이지로 전달된다

참고
그러나 보통 페이지가 리다이렉트 되도록 한 경우 (기존 페이지에서 새로운 페이지로 변경 된 경우) 데이터를 기존 양식과 다르게 갖는 경우가 대부분이므로 데이터를 가지고와도 쓸모없는 경우가 많다. 따라서 POST로 갖고와도 GET으로 바꿔서 새 URI를 요청하는 경우가 많다


일시적인 리다이렉션 - 302, 307, 303 (주류)

  • 리소스의 URI가 일시적으로 변경
  • 따라서 검색 엔진 등에서 URL을 변경하면 안된다
  • 302 Found

    • 리다이렉트시 요청 메시지가 GET으로 (거의)변할수 있고, 이에따라 메시지 바디는 제거될수 있다(~= 301 Moved Permanently과 똑같다)
  • 307 Temporary Redirect

    • 302와 기능이 똑같다
    • POST 유지
    • 단, 리다이렉트시 요청 메서드와 본문을 유지한다 (요청 메시지 변경은 X, MUST NOT)
  • 303 See Other

    • 302와 기능이 똑같다
    • 단, 라다이렉트시 요청 메서드가 GET으로 확정적으로 변경된다

정리

302, 307, 303은 일시적 리다이렉트이고, 307은 메서드를 절대 변경하지 않고(POST는 POST로 유지) 데이터도 잃어버리지 않는 것이고 VS 303은 메서드를 GET으로 확정적으로 메서드를 바꿔서 새로 요청하는 것이다

302는 기존의 영구적 리다이렉트 301과 동일하다 (메소드가 바뀔수도있고 아닐수도있고, 그에 따라서 메시지를 잃어버릴수도 있고 아닐수도 있고)

그러나 사용은 302를 많이 사용한다. 큰 문제는 없고 기본적으로 리다이렉트시 데이터를 갖고있지만 않으면 상관이 없다


PRG : Post/Redirect/Get

일시적인 리다이렉션의 사용은?

  • POST로 주문 후에 웹 브라우저를 새로고침하면?
    • 새로고침은 웹브라우저에 다시 요청하는 것이다
    • 따라서 중복 주문이 될 수 있다(POST 중복 - 멱등하지 X)

PRG 사용 전

  1. 주문을 한다 URL:/order
  • 요청 (html form등을 통해 전달된 데이터를 가지고)
POST /order HTTP/1.1
Host :localhost:8080

itemId=mouse&count=1
  1. 판매 사이트의 서버가 주문을 받아서 주문데이터를 저장한다. mouse 1개

  2. 요청자에게 응답 메시지를 전달한다

HTTP/1.1 200 OK

<html>주문 완료</html>
  1. 결과(주문완료) 화면에서 새로고침
  • 마지막 요청이 POST 요청이였으므로 현재 창에서 새로고침을 하게 되면 POST요청이 중복해서 더 들어가게 된다

따라서, 이러한 중복 주문 등을 막아놔야한다. 서버에서도, 클라이언트에서도

-> PRG, 일시적 리다이렉션에서 많이 사용하는 패턴

  • POST로 주문후에 새로고침으로 인한 중복 주문 방지
  • POST로 주문후에 주문 결과 화면을 GET 메서드로 리다이렉트
  • 새로고침해도 결과화면을 GET으로 조회할 뿐이다
  • 중복 주문 대신에 결과 화면만 GET으로 요청하게 된다

PRG 사용 후

  1. 주문을 한다 URL:/order
  • 요청 (html form등을 통해 전달된 데이터를 가지고)
POST /order HTTP/1.1
Host :localhost:8080

itemId=mouse&count=1
  1. 판매 사이트의 서버가 주문을 받아서 주문데이터를 저장한다. mouse 1개

  2. 요청자에게 응답 메시지를 전달한다

HTTP/1.1 302 Found // 기존 200 OK에서 변경되었다
Location: /order-result/orderId
  1. 요청 클라이언트는 응답메시지의 메서드가 302 일시적 리다이렉션을 확인하고 Location으로 리다이렉트한다

  2. 이때, 기존 요청 메시지에서 POST는 GET으로 변경어되서

GET /order-result/orderId HTTP/1.1
Host :localhost:8080

을 서버에 요청하게 된다

  1. 서버는 GET 메서드를 확인하고 주문 아이디의 주문데이터를 확인하고 해당 주문내역을 반환하게 된다
HTTP/1.1 200 OK

<html>주문완료</html>

연속적으로 새로고침을 하더라도 중복 주문의 위험이 존재하지 않게 된다

정리

  • 302 FOUND -> GET으로 (거의)변할 수 있다
  • 307 Temporary Redirect -> 메서드가 불변이다 (유지)
  • 303 See Other -> GET으로 변한다

초기에는 302의 메서드를 구상하면서 주어진 메서드를 그대로 유지하는 것이였으나, 웹브라우저 대부분이 GET으로 바꿔버렸다
이에 따라, 명확한 307, 303이 등장했다

301의 메서드 또한 302와 동일하고 이에 대한 보완으로 308이 등장

  • 모호성이 없는 307(안바뀜), 303(바뀜)을 사용하기를 권장하지만 이미 많은 애플리케이션 라이브러리들이 302를 기본값으로 사용한다
  • 자동 리다이렉션시에 GET으로 변해도 무방하다면 302를 사용해도 상관이 없다

기타 리다이렉션 300, 304

  • 300 Multiple Choices
    • 사용하지 않는다
  • 304 Not Modified
    • 캐시를 목적으로 사용한다
    • 클라이언트에게 리소스가 변경(수정)되지 않았음을 알려준다. 따라서 클라이언트는 로컬PC에 저장된 캐시를 재사용하게 된다 (캐시로 리다이렉트 한다)
    • 304 응답은 응답에 메시지 바디를 포함 하면 안된다
      (로컬 캐시를 사용하라는 것이므로)
    • 조건부 GET, HEAD 요청시 사용한다

클라에서 웹 창을 새로고침을 하게 되었을 때, 변경된게 없다면 304 Not Modified를 응답하게 되고 이를 받은 웹브라우저는 캐시 메모리에서 리다이렉트하게 된다 (서버에서 새로 다운 받는게 아니므로 매우 빠르다 - 웹을 켜놓고 연속으로 새로고침을 누를때와 종료 후 새로 키는 차이)


4xx (Client Error)

  • 클라이언트의 요청에 잘못된 문법등으로 서버가 요청을 수행할 수 없는 경우
  • 오류의 원인이 클라이언트에 있다
  • 클라이언트가 이미 잘못된 요청, 데이터를 보내고 있으므로, 똑같은 재시도를 해도 계속 실패한다 (수정이 필요)

400 Bad Request

클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없는 경우

  • 요청구문, 메시지 등등의 오류
    • 요청 파라미터가 잘못되거나, API 스펙이 맞지 않을 때
    • 서버는 이러한 요청을 잘 걸러서 거절해줘야 한다
  • 클라이언트는 요청 내용을 다시 검토하고 보내야한다

401 Unauthorize

클라이언트가 해당 리소스에 대한 인증이 필요하다

  • 인증(Authentication)되지 않음
  • 401 오류 발생시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명한다

용어참고

  • 인증 (Authentication) : 본인이 누구인지 확인하는 것 (로그인)
  • 인가 (Authorization) : 권한 부여 (ADMIN 권한 처럼 특정 리소스에 접근할 수 있는 권한, 먼저 인증이 있어야 인가가 있다)
  • 오류 메시지가 Unauthorized이지만 의미는 인증이 되지 않음이다 (단어로는 Unauthentication이 인증되지 않았다는 뜻)

403 Forbidden

서버가 요청을 이해했지만 승인을 거부한 경우

  • 주로 인증(Authentication) 자격 증명은 있지만, 접근 권한이 불충분한 경우에 발생한다
    • 예) Admin 등급이 아닌 사용자가 로그인 했지만, Admin 등급의 리소스에 접근하는 경우

404 Not Found

요청 리소스를 찾을 수 없음

  • 요청 리소스가 서버에 없는 경우 (URL을 잘못 치거나, 잘못된 요청을 한 경우)
  • 또는 클라이언트가 권한이 부족한 리소스에 접근했지만 해당 리소스를 숨기고 싶을 때 (존재 여부자체를 가리고싶어서 서버에서 그렇게 설정한 경우)

5xx (Server Error)

  • 서버 문제로 오류 발생
  • 서버에 문제가 있기 때문에 재시도하면 성공 할 수도 있다 (복구가 되면 된다)

500 (Interanl Server Error)

서버 내부 문제로 오류 발생, 애매할 경우 대부분 500오류

503 (Service Unavailable)

서비스 이용 불가

  • 서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리 할수 없는 경우
  • Retry-After헤더 필드로 얼마뒤에 복구되는지 보낼 수도 있다

참고

5xx대에러는 널포인터 Exception Error, DB에러, 서버에러, 등등 정말 시스템상으로 문제가 발생해서 셧다운이 되는 경우가 아니라면 웬만하면 5xx대 에러는 내면 안된다. 예를 들어 15세 이상 이용가능 서비스를 12세가 해당 서비스에 접근하는 경우 클라이언트 에러나 그외의 에러를 내야되고, 고객이 출금을하는데 보유 잔고보다 더 많은 금액을 출금시도하는 경우에도 마찬가지이다. 즉 서비스를 이용하는데 부적절한 접근의 경우에는 그에 맞는 에러를 내야지 서버에러를 내면 안된다. 서버에러는 실제적으로 백엔드상에서의 문제가 발생했을때만 내야한다

profile
내꿈은 숲속의잠자는공주

0개의 댓글