
REST(Representational State Transfer)와 RESTful이라는 표현은 개발자 채용 공고에서 거의 빠지지 않고 등장하는 단어이다.
부트캠프에서 강사님이 REST가 정말 중요하다고 했는데, 당시에 나는 그 말이 크게 와닿지 않았다.
그래서 REST와 RESTful이 정확히 무엇을 의미하는지 질문했고,
다음과 같은 답변을 들었다.
이 답변으로는 나는 도저히 RESTful이 무엇인지 이해할 수가 없었다.
지금 생각해보면, 프로젝트 진행을 위해 구현 관점에서 그렇게 답변해주신거 같기도 하다.
당시에는 프로젝트를 완성하는 것이 우리 개발팀에게 우선이었기 때문에
JSON으로 응답하고, HTTP Status를 헤더에 포함시키는 방식으로
그대로 구현을 이어갔다.
하지만 머릿속에는 계속해서 다음과 같은 질문들이 남아 있었다.
이런 질문들에 명확히 답하지 못하고 "알고 있는 척"하면서 개발하고 있다는 느낌이 계속 들었다.
최종 프로젝트에 가까워지면서, 이번에는 제대로 이해한 상태로 구현해보고 싶다는 생각이 들어,
그 계기로 REST에 대해 다시 공부하게 되었다.
이 글은 그때 공부했던 내용을 바탕으로
REST가 무엇인지, 그리고 RESTful하다는 말이
도대체 무엇을 의미하는지 정리하고 복기하기 위한 글이다.
다시 공부해보니, 그 때도 조금 틀린 부분이 있었다라는 것을 알게 되었다.
먼저, REST는 Roy Fielding(이하 로이 필딩)의 다음 논문에서 제시된 아키텍처 스타일이다.
Architectural Styles and the Design of Network-based Software Architectures
제목에서 알 수 있듯이, 제목에는 전혀 REST를 찾아볼 수 없다.
이 논문의 주된 목적은 REST 자체를 소개하는 데 있지 않으며, 제목을 풀어 쓰자면 다음과 같다.
네트워크 기반 분산 소프트웨어 시스템에서 아키텍처 스타일이 시스템에 품질 속성에 어떤 영향을 미치는지 분석하는 것이다.
제목을 읽어도 사실 무슨 말인지 알기 어렵다,,
그래서 논문 전체를 모두 다루기에는 범위가 넓기 때문에,
이 글에서는 REST를 이해하는데 필요한 내용에 한해서만,
논문의 핵심 내용을 간단히 정리하고자 한다.
논문에서는 로이 필딩은 아키텍처를 단순한 기능 구현 방식이 아니라,
제약 조건의 선택으로 바라보고 있다.

개발자가 일반적으로 떠올리는 아키텍처가
MVC 구조나 SOLID 원칙처럼 코드 레벨의 구조라면,
논문에서 말하는 아키텍처는 다음 요소의 조합으로 설명한다.
그리고 어떤 제약 조건(Constraint)을 선택했는지가
시스템의 다음 품질 속성에 직접적인 영향을 미친다고 설명한다.
즉, 로이 필딩의 아키텍처란, 클라이언트·서버·네트워크 전반의 상호작용에 적용되는 구조적 선택을 말한다.
로이 필딩은 기존의 분산 시스템 아키텍처들이 인터넷 환경을 충분히 고려하지 않은 전제를 가지고 있다고 지적했다.

