layout: post
title: "웹을 지탱하는 기술 스터디 - Chapter8"
date: 2022-04-08T00:00:00-00:00
author: sangyeop
categories: Sproutt-2nd
응답에 잘못된 스테이터스 코드를 할당하면 클라이언트가 혼동하여 시스템 전체 동작에 지장을 초래하기 때문에 스테이터스 코드를 바르게 이해하는 것이 중요하다.
응답 메시지의 첫째 줄에 있는 스테이터스 라인은 프로토콜 버전, 스테이터스 코드, 텍스트 프레이즈로 이루어진다.
Http/1.1 200 OK
여기서 200
이 스테이터스 코드가 된다. 텍스트 프레이즈는 사람이 읽을 수 있도록 표기한 것이기 때문에, 이외의 문구도 들어갈 수 있다.
스테이터스 코드는 3자리 숫자이며, 첫째 자리 숫자에 따라 5가지로 분류된다.
status code | description |
---|---|
1xx : 처리중 | 처리가 계속되고 있음을 나타낸다. 클라이언트는 그대로 요청을 계속하던지 서버의 지시에 따라 프로토콜을 업데이트 하여 재전송한다. |
2xx : 성공 | 요청이 성공했음을 나타낸다 |
3xx : 리다이렉트 | 다른 리소스로 리다이렉트를 나타낸다. 클라이언트는 이 스테이터스 코드를 받았을 때 응답메시지의 Location 헤더를 보고 새로운 리소스로 접속한다. |
4xx : 클라이언트 에러 | 클라이언트 에러를 나타낸다. 원인은 클라이언트의 요청에 있다. 에러를 해결하지 않는 한, 정상적인 결과를 얻을 수 없기 때문에 같은 요청을 그대로 재전송할 수는 없다. |
5xx : 서버 에러 | 서버 에러를 나타낸다. 원인이 서버에 있다. 서버 측의 원인이 해결되면, 동일한 요청을 재전송해서 정상적인 결과를 얻을 가능성이 있다. |
이런식의 분류는 클라이언트와 서버 간의 약속을 최소한으로 억제하고 클라이언트와 서버의 결합을 가능한 한 완화하기 위해 고안된 것이다. 이를 소결합이라고 한다.
또한 추후에 새롭게 추가된 스테이터스 코드를 잘 알지 못하더라도 처음 숫자의 약속만 지켜진다면 최소한의 처리가 가능하기 때문에 매우 용이하다.
요청이 성공했음을 나타낸다. GET
의 경우에는 바디에 리소스의 표현이 들어간다.
GET
요청GET /test HTTP/1.1
Host:example.com
GET
응답HTTP/1.1 200 OK
Content-Type:text/plain; charset=utf-u8
Hello, World!
PUT
과 POST
의 경우에는 바디에 처리 결과가 들어간다.
PUT
요청PUT /test HTTP/1.1
Host:example.com
Content-Type:text/plain; charset=utf-8
안녕하세요!
PUT
응답HTTP/1.1 200 OK
Content-Type:text/plain; charset=utf-8
안녕하세요!
리소스를 새로 작성했다는 것을 나타낸다. POST
와 PUT
에 대한 응답으로서 반환된다.
POST
의 경우, 새로 작성한 리소스 URI는 응답 메시지의 Location 헤더에 절대 URI로 들어간다.
POST
요청POST /list HTTP/1.1
Host:example.com
Content-Type:text/plain; charset=utf-8
안녕하세요!
POST
응답HTTP/1.1 201 Created
Location:http://example.com/list/item1
Content-Type:text/plain; charset=utf-8
안녕하세요!
PUT
의 경우 클라이언트가 새로운 리소스 URI를 이미 알고 있으므로 Location 헤더는 들어가지 않는다.
PUT
요청PUT /newitem HTTP/1.1
Host:example.com
Content-Type:text/plain; charset=utf-8
안녕하세요!
PUT
응답HTTP/1.1 201 Created
Content-Type:text/plain; charset=utf-8
안녕하세요!
지정한 리소스를 새로운 URI로 이동했음을 나타낸다. 예전 URI를 유지하면서 새로운 URI로 이동할 때 이 코드를 사용한다.
다른 URI로 클라이언트가 자동적으로 재접속하는 처리를 리다이렉트라고 부른다.
리다이렉트에 대한 처리결과를 다른 URI로 취득할 수 있음을 나타낸다. 보통 브라우저에서 POST
로 리소스를 조작한 결과를 GET
으로 가져올 때 사용한다.
POST
요청 - 리소스 조작POST /login HTTP/1.1
Host:example.com
Content-Type:application/x-www-form-urlencoded
username=yohei&password=foobar
HTTP/1.1 303 See Other
..
..
..
요청 구문이나 파라미터가 잘못되었음을 나타낸다. 그 밖에 적절한 클라이언트 에러를 나타내는 코드가 없을 경우에도 사용 되며, 클라이언트가 모르는 4xx 계열 스테이터스 코드가 반환된 경우 400 Bad Request
와 같은 처리를 하도록 규정이 되어있다.
적절한 인증정보를 부여하지 않은 채 리다이렉트를 수행했음을 나타낸다. 응답의 WWW-Authenticate
헤더에서 클라이언트에 대해 인증방식을 전달한다.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="example.com"
지정한 리소스를 찾을 수 없음을 나타낸다. 응답 바디에는 그 이유가 들어간다.
HTTP/1.1 404 Not Found
Content-Type:text/plain; charset=utf-8
http://example.com/test를 찾을 수 없습니다.
서버 측에 무엇인가 이상이 발생해서 정상적인 응답을 보낼 수 없음을 나타낸다. 응답 바디에는 그 이유가 들어간다.
HTTP/1.1 500 Internal Server Error
Content-Type:text/plain; charset=utf-8
서버에 이상이 발생했습니다. 잠시 후 다시 접속해 주십시오.
다른 적절한 서버 에러를 나타내는 스테이터스 코드가 없을 경우, 클라이언트가 알지 못하는 5xx
계열이 반환된 경우 500 Internal Server Error
와 같은 동작을 처리하도록 스펙으로 정해져 있다.
서버가 점검 등으로 일시적으로 액세스 할 수 없음을 나타낸다. 응답 바디에는 그 이유가 들어간다. Retry-After
헤더로 서비스 재개 시기가 대략 몇 십 초 후인지 통지 할 수 있다.
HTTP/1.1 503 Service Unavailable
Content-Type:text/plain; charset=utf-8
Retry-After:3600
지금은 점검 중입니다. 잠시 후 다시 접속해 주십시오.
프로그램용 웹 API인 경우에는 클라이언트가 반드시 HTML을 해석할 수 있다고 단정할 수 없기 때문에, 웹 API는 클라이언트가 해석할 수 있는 형식으로 에러 메시지를 반환해 주어야 한다.
예를 들면 AtomPub
클라이언트의 경우 Atom
형식이라면 해석할 수 있기 때문에 AtomPub
을 이용한 웹 API의 경우에는 에러 메시지는 Atom
으로 반환하는 것이 한 방법이다.
HTML
반환하는 경우Accept: application/xhtml+xml:q=0.9, text/plain:q=0.3
Atom
반환하는 경우Accept: application/atom+xml:q=0.9, text/plain:q=0.3
웹 서비스의 경우에 404 Not Found
로 반환해야할 정보를 200 OK
로 반환하면 검색 엔진 로봇이 정식 리소스로 착각하고 인덱스 처리가 수행되어 버리는 등의 문제가 발생할 가능성이 있다.
스테이터스 코드 중에서 4xx
에러는 다른 계열에 비해 코드의 종류가 많다. 이는 다양한 종류의 클라이언트 에러가 존재한다는 것을 의미한다.
스테이터스 코드는 스펙에 고정되어 있기 때문에 새로이 추가할 수 는 없다. 개발 중인 웹 서비스 웹 API에서 에러가 발생했을 때, 어떤 스테이터스 코드를 반환할지 결정하는 것은 아주 중요한 설계 검토사항이다.
스테이터스 코드의 구현
Apache
정적인 파일을 보내는 경우, 보내는 파일의 조건에 따라 자동적으로 스테이터스 코드가 결정된다
서블릿
HttpServletResponse
클래스의setStatus()
와setError()
메서드를 이용해 스테이터스 코드를 설정한다Ruby on Rails
컨트롤러에서
render
메서드를 사용해 결과를 렌더링 할 때 인수로 스테이터스 코드 값을 전달한다.