Medium - RESTful API Designing Guidelines — The Best Practices

원문 - Mahesh Haldar

Trend 파악을 위한 Medium 기고문 포스팅 - RESTful API 디자인 가이드라인, 가장 좋은 사례; 멋지게 제작된 API를 가지는 것은 응용프로그램 성능에 좋은 영향을 끼칩니다.

페이스북, 구글, 깃허브, 넷플릭스와 다른 기술 기반 회사들은 개발자들과 제품에게 자사의 API를 통한 데이터를 소비할 수 있도록 해주고 해당 기업을 위한 플랫폼이 되도록 장려하고 있습니다.

여러분이 다른 개발자나 제품을 위한 API를 작성하지 않더라도 멋지게 제작된 API를 가지고 있는 것은 여러분의 응용프로그램을 항상 건강하게 만들어 줍니다. 오랜기간 인터넷에서 항상 API를 디자인하는 최선의 방법에 대해서 토론이 있어왔지만 이것은 가장 미묘한 부분입니다. 아직도 공식적인 가이드가 정해지지 않았죠.

API는 많은 개발자들이 데이터와 통신할 수 있는 인터페이스입니다. 잘 설계된 API는 항상 사용하기 쉬우며 개발자의 삶을 매우 부드럽게 만들어줍니다. API는 개발자를 위한 GUI이며 만약 사용에 혼란이 있다면 개발자는 다른 대체품을 찾거나 사용하는 것을 관둘 것입니다. 개발자의 경험은 API의 퀄리티를 평가하는 요소 중에 가장 중요한 것입니다. API는 아티스트가 무대에서 연주하는 것과 같고 사용자는 관객인 것입니다.

Terminologies

다음은 REST API들과 관계있는 중요한 용어들입니다.

  • Resource - 자원은 객체나 어떤 것의 상태를 대표하는 것으로 관련된 데이터가 있고 작업을 수행할 수 있는 메소드 셋들이 있습니다. animals, schools, employees 같은 것이 자원이고 delete, add, add같은 것이 해당 자원에 수행할 수 있는 오퍼레이션 들입니다.

  • Collections - 컬렉션은 자원의 집합입니다. companies는 company 자원의 컬렉션입니다.
  • URL - URL은 자원이 위치한 경로이며 해당 자원에 수행할 수 있는 액션이 될수도 있습니다.

API Endpoint

더욱 자세한 이해를 위해 적당한 직원들을 가진 회사들을 위한 API들을 작성해봅시다.

/getAllEmployee API는 직원들의 리스트를 보내줄 것입니다. 이 외에도 다음과 같은 API들이 있을 수 있습니다.

  • /addNewEmployee
  • /updateEmployee
  • /deleteEmployee
  • /deleteAllEmployee
  • /promoteEmployee
  • /promoteAllEmployee

이런 API 엔드포인트들은 엄청나게 많을 것이고 모두 다른 오퍼레이션일 것입니다. 이런 것은 많은 중복된 액션을 포함하고 있습니다. 그렇기 때문에 이런 API 엔드포인트들은 API 갯수가 증가할 수록 유지보수하기가 힘들어 질 것입니다.

What is wrong?

URL은 액션이나 동작이 아니라 항상 자원만 명사형태로 가지고 있어야 합니다. /addNewEmployee API 경로는 addNew 액션과 Employee 자원이름을 가지고 있습니다.

What is the correct way?

/companies 엔드포인트가 액션이 없는 좋은 예입니다. 그러나 문제는 “companies자원에 대해서 어떤 액션이 수행될 지 서버에게 어떻게 알려주냐”라는 것입니다. 추가될지, 삭제될지, 업데이트 될지 어떻게 전달해야 할까요?

이것은 HTTP method( GET, POST, DELETE, PUT)을 사용해서 해결합니다.

API 엔드포인트의 자원은 항상 복수형으로 표시되어야 ㅏ며 자원의 인스턴스에 접근하고 싶다면 URL에 ID를 전달하는 방식입니다.

  • /companies 경로의 GET 메소드는 모든 회사의 리스트를 리턴해야 합니다.
  • /compnaies/34 경로의 GET 메소드는 34회사의 상세 정보를 리턴해야 합니다.
  • /compnaies/34 경로의 DELETE 메소드는 34회사를 삭제하는 것이여야 합니다.