REST 이전의 분산 시스템들은 대체로 다음과 같은 가정을 전제로 설계되었다.
이러한 전제는 소규모 폐쇄 환경에서는 어느 정도 성립할 수 있지만,
인터넷과 같이 지연·실패·단절이 일상적인 환경에서는 구조적으로 유지되기 어렵다.
즉, 네트워크를 신뢰하는 설계는 시스템이 커질수록 장애에 취약하다.
당시 분산 시스템 아키텍처는 클라이언트와 서버가 서로의 내부 구조에 강하게 의존하는 경우가 있었다고 한다.
이러한 강한 결합은 시스템 규모가 커질수록 변경 비용이 기하 급수적으로 증가한다.
이어서, 공통적인 특징으로 서버가 클라이언트의 진행 상태를 세션으로 관리하는 방식이었다.
위 구조에서는, 로드 밸런싱과 수평 확장이 복잡해지고, 시스템의 확장성이 구조적으로 제한된다.
여기서 로이 필딩은 HTTP, URI, 캐시, 프록시, 무상태 요청 등의 기술은 이미 발전하고 잘 동작하고 있지만,
이 기술들의 조합(제약조건)이 어떤 아키텍처적인 특성을 만들어내었고, 아키텍처 특성들이 어떻게 변화하는지 설명할 일관된 아키텍처 스타일이 없었다고 한다.
이 부분이 조금 어려운데, 비유로 설명해보자면
당시 웹은 이미 잘 작동하는 요리였는데, 왜 이 재료 조합이 대규모로 실패하지 않는지를 설명하는 레시피(재현성)이 존재하지 않았다고 이해해보면 좋을 것 같다.
이제 다시 REST로 돌아와 보자.
로이 필딩은 웹이 실제로 따르고 있던 설계 원리를 분석했고,
그 결과를 하나의 아키텍처 스타일로 정식화했다.
그렇게 정의된 아키텍처 스타일이 바로
REST(Representational State Transfer) 다.
논문에서는 REST를 다음과 같이 정의한다.
REST는 분산 하이퍼미디어 시스템을 위한 아키텍처 스타일이다.
여기서 말하는 분산 하이퍼미디어 시스템이란,
이 정의에서 가장 중요한 점은, REST가 특정 기술이나 구현 규칙을 의미하지 않는다는 것이다.
REST는 프레임워크도 아니고, API 작성 규칙의 목록도 아니다.
REST는 단순히 제약 조건의 집합이다.
즉, REST란 어떤 제약 조건들을 선택했을 때,분산 시스템이 어떤 성질을 갖게 되는지를 설명하는 아키텍처적 모델로 이해할 수 있다.
다시 말해, REST는 “어떻게 구현할 것인가”가 아니라 “어떤 제약을 선택할 것인가”에 대한 이야기다.
REST가 어떤 제약 조건을 선택했는지 살펴보기 전에,
먼저 REST라는 이름 자체가 무엇을 의미하는지부터 정리해보자.
REST는 Representational State Transfer의 약자다.
이 이름은 REST의 핵심 개념을 그대로 담고 있다.
먼저 Representational이다.
로이 필딩의 REST에서 가장 중요한 구분 중 하나는
자원(Resource) 과 표현(Representation) 을 분리해서 바라보는 것이다.
예를 들어 다음과 같이 생각할 수 있다.
사용자 123사용자 123이라는 자원은 하나지만, 이를 표현하는 방식은 JSON일 수도 있고, XML이나 HTML일 수도 있다.
즉, 클라이언트는 자원 자체에 직접 접근하지 않고, 항상 자원의 표현(Representation)을 통해 상호작용한다.
이를 통해 다음과 같은 효과를 얻을 수 있다.
이러한 분리는 결국, 우리가 항상 중요하게 말하는 느슨한 결합(loose coupling) 을 가능하게 한다.
다음은 State다.
REST에서 말하는 상태(State)는
서버의 상태가 아니라 클라이언트의 애플리케이션 상태(Application State) 를 의미한다.
애플리케이션 상태란,
REST에서는 서버가 이 애플리케이션 상태를 저장하지 않는다.
대신 서버는 자원의 표현(Representation) 을 전달하고,
클라이언트는 그 표현을 해석하여
자신의 애플리케이션 상태를 변경한다.
즉,
이 과정이 바로 State Transfer다.
Transfer는 이 상태 변화가
표현(Representation)의 교환을 통해 이루어진다는 의미다.
서버는 상태를 “관리”하지 않고,
표현을 “전달”할 뿐이다.
지금까지를 한 문장으로 정리하면 다음과 같다.

