devcken.io

Thoughts, stories and ideas.

RESTful API Designing guidelines - The best practices

이 포스트는 원문인 RESTful API Designing guidelines - The best practices을 번역한 것입니다. 심각한 오역이나 오글거리는 표현이 있을 수도 있으므로 주의하시기 바랍니다.

페이스북, 구글, 깃허브, 넷플릭스 그리고 다른 몇몇 기술 회사들은 개발자들과 제품에 그들의 데이터를 API를 통해 소비할 기해를 주어왔고 그들을 위한 플랫폼이 되었습니다.

여러분들이 다른 개발자들과 제품을 위한 API를 작성할 때 조차, 아름답게 만들어진 API를 갖는다는 것은 여러분의 애플리케이션에게 매우 유익합니다.

API 설계의 가장 좋은 방법에 관해 인터넷에서는 오랜 기간동안 논쟁이 있어 왔고, 가장 미묘한 것 중 하나입니다. 동일하게 정의된 공식적인 가이드라인은 없습니다.

API는 많은 개발자가 데이터와 상호 작용하는 하나의 인터페이스입니다. 잘 디자인된 API는 언제든지 사용하기 쉬우며 개발자들의 삶을 윤택하게 만들어줍니다. API는 개발자들을 위한 GUI로, 혼란스럽거나 자세하지 않다면 개발자는 대안을 찾거나 사용을 중단할 겁니다. 개발자의 경험은 API의 질을 측정하는데 있어 가장 중요한 지표입니다.

API는 무대 위에서 공연을 하는 예술가와 같으며, 사용자는 관중과 같다.

1) 용어

다음은 REST API와 관련된 가장 중요한 용어입니다

  • 리소스(resource)는 그와 관련된 데이터를 가지고 있고 그에 대해 동작하는 메서드 집합이 존재하는 것의 객체 혹은 표현입니다. 예를 들어, 동물, 학교 그리고 피고용자가 리소스가 될 수 있으며 delete, add, update는 이러한 리소스에 대해 실행되는 동작입니다.
  • 컬렉션(collections)는 리소스 집합으로, 예를 들어 CompaniesCompany 리소스의 컬렉션입니다.
  • URL(Uniform Resource Locator)는 리소스가 위치할 수 있고 어떤 동작이 리소스에 대해 실행될 수 있는 경로입니다.

2) API 엔드포인트

좀 더 알아보기 위해 Employees를 지닌 Companies에 대한 몇 가지 API를 작성해보겠습니다.

/getAllEmployess는 피고용자 목록으로 응답하는 API입니다. 다음과 같이 Company에 대한 좀 더 많은 API들이 있을 수 있습니다:

  • /addNewEmployee
  • /updateEmployee
  • /deleteEmployee
  • /deleteAllEmployees
  • /promoteEmployee
  • /promoteAllEmployees

그리고 다른 동작에 대한 이와 비슷한 다른 수 많은 API 엔트포인트들이 있을 수 있습니다. 그들 모두 많은 중복된 동작을 포함할 수 있습니다. 따라서, 이 API 엔드포인트는 API가 늘어날수록 유지하는데 부담이 될 것입니다.

무엇이 잘못됐는가?

URL은 동작이나 동사가 아닌 리소스(명사)만을 포함해야 합니다. /addNewEmployee라는 API 경로는 Employee라는 리소스 이름과 함께 addNew라는 동작을 포함하고 있습니다.

그러면 무엇이 옳은 방법인가?

/companies 엔드포인트는 동작을 포함하지 않는 좋은 예입니다. 그러나 companies라는 리소스에서 실행될 동작, 즉 추가, 삭제 혹은 갱신에 대해 서버에게 어떻게 알릴 수 있는지 의문입니다.

이 부분이 동사(verbs)라고도 불리는 HTTP 메서드(GET, POST, DELETE, PUT)가 활약할 곳입니다.

리소스는 API 엔드포인트 내에서 항상 복수(plural)여야 하며 리소스 중 하나의 인스턴스에 접근해야 하는 경우, URL 내에 아이디를 전달할 수 있습니다.

  • GET 메서드의 /companies는 전체 회사 목록을 가져와야 합니다
  • GET 메서드의 /companies/34는 34번 아이디의 회사의 상세 정보를 가져와야 합니다
  • DELETE 메서드의 /companies/34는 34번 아이디의 회사를 삭제해야 합니다

