REST API 에 대한 고찰

REST API 에 대한 고찰

개발일기

 

📜 참고 - REST 위키백과

📜 참고 - REST Wikipedia

📜 참고 - Youtube naverd2 - 그런 REST API로 괜찮은가

📜 참고 - WWW란 무엇인가?

 

🚀 서문


아무리 찾아봐도 업계에서 사용하는 REST의 뜻과 로이 필딩이 말하는 REST는 다르다.

 

이게 현재 내가 내린 결론이다.

 

문득 “지금 이걸 완벽하게 이해하는 게 지금의 나한테 중요한가?” 라는 생각도 든다.

 

맞는 말이다.

끽해야 주니어 개발자인 내가 이런 Deep한 부분까지 신경 쓰면서 개발할 일은 없을 것이다.

업계에서 통용되는 REST API에 대한 의미를 알고 활용할 정도만 돼도 문제없을 것이다.

 

그래서 이 포스팅은 감정적인 성격의 포스팅이다.

내가 제대로 이해하고 있지 못하다는데서 오는 찝찝함.

그게 이 글을 작성하는 이유다.

근데 작성하고 보니 더 찝찝해졌다.

 

💡 REST


REST(Representational State Transfer)

2000년에 로이 필딩(Roy Fielding)이 박사 학위 논문에 정의하며 세계에 퍼진 단어다.

로이 필딩은 웹(Web)을 탄생시킨

티머시 존 버너스 리(Timothy John Berners-Lee)의 제자로

역시 웹의 탄생부터 깊게 관여해온 선구자이다.

웹(Web)은 인터넷에서의 정보 공유를 어떻게 할 것인지에 대해

여러 전문가 집단에 의해 정의됐다.

 

  1. 표현 방식 : HTML (관리 그룹 : W3C)

  2. 통신 방식 : HTTP (관리 그룹 : IETF)

  3. 식별자 : URI

 

로이 필딩이 REST에 대한 발표를 할 때 웹과 HTTP는 존재했지만

2021년인 현재와는 매우 환경이 다르다는 걸 우선 완벽하게 인지해야 할 것 같다.

로이 필딩은 HTTP의 상위 버전인 HTTP/1.0을 정립할 때 발생하는 호환성 문제를 고심했다고 한다.

우리는 자바 1.6으로 작성된 간단한 애플리케이션을 자바 1.8로 업데이트하는 일 조차 두려워한다.

호환성에 의한 에러가 무수히 뜰 수 있기 때문이다.

로이 필딩은 어땠을까? 무려 세계적인 통신 규약 자체를 업데이트하는데

이때 전 세계적으로 터져 나올 호환성 문제에 대해 어마어마한 부담을 느끼지 않았을까?

 

나는 그 부담감을 감히 상상조차 할 수 없다.

 

로이 필딩REST라는 것은 소프트웨어 아키텍처(Software Architecture)이다.

대저 아키텍처라 함은 제약조건의 묶음을 말한다.

 

