REST API, RESTful 등의 용어에 사용되어 한 번쯤은 들어봤지만, 다른 사람들에게 설명하라면 조금 곤란해지는 REST. REST가 만들어지게 된 배경, 개념, 사용해야 하는 이유에 대해 알아봅니다.
(이 글은 2024-01-06 미니 개발 세미나 발표 내용을 기반으로 하였습니다)
미니 개발 세미나 노션 바로가기
REST란 무엇일까요?
개발을 접해본 분들이라면, REST가 생소하게 들리지는 않을 것입니다. REST API나 RESTful이라는 단어를 한 번쯤은 들어봤을 테니까요.
이 글에서는 REST API, RESTful이라는 단어가 있게 한 REST라는 개념에 대해 알아봅니다.
저도 이 글을 쓰기 전에는 REST가 무엇인지 잘 알지 못했습니다. 그래서 위와 같은 생각들을 했죠.
REST에 대해 검색해보면 위와 같이 어떻게 URI를 만드는지 방법이 세세하게 적혀 있습니다.
그런데 어떤 블로그도 무엇을 지켜야 하는지는 잘 설명하는데, 왜 이것들을 지켜야 하는지는 설명해주지 않더라고요.
그래서 직접 REST라는 개념이 처음 사용된 논문을 읽어보기로 했습니다.
REST (Representational state transfer) is a software architectural style that was created to guide the design and development of the architecture for the World Wide Web.
Wikipedia에 쓰인 REST의 정의입니다. 한국어로 번역하면, REST는 “월드 와이드 웹(WWW)에 사용되는 아키텍처의 디자인과 개발을 돕기 위해 만들어진 소프트웨어 아키텍처 스타일”입니다.
Roy Fielding이라고 하는 컴퓨터과학자가 주장한 개념이죠.
제가 REST를 Roy Fielding이 ‘주장한’ 개념이라고 했는데, 여기서 힌트를 얻으신 분들이 계실지 모르겠습니다.
REST는 HTTP, HTML, URI 규칙 등과는 달리, 명세도 아니고, 꼭 지켜야 하는 것도 아니고, 프로토콜도 아니고, API도 아닙니다.
REST는 그저 소프트웨어 아키텍처 스타일입니다. 필요에 따라 이 스타일을 지켜 설계할 수도 있는 것이고, 때에 따라 그렇지 않을 수도 있는 것이죠.
소프트웨어 엔지니어인 우리들은 REST가 무엇인지, 장단점이 무엇인지 이해한 뒤, 내 프로젝트에 사용해야 할지 말아야 할지 결정하면 되는 것입니다.
여기까지 들었을 때에는 REST가 무엇인지 잘 와닿지 않죠. 그럼 REST가 나오게 된 배경을 알아보도록 하겠습니다.
왼쪽 사진에 나와 있는 사람은 웹의 아버지라고 할 수 있는, 팀 버너스리입니다.
월드 와이드 웹의 개념을 처음 만들었고, HTTP, HTML을 만든 사람입니다.
1989년, 전세계의 컴퓨터는 팀 버너스리의 월드 와이드 웹을 통해 전 세계의 다른 모든 컴퓨터들과 소통할 수 있게 되었습니다.
팀 버너스리는 웹에 대해 다음과 같이 설명합니다.
“웹의 주요 목표는 사람과 기계들이 의사소통할 수 있는 공유 정보 공간을 만드는 것이었습니다.”
하지만 10년도 되지 않은 이때, 초기 웹에 문제가 발생합니다.
이 당시에 웹은 사용량이 급격하게 늘어나고 있었고, 글로벌 서비스를 위해 웹에 눈독들이고 있는 회사들도 많았습니다.
그리고 웹은 이미 전세계로 빠르게 퍼져나가 사용되고 있는 상태였습니다.
웹의 사용량이 급격하게 늘어나고 있다는 문제를 그대로 두었다가는 웹 인프라가 붕괴될 우려가 있었습니다.
그리고, 때에 따라 변화하는 웹 환경에 적응하기 위해서는 웹 아키텍처를 변경해야 했는데, 웹이 이미 전세계로 퍼져나간 뒤였기 때문에, 기존의 웹 기능을 망가뜨리지 않으면서 새로운 기능들을 추가하거나 변경시킨다는 것이 쉬운 일이 아니었습니다.
그래서 Roy Fielding은 2000년 자신의 박사 학위 논문에서 이런 웹이 가진 문제점들을 해결해보기 위한 일종의 지침을 제안합니다.
이렇게 REST가 만들어지게 되었고, 지금까지 인기를 얻고 있는 것이고요.
정리하면, REST는 웹의 문제를 해결하기 위해 만들어진, 웹에 특화된 아키텍처 스타일 지침입니다.
REST는 프로토콜도, API도 아닌 아키텍처 스타일로써, 여섯 가지의 제약조건으로 이뤄져 있습니다.
REST는 여섯 가지의 제약 조건만 지킨다면 컴포넌트들의 구현이나 프로토콜의 종류에 대해서는 신경 쓰지 않습니다.
오른쪽 하단에 REST의 제약 조건이 적혀 있는데,
그러면 왜 REST에서 왜 이러한 여섯 가지의 제약조건을 제시했는지 그 근거를 알아볼까요?
Roy Fielding은 REST라는 아키텍처 스타일을 만들기 위해 우선 아무 제약 조건도 없는 상황에서부터 시작했습니다.
컴포넌트 간 아무런 경계 구분이 없는, 팀 버너스리의 월드 와이드 웹에서부터 시작한 것입니다.
Roy Fielding은 여기에서부터 제약 조건을 아래에서부터 위로 하나씩 쌓아올리기 시작합니다.
첫 번째 제약조건은 클라이언트-서버 제약조건입니다.
이름에서부터 쉽게 알 수 있듯이, 이 제약조건은 아키텍처가 클라이언트 서버 아키텍처 패턴을 따르도록 하면 됩니다.
이 제약조건이 필요한 이유는 관심의 분리 때문인데요.
웹 서비스를 이용할 때 크롬 버전을 업데이트했다고 해서 웹서버의 기능을 사용하지 못하는 일이 있었나요?
아닐 겁니다.
기존 웹의 기능을 망가뜨리지 않으면서 새로운 기능을 추가할 수 있도록 하는 것이 중요한 목표 중 하나였는데, 클라이언트-서버 아키텍처 패턴을 사용하게 되면 관심의 분리가 일어나기 때문에 상호독립적으로 기능을 추가하고 배포하는 것이 자유로워집니다.
오른쪽 아래와 같이 앱을 업데이트해야 앱을 사용할 수 있다고 하는 메세지가 떴던 경험 한 번쯤 있으시죠? 이런 경우는 RESTful하지 않다고 할 수 있습니다.
그 다음 제약조건은 stateless 제약조건입니다.
클라이언트-서버 제약조건이 이미 충족되었다는 가정 하에 stateless 제약조건을 추가하는 겁니다.
모든 통신이 stateless해야 한다는 제약조건인데요, 이때 서버에 저장된 어떤 문맥도 활용하지 않고 요청 그 자체를 통해 그 요청을 완전히 이해할 수 있어야 합니다.
이 제약조건을 추가함으로써 visibility, reliability, scalability 측면에서 장점을 가지게 되는데요, 특히 웹 사용자가 아주 많아질 경우에 각각의 컴포넌트들이 뭔가를 저장할 필요가 없어지므로 scalability 측면에서 이점을 얻게 됩니다.
그 다음 제약조건은 cache 제약조건인데요,
응답이 캐시 가능하다면 캐시를 사용하자는 제약조건입니다.
이로써, 반복된 요청의 경우에는 캐시를 사용함으로써 네트워크로 요청이 오고 갈 필요성이 줄어들기 때문에 지연이 감소하게 되고, 효율성, 확장성, 사용자 측면 성능도 증대되는 효과가 생깁니다.
여기까지 봤을 때는 HTTP와 상당히 비슷한 제약조건을 가진다는 것을 확인해볼 수 있는데, 실제로 Roy Fielding은 HTTP의 개발에도 참여했기 때문에, 아주 놀랄만한 일은 아닐 겁니다.
그 다음으로는 Uniform interface 제약조건입니다.
컴포넌트 간 통일된 인터페이스를 가져야 한다는 조건인데, 클라이언트는 클라이언트의 역할을, 서버는 서버의 역할을 해야 하고, 그 역할이 제각각이 아니라 통일되어 있어야 한다는 말입니다.
REST는 다음 4가지의 인터페이스 제약으로 정의된다고 하는데, 하나하나씩 보시죠.
identification of resource 제약조건은, 자원은 하나의 식별자를 통해 식별된다는 조건입니다.
위 그림을 보시면, 서버 안에 있는 문서 1을 /documents/1이라는 URI를 통해 식별하고 있죠.
그리고 manipulation of resources through representations 제약 조건은, 자원이 표현의 교환을 통해 다뤄져야 한다는 제약조건입니다. 여기서 representation이라는 것은 리소스 혹은 리소스의 상태에 대한 데이터를 말하며, 위 그림에서는 HTTP 요청과 응답을 통해 표현을 교환하며 자원을 다루고 있는 것을 볼 수 있죠.
그 다음으로 self-descriptive message라는 것은 표현은 자기 자신을 통해 모든 것이 설명되는 메시지를 통해 교환되어야 한다는 제약조건입니다.
HTML을 보내주고 있는 왼쪽과, json을 보내주고 있는 오른쪽을 비교해봅시다.
html을 보내주고 있는 왼쪽은 self-descriptive messages 제약조건을 만족한다고 볼 수 있을까요?
네 그렇다고 볼 수 있습니다. 만약 HTML이나 json을 파싱하는 방법을 아예 모른다고 가정해봅시다.
아래 바디로 전달된 HTML 파일을 해석할 수 있나요? 네. text/html은 웹상에 어떻게 해석하는지 그 사양이 누구나에게 공개되어 있기 때문에 누구든 HTML 파서를 만들어서 이 메세지의 의미를 파악할 수 있습니다.
그럼 json 파일은요? text/json 명세를 통해 아래 json 파일을 파싱하는 데까지는 성공할 텐데, 그 이후 id나 title이 뭘 뜻하는지 알 수 없을 것입니다. 이것들은 백엔드와 프론트엔드 개발자가 약속하기 나름이겠죠.
그래서 오른쪽은 self-descriptive하지 않다고 할 수 있습니다.
마지막으로 hypermedia as the engine of application state, 줄여서 HATEOAS입니다.
어플리케이션의 상태를 바꾸기 위해 하이퍼미디어가 사용된다는 건데요,
클라이언트에게 응답으로 보낸 하이퍼미디어만으로 어플리케이션의 상태를 바꿀 수 있어야 합니다.
여기서 상태라는 것은 HTML 페이지를 예로 들자면 각각의 웹페이지를 나타낸다고 볼 수 있는데요,
각각의 웹페이지 내에 다른 웹페이지로 갈 수 있는 하이퍼링크가 있고, 그 링크를 통해 다른 웹페이지로 이동할 수 있습니다. 즉, 링크를 통해 어플리케이션의 상태를 바꿀 수 있는 거죠.
바로 전 슬라이드에서 왼쪽에 있었던 HTML은 HATEOAS를 만족합니다. 페이지 안에 다른 상태로 전이할 수 있도록 하는 링크가 존재하니까요.
그런데 오른쪽에 있었던 json은 HATEOAS를 만족하지 않습니다. json을 받은 이후에 다른 상태로 전이할 수가 없으니까요.
오른쪽에 있었던 json 예제를 HATEOAS를 만족하도록 바꾸면 이 슬라이드의 오른쪽대로입니다.
application/vnd.api+json이라는 컨텐트 타입은 IANA라는 기관에서 명세를 갖고 있고, 누구나 볼 수 있습니다. 그래서 self-descriptive를 만족하게 되고요.
오른쪽에 links라는 프로퍼티를 통해 다른 상태로 전이할 수 있도록 하여 HATEOAS도 만족하게 됩니다.
이것들은 uniform interface 제약 조건을 넣었을 때 개선되는 점들입니다. (참고용)
그 다음 제약조건은 layered system으로, 아키텍처가 계층적인 레이어 구조를 가져야 하며, 각각의 컴포넌트가 자신과 곧바로 상호작용하는 컴포넌트를 제외한 나머지를 볼 수 없다는 제약조건입니다.
실제 예시를 들어보면 클라이언트, 프록시, 리버스 프록시, 서버와 같이 레이어 구조를 가지도록 할 수 있죠.
이렇게 함으로써 컴포넌트들의 독립성을 향상시킬 수 있고, 레거시 서비스나 클라이언트를 캠슐화함으로써 문제를 방지할 수 있습니다.
여섯 번째 제약조건은 지켜도 되고, 지키지 않아도 되는 optional한 제약조건인데요.
REST에서 클라이언트가 코드를 다운로드하고 실행하는 것을 허용한다는 제약조건입니다.
웹 브라우저에서 javascript가 돌아갈 수 있다는 것이 대표적인 예시입니다.
클라이언트가 배포된 이후에도 다양한 기능들을 동적으로 실행할 수 있으므로, 클라이언트가 단순화되고 시스템의 확장성이 높아지는 효과가 생깁니다.
REST를 기반으로 만들어진 아키텍처의 예시입니다.
그럼 정리를 해볼까요.
REST는 위와 같이 여섯 가지 제약 조건으로 이뤄져 있는 아키텍처 스타일입니다.
위 여섯 가지 제약 조건을 모두 만족한다면, RESTful하다고 하죠.
이런 제약조건을 모두 만족하도록 API를 만들면 REST API라고 합니다.
HTTP 위에서 웹서버, 웹브라우저를 사용하면 대부분 쉽게 제약조건이 만족되는데, 이중에서 self-descriptive messages와 HATEOAS 제약조건을 만족하기 어렵다고 하니, RESTful하고 싶다면 참고하면 좋겠습니다.
그럼 왜 REST를 사용해야 할까요?
사실 REST를 만든 당사자인 Roy Fielding은 REST가 필요 없으면 쓰지 말라고 합니다.
제가 이런 말을 하면 못 믿으실까봐, Roy Fielding 본인이 했던 말들을 그대로 가져와봤습니다.
하나씩 읽어보겠습니다.
REST는 통제 불가능한 시스템을 유지시키기 위한 진화 가능성을 강조합니다. 당신이 만약 시스템을 잘 통제하고 있다고 생각하거나, 진화하는 데에 관심이 없다면, REST에 대해 따지느라 시간을 낭비하지 마세요.
이미 배포된 컴포넌트를 망가뜨리거나 바꿀 필요 없이 어떻게 시스템을 우아하게 진화시킬까, 그것이 정확히 REST가 풀려고 하는 문제입니다. … 다른 말로 하자면, API를 RESTful하게 짜지 마세요. 당신이 원하는 속성들을 넣어서 API를 짜세요. REST는 다수의 기관 관리 하에 있는 시스템으로부터 진화 가능성 같은 속성들을 이끌어낼 수 있기 때문에 유용한 겁니다. 진화 가능성은, 시스템을 변화에 적응시키기 위해 그 시스템을 재시작하거나 재배포할 필요가 없다는 뜻입니다.
즉, Roy Fielding은 진화 가능성을 염두에 두고 있지 않다면 REST가 필요 없다고 말하는 겁니다.
그래서, RESTful한 API를 만들려고 노력하기 이전에, 나에게 REST가 필요한지 먼저 생각해보는 게 좋을 것 같네요.
3줄 요약 해보겠습니다.
감사합니다.
대부분 자료를 논문과 Naver D2 영상으로부터 얻었습니다.
Architectural Styles and the Design of Network-based Software Architectures, Roy Thomas Fielding, 2000
그런 REST API로 괜찮은가 - Naver D2
Roy Fielding on Versioning, Hypermedia, and REST - InfoQ
A bit of REST (Representational State Transfer) - Roy T. Fielding
논문을 통한 REST에 대한 고찰
[Network] REST란? REST API란? RESTful이란?
좋은 글 잘 읽었습니다. 감사합니다.