REST API란?

Coastby·2023년 3월 27일
0

네트워크

목록 보기
1/4

처음 API를 만들기 시작하면서 REST API를 알게되었다. 그리고 프로젝트를 진행하면서도 REST API를 만들고, 나름 RESTful하게 설계했다고 생각하고 있었다. 이러한 생각의 기저에는 이전에 블로그에 이와 관련된 내용을 정리했었고, 많이 찾아봤었다는 근거가 있었다.

하지만, 이번에 면접 준비를 하면서 REST API란 무엇인가를 말해보려고 하니 정리가 되지 않았다... 상태의 표현을 전달하는...?? 응ㅇ..??
결국은 REST API에 대해서 알지 못했던 것이다. RESTful한 설계하는 방법도, REST에 대해서도 몰랐던 것이다. 그래서 다시 정리를 해보았다.

REST API

📌 REST란?

REpresentational State Transfer
a way of providing interoperability (상호운용성)* between computer systems on the Internet

*상호운용성 : 기종이 다른 컴퓨터나 단말기를 연결하여 통신할 수 있으며 다른 기기의 이용자 간에 원활하게 정보를 교환하거나 일련의 처리를 수행할 수 있는 특성.

📎 WEB

인터넷에서 정보를 공유할 때 정보들을 하이퍼텍스트로 연결한다. 이를 웹이라고 하며 아래와 같은 구성요소가 있다.

  • 표현 형식 : HTML
  • 식별자 : URI
  • 전송 방법 : HTTP 프로토콜

이 중에서 HTTP의 장점을 최대한 활용할 수 있는 아키텍처로 Roy Fielding이 REST를 소개하였고, 지금까지 정석처럼(?) 쓰이고 있다.

HTTP는 인터넷 프로토콜 중에서 애플리케이션에서 쓰이는 프로토콜이다.

📌 REST API란?

REST API란, REST 아키텍쳐 스타일을 따르는 API이다.

📎  REST란 :
분산 하이퍼미디어 시스템 (웹)을 위한 아키텍쳐 스타일이다.

  • 아키텍쳐 스타일 : 제약조건의 집합
  • 사실은 REST는 하이브리드 아키텍쳐 스타일이다
    → 아키텍쳐 스타일의 집합인 아키텍쳐 스타일

위의 내용을 정리하면, REST란 웹 (HTTP)의 상호운용성을 위한 제약조건들의 집합이다.
그렇다면 그 제약 조건들을 알아봐야 한다.

📌 REST를 구성하는 스타일 (제약조건)

1️⃣ Client - Server

  • 관심사의 분리 (Seperation of concern)
  • 데이터 저장에 대한 관심사사용자 인터페이스에 대한 관심사를 분리
  • 클라이언트 : 사용자 인터페이스의 이식성(portability)을 개선
  • 서버 : 확장성(scalability)를 개선

2️⃣ stateless

  • 클라이언트가 서버로 보내는 요청에는 해당 요청을 이해하는 데에 필요한 모든 정보가 포함되어있어야 하고, 서버측에 저장된 정보를 이용할 수 없다.
  • 장점 : 이는 가시성, 신뢰성, 확장성을 향상시킨다.
    • 가시성 (visibility) : 요청에 대한 전체적인 특징을 파악하기 위해 해당 요청 외에 다른 것들을 고려하지 않아도 된다.
    • 신뢰성 (reliability) : 부분적인 장애를 복구하기 위해서 고려해야할 것들이 많지 않다.
    • 확장성 (scalability) : 서버측 컴포넌트가 요청에 대한 정보를 저장하지 않아도 되기 때문에 리소스를 확보할 수 있고, 요청에 대한 정보를 관리하지 않기 때문에 구현이 더욱 쉬워진다.
  • 단점
    • 서버측에 요청에 관한 정보가 저장되지 않기 때문에, 반복되는 일련의 요청이 발생하여 네트워크 성능을 저하시킨다.
    • 상태를 클라이언트측에 저장하기 때문에 서버측의 일관된 제어를 받을 수 없다.