📕 REST에는 6가지 제약조건이 있다


  • 클라이언트-서버 구조(Client-server architectur)

    • The principle behind the client–server constraints is the separation of concerns. Separating the user interface concerns from the data storage concerns improves the portability of the user interfaces across multiple platforms. It also improves scalability by simplifying the server components. Perhaps most significant to the Web is that the separation allows the components to evolve independently, thus supporting the Internet-scale requirement of multiple organizational domains.

    • 클라이언트-서버 구조의 원칙은 관심사(책임)의 분리이다. 유저 인터페이스에 의한 문제와 서버 데이터에 의한 문제를 분리시키면 여러 플랫폼에서 유저 인터페이스의 이식성이 향상된다(낮은 결합도를 말하는 듯하다). 또한 서버가 단순화됨으로써 서버의 확장성 또한 개선될 것이다. 아마도 웹에서 가장 중요한 가치는 각 요소들이 독립적으로 진화할 수 있게끔 관심사를 분리하여 인터넷 환경에서 각 도메인들의 요구사항을 지원해 줄 수 있게 하는 것이다.

 

  • 비상태성(Statelessness)

    • In a client–server interaction, state is made up of intrinsic state and extrinsic state. Intrinsic state, called resource state, is stored on the server and consists of information that is independent of the server’s context, thereby making it sharable to all clients of the server. Extrinsic state, called application state, is stored on each client and consists of information that is dependent on the server’s context and therefore cannot be shared. Clients are responsible for passing application state to the server when it needs it. The constraint of storing application state on the client rather than on the server makes the communication stateless.

    • 클라이언트-서버의 상호 작용은 고유한 상태와 외적인 상태로 구성된다. 고유한 상태는 리소스 상태라고도 부르는데 이것은 서버에 저장되며 서버의 콘텍스트와 상호 독립적으로 구성되므로 서버의 모든 클라이언트와 공유할 수 있다(현대의 세션을 말하는 듯하다). 외적인 상태는 애플리케이션 상태라고도 부르며, 이는 각 클라이언트에 저장되고 서버에 종속되어 공유될 수 없는 정보로 구성된다(현대의 쿠키를 말하는 듯하다). 클라이언트는 상태에 대한 정보가 필요할 때 서버에 애플리케이션 상태를 전달하는 역할을 해야 한다. 애플리케이션 상태를 서버가 아닌 클라이언트에 저장함으로서 통신을 비상태성으로 만든다.

 

  • 캐시 가능(Cacheability)

    • As on the World Wide Web, clients and intermediaries can cache responses. Responses must, implicitly or explicitly, define themselves as either cacheable or non-cacheable to prevent clients from providing stale or inappropriate data in response to further requests. Well-managed caching partially or completely eliminates some client–server interactions, further improving scalability and performance.

    • 월드 와이드 웹(www)처럼 클라이언트와 이를 중개하는 장치는 응답을 캐시 할 수 있어야 한다. 이 응답은 암시적으로나 명시적으로나 캐시 가능한지 혹은 불가능한지 반드시 정의되어야만 한다. 알맞게 관리되는 캐시는 클라이언트-서버의 결합도를 낮추어 확장성과 성능의 향상을 가져올 것이다.

 

  • 계층적 시스템(Layerd system)

    • A client cannot ordinarily tell whether it is connected directly to the end server or to an intermediary along the way. If a proxy or load balancer is placed between the client and server, it won't affect their communications, and there won't be a need to update the client or server code. Intermediary servers can improve system scalability by enabling load balancing and by providing shared caches. Also, security can be added as a layer on top of the web services, separating business logic from security logic. Adding security as a separate layer enforces security policies. Finally, intermediary servers can call multiple other servers to generate a response to the client.

    • 대충 OSI 7 계층에 대한 내용으로 보인다. 혹은 URL의 트리구조를 말하는 것인 것 같기도 하다.

 

  • 서버에 의한 클라이언트 제어(Code on demand)

    • Servers can temporarily extend or customize the functionality of a client by transferring executable code: for example, compiled components such as Java applets, or client-side scripts such as JavaScript.

    • 서버는 Java Applets이나 JavaScript와 같은 클라이언트 사이드 스크립트를 클라이언트에 전송하여 클라이언트의 기능을 임시적으로 확장시키거나 커스터마이징 할 수 있어야 한다.

 

📜 일관적인 인터페이스(Uniform interface)


  • The uniform interface constraint is fundamental to the design of any RESTful system. It simplifies and decouples the architecture, which enables each part to evolve independently. The four constraints for this uniform interface are:

  • 일관적인 인터페이스 제약조건은 모든 RESTful 한 시스템의 근본적인 설계이다. 일관적인 인터페이스는 아키텍처를 단순화시키고 관심사를 분리하여 각 부분이 독립적으로 진화할 수 있게 해 준다. 이 제약조건은 다음의 네 가지가 있다.

 

  • 요청의 자원 식별(Resource identification in requests)

    • Individual resources are identified in requests, for example using URIs in RESTful Web services. The resources themselves are conceptually separate from the representations that are returned to the client. For example, the server could send data from its database as HTML, XML or as JSON—none of which are the server's internal representation.

    • 요청에서 각 자원은 식별된다. 예를 들면 RESTful 웹 서비스에서 URI를 사용하는 것이다. 각 자원들은 클라이언트에게 반환되는 표현과 개념적으로 분리되어 있다. 예를 들자면 서버는 데이터베이스에서 내부 데이터들을 보내는 대신, 그 데이터들을 HTML, XML, JSON 등으로 표현하여 보낼 수 있다.

 

  • 표현에 의한 자원 조작(Resource manipulation through representations)

    • When a client holds a representation of a resource, including any metadata attached, it has enough information to modify or delete the resource's state.

    • 클라이언트가 자원을 표현하는 메타데이터를 갖고 있다면, 자원의 상태를 수정하거나 삭제할 수 있는 충분한 정보를 갖고 있는 것이다.

 

  • 하이퍼미디어는 애플리케이션의 상태를 실행시킨다(Hypermedia as the engine of application state (HATEOAS))

    • Having accessed an initial URI for the REST application—analogous to a human Web user accessing the home page of a website—a REST client should then be able to use server-provided links dynamically to discover all the available resources it needs. As access proceeds, the server responds with text that includes hyperlinks to other resources that are currently available.

    • REST 애플리케이션에 처음 접속한 REST 클라이언트는 서버에서 제공하는 링크를 동적으로 사용하여 필요한 모든 가용 자원을 알 수 있어야 한다. 접속이 진행되면 서버는 현재 사용 가능한 다른 자원에 대한 하이퍼링크를 클라이언트에게 알려줄 수 있어야 한다. (HTML 문서를 말하는 듯함. HTML에 처음 접속하면 버튼(링크)을 통해 다른 페이지로 자유롭게 이동할 수 있는 부분들. www에 따르면 하이퍼미디어는 하이퍼텍스트의 집합을 의미한다.)

 

