본문 바로가기

dev/Rest API

REST API URI설계

프로젝트를 진행하며 RESTful API를 설계하게 되었다.

2008년 Leonard Richardson은 Web API에 대한 성숙도 모델을 다음과 같이 제시했다.

  • 수준 0: 한 URI를 정의합니다. 모든 작업은 이 URI에 대한 POST 요청입니다.
  • 수준 1: 개별 리소스에 대한 별도의 URI를 만듭니다.
  • 수준 2: HTTP 메서드를 사용하여 리소스에 대한 작업을 정의합니다.
  • 수준 3: 하이퍼미디어(HATEOAS, 아래에 설명)를 사용합니다.

Fielding의 정의에 따르면 수준 3에 이르는 Web API가 진정한 RESTful API에 해당한다.

현재는 아직 공부가 부족해 HATEOAS는 적용하지 못할 것 같다. 수준2 까지 모델을 설계해 본 후, 차후 REST에 대한 이해가 깊어지면 HATEOAS까지 적용해 완전히 RESTful한 API를 설계하고자 한다. 우선 수행해야 할 일은 리소스를 식별하고 리소스에 대한 URI를 설계하는 것이라고 생각된다. 따라서 프로젝트를 진행하며 참조가 될 수 있도록 URI와 관련된 내용을 추려 정리했다.

REST API URI 설계

REST API의 URI 설계에 있어 핵심적인 디자인 원칙은 다음과 같다.

  • REST API는 리소스를 중심으로 디자인된다. 이 때, 리소스는 클라이언트가 액세스할 수 있는 모든 종류의 개체, 데이터, 서비스를 포함한다.
  • 각 리소스는 URI에 의해 고유하게 식별된다.

즉, URI 디자인은 리소스를 중심으로 이루어져야 한다. 흔히 REST API를 설계할 때 URI에 동사를 넣지 말라는 것은 동사가 '리소스에 대한 작업'을 의미하기 때문이다. REST API에서 리소스에 대한 작업은 HTTP 메서드를 사용해 정의된다. post /users/create-user와 같은 URI는 지양해야 한다.

리소스에 대한 명명 규칙

URI에는 일관된 명명 규칙을 부여하는 것이 좋다. 컬렉션은 복수 명사를 사용하고, 단일 항목은 단수 명사를 사용하는 것이 권장된다. 이런 방식으로 리소스의 이름을 지으면 매우 직관적인 URI가 된다. 예를 들어 /users/yoonho 라는 URI를 보면 직관적으로 user 컬렉션의 yoonho라는 개체임을 알 수 있다.

리소스 사이의 관계 표현

URL을 설계할 때 리소스 사이의 관계를 고려할 수 있다. 예를 들어 customer와 order이 서로 관계를 가지고 있을 때, /customers/5/orders로 고객 5에 대한 주문을 나타낼 수 있다. 그리고 그 반대 방향으로 /orders/99/customer처럼 주문 99에 대한 고객 목록을 나타낼 수도 있다. 이러한 방식의 활용을 위해 URI는 컬렉션/항목/컬렉션 보다 더 복잡하게 설계하지 않는 것이 좋다. 그 이상으로 복잡해 지게 되면 구현에 어려움이 생길 수 있으며 복잡성에 대한 관리가 쉽지 않다.(이런 경우에는 HATEOAS 접근 방식을 사용하여 관련 리소스를 탐색하는 것이 권장된다고 한다.)

HTTP 메서드를 사용한 작업 정의

리소스에 대한 작업은 GET, POST, PUT, PATCH, DELTE 와 같은 HTTP 메서드를 사용해 정의된다. 재미있는 점은 같은 요청이라도 대상이 컬렉션인지 아니면 개별 항목인지에 따라 의미가 달라진다는 것이다. 아래 표가 정말 좋은 예시인 것 같다.

Azure docs, API 디자인

쿼리 스트링으로 컬렉션을 필터링

REST API에서는 컬렉션을 단일 URI로 표시한다. 이 경우 컬렉션의 일부만 필요할 때에도 컬렉션 전체를 가져오는 문제가 발생할 수 있다. 예를 들어 GET /users 는 모든 사용자를 조회할 것이다. 이럴 때 쿼리 스트링을 사용해서 필터링을 수행할 수 있다. 만약 역할 id가 1인 사용자만 조회하고 싶으면 GET /users?role=1로 필터링을 수행할 수 있다.

쿼리 스트링은 다음과 같이 활용될 수도 있다.

  • 반환되는 항목값(limit)을 전달해 DoS 공격을 방지할 수 있다.
  • pagination 구현에 사용될 수 있다(limit, offset)
  • 정렬 매개 변수를 제공할 수 있다.

쿼리 스트링 vs Path 변수

  • 리소스 식별을 할 때는 path variable을 사용한다.
  • 정렬, 필터링을 할 때는 query parameter를 사용한다.

위 정의를 고려했을 때, 검색에는 query parameter가 어울리고 수정 및 삭제는 path variable이 어울린다고 판단된다.

참조

'dev > Rest API' 카테고리의 다른 글

Rest API에서 로그인 구현  (0) 2019.03.14