즉, REST란
자원의 표현을 주고받는 과정을 통해
클라이언트의 상태가 전이되는 구조를 의미한다.
그래서 REST는
다시 돌아와서 REST가 대략 어떤 것인지 파악했으니,
이제 더 깊은 이해를 위해 REST가 어떤 제약 조건을 선택했는지 살펴보고자 한다.
로이 필딩의 REST에서는 다음 6가지의 제약조건이 존재한다.
(1) Client-Server: 클라이언트와 서버를 분리함.
(2) Stateless: 클라이언트는 애플리케이션 상태를 저장하지 않음.
(3) Cache: 응답은 캐시 가능 여부 명시함.
(4) Uniform Interface: 자원의 상호작용을 일관된 인터페이스로 통일함.
(5) Layered System: 중간 계층을 허용함.
(6) Code-on-Demand(Optional): 서버가 실행 코드를 클라이언트에 전달할 수도 있음.
각 제약 조건을 깊게 다뤄보고자 한다.
사용자 인터페이스(클라이언트)와 데이터•비즈니스 로직(서버)을 분리하라는 제약이다.
각각은 분리된 역할만 수행한다.
이 분리를 통해 각각은 독립적으로 확장될 수 있다.
REST는 이를 통해 클라이언트와 서버가 강하게 결합되는 구조를 의도적으로 피한다.
Stateless는 REST를 가장 잘 드러내는 제약조건이다.
제약의 의미는 다음과 같다.
여기서 애플리케이션의 상태는 클라이언트가 현재 어떤 페이지에 있으며, 다음으로 할 수 있는 것은 주문을 하거나, 장바구니 페이지로 이동하거나를 의미한다.
따라서, 서버는 애플리케이션이 어떤 페이지에 있는지 이전에 어떤 작업을 했는지에 대해 알 필요도 없으며 알 수 없어야한다. 서버는 위와 같은 애플리케이션의 상태에 개입하지 않는다.
이를 통해서 REST는 수평 확장이 쉬워지고, 로드 밸런싱 및 장애 복구에 용이해진다.
Cache 제약은 응답이 캐시가 가능한지 여부를 명시해야한다는 제약이다.
REST에서는 모든 응답은 캐시가 가능하거나, 캐시가 불가능함을 표현해야한다는 것이다. 이를 통해 얻을 수 있는 효과는 다음과 같다.
이 제약은 REST가 중간 계층의 개입을 허용하는 아키텍처임을 보여준다.
Uniform Interface는 클라이언트와 서버가 상호작용하는 방식이 일관된 인터페이스를 따라야한다는 것을 의미한다.
Uniform Interface는 다음 하위 원칙을 가지고 있으며 각각을 예시로 뜯어보고자 한다.

무엇을 한다)가 아니라 자원(무엇이다)을 식별할 수 있어야잘못된 접근
/createUser
/getUserInfo?id=123
잘 된 접근
/users -> 사용자라는 자원
/users/123 -> 특정 사용자라는 자원 GET /orders/1
{
"orderId": 1,
"status": "CREATED",
"totalPrice": 30000
}PUT /orders/1
{
"status": "CANCELED",
}해당 제약 조건은 단순하다.
응답 메시지 하나만 보고도 다음을 알 수 있어야한다는 점이다.
즉, 외부 문맥에 의존하지 않아야한다는 것이다.
자기 설명적이지 않은 예시
// 요청
POST /users
Content-Type: application/json
// 응답
{
"name": "kim",
"age": 20
}
자기 설명적인 예시
// 요청
POST /users
Content-Type: application/json
// 응답
HTTP/1.1 201 Created
Location: /users/123
{
"name": "kim",
"age": 20
}
메시지 자체에 의미, 처리 결과, 다음 행동의 힌트가 포함되어 있는 것을 알 수 있다.
먼저, HATEOAS는 Hypermedia As The Engine Of Application State의 약자인데, 영어 약자를 풀어서 해석다면 다음과 같다.
하이퍼미디어를 애플리케이션 상태 전이의 엔진으로 사용한다는 의미이다.
REST에서 HATEOAS가 의미하는 것은
클라이언트는 다음에 무엇을 호출해야하는지를 미리 알고 있지 않아도 되며, 서버가 응답한 포함 링크를 통해서 상태 전이를 안내한다.이다.
이는 다음 응답이 가능하다는 것을 의미한다.
// 요청
GET /orders/1
// 응답
{
"orderId": 1,
"status": "CREATED",
"_links": {
"self": { "href": "/orders/1" },
"pay": { "href": "/orders/1/pay" },
"cancel": { "href": "/orders/1/cancel" }
}
}
클라이언트는 이 응답으로 현재 상태에서 다음과 같은 것이 가능하다는 것을 알 수 있다.
다음으로는 중첩 구조로 REST는 시스템이 여러 계층으로 구성될 수 있음을 허용한다.
예시로 다음과 같다.