💡 하이퍼미디어(Hypermedia)

하이퍼미디어(hypermedia)란 하이퍼텍스트(hypertext)의 커다란 집합체라고 말 할 수 있다. 하이퍼텍스트는 일반적인 텍스트와 별 다른 차이가 없지만 하이퍼텍스트 링크 즉, 하이퍼링크(hyperlink)라는 다른 문서로의 연결고리를 가진다는 큰 특징을 가지고 있다. 다시말해, 하이퍼텍스트란 어떤 문서내의 특정 단어 또는 문장으로써, 그 단어 또는 문장 상에서 사용자가 마우스를 클릭하게 되면 스크린상에 새로운 문서를 나타나게 하는 텍스트를 의미한다.
하이퍼미디어란 간단히 말하자면 하이퍼텍스트와 멀티미디어를 조합시킨 형태라고 할 수 있다. 이는 다시말해, 다른 문서 또는 텍스트로의 하이퍼링크를 가지는 하이퍼텍스트 문서이면서, 연결되어 있는 문서의 형태가 단순한 텍스트뿐만 아니라 여러 형태 즉, 음성 또는 영상(정지영상, 동영상) 등의 멀티미디어 데이타라는 것이다. 예를 들면, 사용자가 문서상의 한 하이퍼텍스트를 클릭하게 되면, 그와 연결된 문서 즉, 단순한 텍스트 문서 또는 어떤 음성, 이미지내지는 동영상이 나타날 수 있는 것이다. WWW를 하이퍼미디어 정보 검색 시스템이라고 하는 것은 WWW가 하이퍼텍스트를 기반으로 멀티미디어 데이타의 전송이 가능한 시스템이기 때문이다.

 

  • 메시지는 스스로를 설명해야 한다(Self-descriptive Messages)

    • Each message includes enough information to describe how to process the message. For example, which parser to invoke can be specified by a media type.

    • 각 메시지는 스스로를 어떻게 처리해줘야 하는지에 대한 충분한 정보가 포함되어 있어야 한다. 예를 들자면, 미디어 타입의 파서를 명시해서 호출해야 한다. (미디어 타입만 가지고도 클라이언트 측에서 어떻게 처리를 해야 할지 알 수 있어야 할 만큼 정보가 명시되어있어야 한다는 뜻 같음. Ajax의 Content Type을 명시하는 부분을 말하는 듯함)

 

굉장히 많고 복잡하다.

특히 표현(Representational)상태(State)라는 단어가 굉장히 많이 나온다.

이 부분이 잘 이해가 가지 않는데 문맥상 추론하기에 HTML표현이라고 하고 있는 것 같고,

상태코드상태라고 부르고 있는 것 같다.

 

우리는 위의 제약조건들이 발표된 시기가 2000년임을 기억해야 한다.

현재 우리가 사용하고 있는 HTTP에 의해 저 위의 대부분의 제약조건들이 실제로 지켜지며 작동되고 있다.

다만 Self-descriptive MessagesHATEOAS는 개발자가 직접 신경쓰지 않으면 잘 지켜지지 않기 때문에

로이 필딩은 대부분의 시스템이 RESTful하지 않다고 말하고, 굳이 RESTful에 목매지 말라는 이야기도 덧붙이고 있다.

 

How do i improve HTTP without breaking the Web?

 

애당초 로이 필딩이 REST를 발표하게 된 계기이다.

그러니까 로이 필딩의 궁극적인 목표는

클라이언트와 서버의 책임이 완벽하게 분리되고 독립적으로 진화하여

서버의 기능이 변경되더라도 클라이언트는 아무 문제없이 동작할 수 있는 환경이었던 것 같다.

 

가장 RESTful 한 것은 웹(Web)이다.

 

웹 브라우저가 변경되더라도 클라이언트는 같은 결과물을 서버에서 받아볼 수 있다.

웹 브라우저가 크롬(Chrome)이었다가 사파리(Safari)로 바뀐다고 클라이언트가 서버로부터 다른 정보를 받는 경우는 없다.

클라이언트와 서버는 상호 독립적이며 클라이언트가 바뀌더라도 서버는 같은 요청을 받고 같은 결과를 보내 줄 수 있다.

 

