상태 코드
요청을 받은 쪽이 처리 결과를 미리 정해둔 값 하나로 돌려주는 것입니다. 받는 쪽 프로그램은 그 값만 보고 다음에 무엇을 할지 정합니다. 값 옆에는 사람이 읽으라고 짧은 문장이 따라붙습니다.
쉽고 빠른 이해
요청을 처리한 쪽이 결과를 정해진 값 하나로 돌려주는 것입니다. 웹 페이지 요청이 성공하면 200 이라는 값이 돌아옵니다.
결과를 사람이 읽는 문장으로만 돌려주면 받는 프로그램이 매번 그 문장을 뜯어서 성공인지 실패인지 알아내야 합니다. 문장은 구현마다 다르게 적힐 수 있어 믿고 비교할 수 없습니다. 그래서 기계가 보는 값과 사람이 보는 문장을 갈라 붙였습니다.
이렇게 돕습니다.
- 받는 쪽은 값 하나만 보고 다음 행동을 정합니다. 문장까지 뜯어볼 필요가 없습니다
- 값의 첫 자리가 부류를 정해서, 처음 보는 값을 받아도 그 부류로 처리할 수 있습니다
- 값 옆의 문장은 사람이 참고만 하고, 판단 근거로는 값만 씁니다
대가로 옆에 붙는 문장은 구현마다 다르게 적힐 수 있어 정보로 믿고 쓸 수 없습니다.
상세
처음 가보는 건물에서 307호로 오라는 말을 들으면, 그 방을 한 번도 본 적 없어도 엘리베이터에서 3층을 누릅니다. 앞자리가 층이라는 것만 알면 그 방이 무슨 방인지는 올라가서 알아도 됩니다. 그 층에 방이 몇 개 더 생겨도 찾아가는 방법은 그대로입니다.
상태 코드는 요청을 처리한 쪽이 그 결과를 미리 약속된 값 하나로 알려주는 값입니다. 값은 짧은 정수나 이름이라 받는 쪽이 응답 내용을 뜯어보지 않고 이 값만으로 분기할 수 있습니다. 무엇이 성공이고 무엇이 실패인지를 요청마다 새로 약속할 필요가 없어집니다.
값과 설명 문장은 자리가 다릅니다. 값은 기계가 읽습니다. 그 옆의 문장은 사람이 읽습니다. 같은 값에도 문장은 구현마다 다르게 적힐 수 있습니다. 그래서 받는 쪽은 문장이 아니라 값을 판단 근거로 삼습니다.
세 자리 값을 쓰는 체계에서는 값이 낱개로 흩어져 있지 않고 부류로 묶입니다. 부류가 "이 응답을 어떻게 다뤄야 하는가" 를 정합니다. 그래서 받는 쪽이 모르는 값을 만나도 그 값이 속한 부류만 보고 처리할 수 있습니다. 나중에 새 값이 늘어나도 이미 나가 있는 프로그램이 곧바로 깨지지 않는 것은 이 규칙 덕분입니다.
배경
결과를 사람이 읽는 문장으로만 돌려주면, 받는 쪽 프로그램은 성공인지 실패인지 알아내려고 그 문장을 뜯어야 합니다. 문장은 같은 뜻이라도 표현이 갈립니다. 서버마다 다르게 적히기도 합니다. 그러면 받는 쪽이 문자열 비교에 매달리게 됩니다.
그래서 기계가 읽는 값과 사람이 읽는 문장을 갈라 붙였습니다. RFC(Request for Comments) 959 는 FTP(File Transfer Protocol) 응답의 모양을 적습니다. 세 자리 숫자와 그 뒤의 문장으로 이루어집니다. 숫자는 자동 장치가 다음에 어떤 상태로 갈지 정하는 데 쓰라는 것입니다. 문장은 사람 사용자를 위한 것이라고 못 박습니다.
같은 문서는 세 자리 안에 정보가 충분히 담기도록 의도했다고 적습니다. 사용자 프로세스가 문장을 살펴볼 필요가 없게 하려던 것입니다. 문장은 서버마다 달라질 수 있습니다. 그래서 상태 코드 하나에 여러 문장이 붙기 쉽다고 덧붙입니다.
세 자리가 각각 다른 몫을 지는 것도 여기서 정해졌습니다. 첫 자리는 응답이 성공인지 실패인지 아니면 아직 안 끝났는지를 가릅니다. 둘째 자리는 어떤 종류의 오류인지를 담습니다. 셋째 자리는 가장 잘게 나눈 정보를 담습니다.
같은 꼴이 웹으로 이어졌습니다. RFC 1945 는 HTTP(HyperText Transfer Protocol)/1.0 의 응답을 두 부분으로 나눠 정의합니다. 세 자리 정수인 Status-Code, 그리고 앞서 말한 값 옆의 문장을 가리키는 Reason-Phrase 입니다. Status-Code 는 자동 장치를 위한 것입니다. Reason-Phrase 는 사람 사용자를 위한 것입니다. 클라이언트는 Reason-Phrase 를 살펴보거나 표시할 의무가 없다고 적혀 있습니다. 뒤에 나온 RFC 9112 는 이 문장 자리가 왜 아직 남아 있는지를 밝힙니다. 대화형 텍스트 클라이언트와 함께 더 자주 쓰이던 앞선 인터넷 응용 프로토콜에 대한 예우가 주된 이유라고 적습니다.
갈래
값의 첫 자리가 부류를 정합니다. 부류는 받는 쪽의 다음 행동을 정합니다. 이것이 갈리는 축입니다. 다만 첫 자리를 쓰지 않는 체계도 있습니다. gRPC 처럼 값마다 이름을 붙이는 방식입니다.
| 첫 자리 | HTTP · RFC 9110 | FTP · RFC 959 |
|---|---|---|
| 1 | Informational — 요청을 받았고 처리가 이어집니다 | Positive Preliminary — 동작을 시작했고 다음 응답이 또 옵니다 |
| 2 | Successful — 요청을 받아 이해하고 받아들였습니다 | Positive Completion — 동작을 끝냈습니다. 새 요청을 보내도 됩니다 |
| 3 | Redirection — 요청을 끝내려면 동작이 더 필요합니다 | Positive Intermediate — 명령은 받아들였지만 정보가 더 올 때까지 보류입니다 |
| 4 | Client Error — 요청 구문이 잘못됐거나 들어줄 수 없습니다 | Transient Negative Completion — 받아들이지 않았지만 오류가 일시적이라 다시 요청할 수 있습니다 |
| 5 | Server Error — 유효해 보이는 요청을 서버가 들어주지 못했습니다 | Permanent Negative Completion — 받아들이지 않았습니다. 같은 요청을 되풀이하지 말기를 권합니다 |
HTTP 다섯 부류
유효한 값은 100 부터 599 까지입니다. 첫 자리가 응답의 부류를 정하고 나머지 두 자리는 분류 역할을 하지 않습니다. RFC 9110 은 상태 코드를 세 자리 정수로, 요청의 결과와 응답의 의미를 설명하는 값으로 정의합니다.
값은 나중에 늘릴 수 있습니다. 클라이언트가 등록된 모든 상태 코드의 뜻을 이해할 필요는 없다고 적혀 있습니다. 그렇게 이해하는 편이 분명 바람직하다고 덧붙입니다. 다만 반드시 이해해야 하는 것은 첫 자리가 가리키는 부류라고 못 박습니다. 모르는 값을 받으면 첫 자리는 그대로 두고 나머지 두 자리를 0 으로 채운 값을 받은 것처럼 다뤄야 합니다. 이 값의 첫 자리가 무엇이든 상관없다는 뜻으로 자리표시 x 를 써서, 이 규칙을 x00 이라고 적습니다. 명세가 든 예가 471 입니다. 471 을 처음 보더라도 첫 자리에서 요청 쪽에 문제가 있었음을 알 수 있습니다. 400 Bad Request 를 받은 것처럼 다루면 됩니다.
FTP 다섯 부류
첫 자리 다섯 값의 뜻은 위 표와 같습니다. FTP 는 둘째 자리도 뜻을 갖습니다. 세 자리는 이렇게 각각 다른 몫을 집니다. 첫 자리는 부류, 둘째 자리는 기능 묶음, 셋째 자리는 그 안에서 가장 잘게 나눈 정보입니다. 여기서도 앞서 쓴 자리표시를 그대로 씁니다. 셋째 자리처럼 값이 상관없는 자리는 z 로 적습니다. 둘째 자리를 기준으로 x0z 는 구문, x1z 는 정보, x2z 는 연결, x3z 는 인증과 계정, x4z 는 아직 정하지 않은 자리, x5z 는 파일 시스템입니다.
| 자리 | 뜻 | 값 |
|---|---|---|
| 자리 1 | 부류 | 1~5 |
| 자리 2 | 기능 묶음 | 구문 · 정보 · 연결 · 인증과 계정 · 아직 정하지 않은 자리 · 파일 시스템 |
| 자리 3 | 세부 정보 | 가장 잘게 나눈 정보 |
첫 자리가 다섯 개로 갈린다는 모양은 같지만 가르는 축이 같지 않습니다. HTTP 는 4xx 와 5xx 를 요청한 쪽 잘못이냐 받은 쪽 잘못이냐로 가릅니다. FTP 는 둘째 자리에도 값이 상관없다는 자리표시를 씁니다. z 와 같은 뜻으로 y 를 씁니다. 그래서 4yz 와 5yz 를 일시적이냐 영구적이냐로 가릅니다. 같은 자리에 있는 숫자라고 같은 뜻으로 읽으면 어긋납니다.
gRPC 상태 코드
세 자리 정수만 쓰이는 것은 아닙니다. gRPC 는 값마다 이름이 붙은 작은 정수를 씁니다. OK 가 0, CANCELLED 가 1, NOT_FOUND 가 5, PERMISSION_DENIED 가 7 입니다. 공식 문서의 목록은 값과 이름과 설명을 나란히 적을 뿐, 첫 자리로 묶는 부류를 두지 않습니다.
예시
HTTP 상태줄
응답 메시지의 첫 줄이 상태줄입니다. RFC 9112 는 그 줄의 모양을 이렇게 적어 둡니다.
status-line = HTTP-version SP status-code SP [ reason-phrase ]
status-code = 3DIGIT
상태줄은 이렇게 세 조각으로 쪼개집니다.
flowchart TD
A["상태줄"] --> B["HTTP-version"]
A --> C["status-code · 3자리 정수"]
A --> D["reason-phrase · 있어도 되고 없어도 됨"]
실제로 오가는 응답은 이렇게 생겼습니다.
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain
200 이 상태 코드입니다. OK 가 Reason-Phrase, 그 옆의 문장입니다. 명세는 클라이언트가 이 문장의 내용을 무시하도록 권합니다. 믿을 만한 정보 통로가 아니기 때문입니다. 지역에 맞게 번역될 수 있습니다. 중계 장치가 덮어쓸 수 있습니다. 다른 판의 HTTP 로 전달될 때 버려질 수도 있습니다.
SMTP 응답 줄
SMTP(Simple Mail Transfer Protocol)도 같은 자리에 값을 실어 보냅니다. RFC 5321 이 든 예에서 C 는 보내는 쪽, S 는 서버입니다.
C: EXPN Example-People
S: 250-Jon Postel <Postel@isi.edu>
S: 250-Fred Fonebone <Fonebone@physics.foo-u.edu>
S: 250 Sam Q. Smith <SQSmith@specific.generic.com>
거절할 때는 다른 값이 옵니다.
C: EXPN Executive-Washroom-List
S: 550 Access Denied to You.
250 은 요청한 메일 동작을 끝냈다는 값입니다. 550 은 요청한 동작을 하지 않았다는 값입니다. 앞의 예는 여러 줄로 이어집니다. 이어지는 동안에는 값 뒤에 붙임표가 붙습니다. 250- 로 적힙니다. 마지막 줄만 250 으로 적혀 있습니다. 값은 같아도 줄이 더 남았는지가 이 자리에서 갈립니다.
관련 항목
웹에서 마주치는 값
HTTP 100 · HTTP 101 · HTTP 200 · HTTP 201 · HTTP 202 · HTTP 204 · HTTP 206 · HTTP 301 · HTTP 303 · HTTP 304 · HTTP 307 · HTTP 308 · HTTP 401 · HTTP 403 · HTTP 404 · HTTP 405 · HTTP 409 · HTTP 410 · HTTP 500 · HTTP 502 · HTTP 503 · HTTP 504
메일에서 마주치는 값
SMTP 211 · SMTP 220 · SMTP 221 · SMTP 250 · SMTP 354 · SMTP 421 · SMTP 450 · SMTP 500 · SMTP 502 · SMTP 550
값이 실리는 자리와 정해지는 표준
상태줄 · Reason-Phrase · Retry-After · IANA(Internet Assigned Numbers Authority, 인터넷 주소 할당 기관) · HTTP 상태 코드 레지스트리
이 값 체계를 저마다 정하는 프로토콜
다른 이름: status code · response code · 응답 코드