위 제약은 다음을 설명한다.
이를 통해 REST는
위 제약은 서버가 클라이언트에 실행 코드를 전달할 수 있도록 허용하는 제약이다.
대표적으로 JavaScript가 있다.
다만 이 제약은 REST의 유일한 선택적 제약 조건이며, REST를 성립시키기 위해 필수는 아니다.
지금까지 REST가 어떤 배경에서 등장했고,
어떤 제약과 원칙을 통해 정의되었는지를 살펴보았다.
이제 다시 처음의 질문으로 돌아가 보자.
그래서 RESTful한게 무엇인가?
RESTful하다는 것은
어떠한 형식이나 규현 규칙을 따르고 있는것을 묻는 말이 아니다.
REST라는 아키텍처 스타일의 관점을 가지고 설계되었는가를 묻는 것이다.
예시로 다음과 같은 요소들은 REST를 구현할 때 자주 등장하지만,
그 자체가 REST의 본질은 아니다.
위 내용이 완전히 틀리다고 할 수는 없지만 REST의 본질적 의미와는 다르다고 할 수 있다.
RESTful함을 한 문장으로 정리하면,
나는 다음과 같이 정리해볼 수 있을 것 같다.
시스템의 자원(Resource)을
그 자원의 표현(Representational State)으로 교환함으로써,
클라이언트와 서버 간의 결합을 느슨하게 유지하려는
아키텍처적 원칙을 얼마나 잘 따르고 있는가
만약 면접장에서
“RESTful이 무엇인가요?”라는 질문을 받는다면,
나는 다음과 같이 답할 수 있을 것 같다.
RESTful하다는 것은
시스템의 자원을 표현의 형태로 주고받으며,
분산 환경에서 강한 결합을 피하고
확장성과 변화에 유리한 구조를 만들기 위해
REST가 제시한 제약과 원칙을
얼마나 의식적으로 설계에 반영했는지를 의미합니다.
REST 원칙을 살펴보면서 느낀 점은,
SOLID 원칙이나 OAuth의 토큰 기반 인증 방식 등
다른 설계 원칙들과 공통적으로 느슨한 결합을 지향하고 있다는 점이다.
현대의 분산 네트워크 환경에서의 시스템의 확장과 변경을 위해서는 각 책임과 역할을 명확히 분리하는 구조가 필수적이다. 그래서 더욱이 아키텍처 구조를 잘 아는 것이 중요하다고 생각이 들었다.
또한, 로이 필딩이 REST를 정식화 한지 2000년 이후 26년지 지났다.
따라서 최신 현대의 새로운 아키텍처 스타일이 있는지를 찾아보았더니 추가적으로 현대의 변화한 아키텍처 스타일 또는 변형된 REST 아키텍처는 없었다.
가장 최신, 인용 수가 높은 논문은 2017년에 다음 논문이 있었는데, 이 논문도 회고(Reflection) 논문으로 REST 등장 이후 웹이 어떻게 발전했는지, REST가 왜 여전히 유효한지를 설명하는 논문 같아 보였다.
Reflections on the REST architectural style and "principled design of the modern web architecture" (impact paper award)
새로운 아키텍처가 제시되지 않는 것을 보아 REST가 아주 기본 원칙으로 잘 구성되어 있다는 생각도 들고,
이제는 웹이 아니라 다른 하이퍼미디어 전송을 위한 무언가가 탄생해야할 때가 아닌가 싶기도 하다.
이어서, 다음으로 다루고자 하는것은 원칙보다 실제 Practice 환경에서 REST가 어떻게 구현되고 있는지를 다음 순서로 살펴보고자 한다.
항상 마지막으로 남기는 말인데,
블로그는 언제나 참고를 위한 자료로 사용하고 공식 문서를 통해 이해하는 것이 더욱 명확하다.
최근에는 GPT로도 어려운 논문을 도와서 읽을 수도 있으니, GPT 등의 생성형 AI를 잘 활용하는 것도 좋아 보인다.