그래서 웹(Web)은 가장 RESTful 한 시스템이다.

 

그런 REST API로 괜찮은가에 따르면

Self-descriptive MessagesCustom Media Type이나 Profile Link Relation 등으로 충족시킬 수 있고,

HATEOAS는 HTTP 헤더나 바디에 Link를 달아 만족시킬 수 있다고 한다.

이는 개발자가 직접 세팅해줘야 하기 때문에 귀찮고 번거로우며,

이 귀찮음을 감수하고 추가 개발했다고 하더라도 그로 인해 당장 얻어지는 이득이 없다.

이러한 사실로 인해 로이필딩이 말하는 진정한 의미의 Restful은 나오기 힘든 것같다.

 

😎 결론


로이 필딩은 HTTP/1.0 로 업데이트를 진행하며

전 세계 시스템의 하위 호환성에 문제가 생기는 것을 걱정했고,

이를 미연에 방지하고 미래에 계속될 HTTP 업데이트 또한 문제없기를 바라며 REST의 개념을 도출해냈다.

현대에 이르러 전 세계적으로 HTTP/1.1이 사용되고 있고

HTTP/2.0이 도입되고 있는 추세이며, 20년 말에는 HTTP/3.0에 대한 논의가 나왔다고 한다.

HTTP/1.0부터의 모든 버전이 로이 필딩이 REST라고 명명한

소프트웨어 아키텍처(Software Architecture)의 영향을 받아 발전했기 때문에

지금에 이르러선 HTTP을 통한 통신을 하는 것만으로 사실상 대부분의 REST 제약조건을 지키는 셈이다.

 

하지만 HTTP를 통해 통신을 한다고 하더라도

일관된 인터페이스라는 제약조건은 개발자가 제대로 신경 쓰지 않으면

실제로 잘 지켜지지 않기 때문에 엄격한 의미에서 RESTful 하지 않다고 이야기하는 것이다.

 

로이 필딩은 REST라면 반드시 이러한 문법(Syntax)을 지켜야한다고 분명하게 이야기하지 않았다.

REST는 그저 소프트웨어 아키텍처(Software Architecture)일 뿐이고

이것이 포함하는 모든 제약사항을 충족시키는 시스템이 진정 RESTful한 것이라고 말하고 있을 뿐이다.

 

처음 REST API에 대해 구글링을 할때 HTTP의 Get, Post, Put, Delete, PatchCRUD를 연관시키고,

URL은 동사가 아닌 명사여야 한다는 둥의 글들이 나를 더욱 혼란스럽게 만들었었다.

하지만 위 내용들과 별개로 아직도 대부분의 시스템이 Get과 Post만을 이용해 사용되어지고 있다.

Spring 4.3에도 HTTP의 5가지 Method에 대한 애노테이션이 추가되었지만

현실적으로 @GetMapping@PostMapping을 이용한 개발만이 주를 이루고있다.

 

그래서 내 생각에 현재 업계에서 통용되는 REST와 학술적 의미의 진정한 REST는 분명한 차이가 있다고 생각한다.

 

전 세계적으로 모바일 시장이 커짐에 따라 API서버를 통한 멀티플랫폼 서비스가 시작됐다.

또한 웹 분야에서 현재 우리나라 업계는 SPA(Single Page Application) 방식의 개발이

트렌드로 자리 잡으며 프론트 개발자와 백엔드 개발자로 업무분담이 세부화 되어가는 시점인데,

각 페이지를 교체하며 계속해서 렌더링 하는 기존의 방식보다

모든 페이지를 최초에 한번 렌더링 해놓고

API서버를 통한 비동기 통신을 이용해 페이지를 동적으로 교체하는 현재의 방식은 성능이 더 뛰어나다.

 

또한, 이러한 방식의 개발은 프론트 개발자와 백엔드 개발자가

서로 이 API에는 어떠한 URI를 보내면 어떠한 응답이 올 것이다 라는걸

미리 약속하고 진행하기 때문에 각자의 업무를 세부적으로 분담할 수 있고, 협업에 용이하다.

 

하지만 이 방식으로 일을 진행하기 위해 API기반의 설계와 개발이 필요하기 때문에

대부분의 채용공고에 REST, RESTful에 대한 이해같은 글귀같은 것들이 있는 것으로 사료된다.

 

결론적으로 업계에서 말하는 REST API란 학술적 의미의 Rest가 아닌 HTTP Body를 주로 이용하는 @RestController와 같은 통신방식을 의미하는 걸로 이해가 된다.

 

마치며 이를 REST API가 아닌 HTTP API라고 불러야 함이 옳지 않을까? 라는 생각을 해본다.

 


© 2022. All rights reserved.