REST API 디자인

SungBum Park·2021년 5월 2일
0

REST API

REST(Representational State Transfer)는 하이퍼 미디어 기반 분산 시스템을 구축하기 위한 아키텍처 스타일이다. 간단하게 말하면 HTTP 환경에서 서버와 클라이언트 사이에 주고받는 API의 규칙이라고 말할 수 있다.

말그대로 규칙이므로 이를 준수하지 않는다고 해서 에러가 나거나 API를 사용할 수 없는 것은 아니다. 하지만 이를 지키지 않으면 유지보수 관점에서 매우 좋지 않다. REST API는 매우 범용적인 API이고, 대부분의 개발자가 공유하는 자원의 표현 방법이다. 이러한 관점에서도 REST API는 매우 중요하다.

REST API에서 알아야할 기본 정의들

  • Resource: API에서 정의하는 자원, 객체, 식별자 등
  • Collections: Resource의 집합
  • URL(Uniform Resource Locator): Resource의 위치

URL VS URI (Uniform Resource Identifier)
URL과 URI는 자주 혼용된다. 예제를 보면 간단히 구분할 수 있다.

Ex, https://velog.io/@codemcd

URL은 자원의 정확한 위치를 표현한 것이고, URI는 자원들을 구분할 수 있는 식별자이다.

RESTful API를 디자인하는 5가지 기본 설계 지침은 다음과 같다.

  • Reousrces
  • HTTP Method
  • HTTP Headers
  • Query Parameter
  • Status Code

Resources

Resource를 표현하는 방법은 URL이다. 일반적으로 REAT API의 URL 형식은 다음과 같다.

[프로토콜]://[IP]/[버전]/[resource 명]/[ID]
Ex, https://restfulapi.com/v1.0/users/123

[프로토콜]://[IP]는 웹 브라우저가 이해하는 기본적인 URL 구조이며, 그 뒤에 어떤 것을 정의하는지가 어떤 API를 호출할지 결정한다. 즉, URL은 하나의 API를 식별하는 식별자 역할도 한다.(URI)

위는 일반적으로 가장 많이 사용되는 자원 표현 방법을 순서대로 나열한 것이다. 그 이외에 더 추가될 수도 있고, 사용이 안될 수도 있다.

표현의 세부 규칙은 다음과 같다.

  • Resource 명은 명사로 표현하고, 복수형을 사용한다.
  • URL case는 camelCase, snake_case, spinal-case 중 적절한 케이스를 선택하고, 일관되도록 사용한다. (3 가지 모두 거대 기업에서 사용하므로, 적절히 취향에 따라 선택해서 사용하면 좋을 듯 하다.)

HTTP Method

Resource가 어떤 행동을 할지는 HTTP Method를 통해 표현한다.

GET

지정된 URL의 자원을 가져오는 요청이다.

  • GET 요청은 서버에 어떠한 영향을 주지 않는 안전한 메서드여야 한다.
  • GET 요청은 멱등성을 가진다.

멱등성?
동일한 요청을 한 번 보내는 것과 여러 번 연속으로 보내는 것이 같은 효과를 지니고, 서버의 상태도 동일하게 유지할 때 해당 HTTP 메서드는 멱등성을 가졌다고 말한다.

  • 멱등성 메서드는 통계, 기록 등을 제외하면 어떠한 side effect도 존재해서는 안된다.
  • 안전한 메서드(GET, HEAD, OPTION)는 멱등성도 가진다.
  • 올바르게 구현된 GET, HEAD, PUT, DELETE 메서드는 멱등성을 가진다.
  • 멱등성을 따질 땐 실제 서버의 상태만 보면 되며, 응답 코드는 요청마다 다를 수 있다. (DELETE 요청의 첫번 째 응답 코드는 200이지만, 두 번째 요청부터는 404를 반환한다.)

출처: https://developer.mozilla.org/ko/docs/Glossary/Idempotent

안전한 메서드?
서버의 상태를 변경하지 않는 메서드를 말한다. (read-only) GET, HEAD, OPTION 메서드가 안전한 메서드에 속한다.
출처: https://developer.mozilla.org/en-US/docs/Glossary/Safe

