
RESTful 설계의 컨셉은 시스템에서 제공하는 Resource를 'Bucket'화 하는 것
RESTful API는 현대의 웹 서비스 디자인에서 가장 중요한 아키텍처 스타일이라고 생각합니다. 이를 통해 우리는 효율적이고 확장 가능한 웹 서비스를 만들 수 있게 되었습니다.
따라서 이번 글에서는, RESTful API의 주요 개념과 최선의 실천 방법을 소개하겠습니다.
자원(Resource, Document)
컬렉션(Collection)
스토어(Store)
URI, URL(Uniform Resource Identifier, Locator)
GET /getPosts, POST /createPost, POST /updatePost 등의 형식이 아닌, GET /posts, POST /posts, PUT, PATCH /posts/{ id } 등의 형식을 사용한다.GET /posts, GET /posts/1 등의 형식을 사용해서, posts라는 컬렉션에 접근하고, posts의 id가 1인 리소스에 접근하는 것이 좀 더 직관적입니다.상태코드를 사용하면, 클라이언트가 서버의 상태를 쉽게 파악할 수 있습니다.
따라서, body 상에서 별도의 status를 표기하는것은 불필요한 중복이 될 수 있습니다.
그리고, 가능한 한 최대한 200, 400보다는 201, 204, 409, 429 등 용도에 맞는 구체적인 상태코드를 사용하는게 좋습니다.
| 상태코드 | 설명 | 예시 |
|---|---|---|
| 100 - 199 | 정보 | 102 processing |
| 200 - 299 | 성공 | 200 OK |
| 300 - 399 | 리다이렉션 | 301 moved permanently |
| 400 - 499 | 클라이언트 에러 | 400 bad request |
| 500 - 599 | 서버 에러 | 500 internal server error |
GET /posts/1/comments는 id가 1인 post의 댓글을 가져오는 것입니다.GET /posts?author=1은 id가 1인 작성자의 post를 가져오는 것입니다.GET /posts?sort=created_at은 작성일자를 기준으로 post를 정렬하는 것입니다.GET /posts?page=1&limit=10은 1페이지에 10개의 post를 가져오는 것입니다.GET /v1/posts, GET /v2.0/posts, GET /2.0/posts 등POST /store/{store-id}/products
나쁜 예시
Content-Type: application/json
{
"name": "Product `""
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"result": { "id": 1 }
}
좋은 예시
Content-Type: application/json
{
"name": "Product 1"
}
HTTP/1.1 201 Created --> 상태 코드를 적극 사용
Location: /store/1/products/1 --> 생성된 리소스의 위치를 명세
HTTP/1.1 200 OK
Content-Type: application/json
Content-Location: /store/1/products/1 --> 생성된 리소스의 위치를 명세
{
"id": 1,
"name": "Product 1"
}
GET /store/{store-id}/products
나쁜 예시
HTTP/1.1 200 OK
Content-Type: application/json
{
"result": [{
"id": 1,
"name": "Product 1"
}]
}
좋은 예시
HTTP/1.1 200 OK
Content-Type: application/vnd.store.product+json --> 자기설명적인 명확한 응답
[{
"id": 1,
"name": "Product 1",
"links": [{
"self": "/store/1/products/1" --> HATEOAS를 준수하여 다른 리소스에 간편히 접근 가능
}]
}]
GET /store/{store-id}/products/{product-id}/comments
나쁜 예시
HTTP/1.1 200 OK
Content-Type: application/json
{
"result": [{
"id": 1,
"product_id": 1,
"text": "Comment 1"
}]
}
좋은 예시
HTTP/1.1 200 OK
Content-Type: application/vnd.store.product.comment+json
[{
"id": 1,
"store_id": 1,
"product_id": 1,
"text": "Comment 1",
"links": [{
"self": "/store/1/products/1/comments/1",
"product": "/store/1/products/1" --> 응답값만으로 해당 comment가 어느 store, product에 속한 것인지 알 수 있음.
"store": "/store/1",
}]
}]
파일 속성확인 / 다운로드
GET /files/{file-id}GET /files/{file-id}/properties 별도 사용GET /files/{file-id}?properties=true 쿼리스트링 사용GET /files/{file-id} 엔드포인트 사용Accept: application/json 헤더를 통해 JSON을 요청Accept: application/octet-stream 헤더를 통해 파일을 요청 혹은Accept: image/png 헤더를 통해 이미지를 요청GET 요청시 데이터 변경이 필요한 경우?
GET /mails/{mail-id}?preview=true, 정석은 아니지만, 일반적으로 많이 사용됨.한번의 리퀘스트로 인해 다수의 객체의 변경이 생기는 경우?
RESTful API는 그 특성상 명확한 규칙이 있는것은 아닙니다.
하지만 많은 개발자가 이를 적용해서 조금씩만 더 신경을 써 주신다면, 일관성과 표준화를 통해 좀 더 효율적인 개발환경이 구성 될 것이라고 생각합니다.
참고
REST API Best Practices – REST Endpoint Design Examples
RESTful API Designing guidelines — The best practices