3️⃣ cache

  • 네트워크 성능을 향상시키기 위해 cache 제약조건을 추가한다.
  • Cache 제약조건 : 응답데이터가 cachable한지, non-cacheable한지 지정되어야 한다.
  • cacheable한 경우, 클라이언트 캐시에 동일한 요청에 대해 응답데이터를 나중에 재사용할 수 있는 권한이 부여된다.
  • 장점
    • 서버-클라이언트간의 통신을 제거함으로써 통신 지연시간을 감소시킬 수 있다.
    • 이를 통해, 네트워크 효율성 (efficiency), 확장성 (scalability), 사용자 만족도 (user-perceivedd performance)를 향상시킬 수 있다.
  • 단점
    • 신뢰성 (reliability) 저하 : 캐시 내에 오래된 (stale) 데이터가 포함되어 있다면 요청-응답에 대한 신뢰성이 저하될 수 있다.

4️⃣ layered system

  • 각 컴포넌트에 직접 접하고 있는 계층 너머의 컴포넌트를 볼 수 없도록 컴포넌트의 동작을 제한함으로써 아키텍처가 계층적인 층을 구성하도록 한다.
  • 어떤 시스템이 가지고 있는 지식 (knowledge)을 단일 계층으로 제한함으로써, 전체적인 시스템의 복잡도를 감소시키고 substrate independence를 촉진시킨다.
  • 계층구조를 이용함으로써, 기존의 레거시 (legacy) 서비스를 캡슐화하고, 새로운 서비스를 기존의 클라이언트로부터 보호한다.
  • 자주 사용되지 않는 기능을 공유 중개 컴포넌트 (shared intermediary)로 이동시킴으로써 컴포넌트를 단순화할 수 있다.
  • 중개 컴포넌트는 여러 네트우어크, 프로세서 사이에서 서비스의 로드 밸런싱을 가능하게하여 시스템의 확장성을 향상시킬 수 있다.
  • 단점
    • 데이터의 처리에 대한 오버헤드와 지연 (latency)이 심화되어, 사용자 가 성능 감소를 느낄 수 있다.
    • 단, cache 제약조건을 지원하는 네트워크 기반 시스템에서 중개 컴포넌트에 공유 캐시를 둠으로써 상쇄될 수 있다.
  • 이 제약조건을 추가하게되면, 여러 계층간의 데이터 전송이 이루어져야하므로 네트워크 성능이 감소한다. 또 각 컴포넌트간의 인터페이스를 정의해야하므로 추가적인 작업이 필요하다.
  • 하지만 cache (네트워크 성능 향상), uniform interface (일관된 인터페이스 정의)등의 제약조건으로 이러한 단점을 상쇄할 수 있다.

→ 위의 1️⃣ ~ 4️⃣ 조건들은 HTTP만 따라도 지킬 수 있는 것들이다.
핵심은 아래의 urniform interface 조건이다.

5️⃣ uniform interface

identification of resources (자원에 대한 식별)

  • 이름을 지닐 수 있는 모든 정보
  • 개념적인 대상 (ex. 문서, 이미지, 자원들의 집합..)
  • URI를 통해 자원을 식별해야 한다.

manipulation of resources through representations

  • representation : 특정한 상태의 자원에 대한 표현
  • 자원은 다양한 방식으로 표현 가능 (ex. 문서, 파일, HTTP 메세지 엔티티..)

self-descriptive messages

  • 온전히 메세지 내용만으로 이해할 수 있어야한다.
  • 클라이언트와 서버 사이의 컴포넌트들은 메세지의 내용을 참고하여 적절한 작업을 수행할 수 있어야 한다.
  • Host 헤더에 도메인명 기재 필요
    • 이는 가상호스트 문제 때문이다. 하나의 IP주소에 복수의 도메인명이 존재할 수 있다. IP주소만으로는 정확한 요청 대상을 찾아낼 수 없기 때문에 도메인을 기재해야 한다.
  • 캐쉬 관련 헤더를 통한 캐쉬 전략 지정