POST

서버로 데이터를 전송하는 요청이다.

  • 데이터는 요청 메시지의 본문(페이로드, payload)에 담는다.
  • 일반적으로 요청한 데이터로 새로운 리소스를 만드는 데 사용한다.
  • POST 메서드는 안전하지 않은 메서드며, 멱등성을 보장하지 않는다.

PUT

요청 본문에 리소스 정보를 담아 서버에게 새로운 리소스를 생성하거나 요청한 리소스로 업데이트하는 요청이다.

  • PUT의 스팩은 요청 리소스를 만들거나 업데이트이지만, 대부분 업데이트만 지원한다.
  • PUT 메서드는 안전하지 않은 메서드이지만, 멱등성은 보장한다.(POST와 차이)

PATCH

리소스의 부분적인 수정을 위한 요청이다.

  • PUT 메서드는 리소스 전체를 업데이트하며 요청 데이터 역시 리소스 전체를 담아야 하지만, PATCH 메서드는 요청 본문에 수정이 필요한 리소스의 정보만 담는다.
  • PATCH 메서드는 안전하지 않은 메서드이며, 멱등성을 보장하지 않는다.
  • PATCH 메서드 역시 PUT과 같이 전체 리소스를 요청하는 등의 방법으로 PUT과 같이 멱등성을 보장할 수도 있다.

DELETE

지정한 리소스를 삭제하는 요청이다.

  • DELETE 메서드는 안전하지 않은 메서드이지만, 멱등성은 보장한다.

HTTP Headers

HTTP 헤더는 요청, 응답, 엔티티 바디에 대한 정보를 제공한다. 헤더의 종류는 다음과 같다.

  • General Header: 요청 및 응답 메시지 모두에 포함될 수 있다.
  • Client Request Header: 요청 메시지에만 포함될 수 있다.
  • Server Response Header: 응답 메시지에만 포함될 수 있다.
  • Entity Header: 엔티티 바디에 대한 메타 정보와 관련된 헤더

미디어 유형(Content Type)

미디어 유형은 HTTP 통신에서 리소스의 유형을 말한다. HTTP에서는 MIME 타입이라고도 불린다. 미디어 형식을 정의할 때는 HTTP 헤더 중 Content-Type 헤더에 정의한다. 이는 응답과 요청 메시지 모두에 정의할 수 있는 General Header이다.

요청 메시지 헤더에서는 Accept 헤더를 통해 응답 메시지에서 받을 미디어 유형을 정의할 수 있다.

실제 MIME 타입은 이 링크에서 확인할 수 있다.

Query Parameters

GET 메서드로 자원을 요청할 때는 어떤 자원을 요청할지에 대한 수 많은 경우의 수가 존재한다. 특정 사용자 조회, 정렬된 자원 조회 등이 그 예시이다. 이러한 조회 기능을 식별하기 위해서 Query Parameter과 Path Variable 두 가지를 사용한다.

위 두 가지는 간단한 예제를 보면 쉽게 구분할 수 있다. 예를 들어, id가 123인 사용자를 조회하는 URL을 살펴보자.

Query Parameter

/users?id=123

Path Variable

/users/123

사실, 한 기능에 대해 대부분은 Query Parameter와 Path Variable 둘 다 표현할 수 있다. 그렇다면 이 두 가지에 대한 베스트 프랙티스는 무엇일까?

Query Parameter VS Path Variable, Best Practice

Path Variable은 자원을 식별할 때 사용한다. 즉 위 예제에서 id가 123인 사용자를 조회할 때는 Query Parameter보다는 Path Variable을 사용하는 것이 좋다.

/users/123
/articles/123
/comments/123

Query Parameter는 자원에 대한 정렬이나 필터링 등을 수행할 때 사용하는 것이 좋다. 대표적으로 다음과 같은 경우가 있을 수 있다.

  • Paging: 페이징 처리
  • Filtering: 속성의 기대값을 지정하여 자원을 필터링한다. 한 속성에 대한 여러 개의 기대값으로 필터링이 가능하고, 여러 개의 속성으로 필터링도 가능하다.
  • Sorting: 자원을 정렬한다.
  • Searching: Filtering과 유사하지만, 정확한 기대값이 아닌 경우 이에 속한다.
