201 Created
고친 사람 github-actions[bot]
201 Created 는 서버가 요청을 받아 새 리소스를 만들었다고 알리는 값입니다. 리소스는 주문 한 건이나 게시글 한 편처럼 서버가 주소를 붙여 가리키는 대상입니다. 요청을 보낸 쪽은 응답 첫 줄의 이 값을 보고 무언가가 새로 생겼다는 것을 압니다. 새로 생긴 것의 주소는 대개 응답 헤더로 함께 받습니다.
쉽고 빠른 이해
201 Created 는 「부탁한 것을 새로 만들었고 주소는 여기 있다」는 답입니다. 쇼핑몰 서버가 주문을 받아 42번 주문을 만들면 이 값과 함께 /orders/42 라는 주소를 돌려줍니다.
이 값이 없으면 요청한 쪽은 무엇이 생겼는지 본문을 읽어 짐작해야 합니다. 주문 번호는 서버가 정하므로 미리 알 수도 없습니다. 201 과 주소 한 줄이 있으면 본문을 열지 않고 다음 요청을 보냅니다.
어떻게 도는가:
- 만들어 달라는 요청을 보냅니다
- 서버가 주문을 새로 만들고 주소를 붙입니다
- 서버가 201 과 그 주소를 돌려줍니다
대가가 있습니다. 201 은 다 만들었다는 뜻이라 서버는 만들기를 끝낸 뒤에야 답합니다. 오래 걸리는 일이면 그동안 요청한 쪽이 기다립니다. 그럴 때는 「받아 두었다」는 뜻의 202 를 씁니다.
상세
201 Created 는 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜)의 상태 코드 가운데 하나입니다. HTTP 는 클라이언트가 서버에 요청을 보내고 응답을 받는 규약입니다. 클라이언트는 브라우저나 다른 서버처럼 요청을 보내는 쪽입니다.
상태 코드는 응답이 어떻게 끝났는지를 세 자릿수로 알리는 값입니다. 서버는 응답의 첫 줄에 이 값을 적어 보냅니다.
201 은 요청이 성공했고 그 결과로 새 리소스가 생겼다는 뜻입니다. 리소스는 게시글 한 편이나 주문 한 건처럼 서버가 주소를 붙여 가리키는 대상입니다. 회원 가입, 주문 넣기, 파일 올리기처럼 무언가를 새로 만드는 요청이 성공하면 이 값을 돌려줍니다.
맨 앞 숫자 2 는 성공이라는 표시입니다. 2 로 시작하는 코드를 묶어 2xx 계열이라고 부릅니다. 같은 2xx 계열의 200 OK는 요청을 처리했다는 뜻입니다. 201 은 그보다 좁게, 처리한 결과로 새것이 생겼다는 것까지 알립니다.
응답 한 벌로 보는 201
주문 하나를 새로 넣으면 요청과 응답이 이렇게 오갑니다. 클라이언트는 POST 메서드로 주문 목록의 주소에 새 주문의 내용을 보냅니다. POST 는 서버에 처리를 맡기는 요청 방식입니다.
POST /orders HTTP/1.1
Host: shop.example.com
{"item": "커피", "count": 2}
서버는 주문을 만들고 42번이라는 번호를 붙였습니다. 그리고 아래 응답을 돌려줍니다.
HTTP/1.1 201 Created
Location: /orders/42
{"id": 42, "item": "커피", "count": 2}
첫 줄을 상태 줄이라고 부릅니다. 프로토콜 버전 HTTP/1.1, 상태 코드 201, 설명 문구 Created 가 차례로 놓입니다.
숫자 뒤의 설명 문구를 사유 구절이라고 부릅니다. 사람이 읽으라고 붙인 글자라서 프로그램은 이 글자를 안 보고 숫자만 봅니다.
둘째 줄의 Location 이 201 과 짝을 이룹니다. 새로 생긴 주문의 주소를 알리는 줄입니다.
빈 줄 아래는 응답 본문입니다. 201 의 본문에는 대개 새 리소스의 내용이나 그 리소스로 가는 링크를 담습니다. 위 응답은 만들어진 주문의 내용을 담았습니다. 본문을 비워 보내도 됩니다.
Location 헤더가 알리는 새 주소
헤더는 상태 줄 아래에 「이름: 값」 꼴로 붙는 부가 정보입니다. Location 헤더는 그 가운데 새 리소스가 어디 있는지를 알리는 헤더입니다.
이 헤더가 필요한 까닭은 새 주소를 서버가 정하기 때문입니다. 주문 번호 42 는 서버가 주문을 만드는 순간에 붙였습니다. 클라이언트는 요청을 보낼 때 이 번호를 알 수 없습니다.
클라이언트는 받은 주소로 GET 요청을 보내 새 주문을 다시 읽습니다. GET 은 리소스를 가져오는 요청 방식입니다. 아래 그림은 주문을 만들고 다시 읽기까지의 순서입니다.
sequenceDiagram
participant 클라이언트
participant 서버
클라이언트->>서버: POST /orders
Note over 서버: 주문 42 를 만든다
서버-->>클라이언트: 201 Created, Location /orders/42
클라이언트->>서버: GET /orders/42
서버-->>클라이언트: 200 OK, 주문 42 의 내용
서버가 처음 돌려주는 응답이 201 입니다. 클라이언트는 본문을 해석하지 않고 헤더에서 주소만 꺼내 다음 요청을 만듭니다.
Location 값은 위처럼 서버 이름을 뺀 경로만 적어도 됩니다. 그러면 클라이언트는 요청을 보낸 주소를 기준으로 전체 주소를 채웁니다. https://shop.example.com/orders 로 보낸 요청이면 새 주소는 https://shop.example.com/orders/42 입니다.
Location 이 없는 201 도 있습니다. 그때는 요청을 보낸 주소 자체가 새 리소스의 주소입니다. 아래에서 볼 PUT 으로 만든 경우가 그렇습니다.
200 대신 201 을 돌려주는 까닭
201 과 200 은 둘 다 성공입니다. 그래도 둘을 가르는 까닭은 응답을 받은 클라이언트가 할 일이 달라지기 때문입니다.
201 을 받은 클라이언트는 새것이 생겼다는 것을 본문 없이 압니다. 새 주소는 Location 에서 꺼내 다음 요청에 씁니다.
200 만 받았다면 본문을 열어 무엇이 생겼는지 찾아야 합니다. 그런데 본문의 모양은 API(Application Programming Interface, 프로그램끼리 기능을 불러 쓰는 약속)마다 다릅니다. 새 주소를 찾는 코드도 API 마다 새로 짜야 합니다. 201 과 Location 은 이 수고를 약속된 값 둘로 덜어 줍니다.
201 과 이웃한 코드
201 을 쓸지 말지는 두 기준으로 갈립니다. 새 리소스가 생겼나, 그리고 그 일이 응답 전에 끝났나입니다.
| 상황 | 코드 | 뜻 |
|---|---|---|
| 새 리소스를 다 만들었다 | 201 Created | 만들었고 주소는 Location 에 있다 |
| 만들기를 받아 두기만 했다 | 202 Accepted | 처리는 아직이다. 결과는 나중에 따로 확인한다 |
| 새로 만든 것 없이 처리만 했다 | 200 OK | 결과를 본문에 담았다 |
| 새로 만든 것도 돌려줄 본문도 없다 | 204 No Content | 처리했고 본문은 비었다 |
| 같은 것이 이미 있어 만들지 않았다 | 409 Conflict | 요청이 서버의 지금 상태와 부딪혔다 |
표의 첫 두 줄은 시점으로 갈립니다. 201 은 만들기가 끝났다는 약속입니다. 그래서 서버는 리소스를 다 만든 뒤에야 201 을 보낼 수 있습니다.
동영상 변환처럼 오래 걸리는 작업이면 그동안 클라이언트가 응답을 기다립니다. 이럴 때는 202 로 먼저 답합니다. 작업은 그 뒤에 따로 돌립니다. 클라이언트는 202 를 보고 결과를 나중에 따로 확인해야 한다는 것을 압니다.
마지막 줄의 409 는 맨 앞 숫자가 4 입니다. 4 로 시작하는 4xx 계열은 요청 쪽에 문제가 있다는 뜻입니다. 가입하려는 아이디가 이미 있을 때처럼 새로 만든 것이 없으면 201 을 쓰지 않습니다. 이때 흔히 409 를 돌려줍니다.
POST 와 PUT 에서의 201
새 리소스를 만드는 요청 방식은 대개 둘입니다. 앞에서 본 POST 와 PUT 입니다. 둘은 새 주소를 누가 정하느냐로 갈립니다.
PUT 은 「이 주소에 이 내용을 놓아라」는 요청 방식입니다. 클라이언트가 PUT /users/kim 처럼 주소를 직접 정해 보냅니다. 그래서 PUT 이 만든 리소스의 주소는 클라이언트가 이미 압니다. 이 때문에 PUT 이 돌려주는 201 에는 Location 이 없어도 됩니다.
| 메서드 | 새 주소를 정하는 쪽 | 201 을 돌려줄 때 | 201 이 아닐 때 |
|---|---|---|---|
| POST | 서버 | 새 리소스를 만들었다. Location 에 새 주소를 싣는다 |
새로 만든 것이 없으면 200 이나 204 |
| PUT | 클라이언트 | 그 주소에 없던 리소스를 새로 만들었다 | 있던 리소스를 바꿨으면 200 이나 204 |
표의 PUT 줄이 201 의 쓸모를 보여 줍니다. PUT 요청은 모양이 같아도 결과가 둘로 갈립니다. 클라이언트는 201 인지 200·204 인지를 보고 방금 새로 만든 것인지 있던 것을 바꾼 것인지 압니다.
응답이 사라진 201
POST 로 만들기를 요청했는데 201 응답이 도중에 사라질 수 있습니다. 서버는 주문을 만들었지만 클라이언트는 성공했는지 모릅니다. 클라이언트가 같은 요청을 다시 보내면 서버는 주문을 하나 더 만들고 또 201 을 돌려줍니다.
이 일은 POST 가 멱등하지 않아서 생깁니다. 멱등하다는 것은 같은 요청을 여러 번 보내도 한 번 보낸 것과 결과가 같다는 뜻입니다.
PUT 은 멱등합니다. 같은 주소에 같은 내용을 두 번 놓아도 리소스는 하나입니다. 첫 요청에는 201 이 옵니다. 다시 보낸 요청은 있던 것을 바꾼 셈이므로 200 이나 204 를 받습니다.
POST 의 중복을 막는 흔한 방법은 요청마다 고유한 값을 붙이는 것입니다. 이 값을 멱등성 키라고 부릅니다. 서버는 같은 키로 다시 온 요청을 새로 처리하지 않고 처음 만든 결과를 돌려줍니다.
관련 항목
201 이 속하는 상위 분류
상태 코드 · 상태 코드 등급 · 성공 응답 · HTTP · HTTP 응답
201 과 함께 응답을 이루는 구성 요소
상태 줄 · 사유 구절 · 헤더 · Location 헤더 · 응답 본문 · Content-Type · ETag
201 대신 고르는 다른 상태 코드
200 OK · 202 Accepted · 204 No Content · 303 See Other · 409 Conflict
201 을 돌려받는 요청 메서드
요청 메서드 · POST · PUT · PATCH · GET
201 이 알리는 새 리소스의 주소 체계
자원 · URI · 상대 URI · 요청 대상 · 자원 지향 설계
201 응답이 사라졌을 때 쓰는 중복 방지 장치
멱등성 · 멱등성 키 · 재시도 · 중복 요청 · 타임아웃
201 을 두고 내리는 설계 판단
다른 이름: 201 · HTTP 201 · 201 (Created) · 상태 코드 201