다음은 리소스 내에 리소스를 지닌 경우(예를 들어, 한 회사의 피고용자들)와 같은 다른 유스케이스의 예입니다:

  • GET /companies/3/employees는 3번 아이디 회사의 전체 피고용자 목록을 가져와야 합니다
  • GET /companies/3/employees는 3번 아이디 회사에 속하는 45번 아이디의 피고용자의 상세 정보를 가져와야 합니다
  • DELETE /companies/3/employess/45는 3번 아이디 회사에 속하는 45번 아이디의 피고용자를 삭제해야 합니다
  • POST /companies는 새로운 회사를 생성하고 생성된 새로운 회사의 세부 정보를 반환해야 합니다

이제 API가 좀 더 간결하고 조화롭지 않은가요?

결론: 경로는 리소스에 대한 복수 형태를 취해야 하며 HTTP 메서드는 리소스에 실행될 동작의 종류를 정의해야 합니다.

3) HTTP 메서드(verb)

HTTP는 리소스에 실행될 동작의 유형을 나타내기 위한 메서드 집합을 정의해왔습니다.

URL은 하나의 문장으로, 리소스는 명사이고 HTTP 메서드가 동사다.

중요한 HTTP 메서드는 다음과 같습니다:

  1. GET 메서드는 리소스의 데이터를 요청하며 어떠한 다른 부가 작용도 만들어내서는 안됩니다.
    예를 들어, /companies/3/employees는 3번 회사의 모든 피고용자 목록을 반환합니다.
  2. POST 메서드는, 대부분의 경우 웹 폼이 제출된 경우, 데이터베이스 내에 리소스를 생성하도록 서버에 요청합니다.
    예를 들어, /companies/3/employees는 3번 회사의 새로운 피고용자를 생성합니다. POST는 멱등적이지 않으며 이는 여러 번의 요청이 다른 효과를 만들어낸다는 것을 의미합니다.
  3. PUT 메서드는 리소스를 갱신하거나, 리소스가 존재하지 않는 경우 생성하도록 서버에 요청합니다.
    예를 들어, /companies/3/employees/john은 서버에 3번 회사의 피고용자 컬렉션 내 john이라는 리소스를 갱신하거나 존재하지 않는 경우 생성하도록 요청합니다. PUT은 멱등적이며 이는 여러 번 요청하더라도 동일한 효과를 갖는다는 것을 의미합니다.
  4. DELETE 메서드는 리소스 혹은 그것의 인스턴스가 데이터베이스에서 제거되도록 요청합니다.
    예를 들어, /companies/3/employees/john/은 3번 회사의 피고용자 컬렉션에서 john이라는 리소스를 삭제하도록 서버에 요청합니다.

다른 포스트에서 알아볼 몇 가지 다른 메서드들도 있습니다.

4) HTTP 응답 상태 코드

클라이언트가 API를 통해 서버에 요청을 할 때, 클라이언트는 실패했는지, 전달되었는지 혹은 요청이 잘못되었는지 등 피드백을 받아야 합니다. HTTP 상태 코드는 다양한 시나리오에서의 다양한 원인을 지닌 표준화된 코드 뭉치입니다. 서버는 항상 올바른 상태 코드를 반환해야 합니다.

다음은 HTTP 코드에 대한 중요한 카테고리입니다:

2xx (성공 범주)

이 상태 코드들은 요청된 동작이 수신되었고 서버에 의해 성공적으로 처리되었다는 것을 나타냅니다.

  • 200 OK GET, PUT 혹은 POST에 대한 성공을 나타내는 표준 HTTP 응답
  • 201 Created 새로운 인스턴스가 생성된 경우라면 이 상태 코드가 반환되어야 합니다. 예를 들어, POST 메서드를 사용해 새로운 인스턴스 생성 시, 201 상태 코드를 반환해야 합니다.
  • 204 No Content 요청이 성공적으로 처리되었지만 반환할 내용이 없다는 것을 나타냅니다. DELETE가 좋은 예입니다.
    DELETE /companies/43/employees/2는 2번 피고용자를 삭제하는데, 명시적으로 시스템에 삭제를 요청한 것이므로, API의 응답 본문 내에 어떤 데이터도 반환할 필요가 없습니다. 만약 employee 2가 데이터베이스 내에 존재하지 않는 것처럼, 오류가 있다면, 응답 코드는 2xx Success 범주가 아닌 4xx Client Error 범주가 되어야 합니다.

3xx (리다이렉션 범주)

  • 304 Not Modified 클라이언트가 캐시 내에 이미 응답을 지니고 있다는 것을 의미합니다. 따라서 동일한 데이터를 다시 전송할 필요가 없습니다.