# 스택 오버플로우 URL 참고
/questions?page=10&pagesize=20			# 10번 째 페이지의 질문 20개 조회
/questions?filter=NoAnswers			# 답변이 없는 질문 조회
/questions?sort=RecentActivity			# 최근 생성된 일자순으로 정렬된 질문 목록 조회
/questions/search?q=query+parameter		# 검색어 'query parameter' 질문 조회

Status Code (상태 코드)

REST API 요청의 응답으로 적절한 상태 코드를 반환하는 것이 중요하다. 상태코드는 HTTP 응답 헤더에 명시되어 있으며, [상태 코드] [사유 구절] 의 모습을 하고 있다.

대표적으로 다음과 같은 상태 코드가 있다.

200-299: 성공 상태 코드

  • 200 OK: 요청이 성공적으로 처리되었다는 의미 (성공의 의미는 HTTP 메서드에 따라 다름)
  • 201 Created: POST, PUT 요청과 같이 서버에 자원을 생성했다는 의미 (응답 Location 헤더에 생성된 자원 정보를 포함)

300-399: 리다이렉션 상태 코드

  • 302 Found: 요청한 자원의 URI가 일시적으로 변경되었다는 의미
  • 304 NotModified: 클라이언트에게 응답이 수정되지 않았음을 의미 (주로 캐시를 위한 목적)

400-499: 클라이언트 에러 상태 코드

  • 400 Bad Request: 잘못된 문법으로 서버가 요청을 이해할 수 없다는 의미
  • 401 Unauthorized: 클라이언트는 요청한 응답을 받기 위해서 인증을 해야한다는 의미
  • 403 Forbidden: 클라이언트는 요청한 자원에 접근할 권리가 없다는 의미 (401과 차이는 403은 서버가 클라이언트가 누구인지 알고 있음)
  • 404 Not Found: 서버가 요청받은 자원을 찾을 수 없다는 의미 (브라우저에서는 존재하지 않는 URL 의미로 사용)

500-599: 서버 에러 상태 코드

  • 500 Internal Server Error: 서버에서 요청을 처리하는 중 알 수 없는 에러가 발생했다는 의미 (API 개발자 입장에서 가장 피해야할 상태 코드)

그 외

버전 관리

API를 개발한 이후, 변경될 가능성은 매우 크다. 특히 요청 본문이나 응답 본문에 변경이 발생하면 해당 API는 서버나 클라이언트에서 정상적으로 동작하지 않을 수 있다. 이를 유연하게 대응하고자 API에 버전을 명시하는 방법이 있다.

그렇다면 API의 버전 관리 방법에 대해 간단히 살펴보자.

버전 관리 없음

사실, REST API에서 추구하는 방법은 버전 관리를 하지 않는 것이다. 하지만 이는 변경에 대응하기가 어려워진다.

URI 버전 관리

URI에 버전을 명시하는 방법이다.

/v1/users/123	# API v1의 id가 123인 유저 정보를 조회

버전을 표현하는 방식은 v[메이저 버전] 또는 v[메이저 버전].[마이너 버전] 으로 표현할 수 있다.

Query Parameter 버전 관리

/users/123?version=1

Header 버전 관리

요청 헤더에 버전 정보를 명시할 수 있다.

GET https://restapi.com/users/123 HTTP/1.1
Custom-Header: api-version=1
GET https://restapi.com/users/123 HTTP/1.1
Accept: application/vnd.adventure-works.v1+json

어떤 버전 관리 방법을 선택할 지는 성능, 캐싱 등 상황에 따라 다르다. 일반적으로 캐싱에 적절한 URI 또는 Query Parameter 방식을 사용한다. (그 중에서도 URI 방식을 대부분 사용하는 듯 하다.)

참고 자료

profile
https://parker1609.github.io/ 블로그 이전

1개의 댓글

comment-user-thumbnail
2024년 6월 26일

Games that involve quick Banana Clicker decision-making can improve real-life decision-making abilities.

답글 달기