 |
|
본격적으로 시작하자: RESTful API 만들기
이 절에서는 기존 데이터베이스 기반 애플리케이션의 기능을 그대로 이용하는 웹 서비스에서 쓸 RESTful한 API를 만들 것이다.
RESTful한 경기
주자마다 각기 다양한 거리를 달리는 경기(이를테면 시카고 마라톤 대회 같은)를 관리해야 하는 온라인 애플리케이션이 있다고 하자. 이 애플리케이션은 경기(혹은 행사)와 주자를 연결해 관리한다. 그리고 특정 주자의 시간(경기에서 얼마나 오랫동안 달렸는지)과 위치(주자가 경기를 마친 위치)를 보여준다. 경기 관리 회사인 Acme Racing에서는 후원사들이 새로 경기를 생성할 수 있도록 그리고 특정 경기에 대해 공식적인 결과를 제공할 수 있도록 하는 RESTful한 웹 서비스를 여러분이 만들어 주길 원한다고 하자.
Acme Racing에서는 이미 비슷한 요구 사항을 지원하고 있으며 간단한 데이터베이스와 연결된 도메인 모델을 사용하는 낡고 덩치 큰 클라이언트 애플리케이션을 갖고 있다. 따라서 이 기능을 웹에 노출하는 것이 바로 여러분이 해야 할 남은 과제다. REST의 아름다움은 하부 애플리케이션과 암묵적으로 느슨하게 결합된다는 점이라는 걸 기억하자. 따라서 지금 이 상황에서 여러분이 할 일은 데이터 모델이나 그와 연관된 기술에 대해 고민하는 게 아니라 회사가 요구하는 내용을 지원하는 RESTful한 API를 만드는 것이다.
경기에 필요한 URI들
Acme Races는 후원사들이 다음과 같은 일을 할 수 있었으면 할 것이다.
- 기존 경기의 상세 내용 보기
- 신규 경기 생성
- 기존 경기 갱신
- 기존 경기 삭제
REST는 이름이 부여된 자원으로 귀결되기 때문에 API는 일련의 URI 패턴이 될 것이며, 자원에 결합된 행동은 표준 HTTP 명령을 통해 불려질 것이다.
여러분도 알 수 있겠지만 고객의 요구 사항은 CRUD에 잘 들어 맞는다. 그리고 표 1에서 봤겠지만 REST는 순서대로 HTTP의 POST, GET, PUT, DELETE 요청을 통해 CRUD를 지원한다. 따라서 이러한 요구 사항을 지원하는 기본적인 RESTful한 URI는 http://racing.acme.com/race가 될 것이다. 이 경우 race는 클라이언트가 쓸 자원이다.
이 URI를 HTTP GET을 써서 불러내면 경기 목록이 반환될 것이다(아직까지는 응답 형식에 대해서는 걱정하지 말자). 신규 경기를 추가하려면 적절한 정보(예를 들어 이름, 날짜, 거리 같은 필수 경기 정보를 담은 XML 문서)를 담아 HTTP POST를 이용하여 동일 URI를 불러낼 것이다.
기존 경기를 갱신하고 삭제하기 위해 경기의 특정 인스턴스에 대해 액션을 취할 필요가 있을 것이다. 따라서 개개 경기는 http://racing.acme.com/race/race_id의 URI를 써서 해결할 수 있다. 이 경우 race_id는 어떠한 경기 식별자에 대한 틀을 나타낸다(1 또는 600meter 따위). 따라서 기존 경기 인스턴스를 보는 것은 해당 URI에 HTTP GET이 될 것이다. 경기를 갱신하거나 삭제하는 것은 각각 PUT, DELETE 요청이 될 것이다.
또한 Acme Racing은 경기에 참여하고 있는 주자를 고려하여 데이터가 노출되길 바라고 있다. 따라서 서비스에서 다음 사항이 지원되었으면 할 것이다.
- 특정 경기에 참여하는 모든 주자에 대한 정보 얻기. 이 데이터에는 이미 완료된 경기의 시간과 순위도 포함되어야 한다.
- 특정 경기에서 한 명 이상의 주자 생성
- 특정 경기에서 주자의 정보(나이 등) 갱신
- 특정 경기에서 주자 삭제
또한 Acme는 특정 경기에 참여중인 특정 주자에 대한 개인별 데이터를 사용자들이 볼 수 있도록 해주고 싶어할 것이다.
경기에서와 마찬가지로 경기와 연관된 주자에 RESTful한 URI를 적용하는 것이 논리적일 것이다. 예를 들어 특정 경기에 대해 모든 주자를 보는 것은 http://racing.acme.com/race/race_id/runner 에 대한 GET 요청을 통해 구현될 것이다.
한 경기에서 어떤 주자의 개인 데이터를 얻는 것은 http://racing.acme.com/race/race_id/runner/runner_id 와 같이 해결될 수 있을 것이다.
race_id처럼 runner_id는 ID에 대한 논리적 구현의 틀이며 ID는 숫자, 이름, 숫자와 글자의 조합 등이 될 것이다.
주자를 경기에 추가하는 것은 http://racing.acme.com/race/race_id/runner 에 대한 POST 요청이 될 것이다. 특정 주자를 갱신하거나 삭제하는 것은 각각 PUT과 DELETE 요청으로 http://racing.acme.com/race/race_id/runner/runner_id에 대해 이뤄질 것이다.
그러므로 정리하면 다음 URI들(각기 네 개의 표준 HTTP 요청을 일부 혹은 모두 지원한다)이 Acme Racing의 요구 조건을 수용한다고 하겠다.
- /race
- /race/race_id
- /race/race_id/runner
- /race/race_id/runner/runner_id
기억하자. 특정 URI는 하나 이상의 HTTP 동사에 매핑될 수 있다(예를 들어 /race에 HTTP GET을 적용하면 데이터를 반환할 것이며, 적절한 데이터를 갖고 /race에 POST를 적용하면 서버에서는 데이터를 생성할 것이다). 또한 일부 HTTP 명령은 구현되지 않을 수도 있다. 예를 들어 /race는 DELETE 명령을 지원하지 않을 것이다(Acme Racing은 모든 경기를 삭제하고 싶어하지 않을 것이므로). /race/race_id는 DELETE 명령을 지원할 수도 있다. 경기의 특정 인스턴스를 삭제하는 것은 비즈니스 요구 사항이기 때문이다.
|