[웹을 지탱하는 기술] chp 8. Status Code

sameul__choi·2022년 4월 6일
0
post-thumbnail

HTTP는 요청/응답형 프로토콜이다. 모든 요청에는 응답이 돌아오고, 이 장에서는 요청의 응답으로 들어오는 스테이터스 코드에 의미에 대해 알아보자.

00 스테이터스 코드의 중요성

우리에게 친숙한 404, 500 등 이러한 숫자들은 클라이언트의 움직임을 좌우하는 중요한 역할을 담당하고 있다.

웹 서비스와 웹 API를 설계하는데 있어서 스테이터스 코드를 어떻게 선택하느냐는 중요하다. 응답에 잘못된 스테이터스 코드를 할당해 버리면 클라이언트가 혼동하여 시스템 전체의 동작에 지장을 초래하게 된다. 그러므로 스펙에서 정해진 스테이터스 코드의 의미를 바르게 이해해야 한다.

01 스테이터스 코드의 분류와 의미

HTTP 1.1의 스테이터스 코드는 RFC 2616에서 정의 되었다. 이 정의에서는 스테이터스 코드가 3자리의 숫자이고, 첫째 자리의 숫자에 따라 다음의 5가지로 분류한다고 기재되어 있다.

1xx : 처리중
처리가 계속 되고 있음을 나타내며 클라이언트는 그대로 요청을 계속하던지 서버의 지시에 따라 프로토콜을 업데이트하여 재전송한다.

2xx : 성공
요청이 성공했음을 나타낸다

3xx : 리다이렉트
다른 리소스로의 리다이렉트를 나타낸다. 클라이언트는 이 스테이터스 코드를 받았을 때 응답메세지의 Location 헤더를 보고 새로운 리소스로 접속한다.

4xx : 클라이언트 에러
클라이언트 에러를 나타낸다. 원인은 클라이언트의 요청에 있다. 에러를 해결하지 않으면 정상적인 결과를 얻을 수 없기 때문에 같ㅇ느 요청을 그대로 재전송할 수는 없다.

5xx : 서버 에러
서버에러이다. 원인은 서버에 있고 서버 측의 원인이 해결되면, 동일한 요청을 재전송하여 정상적인 결과를 얻을 가능성이 있다.

이처럼 첫 번째 숫자를 분류함으로써, 클라이언트는 우선 그 숫자를 보고 서버가 어떤 응답을 보낸 것인지 이해할 수 있으며, 클라이언트 측에서 어떻게 처리해야 할 지 대략 알수 있게 된다.

첫 번째 숫자를 이용한 분류 방식은 클라이언트와 서버 간의 약속을 최소한으로 억제하고 클라이언트와 서버의 결합을 가능한 한 완화하기 위해, 즉 소결합을 위해 고안된 것이다.

이를 통해 독립성이 높아지고, 컴포넌트 치환이나 확장이 용이해진다. HTTP로 말하자면, 컴포넌트란 서버와 클라이언트를 말한다. 다시 말해 서버의 버전업이나 클라이언트의 치환을 수행하기 쉬워진다는 것이다.

02 자주 사용되는 스테이터스 코드

우리는 가장 많이 사용되는 스테이터스 코드 9개를 살펴볼 것이다. 이 스테이터스 코드들은 빈번하게 사용되기 때문에 암기 하는 것이 좋다. 스테이터스 코드의 목록은 IANA가 관리하고 있다.

200 OK - 요청 성공

200OK는 요청이 성공했다는것을 말한다. GET의 경우는 바디에 리소스의 표현이 들어간다. PUT과 POST의 경우는 바디에 처리결과가 들어 간다.

201 Created - 리소스 작성 성공

201 Created는 리소스를 새로 작성했다는 것을 나타낸다. POST와 PUT에 대한 응답으로서 반환된다. 응답 바디에는 관습적으로 새로 작성한 리소스의 표현을 넣는 일이 많은데, 아무것도 넣지 않아도 상관 없긴 하다.

POST의 경우, 새로 작성한 리소스의 URI는 응답 메세지의 Location 헤더에 절대URI로서 들어간다.

PUT의 경우엔 클라이언트가 새로운 리소스의 URI를 이미 알고 있으므로 Location 헤더는 들어가지 않는다.

301 Moved Permanently - 리소스의 항구적인 이동

301은 요청에서 지정한 리소스를 새로운 URI로 이동했다는 것을 의미한다. 예전 URI를 계속 유지하면서 새로운 URI로 이동할 때 이 스테이터스 코드를 이용한다. 새로운 URI는 응답의 Location 헤더에 절대 URI로 들어간다.

303 See Other - 다른 URI의 참조

303은 리다이렉트에 대한 처리 결과를 다른 URI로 취득할 수 있음을 나타낸다. 전형적으로는 브라우저에서 POST로 리소스를 조작한 결과를 GET으로 가져올 때 사용한다.