hypermedia as the engine of application statee (HATEOAS)

  • 어플리케이션의 상태는 hyperlink를 통해서 전이되어야한다.
    • HTML에서는 대체로 만족한다.
    • JSON에서는 link 헤더, 또는 body에 하이퍼링크를 포함하면서 만족시킬 수 있다.

○ 목적

  • 서버와 클라이언트가 독립적으로 진화할 수 있다.
    • self-descriptive (확장 가능한 커뮤니케이션) : 서버나 클라이언트가 변경되더라도 오고가는 메시지는 언제나 self-descriptive하므로 언제나 해석이 가능하다.
    • HATEOAS (애플리케이션 상태 전이의 late binding) : 어디서 어디로 전이가 가능한지 미리 결정되지 않는다. 어떤 상태로 전이가 완료되고 나서야 그 당음 전이될 수 있는 상태가 결정된다. → 링크는 동적으로 변경될 수 있다. 서버가 링크를 바꾸면 클라이언트는 따라간다.

6️⃣ code-on-demand (optioinal)

  • 서버에서 코드를 클라이언트에 보내서 실행할 수 있다 (javascript)
  • 장점
    • 클라이언트측에서 사전에 구현해야 할 기능을 감소시켜 클라이언트를 단순화할 수 있다.
    • 배포 후에 기능을 다운로드할 수 있어 시스템의 확장성 (extensibility)를 향상시킨다.
  • 단점
    • 가시성 (visibility)를 감소시킨다.
  • 이 조건은 특정한 목적이 있는 경우에 선택적으로 적용할 수 있으며, 그렇지 않은 경우 적용하지 않아도 된다.

REST가 웹의 독립적 진화에 도움을 주었나

앞에서 REST는 웹을 위한 아키텍쳐 스타일이라고 했다.
REST는 웹에서 클라이언트와 서버가 독립적인 진화를 할 수 있도록 돕고 있다. 그 결과 아래와 같은 영향을 줄 수 있었다.

  • HTTP에 지속적으로 영향을 줌
  • Host 헤더 추가
  • 길이 제한을 다루는 방법이 명시 (414 URI Too Long 등)
  • URI에서 리소스의 정의가 추상적으로 변경됨 : “식별하고자 하는 무언가”
  • 기타 HTTP 와 URI에 많은 영향을 줌
  • HTTP/1.1 명세 최신판에서 REST에 대한 언급이 들어감 (Representation)
  • 사실은 Roy T.Fielding이 HTTP와 URI 명세의 저자 중 한명이다.

REST API?

Roy Fielding은 REST API에 대해서 이렇게 말했다.

“An API that provides network-based access to resources via a urniform interface of self-descriptive messages containing hypertext to indicate potential state transitions might be part of an overall system that is a RESTrul application”
-- Roy T.Fielding

즉, "하이퍼텍스트를 포함한 self-descriptive한 메세지의 uniform interface를 통해 리소스에 접근하는 API" 이다.

→ REST 아키텍쳐 스타일을 따르는 API

📌 RESTful하기 위한 팁

추가로, 위의 제약조건 중 만족하기 어려운 self-descriptiveHATEOAS를 만족하기 위한 팁은 아래와 같다.

