詳細検索

RESTful API 101

아바타
글쓴이 Chen Ziyu

RESTful API 101
English에서 번역 • 원문 보기

21세기에 백엔드 엔지니어가 RESTful API를 모른다는 것은 거의 불가능합니다. RESTful API는 가장 인기 있는 API 유형 중 하나이기 때문입니다. 이 API의 인기는 주로 확장성, 유연성, 단순성 덕분이며, 이는 현대 API에서 매우 선호되는 특성입니다. 이러한 특성도 매력적이라면, RESTful 원칙에 따라 API를 구축하는 것을 고려해 보시기 바랍니다. 이 글에서는 RESTful API가 무엇인지 설명하고, 처음부터 설계하는 방법을 시연하겠습니다.

RESTful API란 무엇인가요?

RESTful API의 약어 "REST"부터 시작해 보겠습니다. "REST"는 재표현 상태 전송(REpresentational State Transfer)의 약자입니다. 이는 다섯 가지 제약 조건을 가진 소프트웨어 아키텍처 스타일입니다:

  1. 균일 인터페이스
  2. 무국적자
  3. 캐시 가능
  4. 클라이언트-서버 분리
  5. 계층 시스템.

RESTful API는 본질적으로 위의 어떤 제약도 위반하지 않는 API입니다. 하나씩 살펴보겠습니다.

균일 인터페이스

이 제약은 API 설계와 관련되어 백엔드 엔지니어에게 가장 관련성이 높습니다. 이 제약은 클라이언트의 장치나 애플리케이션 유형에 관계없이 특정 서버와 상호작용하는 데 오직 하나의 통일된 방식만 있어야 한다는 것을 규정합니다. 다음은 이러한 통일된 인터페이스를 구축하기 위한 몇 가지 지침입니다. 균일한 인터페이스는 일관성을 보장하고 API 개발 및 사용을 단순화합니다.

  1. 리소스 기반: 클라이언트는 각 요청에서 어떤 리소스(객체, 데이터 또는 서비스)에 접근하려는지 URI에서 지정해야 합니다.
  2. 표현을 통한 자원 조작: 클라이언트가 자원을 조작(편집 또는 삭제)할 수 있도록 하려면, 자원 수정 또는 삭제에 필요한 정보를 포함하는 자원 표현을 보유해야 합니다.
  3. 자기 설명 메시지: 각 메시지(요청 또는 응답)는 수신자가 메시지를 이해할 수 있을 만큼 충분한 정보를 포함해야 합니다. 이 제약은 클라이언트와 서버 모두에게 적용됩니다. 클라이언트는 요청에 HTTP 메서드를 포함시켜 서버에 요청으로 수행할 작업을 알려야 합니다. 서버가 보내는 응답에는 콘텐츠 유형과 응답 상태 코드를 포함해야 하며, 이를 통해 클라이언트가 응답 정보를 해석할 수 있습니다. 필요하다면 클라이언트와 서버는 메시지에 다른 정보도 포함할 수 있습니다.
  4. 애플리케이션 상태 엔진으로서의 하이퍼미디어(HATEOAS): 각 응답에는 하이퍼미디어가 포함되어야 합니다. 하이퍼미디어는 클라이언트가 현재 응답을 받은 후 추가 요청에 관한 정보입니다. 서버는 이를 통해 클라이언트에게 다음에 무엇을 할 수 있는지 알립니다.

무국적자

이 제약 조건은 서버가 클라이언트의 상태를 추적하는 것을 금지합니다. 결과적으로 클라이언트는 상태 추적을 위해 서버에 의존할 수 없으며, 요청을 이행하는 데 필요한 모든 정보를 포함해야 합니다. 서버는 각 요청을 독립 실행형으로 취급합니다. 이러한 상태 무형성은 서버를 상태 유지 작업에서 해방시켜 가용성을 향상시킵니다.

캐시 가능

이 제약 조건은 서버가 모든 응답에서 응답이 캐시 가능한지 여부와 클라이언트가 캐시할 수 있는 시간을 명시하도록 요구합니다. 이렇게 하면 클라이언트와 서버 간의 불필요한 통신을 없애고 전체 성능과 가용성을 향상시킬 수 있는 효율적인 캐싱 시스템을 구축할 수 있습니다.

클라이언트-서버 분리

