Skip to main content

REST API에 대한 오해

@eungjun-yi님의 그런 REST API로 괜찮은가 컨퍼런스 영상과 Roy Thomas Fielding의 논문 Architectural Styles and the Design of Network-based Software Architectures을 참고해 작성했다.

도대체 REST API란 무엇일까?


REST API의 정의

사실 Roy Thomas Fielding의 논문에서는 "REST API"라는 단어가 직접 언급 돼 있지는 않다. (RESTful 이라는 단어도 논문에는 나오지 않았지만, Roy가 사용하기는 하는데, 이게 REST의 형용사적인 표현인 건지, REST 스타일의 일부가 적용된 Web 서비스인 것인지는 의견이 분분하다. 참고로 AWS에서는 후자로 표현한다.)

그래서 REST API를 말하기 전, REST에 대해 먼저 말하자면, REpresentational State Transfer의 약어이다. 이때, REST는 분산 하이퍼미디어 시스템(ex. 웹)의 추상화 된 아키텍처 스타일이다. 주의해야 할 점은, 분산 애플리케이션을 위한 구조적인 모델이 아니라는 점이다. 또한, REST는 구조적인 제약(혹은 스타일)이지, 프로토콜이 아니다.

따라서 REST API란, REST 아키텍처 스타일을 따르는 API라고 할 수 있다.


REST style을 구성하는 Constraints

  • Starting with Null Style: 1. 아무 것도 없는 상태에서 시스템에 맞춰 익숙한 요소들을 조합해 시스템에 맞는 아키텍처를 만들어내거나, 2. 어떠한 제약도 없는 상태에서, 시스템이 전반적으로 필요로 하는 요구사항부터 시작해 점점 제약 조건을 붙여가며 적용하는 것을 말한다. 1번은 창의력과 이상을 강조하는 데에 반해, 2번은 제약과 시스템 컨텍스트에 대한 이해를 강조한다. REST는 2번의 과정을 통해 개발되었다. 따라서 REST style은 특정 제약 조건들을 조합한 구조적인 스타일이라는 것이다.
  • Client-Server: 사용자 인터페이스를 데이터 저장과 관련된 문제로부터 분리한다. 그로 인해, 사용자 인터페이스의 여러 플랫폼에 대한 이식성을 향상시킬 수 있고, 서버 컴포넌트를 단순화 시킴으로써 확장성을 향상시킬 수 있다. 즉, 클라이언트와 서버는 분리돼 있기 때문에, 클라이언트는 resource에 해당하는 URI외에 알 수 없으며, server application과 상호작용할 수 없다.
  • Stateless: 클라이언트와 서버는 상태를 가지지 않으며 상호작용해야 한다는 제약을 추가했다. 따라서 클라이언트로부터의 모든 요청은 서버가 어떠한 컨텍스트 없이 이해할 수 있도록 자세해야 한다. 또한, 세션의 상태는 클라이언트에서 유지되어야 한다. 이러한 제약을 통해 가시성, 신뢰성, 확장성을 야기할 수 있다.
  • Cache: 클라이언트와 서버 간 무상태를 유지하며 네트워크를 효율적으로 구성하기 위해서 캐시라는 제약을 추가했다. 요청에 따른 응답에는 cacheable한 지, not cacheable한 지 명백하게 표시되어야 한다. 이는 클라이언트 및 서버 모두에서 적용 가능하다.
  • Uniform Interface: 리소스에 대한 모든 요청은 동일한 구조와 표준을 사용해야 한다. HTTP Method와 URI를 통해 클라이언트가 서버의 리소스에 액세스하고 조작할 수 있어야 한다. 또한, 리소스에 대한 메타데이터(자원의 상태 및 버전 등)를 반환해야 한다.
  • Layered System: 클라이언트는 서버와 직접적으로 통신하지만, 서버는 다른 시스템(캐시, 로드밸런서, 게이트웨이 등)과 통신할 수 있다. 이를 통해 시스템을 더욱 유연하고 확장 가능하게 만들 수 있다.

잘못 알고 있는 REST API

REST API의 정의