다른 사용예로 자원 내부에 자원이 있는 경우, 예를 들자면 회사의 직원들 같은 경우 API의 엔드포인트는 다음과 같아야 합니다.

  • GET /companies/3/employees 이렇게 하면 3회사의 모든 직원리스트를 리턴해야 합니다.
  • GET /companies/3/employees/45 이렇게 하면 3회사의 45직원의 상세정보를 리턴해야 합니다.
  • DELETE /companies/3/employees/45 이 메소드는 3회사에 속해있는 45직원을 삭제해야 합니다.
  • POST /companies 는 새로운 회사를 만드는 것이며 새로 만들어진 회사의 상세정보를 리턴해야 합니다.

Conclusion

경로는 항상 자원에 대한 복수형을 담고있어야 하며 HTTP 메소드가 해당 자원에 수행되는 액션의 종류를 나타내야 합니다.

HTTP Methods (Verbs)

HTTP는 자원에 수행할 액션의 종류를 나타내는 메소드들을 정의해 놨습니다. URL 문장은 자원이 어디에 있는지에 대한 것이고 HTTP 메소드는 동사가 되는 것입니다. 다음은 중요한 HTTP 메소드 들입니다.

  • GET 메소드는 자원으로부터 데이터를 요청하는 것으로 어떤 부작용도 만들어서는 안됩니다. 예를들어 GET /companies/3/employees 는 3회사의 모든 직원 리스트를 가져오는 것입니다.
  • POST 메소드는 서버에게 해당 자원을 생성할 것을 요청합니다. 대개 이것은 웹 폼을 제출하는 방식입니다. POST /companies/3/employees는 회사3의 새로운 직원을 만드는 것입니다. POST 는 non-idempotent로써 여러개의 리퀘스트가 다른 영향을 가지게 될 것입니다.
  • PUT 메소드는 서버에게 자원을 업데이트하거나 해당 자원이 없다면 생성하도록 요청하는 것입니다. PUT /companies/3/employees/john 은 서버에 업데이트 혹은 회사 3의 직원 컬렉션에 john 자원이 없다면 생성을 요청합니다. PUT은 idempotent 하기 때문에 다수의 리퀘스트 결과가 항상 같은 영향을 가집니다.
  • DELETE 메소드는 자원이나 그들의 인스턴스를 데이터베이스로부터 제거하는 것을 요청합니다. DELETE /companies/3/employees/john/은 서버에 3회사의 직원 컬렉션으로부터 john 리소스를 삭제하길 요청할 것입니다.

HTTP Response Status Codes

클라이언트가 API를 통해 리퀘스트를 발생시키면 클라이언트는 실패했는지, 통과했는지, 리퀘스트가 잘못되었는지 등의 피드백을 알아야합니다. HTTP 상태 코드는 다양한 시나리오를 설명하는 다양한 표준화 코드 덩어리 입니다. 서버는 항상 올바른 상태 코드를 리턴해야 합니다. 다음은 HTTP 코드에서 중요한 카테고리 입니다.

2xx (Success Category)

이 상태 코드는 서버가 요청한 액션을 받았고 성공적으로 수행했다는 것을 말합니다.

  • 200 OK - GET, PUT, POST가 성공했음을 나타냅니다.
  • 201 Created - 이 상태코드는 새로운 인스턴스가 만들어졌을 때 리턴되어야 합니다. POST 메소드를 사용해서 새로운 인스턴스를 만들었다면 201 코드를 리턴해야 합니다.
  • 204 No Content - 이 상태코드는 성공적으로 수행되었지만 리턴할 내용이 없다는 것을 의미합니다. DELETE 작업이 대표적인 케이스 입니다. DELETE /companies/43/employees/2 는 43회사의 2직원을 삭제하지만 리턴값으로 API의 바디 안에 아무것도 넣을 게 없으므로 명시적으로 시스템에 삭제되었다고 말해주는 것입니다. 만약 에러가 발생해서 employee 2가 DB에 없는 경우에는 2xx 상태 값이 아닌 4xx 에러코드를 리턴해야 합니다.

3xx (Redirection Category)

  • 304 Not Modified - 클라이언트가 응답을 이미 자체 캐시에 가지고 있음을 암시합니다. 그러므로 같은 데이터를 다시 보낼 필요가 없습니다.

4xx (Client Error Category)