4xx (클라이언트 오류 범주)

이 상태 코드들은 클라이언트가 잘못된 요청을 했다는 것을 나타냅니다.

  • 400 Bad Request 클라이언트가 요청한 바를 서버가 이해하지 못해 요청이 처리되지 않았다는 것을 의미합니다.
  • 401 Unauthorized 클라이언트가 리소스에 접근할 수 없다는 것을 의미하며, 요구되는 자격과 함께 다시 요청해야 합니다.
  • 403 Forbidden 요청이 유효하며 클라이언트가 인증되었지만, 클라이언트가 어떤 이유로 페이지나 리소스에 접근할 수 없다는 것을 의미합니다. 예를 들어, 인증된 클라이언트는 때때로 서버의 디렉토리에 접근할 수 없을 때가 해당됩니다.
  • 404 Not Found 요청된 리소스가 현재 이용 불가능하다는 것을 나타냅니다.
  • 410 Gone 요청된 리소스가 의도적으로 옮겨져서 더 이상 이용할 수 없다는 것을 나타냅니다.

5xx (서버 오류 범주)

  • 500 Internal Server Error 요청은 유효하나 서버가 요청을 전혀 처리할 수 없으며 예상치 않은 상태에 대응할 수 없다는 것을 의미합니다.
  • 503 Service Unavailable 서버가 다운되었거나 수신할 수 없어서 요청을 처리할 수 없다는 것을 의미합니다. 대부분 서버를 유지보수 중인 경우에 해당됩니다.

5) 필드 이름의 대소문자 관례

어떠한 대소문자 관례든지 따를 수 있지만, 애플리케이션 상에서는 일관성을 유지해야 합니다. 요청 본문 혹은 응답 타입이 JSON이라면 일관성을 유지하기 위해 camelCase를 따르시기 바랍니다.

6) 검색, 정렬, 필터링 그리고 페이지네이션

이 동작 모두 하나의 데이터셋에 대한 쿼리입니다. 이 동작을 처리하기 위한 새로운 API 집합은 존재하지 않습니다. GET 메서드 API에 쿼리 파라메터를 추가해야 합니다.

이러한 동작들의 구현 방법에 대한 예를 알아보도록 하죠.

  • 정렬 클라이언트가 정렬된 회사 목록을 얻으려고 하는 경우, GET /companies 엔드포인트는 쿼리 내에서 여러 정렬 파라메터에 접근해야 합니다. 예를 들어, GET /companies?sort=rank_asc는 회사 목록을 순위에 의해 올림차순으로 정렬합니다.
  • 필터링 데이터셋을 필터링하기 위해, 쿼리 파라메터를 통해 다양한 옵션을 전달할 수 있습니다. 예를 들어, GET /companies?category=banking&location=india는 인도에 위치한 은행 카테고리의 회사로 회사 목록 데이터를 필터링합니다.
  • 검색 회사 목록 내에서 회사 이름으로 검색할 때 API는 GET /companies?search=Digital Mckinsey가 되어야 합니다.
  • 페이지네이션 데이터셋이 너무 큰 경우, 데이터를 더 작은 조각을 나누어, 성능을 향상시키는데 도움을 주고 응답을 처리하기 더 쉽도록 해야 합니다. 예를 들어, GET /companies?page=23는 23번째 페이지의 회사 목록을 가져온다는 것을 의미합니다.

GET 메서드 내에 많은 쿼리 파라메터가 추가되어 URI가 너무 길면, 서버가 401 URI Too long이라는 HTTP 상태로 응답할 수 있으며, 이런 경우 파라메터를 POST 메서드의 요청 본문 내로 전달할 수 있습니다.

7) 버저닝

여러분의 API가 세계 곳곳에서 소비되고 있고, 어떤 큰 변화로 API가 업그레이드되었다면, 여러분의 API를 사용 중인 기존의 제품 혹은 서비스에 장애를 일으킬 수 있습니다.

http://api.yourservice.com/v1/companies/34/employees는 경로 내에 API의 버전 번호를 지닌 좋은 예입니다. 주요 업데이트가 있는 경우, 새로운 API 집합을 v2 혹은 v1.x.x로 이름지을 수 있습니다.

이 가이드라인은 개발에 대한 저의 경험으로 만들어졌습니다. 위에서 언급한 조언들에 대한 여러분들의 관점을 알고 싶습니다. 댓글을 남겨 제가 알도록 해주세요!

이 포스트가 좋다면, 공유하고 댓글을 남겨주시기 바랍니다.