이 제약은 RESTful API 아키텍처에서 클라이언트와 서버 간의 업무 분리를 보여줍니다. 클라이언트는 자원을 생성, 접근 또는 조작하는 요청만 책임집니다. 서버는 클라이언트의 요청에 대응하여 자원을 제공하고 관리하는 역할만 담당합니다. 클라이언트-서버 분리는 프론트엔드와 백엔드가 독립적으로 진화할 수 있도록 합니다.

레이어드 시스템

클라이언트와 서버 사이에 애플리케이션 아키텍처에는 여러 계층이 있을 수 있습니다. 이러한 중간 계층들은 보통 애플리케이션의 핵심 기능과 보완적인 역할을 합니다. 예를 들어 프록시(부하 분산)와 게이트웨이(프로토콜 변환용)가 있습니다. "계층 시스템" 제약은 각 계층이 바로 옆에 있는 계층 이외의 레이어와 상호작용하지 않도록 제한합니다. 이는 애플리케이션의 구조적 단순성을 보장하고 계층 간 상호작용에 불필요한 복잡성을 도입하는 것을 방지합니다.

RESTful API 구축 방법 (예시)

다음으로, RESTful API를 만드는 구체적인 예시를 들어 설명하겠습니다. 앞서 언급한 제약 조건과 지침을 참고하겠습니다. 기억이 어렵다면 이전 섹션으로 돌아가 주세요. 예를 들어, 블로깅 사이트를 만들고 싶다고 가정해 봅시다. 첫 번째 단계에서는 다음 작업을 수행할 엔드포인트를 개발해야 합니다:

  1. 새 게시물 만들기
  2. 모든 게시물 검색
  3. 게시물 ID로 검색
  4. 게시물 업데이트
  5. 게시물 삭제

몇 개의 URI가 필요한지 추측할 수 있나요? 직관적으로 한 행동에 하나 URI가 필요하기 때문에 다섯 개를 답하고 싶어질 수도 있습니다. 하지만 "자원 기반" 지침을 완전히 준수한다면 두 개의 URI만 필요합니다. URI는 자원에 대한 행동이 아니라 자원을 나타내야 합니다. 여기서 제공하는 두 가지 유형의 자원은 게시물 목록과 단일 게시물입니다. 각각 다음 두 개의 URI를 생성할 수 있습니다:

  1. 게시물 목록: '/api/v1/posts'
  2. 단일 게시물: '/api/v1/posts/'

질문할 수도 있습니다: 두 개의 URI만으로 다섯 개의 서로 다른 액션을 어떻게 표현할 수 있을까요? 답은 간단합니다: HTTP 메서드를 사용해 액션을 표현할 수 있고, 같은 자원에서 수행된 액션도 동일한 URI를 공유할 수 있습니다. 필요한 HTTP 메서드는 다음과 같습니다:

  1. GET: 자원 수집
  2. 게시물: 자원 생성
  3. PUT: 자원 업데이트
  4. 삭제: 자원 제거

이제 위의 다섯 가지 작업을 지원하기 위해 엔드포인트를 어떻게 설계해야 하는지 살펴보겠습니다.

  1. 새 게시물 생성: '[POST] /api/v1/posts'
  2. 모든 게시물 조회: '[GET] /api/v1/posts'
  3. 게시물 ID로 검색 하기: '[GET] /api/v1/posts/'
  4. 게시물 업데이트: '[PUT] /api/v1/posts/'
  5. 게시물 삭제: '[삭제] /api/v1/posts/'

다음으로, 각 엔드포인트의 요청과 응답이 어떻게 보여야 하는지 설계하는 것으로 넘어가겠습니다. 우리는 여전히 균일 인터페이스 제약의 지침을 염두에 두어야 합니다. 이 글에서는 세 번째 행동에 집중해 보겠습니다.

ID로 게시물 조회하기: '[GET] /api/v1/posts/'

"표현을 통한 자원 조작" 지침을 따르려면, 클라이언트가 특정 게시물을 조작(편집 또는 삭제)하는 데 필요한 모든 정보를 갖추었는지 확인해야 합니다. 게시물을 편집하거나 삭제하려면, 클라이언트는 게시물의 ID를 지정해야 서버가 어떤 게시물을 조작할지 식별할 수 있습니다. 게시물을 편집하려면 클라이언트가 편집할 수 있는 필드와 게시물의 ID도 알아야 합니다. 예를 들어 클라이언트가 다음 필드를 편집할 수 있다고 가정해 봅시다:

  1. 제목

그러면 '[GET] /api/v1/posts/'의 응답 데이터는 다음과 같습니다: 응답:

