다양한 web service에서 제공하는 RESTful api들에 왜 RESTful이 붙는지, 그리고 그것이 어떤 것을 의미하는 것인지를 공부하고 정리하기 위해 이 포스트를 작성합니다.

개요

하나의 web api는 베포되고 나면 수정이 어렵다. 특히 클라이언트가 있는 상태라면 더더욱 그러하다.(이를 해결하기 위해 버전을 주고 URI를 분리하기도 한다) 그렇기 때문에 디자인을 신중하게 해야하는데 별도의 가이드가 없는 상황에서는 다른 선구자(?)들의 방식들을 참고할 수밖에 없다. 시간이 된다면 다른 RESTful web api를 분석하도록 하겠다. 안될거야 아마

이 포스트에서는 권장되는 방식들 중 내 입맛에 맞아 보이는 것들을 모아서 정리하려 한다.

권장 REST 디자인

Resource

URI는 간단하고 직관적이여야 한다.

REST API의 URI는 그 자체만으로 직관적으로 이해가 가야 한다.

# 이 resource가 task들의 집합과 관련이 있구나.. 이 api가 version 2인가보다..
/v2/tasks
# tasks들의 집합중에 id 2를 가지고 있는 resource와 관련이 있는가보당..
/v2/tasks/2

동사보다는 명사를 사용하자

URI에 resource를 다루는 행동을 포함하지 않도록 한다. 이러한 부분들이 필요할 경우에는 method를 통해 정의하는 것이 좋다.

아래 URI들은 안티패턴이다.

GET /getTasks
POST /deleteTask/2

아래와 같이 CRUD를 이용해서 구현하는 것을 권장한다.

GET /tasks # task 리스트 return
PUT /tasks/2 # id가 2인 task 수정
POST /tasks # task 생성
DELETE /tasks/2 # 2번 task 삭제

일반적으로 Collection을 나타내는 URI에 권장되는 method 동작은 아래와 같다.

Resource POST GET PUT DELETE
/tasks 새로운 task 추가 task들의 목록 리턴 다수의 task 목록을 업데이트 모든 task 삭제
/tasks/2 동작하지 않음 ID가 2인 task 정보 리턴 ID가 2인 task 정보 업데이트 ID가 2인 task 정보 삭제

하지만 특정 경우에는 위의 CRUD에 매칭이 되지 않을 경우가 있다.

GET /v2/timers/2 # 이는 2번 timer에 대한 정보를 받아온다.
# 이 타이머를 시작하고 싶었을 때는 어떤 method를 사용해야 할까?
# POST /v2/timers/2 로 표현하자니,, 멈추는 행위와 재시작하는 행위도 표현해야 한다는 문제가 있다.

위와 같은 경우에는 POST를 사용해서 아래와 같은 URI를 사용하는 것을 권장한다.

  • /v2/timers/2/start
  • /v2/timers/2/stop
  • /v2/timers/2/restart

URI에 CRUD와 관련된 내용만큼은 포함하지 않는 것이 좋다. flickr의 api가 이러한 부분들을 포함하고 있다.

단수보다는 복수 명사 사용

Collection에 대해서는 복수 명사를 사용한다.

/v2/task -> /v2/tasks

소문자를 사용한다.

URI에서 대문자와 소문자는 다른 리소스를 나타낸다. 대문자가 들어가야 할 분명한 이유가 있는 경우가 없다면 가급적이면 소문자로 작성하여 혼란을 피하는 것이 좋다.

/v2/tasks != /v2/TASKS != /v2/Tasks

구분자로 hyphen을 사용

REST에서 URI는 그 자체로도 의미를 갖기 때문에 공백이 들어갈 경우 %20이 들어가 가독성이 떨어질 수 있다. 그렇기 때문에 hyphen(-)으로 공백을 대체하는 것이 좋다. underscore는 web에서 아주 흔한 링크 및줄로 인해 가려질 수 있어 권장되지 않는다.

soring

sort parameter를 사용한다.

pagination

filter

pretty print 기능

기본적으로는 공백을 없애지만 ?pretty=true로 제공하면 좋다.

작성중..

