[HTTP_NETWORK] HTTP 메시지와 HTTP 상태코드
업데이트:
이번 시간에는 HTTP 메시지, HTTP 상태코드에 대해 알아보자.
1. HTTP 메시지
HTTP에서 교환하는 정보는 HTTP 메시지라 한다. HTTP 메시지는 복수 개행(개행 문자는 CR+LF)의 데이터로 구성된 텍스트 문자열이다. HTTP 메시지는 크게 나누면 메시지 헤더와 메시지 바디로 나눌 수 있고, 최초에 나타나는 개행문자(CR+LF)로 메시지 헤더와 메시지 바디를 구분한다.
2. Request 메시지와 Response 메시지의 헤더
Request 메시지와 Response 메시지는 조금 차이가 있다. 구조를 살펴보면 다음과 같다.
1) Request 메시지 헤더
- 리퀘스트 라인
- 리퀘스트 헤더 필드
- 일반 헤더 필드
- 엔티티 헤더 필드
- 그 외
2) Response 메시지 헤더
- 상태 라인
- 리스폰스 헤더 필드
- 일반 헤더 필드
- 엔티티 헤더 필드
- 그 외
리퀘스트 라인은 리퀘스트에 사용하는 메소드와 리퀘스트 URI, 사용하는 HTTP 버전이 포함된다.
상태 라인은 리스폰스 결과를 나타내는 상태 코드와 설명, 사용하는 HTTP 버전이 포함된다.
헤더 필드는 리퀘스트와 리스폰스의 여러 조건과 속성 등을 나타내는 각종 헤더 필드가 포함된다. 일반 헤더, 리퀘스트 헤더, 리스폰스 헤더, 엔티티 헤더 등 4종류로 이루어져 있다.
3. 전송 효율을 높이기 위한 인코딩
데이터를 그대로 보내는 것보다 변환하거나 압축, 분할해서 보는게 더 효율적일 것이다.
HTTP로 데이터를 전송하는 경우 그대로 전송하는것보다 인코딩(변환)을 해서 전송함으로써 효율을 높일 수 있다. 단, 컴퓨터에서 인코딩 처리를 해야하기 때문에 CPU 등의 리소스는 더 많이 소비하게 된다.
메일을 보낼 때 파일을 압축해서 보내는 것처럼 HTTP에도 이와 같은 기능이 있다. 바로 콘텐츠 코딩이다. 콘텐츠 코딩은 엔티티에 적용하는 인코딩을 가리키는데 엔티티 정보를 유지한채로 압축한다. 콘텐츠 코딩된 엔티티는 수신한 클라이언트 측에서 디코딩한다. 주로 gzip, compress, deflate, identity 등이 있다.
HTTP 통신에서는 리퀘스트 보낸 리소스 전부에서 엔티티 바디의 전송이 완료되지 않으면 브라우저에 표시되지 않는다. 사이즈가 큰 데이터를 전송하는 경우 데이터를 분할해서 조금씩 표시할 수 있는데, 이렇게 엔티티 바디를 분할하는 기능을 청크 전송 코딩이라고 부른다. 이 역시 수신한 클라이언트 측에서 원래의 엔티티 바디로 디코딩한다.
4. 여러 데이터를 보내기 위한 멀티파트
메일의 경우 본문이나 복수의 첨부 파일을 붙여 함께 보낼 수 있는데, 이는 MIME(Multipurpose Internet Mail Extensions)으로 불리는 여러 다른 데이터를 다루기 위한 기능을 사용한다. 멀티 파트에 대한 자세한 내용은 RFC2046을 참고해보자.
5. 일부만 받는 레인지 리퀘스트
데이터 용량이 큰 경우 이는 중간에 커넥션이 끊어지면 처음부터 다시 다운로드를 해야 한다. 이러한 문제를 해결하기 위해 엔티티의 범위를 지정해서 다운로드를 할 필요가 있는데 이와 같이 리퀘스트 하는 것을 레인지 리퀘스트라 한다.
Range 헤더 필드를 사용해서 리소스의 바이트 레인지를 지정하면 상태코드 206 Partial Content 라는 리스폰스 메시지가 돌아온다. 또한 복수의 레인지 리퀘스트에 대한 리스폰스는 multipart/byteranges로 리스폰스가 돌아온다. 서버가 레인지 리퀘스트를 지원하지 않는 경우 200 OK라는 리스폰스 메시지로 완전한 엔티티가 반환된다.
6. 네고시에이션
같은 콘텐츠지만 여러 개의 페이지를 지닌 웹 페이지가 있다. 예를 들어 영어판과 한국어 같이 서로 다른 언어를 사용하는 브라우저가 같은 URI에 접근할 때 각각 영어판과 한국어판을 표시한다. 이와 같은 구조를 콘텐츠 네고시에이션이라 부른다.
콘텐츠 네고시에이션이란 클라이언트에 더욱 적합한 리소스를 제공하기 위한 구조다. 콘텐츠 네고시에이션에는 다음과 같은 것들이 있다.
- 서버 구동형 네고시에이션. 서버 측에서 리퀘스트 헤더 필드의 정보를 참고해서 자동적으로 처리. 브라우저 정보를 근거로 하기 때문에 정말 적절한것인지는 알 수 없음
- 에이전트 구동형 네고시에이션. 클라이언트 측에서 콘텐츠 네고시에이션을 하는 방식. 브라우저에 표시된 선택지 중 유저가 수동으로 선택.
- 트랜스페어런트 네고시에이션. 서버 구동형과 에이전트 구동형을 혼합한 것으로 서버와 클라이언트가 각각 콘텐츠 네고시에이션을 하는 방식.
7. HTTP 상태 코드
클라이언트가 리퀘스트를 보낼 때 서버에서 그 결과가 어떻게 되었는지 알려주는 것이 상태코드의 역할이다. 서버가 리퀘스트를 정상적으로 처리했는지, 아니면 에러였는지를 알 수 있게 해준다.
상태 코드는 다음과 같이 5개가 정의되어 있다.
1xx : Informational. 리퀘스트를 받아들여 처리중
2xx : Success. 리퀘스트를 정상적으로 처리했음
3xx : Redirection. 리퀘스트를 완료하기 위해 추가 동작이 필요
4xx : Client Error. 서버에서 리퀘스트 이해 불가
5xx : Server Error. 서버에서 리퀘스트 처리 실패
1) 2xx 성공(Success)
- 200 OK : 클라이언트가 보낸 리퀘스트를 서버가 정상 처리하였음
- 204 No Content : 서버가 리퀘스트를 받아서 처리하는데 성공했지만 리스폰스에 엔티티 바디를 포함하지 않음. 따라서 204 리스폰스를 받는 경우 표시되어있는 웹 페이지가 변경되는 일은 없음.
- 206 Partial Content : Range에 의해 범위가 지정된 리퀘스트에 의해 서버가 부분적 리퀘스트를 받았음을 의미. 리스폰스에는 Content-Range로 지정된 범위의 엔티티가 포함
2) 3xx 리다이렉트(Redirection)
- 301 Moved Permanently : 리퀘스트된 리소스에는 새로운 URI가 부여되었으므로 이후로는 해당 리소스를 참조하는 URI를 사용해야 함을 나타낸다.
- 302 Found : 리퀘스트된 리소스에는 새로운 URI가 할당되었으므로 그 URI를 참조해주길 바란다는 의미. 301과 비슷하지만 302는 영구적인 이동이 아닌 일시적인 것을 의미.
-
303 See Other : 리퀘스트에 대한 리소스가 다른 URI에 있기 때문에 GET 메소드를 통해 얻어야 한다는 것을 의미. 302 와 같은 기능이지만 리다이렉트 장소를 GET 메소드로 얻어야 한다고 명확하게 되어있다는 점이 다름
- 304 Not Modified : 클라이언트가 조건부 리퀘스트를 보내는 경우 리소스에 대한 액세스는 허락하지만, 조건이 충족되지 않았음을 의미. 304는 3xx에 분류되어 있지만 리다이렉트와는 관계가 없음
- 307 Temporary Redirect : 302 와 같은 의미를 지니지만 307은 브라우저 사양에 따라 POST를 GET으로 치환하지 않음.
301, 302, 303 리스폰스 코드가 돌아오면 대부분의 브라우저에서는 POST를 GET으로 바꾸어 리퀘스트 엔티티 바디를 삭제하고 자동적으로 재송신 하도록 되어있다. 반면 307은 치환하지 않는다.
3) 4xx 클라이언트 에러(Client Error)
- 400 Bad Request : 리퀘스트 구문이 잘못되었음을 나타낸다. 브라우저는 이것을 200 OK와 같이 취급한다.
- 401 Unauthorized : 리퀘스트에 HTTP 인증 정보가 필요하다는 것을 나타낸다. 또한 이미 1번 리퀘스트가 이뤄진 경우 유저 인증에 실패했음을 나타낸다.
- 403 Forbidden : 리퀘스트된 리소스의 액세스가 거부되었음을 나타낸다. 서버 측은 거부 이유를 엔티티 바디에 기재해서 유저 측에 표시한다.
- 404 Not Found : 리퀘스트한 리소스가 서버상에 없다는 것을 나타낸다. 그 외에도 서버 측에서 해당 리퀘스트를 거부하고 싶은 이유를 분명히 하고싶지 않은 경우에도 이용할 수 있다
4) 5xx 서버 에러(Server Error)
- 500 Internal Server Error : 서버에서 리퀘스트 처리 도중 에러가 발생하였음을 나타낸다.
- 503 Service Unavaliable : 일시적으로 서버가 과부하 상태이거나 현재 리퀘스트를 처리할 수 없음을 나타낸다. 이 상태가 해소되기까지 시간이 걸리는 경우 Retry-After 헤더 필드에 따라 클라이언트에 전달하는것이 바람직하다.
상태 코드는 현재 상황과 불일치 할 수도 있다. 흔히 있는 상황으로 웹 애플리케이션에서 애플리케이션 에러가 발생한 경우에도 상태 코드는 200 OK 로 돌아오기도 한다.