Self-descriptive

  • JSON이 RESTful하지 않은 이유

    • 명세에 JSON 문서를 파싱하는 방법은 명시되어 있으므로 성공적으로 파싱에 성공한다.
    • 하지만 “id”가 무엇을 의미하고, “title”이 무엇을 의미하는지 알 방법이 없다.
  • RESTful하게 만들기

    • 방법1 : Media type

      1. 미디어 타입을 하나 정의한다.
      2. 미디어 타입 문서를 작성한다. 이 문서에 “id”가 뭐고, “title”이 무슨 의미인지 정의한다.
      3. IANA에 미디어 타입을 등록한다. 이때 만든 문서를 미디어 타입의 명세로 등록한다.
      4. 메세지를 보는 사람이 명세를 찾아갈 수 있으므로 메세지를 온전히 해석할 수 있다.
    • 방법2 : Profile

      1. 명세를 작성한다.
      2. Link 헤더에 profile relation으로 해당 명세를 링크한다.

      단점 :

      1. 클라이언트가 Link 헤더 (RFC 5988)와 profile (RFC 6906)을 이해해야한다.
      2. Content negotiation을 할 수 없다. : 클랑이언트가 이해하지 못한 것을 서버가 모른다.

HATEOAS

  • JSON이 RESTful하지 않은 이유
    • 다음 상태로 전이할 링크가 없다.
  • RESTful하게 만들기
    • 방법 1 : data에 넣기
      • data에 다양한 방법으로 하이퍼링크를 표현한다. 단점 : 링크를 표현하는 방법을 직접 정의해야한다.
      • JSON으로 하이퍼링크를 표현하는 방법을 정의한 명세들을 활용한다. (JSON API, HAL, UBER, Siren…) 단점 : 기존 API를 많이 고쳐야한다.
    • 방법 2 : HTTP 헤더 이용
      • Link, Location 등을 헤더로 링크를 표현한다. 단점 : 정의된 relation만 활용한다면 표현에 한계가 있다.

정리

  • 오늘날 대부분의 “REST API”는 사실 REST를 따르지 않고 있다.
  • REST의 제약조건 중에서 특히 self-descriptiveHATEOAS를 잘 만족하지 못한다.
  • REST는 긴 시간에 걸쳐 진화하는 웹 애플리케이션을 위한 것이다.
  • REST를 따를 것인지는 API를 설계하는 이들이 스스로 판단하여 결정해야 한다.
  • REST를 따르겠다면, self-descriptiveHATEOAS를 만족시켜야한다.
    • self-descriptive는 custom media type이나 profile link relation 등으로 만족시킬 수 있다.
    • HATEOAS는 HTTP 헤더나 본문에 링크를 담아 만족시킬 수 있다.
  • REST를 따르지 않겠다면, HTTP API로 부르거나, 그냥 REST API라고 부를 수 있다. → 또는 다른 API 표준 선택하기 (GraphQL API)
    GraphQL과 REST의 차이점
    GraphQL과 RESTful API


아래는 흔히 볼 수 있는 RESTful한 설계를 위한 가이드라인이다. 이에 관한 자료는 링크를 참조하면 될 것이다.
RESTful API 설계 가이드

REST 구성

자원(Resource) : URL

  • 모든 자원에 고유한 ID가 존재하고, 이 자원은 Server에 존재한다.
  • 자원을 구별하는 ID는 ‘/groups/:group_id’와 같은 HTTP URL이다.
  • Client는 URL를 이용해서 자원을 지정하고 해당 자원의 상태(정보)에 대한 조작을 Server에 요청한다.

행위(Verb) : HTTP Method

  • HTTP 프로토콜의 Method를 사용한다.
  • HTTP 프로토콜은 GET, POST, PUT, DELETE와 같은 메서드를 제공한다.

표현(Representation of Resource)

  • Client가 자원의 상태(정보)에 대한 조작을 요청하면 Server는 이에 적절한 응답(Representation)을 보낸다.
  • REST에서 하나의 자원은 JSON, XML, TEXT, RSS 등 여러 형태의 Representation으로 나타내어 질 수 있다. JSON 혹은 XML를 통해 데이터를 주고 받는 것이 일반적이다.

REST API 디자인 가이드

첫 번째, URI는 정보의 자원을 표현해야 한다.

두 번째, 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.

📎 참고

profile
훈이야 화이팅

0개의 댓글