요청 Method 별 역할

  • GET Method나 POST Method를 사용하여 다른 요청 Method를 처리해서는 안된다.
  • GET Method는 리소스의 상태 표현을 얻는 데 사용해야 한다.
  • 응답 헤더를 가져올 때는 HEAD Method를 사용해야 한다.
  • PUT Method는 리소스를 삽입하거나 저장된 리소스를 갱신하는 데 사용해야 한다.
  • PUT Method는 변경 가능한 리소스를 갱신하는 데 사용해야 한다.
  • POST Method는 Collection에 새로운 리소스를 만드는 데 사용해야 한다.
  • POST Method는 Controller를 실행하는 데 사용해야 한다.
  • DELETE Method는 그 부모에서 리소스를 삭제하는 데 사용해야 한다.
  • OPTIONS Method는 리소스의 사용 가능한 인터렉션을 기술한 메타데이터를 가져오는 데 사용해야 한다.
    • e.g., Allow: GET, PUT, DELETE

응답 상태 코드

개략적인 코드

코드 설 명
1xx: 정보 전송 프로토콜 수준의 정보 교환
2xx: 성공 클라이언트 요청이 성공적으로 수행됨
3xx: 재전송 클라이언트는 요청을 완료하기 위해 추가적인 행동을 취해야 함
4xx: 클라이언트 오류 클라이언트의 잘못된 요청
5xx: 서버 오류 서버쪽 오류로 인한 상태코드

규칙

  • 200 OK 는 일반적인 요청 성공을 나타내는 데 사용해야 한다.
  • 200 OK 는 응답 바디에 에러를 전송하는 데 사용해서는 안된다
    • REST API는 부실한 HTTP 클라이언트에 부합하려는 타협을 해서는 안된다
  • 201 Created 는 성공적으로 리소스를 생성했을 때 사용해야 한다.
  • 202 Accepted 는 비동기 처리가 성공적으로 시작되었음을 알릴 때 사용해야 한다.
  • 204 No Content는 응답 바디에 의도적으로 아무것도 포함하지 않을 때 사용한다.
  • 301 Moved Permanently는 리소스를 이동시켰을 때 사용한다.
    • URI에 상당부분 수정되었을 경우에 사용되며, 새로운 URI를 Location으로 제공해야 한다.
  • 302 Found는 사용하지 않는다.
    • 명확하지 않아 혼란이 생길 수 있어 303 See Other307 Temporary Redirect를 사용한다(물론 적합할 경우에)
  • 303 See Other는 다른 URI를 참조하라고 알려줄 때 사용한다.
  • 304 Not Modified는 대역폭을 절약할 때 사용한다.
    • cookie
  • 307 Temporary Redirect는 클라이언트가 다른 URI로 요청을 다시 보내게 할 때 사용해야 한다.
    • 일종의 Redirection
  • 400 Bad Request는 일반적인 요청 실패에 사용해야 한다.
    • 4xx중 적절한게 없을 경우 사용
  • 401 Unauthorized는 클라이언트 인증에 문제가 있을 때 사용해야 한다.
  • 403 Forbidden은 인증 상태에 상관없이 엑세스를 금지할 때 사용해야 한다.
  • 404 Not Found는 요청 URI에 해당하는 리소스가 없을 때 사용해야 한다.
  • 405 Method Not Allowed는 HTTP Method가 지원되지 않을 때 사용해야 한다.
  • 406 Not Acceptable은 요청된 리소스 미디어 타입을 제공하지 못할 때 사용해야 한다.
    • Accept요청 해더에 있는 미디어 타입들을 만족시킬 수 없는 경우
  • 409 Conflict는 리소스 상태에 위반되는 행위를 했을 때 사용해야 한다.
    • 요청이 충돌이 나는 경우
  • 412 Precondition Failed는 조건부 연산을 지원할 때 사용한다.
    • 조건부 연산이 존재할 경우 그를 충족시키지 못할때
  • 415 Unsupported Media Type은 요청의 페이로드에 있는 미디어 타입이 처리되지 못했을 때 사용해야 한다.
    • json만 지원하는 URI에 xml을 요청 할때
  • 500 Internal Server Error는 API가 잘못 작동할 때 사용해야 한다.
    • 일반적인 REST API의 오류 응답
    • 대부분의 웹 프레임워크는 exception이 발생할 경우 이를 발생시킨다.

reference

  • [Best Practices for Designing a Pragmatic RESTful API Vinay Sahni](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api)
  • 조대협의 블로그 :: REST 연재-1회 REST 아키텍쳐의 기본
  • [Spoqa Tech Blog REST 아키텍처를 훌륭하게 적용하기 위한 몇 가지 디자인 팁](https://spoqa.github.io/2012/02/27/rest-introduction.html)
  • [GitHub API v3 GitHub Developer Guide](https://developer.github.com/v3/)