400 Bad Request - 요청 오류

400은 요청 구문이나 파라미터가 잘못되었다는 것을 나타낸다.

400은 그 밖에 적절한 클라이언트 에러를 나타내는 스테이터스 코드가 없는 경우에도 사용한다. 또한 클라이언트가 모르는 4xx 계열 스테이터스 코드가 반환된 경우, 400 과 같은 처리를 하도록 스펙으로 정해져 있다.

401 Unauthorized - 접근 권한 없음, 인증 실패

401은 적절한 인증정보를 부여하지 않은채 리다이렉트를 수행했다는 것을 나타낸다.

404 Not Found - 리소스 없음

404는 지정한 리소스를 찾을 수 없다는 것을 나타낸다. 응답 바디에는 그 이유가 들어간다.

500 Internal Server Error - 서버 내부 에러

500은 서버 측에 무엇인가 이상이 발생, 정상적인 응답을 보낼 수 없다는 것을 나타낸다. 응답 바디에는 이상의 이유가 들어간다.

500은 다른 적절한 서버 에러를 나타내는 스테이터스 코드가 없는 경우에도 사용하며 클라이언트가 알지 못하는 5xx 계열이 스테이터스 코드가 반환된 경우, 500과 같은 동작을 처리하도록 스펙으로 정해져 있다.

503 Service Unavailable - 서비스 정지

503은 서버가 점검 등 일시적으로 액세스 할 수 없다는 것을 보여준다. 응답 바디에는 그 이유가 들어가고 응답의 Retry-After 헤더로 서비스 재개 시기가 대략 몇 십 초 후인지 통지 할 수 있다.

03 스테이터스 코드와 에러처리

4xx계와 5xx계의 스테이터스 코드는 모두 에러를 표현한다. 에러 코드는 HTTP 스펙에 규정되어 있지만 바디에 어떤 에러 메시지가 들어가는지에 대해서는 규정되어 있지 않다.

보통 웹 서비스에서 404 Not Found면, '지정한 페이지를 찾을 수 없다.'라는 메세지가 들어간 HTML을 바디에 추가하는 것이 일반적이다.

사람을 대상으로 한 웹 서비스의 경우에는 에러 메시지가 HTML이라도 아무 문제 없지만 프로그램용 웹 API의 경우에는 주의가 필요하다. 그 클라이언트가 반드시 HTML을 해석할 수 있다고 단정할 수 없기 때문이다. 웹 API인 경우는 클라이언트가 해석할 수 있는 형식으로 에러 메세지를 반환해 주는 것이 좋겠다.

04 스테이터스 코드의 오용

웹 서비스에서든 웹 API에서든 HTTP의 스테이터스 코드를 바르게 사용하는 것은 최소한의 매너이다. 하지만 일부 웹 서비스나 웹 API에서는 에러를 200 OK로 반환하는 경우가 있다. 파일을 찾을 수 없다는 에러를 200으로 때리면 이 XML 형식을 모르는 클라이언트는 200을 믿고 정상결과로서 바디를 표시한다. 이 에러를 웹 API 측의 의도대로 처리하기 위해서는 전용 클라이언트를 구현해야 하기 때문에 다양한 클라이언트에서 이용할 수 있다는 웹 API의 특징을 훼손하게 된다. 웹 서비스의 경우도 404 Not Found로 반환해야할 정보를 200으로 반환하면 정식 리소스로 착각하고 인덱스 처리가 수행되어 버리는 등 문제가 발생할 가능성이 있다.

05 스테이터스 코드를 의식해서 설계한다

스테이터스 코드는 크게 5 종류로 분류할 수 있으며 각각 의미가 있다. 스테이터스 코드는 스펙에 의해 고정되어 있기 때문에 임의로 추가할 수는 없다. 중요한 것은 스테이터스 코드를 바르게 사용하는 것이다. 중요한 것은 스테이터스 코드를 바르게 사용하는 것이다. 개발 중인 웹 서비스나 웹 API에서 에러가 발생했을 때, 어떤 스테이터스 코드를 반환할지 결정하는 것은 아주 중요한 설계 검토사항이다.

스테이터스 코드의 구현

서블릿의 경우
서블릿으로 웹 서비스와 웹 API를 구현할 경우는 HttpServletResponse 클래스의 setStatus() 메서드와 setError() 메서드를 사용하여 스테이터스 코드를 설정한다. 단, 수치를 하드코딩하게 되면 소스코드를 이해하기 힘들어진다. 각 스테이터스 코드는 HttpServletResponse의 상수 필드로서 SC_OK(200)이나, SC_NOT_FOUND(404)와 같이 정의되어 있으므로 이것들을 사용하는 편이 좋다.

0개의 댓글