이러한 상태코드는 클라이언트가 발생시킨 요청이 잘못되었음을 나타냅니다.

  • 400 Bad Request - 클라이언트가 요청한 프로세스가 수행되지 않았음을 나타내며 클라이언트가 요청한 것을 서버가 이해하지 못한 경우 입니다.

  • 401 Unauthorized - 클라이언트가 해당 자원에 접근할 권한이 없기 때문에 요구되는 암호정보를 포함해 다시 리퀘스트 하라는 것입니다.

  • 403 Forbidden - 리퀘스트도 유효하고 클라이언트도 인증되었지만 클라이언트가 해당 페이지나 자원에 대해서 허용되지 않았음을 의미합니다. 때때로 인증된 사용자라도 서버의 디렉토리에는 접근하도록 허용되지 않습니다

  • 404 Not Found - 요청한 자원이 사용가능하지 않음을 나타냅니다.

  • 410 Gone - 요청한 자원이 더 이상 사용가능하지 않으며 이동되었음을 나타냅니다.

5xx (Server Error Category)

  • 500 Internal Server Error - 요청이 유효하나 서버가 내부적으로 혼동하거나 예측하지 못한 조건을 수행하도록 요청받은 것입니다.

  • 503 Service Unavailable - 서버가 내려갔거나 사용가능하지 않아서 요청을 수행할 수 없음을 나타냅니다. 대개 이럴 때는 서버가 유지보수 중일 때 입니다.

Field Name Casing Convention

  • 모든 작명 규칙을 사용할 수 있지만 응용프로그램과 동일하게 하는 것이 좋습니다. 리퀘스트 바디와 리스폰스 타입이 JSON 이라면 카멜케이스를 사용하는 것이 좋습니다

Searching, Sorting, Filtering, and Pagination

이런 모든 행동들은 간단히 데이터 셋에 쿼리를 날리는 것입니다. 이런 행동을 처리하는 새로운 API들이 있으면 안됩니다. API의 GET 메소드에 쿼리 인자를 추가해서 처리합니다. 예제를 통해서 이런 것을 어떻게 구현하는지 알아봅시다.

  • Sorting - 클라이언트가 회사의 리스트를 정렬하여 보고싶은 경우 GET /companies 엔드포인트는 다양한 정렬 인자를 쿼리에서 받을 수 있어야 합니다. GET /companies?sort=rank_asc는 회사를 오름차순 순으로 정렬할 것입니다.

  • Filtering - 데이터셋을 필터링 하기 위해서 쿼리 인자를 통해서 다양한 옵션을 줄 수 있습니다. GET /companies?category=banking&location=india 는 회사의 리스트 중에서 카테고리가 금융이고 인디아에 위치한 회사를 리턴할 것입니다.

  • Searching - 회사 리스트에서 회사 이름을 찾을 때 API 엔드포인트는 GET /companies?search=Digital Mckinsey 처럼 되어야 할 것입니다.

  • Pagination - 데이터셋이 매우 큰 경우 데이터셋을 작은 덩어리로 나누어서 성능을 향상시키고 응답을 처리하기 쉽도록 만들 수 있습니다. GET /companies?page=23 의미는 회사들의 리스트의 23번째 페이지라는 것입니다.

만약 너무 많은 쿼리 인자를 GET 메소드에서 사용할 경우 URI를 너무 길게 만들어서 서버가 414 URI Too long 상태값을 보낼 수도 있습니다. 이럴 경우에는 POST 메소드의 리퀘스트 바디로 해서 보낼 수 있습니다.

Versioning

API들이 기본적으로 실제로 쓰이게 할려면 API를 업그레이드 해서 수정사항이 생기는 경우 이미 존재하는 제품이나 여러분의 API를 사용하는 서비스가 동작하지 않게 만들 수 있습니다. http://api.yourservice.com/v1/companies/34/employees 가 좋은 예라고 할 수 있는데 API의 경로에 버전 숫자를 가지고 있습니다. 만약 주요 breaking 업데이트가 있다면 API의 이름을 v2v1.x.x 로 바꿔야 합니다.

Conclusion

이 가이드 라인은 제 개발경험을 기반하므로 여러분이 실제로 적용할 때는 달라질 수 있습니다.

Summary

  • 올바른 API 설계법
  • API 엔드포인트는 자원의 복수형 명사로 해야한다; 동사가 포함될 경우 엔드포인트가 매우 많아질 수도 있다.
  • HTTP 메소드를 이용하여 해당 자원에 취할 액션을 구분한다.
  • URL의 네임 컨벤션은 응용프로그램과 맞추는 것이 좋으며 JSON일 경우 카멜 케이스를 사용하는 것이 일반적이다.
  • 상태 코드 또한 표준화된 경우에 맞게 올바른 카테고리로 보내줘야 한다.

© 2019. All rights reserved.

Powered by Hydejack v8.1.1