보통 REST API를 정의한다 그러면, "URI(Uniform Resource Identifier)를 통해 자원(Resource)을 명시하고, HTTP Method(ex. POST, GET, PUT, DELETE)를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것" 등으로 많이 소개한다. 하지만 이는 완전히 잘못됐다고 생각한다. (특히 CRUD Operation을 적용하는 것...이라니...!?)

"REST(REpresentational State Transfer)에서 URI를 통해 자원을 명시하는 것"?은 오히려 RFC 2396에서 소개하는 URI라는 개념에 대한 내용에 가깝다고 생각한다. 물론 Roy Fielding 또한 논문의 6.2 REST Applied to URI에서 URI에 REST 스타일을 적용했다고 하는데(이는 Roy 본인이 RFC 2396의 저자이기도 하기 때문에 작성된 것으로 보인다.), REST 스타일을 '적용'했다고 했지, REST 스타일의 정의를 표현한 것은 아니라고 생각한다.

즉, 앞에서도 언급했지만 REST는 수많은 구조적인 스타일 중 하나일 뿐이며, 따라서 REST API라고 누군가 묻는다면, "REST 스타일을 따르는 API"라고 하는 것이 가장 정확해 보인다. 그리고 이후로 추가 질문으로 그렇다면 REST가 무엇인지에 대해 묻는다면, 그제서야 REST 아키텍처 스타일의 조건에 대해 말하는 것이 옳다고 생각한다.


논문에서 말하고자 한 REST가 사실상 de facto standard가 된 것에 대해

사실 Roy가 해당 논문에서 REST에 대해 언급한 부분은 오직 CHAPTER 5 Representational State Transfer (REST)에 불과하다. 오히려 앞의 CHAPTER의 경우, 구조적인 스타일을 통해 소프트웨어의 구조를 이해하고 정의하는 것에 대한 내용이다. 구성된 챕터는 다음과 같다.

  • CHAPTER 1. Software Architecture
  • CHAPTER 2. Network-based Application Architectures
  • CHAPTER 3. Network-based Architectural Styles
  • CHAPTER 4. Designing the Web Architecture: Problems and Insights
  • CHAPTER 5. Representational State Transfer (REST)
  • CHAPTER 6. Experience and Evaluation

즉, Roy는 구조적인 스타일을 통해 보다 소프트웨어의 구조를 이해하기 위한 하나의 예시이자 설명으로 REST를 소개한 것이다. 그리고 이는 Starting with Null Style이라는 제약에 따라, 여러 제약들을 하나씩 추가한 예로, REST라는 아키텍처 스타일을 소개한 것일 뿐이다.

이는 CHAPTER 1.5 Styles에 아래와 같이 소개 돼 있다.

Some architectural styles are often portrayed as "silver bullet" solutions for all forms of software. However, a good designer should select a style that matches the needs of the particular problem being solved.

즉, 아키텍처 디자이너는 one-size-fits-all과 같은 "silver bullet" 스타일을 피하라는 내용인데, 안타깝게도 REST가 de facto standard가 된 현실이다.

또한, 분산 하이퍼미디어 시스템에 적합한 예시로 REST를 소개했지, 그 외의 스타일에는 최적이 아닐 것이라고 언급까지 했다. 이는 CHAPTER 5에 아래와 같이 언급돼 있다.

The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.


REST의 REpresentational에 대해

도대체 REpresentational 하다는 것이 무슨 의미일까? 간단히 resource의 representation을 나타내는 것이라고 생각하면 된다.

이를 설명하면 다음과 같다.

  • Resource(URI): jsonplaceholder.typicode.com/todos/1 (HTTP 요청의 대상)

  • Representation:

    1. GET 요청
    2. Accept: */* 형태
      위를 만족하는 현재시점의 Resource(URI)의 표현은 다음과 같다.
    Content-Type: application/json;
    Content-Language: en

    {
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
    }

즉, 요청한 시점에서의 resource를 위 2가지 조건에 따라 표현(representation)한 결과가 위의 json 결과이다.

이는 실제 URI가 위의 json 결과를 의미하는 것이 아니라, 해당 URI의 위 2가지 조건에 따른 표현일 뿐이다. 즉, target resource에 대한 현재의 선택된 representation 하나를 반환하는 것이다.

이는 REST의 representation이란 무엇인가에 아주 자세히 설명 돼 있다.

Related Links