{ 
   "id":1, 
   "title": RESTful API 101", 
   "body": "이 문서는 RESTful API에 관한 것입니다." 
}

또한 클라이언트와 서버가 서로에게 자기 설명 메시지를 보내야 합니다. "자기 설명 메시지" 지침을 염두에 두면, '[GET] /api/v1/posts/'의 요청과 응답을 다음과 같이 설계할 수 있습니다: 요청:

HTTP 메서드: GET
URI: /api/v1/posts/ 
프로토콜: HTTP/1.1
헤더: Accept: application/json

이 요청에서 클라이언트는 HTTP 메서드(GET)를 통해 액션을 지정했습니다. 클라이언트는 URI('/api/v1/posts/')를 포함하여 행동의 대상 자원을 정확히 지정했습니다. 또한 클라이언트는 사용하는 프로토콜(HTTP/1.1)과 수신하는 데이터 유형(application/json)도 포함시켰습니다. 응답:

프로토콜: HTTP/1.1
응답 상태 코드: 200 OK
헤더: Content-Type: application/json
{ 
   "id":1, 
   "title": RESTful API 101", 
   "body": "이 문서는 RESTful API에 관한 것입니다." 
}

이 응답에서 서버는 200 응답 상태 코드를 통해 요청이 성공적으로 처리되었다고 클라이언트에게 알립니다. 또한 클라이언트가 응답 데이터를 해석할 수 있도록 콘텐츠 유형도 추가했습니다.

우리는 여전히 통일 인터페이스를 구축하기 위해 한 가지 더 준수해야 할 가이드라인: "애플리케이션 상태의 엔진으로서의 하이퍼미디어"입니다. 이 가이드라인은 서버가 클라이언트가 취할 수 있는 추가 조치를 포함하도록 요구합니다. 게시물 세부 정보가 포함된 응답을 받은 후, 클라이언트는 게시물을 편집하거나 삭제할 수 있습니다. 따라서 서버는 응답 데이터에 게시물 편집 또는 삭제 요청을 추가할 수 있습니다. 응답:

프로토콜: HTTP/1.1
응답 상태 코드: 200 OK
헤더: Content-Type: application/json
{ 
   "id":1, 
   "title": RESTful API 101", 
   "body": "이 문서는 RESTful API에 관한 것입니다.", 
   "링크":[ 
      { 
         "method":"PUT", 
         "uri":"/api/v1/posts/" 
      }, 
      { 
         "메서드":"DELETE", 
         "uri":"/api/v1/posts/" 
      }
   ]
}

이제 통일된 인터페이스를 구축했으니, 시스템이 "Cacheable" 제약 조건을 준수하는지 확인해 봅시다. Cache-Control 헤더로 이 작업을 할 수 있습니다. 서버가 클라이언트가 최대 10분(600초) 동안 게시물을 캐시할 수 있도록 허용한다고 가정합니다. 그다음 최종 응답은 다음과 같습니다: 응답:

프로토콜: HTTP/1.1
응답 상태 코드: 200 OK
헤더: 
Content-Type: application/json
캐시 제어: 최대 연령=600
{ 
   "id":1, 
   "title": RESTful API 101", 
   "body": "이 문서는 RESTful API에 관한 것입니다.", 
   "링크":[ 
      { 
         "method":"PUT", 
         "uri":"/api/v1/posts/" 
      }, 
      { 
         "메서드":"DELETE", 
         "uri":"/api/v1/posts/" 
      }
   ]
}

'캐시-제어: 최대 연령=600'은 클라이언트가 최대 600초간 데이터를 캐시할 수 있음을 의미합니다.

지금까지 "Uniform Interface"와 "Cacheable" 제약 조건을 살펴보았습니다. 이 예시의 다른 제약 조건들은 시스템 설계와 관련되어 있어 설명하기 어렵지만, RESTful API를 구축할 때 꼭 염두에 두시기 바랍니다.

요약

이 글에서는 RESTful API의 정의와 RESTful API가 위반할 수 없는 다섯 가지 제약 조건을 다루었습니다. 또한 예제와 함께 RESTful API 구축 방법도 보여드렸습니다. 이 글이 RESTful API를 더 잘 이해하는 데 도움이 되었기를 바랍니다.

더 읽기:

https://www.geeksforgeeks.org/rest-api-architectural-constraints/ https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design https://restfulapi.net/hateoas/

Related Articles