[REST] RESTful은 도대체 뭘까?

Daehwan Kim·2026년 1월 28일

REST

목록 보기
1/2
post-thumbnail

서론

REST(Representational State Transfer)와 RESTful이라는 표현은 개발자 채용 공고에서 거의 빠지지 않고 등장하는 단어이다.

부트캠프에서 강사님이 REST가 정말 중요하다고 했는데, 당시에 나는 그 말이 크게 와닿지 않았다.
그래서 REST와 RESTful이 정확히 무엇을 의미하는지 질문했고,
다음과 같은 답변을 들었다.

  • JSON으로 응답해주는게 RESTful이야!
  • HTTP Status를 반환하는게 RESTful이야!

이 답변으로는 나는 도저히 RESTful이 무엇인지 이해할 수가 없었다.

지금 생각해보면, 프로젝트 진행을 위해 구현 관점에서 그렇게 답변해주신거 같기도 하다.

당시에는 프로젝트를 완성하는 것이 우리 개발팀에게 우선이었기 때문에
JSON으로 응답하고, HTTP Status를 헤더에 포함시키는 방식으로
그대로 구현을 이어갔다.
하지만 머릿속에는 계속해서 다음과 같은 질문들이 남아 있었다.

  • REST가 아닌 방식으로도 API를 설계할 수 있는 건가?
  • HTTP Status는 정확히 어떤 의미를 가지는 건지?
  • Status Code를 JSON 바디에 포함시키는 것은 맞는 방식인지?

이런 질문들에 명확히 답하지 못하고 "알고 있는 척"하면서 개발하고 있다는 느낌이 계속 들었다.

최종 프로젝트에 가까워지면서, 이번에는 제대로 이해한 상태로 구현해보고 싶다는 생각이 들어,
그 계기로 REST에 대해 다시 공부하게 되었다.

이 글은 그때 공부했던 내용을 바탕으로
REST가 무엇인지, 그리고 RESTful하다는 말이
도대체 무엇을 의미하는지 정리하고 복기하기 위한 글이다.

다시 공부해보니, 그 때도 조금 틀린 부분이 있었다라는 것을 알게 되었다.


1. REST의 배경

먼저, REST는 Roy Fielding(이하 로이 필딩)의 다음 논문에서 제시된 아키텍처 스타일이다.

Architectural Styles and the Design of Network-based Software Architectures

제목에서 알 수 있듯이, 제목에는 전혀 REST를 찾아볼 수 없다.
이 논문의 주된 목적은 REST 자체를 소개하는 데 있지 않으며, 제목을 풀어 쓰자면 다음과 같다.

네트워크 기반 분산 소프트웨어 시스템에서 아키텍처 스타일이 시스템에 품질 속성에 어떤 영향을 미치는지 분석하는 것이다.

제목을 읽어도 사실 무슨 말인지 알기 어렵다,,

그래서 논문 전체를 모두 다루기에는 범위가 넓기 때문에,
이 글에서는 REST를 이해하는데 필요한 내용에 한해서만,
논문의 핵심 내용을 간단히 정리하고자 한다.


1.1 아키텍처 스타일

논문에서는 로이 필딩은 아키텍처를 단순한 기능 구현 방식이 아니라,
제약 조건의 선택으로 바라보고 있다.

개발자가 일반적으로 떠올리는 아키텍처가
MVC 구조나 SOLID 원칙처럼 코드 레벨의 구조라면,
논문에서 말하는 아키텍처는 다음 요소의 조합으로 설명한다.

  • 컴포넌트(Component)
  • 커넥터(Connector)
  • 데이터(Data)

그리고 어떤 제약 조건(Constraint)을 선택했는지
시스템의 다음 품질 속성에 직접적인 영향을 미친다고 설명한다.

  • 확장성(Scalability)
  • 변경 용이성(Modifiability)
  • 신뢰성(Reliability)

즉, 로이 필딩의 아키텍처란, 클라이언트·서버·네트워크 전반의 상호작용에 적용되는 구조적 선택을 말한다.


1.2 REST 이전 분산 시스템의 한계

로이 필딩은 기존의 분산 시스템 아키텍처들이 인터넷 환경을 충분히 고려하지 않은 전제를 가지고 있다고 지적했다.


(1) 네트워크를 신뢰할 수 있다는 전제

REST 이전의 분산 시스템들은 대체로 다음과 같은 가정을 전제로 설계되었다.

  • 네트워크 지연과 장애는 예외 상황임.
  • 연결은 비교적 오래 유지됨.
  • 메시지는 결국 도착함.

이러한 전제는 소규모 폐쇄 환경에서는 어느 정도 성립할 수 있지만,
인터넷과 같이 지연·실패·단절이 일상적인 환경에서는 구조적으로 유지되기 어렵다.

즉, 네트워크를 신뢰하는 설계는 시스템이 커질수록 장애에 취약하다.


(2) 강한 결합

당시 분산 시스템 아키텍처는 클라이언트와 서버가 서로의 내부 구조에 강하게 의존하는 경우가 있었다고 한다.

  • 클라이언트가 서버의 메서드 시그니처를 알고 있어야 함.
  • 데이터 구조가 변경되면 클라이언트도 함께 수정되어야함.

이러한 강한 결합은 시스템 규모가 커질수록 변경 비용이 기하 급수적으로 증가한다.


(3) 상태 저장 중심의 상호작용

이어서, 공통적인 특징으로 서버가 클라이언트의 진행 상태를 세션으로 관리하는 방식이었다.

  • 다음 요청이 이전 요청의 컨텍스트에 의존함.
  • 서버는 클라이언트별 상태를 가지고 있어야함.
  • 서버 장애 시 각 클라이언트의 상태 복구가 어려움.

위 구조에서는, 로드 밸런싱과 수평 확장이 복잡해지고, 시스템의 확장성이 구조적으로 제한된다.


여기서 로이 필딩은 HTTP, URI, 캐시, 프록시, 무상태 요청 등의 기술은 이미 발전하고 잘 동작하고 있지만,
기술들의 조합(제약조건)이 어떤 아키텍처적인 특성을 만들어내었고, 아키텍처 특성들이 어떻게 변화하는지 설명할 일관된 아키텍처 스타일이 없었다고 한다.

이 부분이 조금 어려운데, 비유로 설명해보자면
당시 웹은 이미 잘 작동하는 요리였는데, 왜 이 재료 조합이 대규모로 실패하지 않는지를 설명하는 레시피(재현성)이 존재하지 않았다고 이해해보면 좋을 것 같다.


2. 그래서 REST?

이제 다시 REST로 돌아와 보자.

로이 필딩은 웹이 실제로 따르고 있던 설계 원리를 분석했고,
그 결과를 하나의 아키텍처 스타일로 정식화했다.
그렇게 정의된 아키텍처 스타일이 바로
REST(Representational State Transfer) 다.

논문에서는 REST를 다음과 같이 정의한다.

REST는 분산 하이퍼미디어 시스템을 위한 아키텍처 스타일이다.

여기서 말하는 분산 하이퍼미디어 시스템이란,

  • 네트워크로 분산된 컴포넌트들이
  • 하이퍼미디어(링크)를 통해 상호작용하며
  • 상태 전이가 이루어지는 시스템을 의미한다.

이 정의에서 가장 중요한 점은, REST가 특정 기술이나 구현 규칙을 의미하지 않는다는 것이다.
REST는 프레임워크도 아니고, API 작성 규칙의 목록도 아니다.

REST는 단순히 제약 조건의 집합이다.

즉, REST란 어떤 제약 조건들을 선택했을 때,분산 시스템이 어떤 성질을 갖게 되는지를 설명하는 아키텍처적 모델로 이해할 수 있다.

다시 말해, REST는 “어떻게 구현할 것인가”가 아니라 “어떤 제약을 선택할 것인가”에 대한 이야기다.


2.1 REST 이름 파헤치기

REST가 어떤 제약 조건을 선택했는지 살펴보기 전에,
먼저 REST라는 이름 자체가 무엇을 의미하는지부터 정리해보자.

REST는 Representational State Transfer의 약자다.
이 이름은 REST의 핵심 개념을 그대로 담고 있다.


1) Representational

먼저 Representational이다.

로이 필딩의 REST에서 가장 중요한 구분 중 하나는
자원(Resource)표현(Representation) 을 분리해서 바라보는 것이다.

  • Resource(자원): 서버가 관리하는 개념적 대상
  • Representation(표현): 자원의 현재 상태를 나타내는 표현 결과

예를 들어 다음과 같이 생각할 수 있다.

  • Resource: 사용자 123
  • Representation: JSON, XML, HTML 등

사용자 123이라는 자원은 하나지만, 이를 표현하는 방식은 JSON일 수도 있고, XML이나 HTML일 수도 있다.

즉, 클라이언트는 자원 자체에 직접 접근하지 않고, 항상 자원의 표현(Representation)을 통해 상호작용한다.
이를 통해 다음과 같은 효과를 얻을 수 있다.

  • 서버는 내부 구현과 구조를 숨길 수 있고
  • 클라이언트는 표현 형식만 이해하면 되며
  • 하나의 자원을 다양한 방식으로 표현할 수 있다

이러한 분리는 결국, 우리가 항상 중요하게 말하는 느슨한 결합(loose coupling) 을 가능하게 한다.


2) State

다음은 State다.

REST에서 말하는 상태(State)는
서버의 상태가 아니라 클라이언트의 애플리케이션 상태(Application State) 를 의미한다.

애플리케이션 상태란,

  • 클라이언트가 현재 어떤 화면에 있는지
  • 다음으로 어떤 행동을 할 수 있는지
    와 같은 진행 흐름을 말한다.

REST에서는 서버가 이 애플리케이션 상태를 저장하지 않는다.
대신 서버는 자원의 표현(Representation) 을 전달하고,
클라이언트는 그 표현을 해석하여
자신의 애플리케이션 상태를 변경한다.

즉,

  • 서버는 다음 상태를 강제하지 않고
  • 클라이언트는 응답을 해석하여
  • 스스로 상태를 전이한다

이 과정이 바로 State Transfer다.


3) Transfer

Transfer는 이 상태 변화가
표현(Representation)의 교환을 통해 이루어진다는 의미다.

서버는 상태를 “관리”하지 않고,
표현을 “전달”할 뿐이다.


정리

지금까지를 한 문장으로 정리하면 다음과 같다.

  • Representational: 자원의 표현을 다룬다
  • State: 클라이언트의 애플리케이션 상태를 의미한다
  • Transfer: 표현의 교환을 통해 상태가 전이된다

즉, REST란
자원의 표현을 주고받는 과정을 통해
클라이언트의 상태가 전이되는 구조
를 의미한다.

그래서 REST는

  • HTTP 규칙도 아니고
  • API 명세서 작성법도 아니며
  • JSON으로 데이터를 주고받는 방식도 아니다.

2.2 REST가 선택한 제약 조건

다시 돌아와서 REST가 대략 어떤 것인지 파악했으니,
이제 더 깊은 이해를 위해 REST가 어떤 제약 조건을 선택했는지 살펴보고자 한다.

로이 필딩의 REST에서는 다음 6가지의 제약조건이 존재한다.
(1) Client-Server: 클라이언트와 서버를 분리함.
(2) Stateless: 클라이언트는 애플리케이션 상태를 저장하지 않음.
(3) Cache: 응답은 캐시 가능 여부 명시함.
(4) Uniform Interface: 자원의 상호작용을 일관된 인터페이스로 통일함.
(5) Layered System: 중간 계층을 허용함.
(6) Code-on-Demand(Optional): 서버가 실행 코드를 클라이언트에 전달할 수도 있음.

각 제약 조건을 깊게 다뤄보고자 한다.


2.2.1 Client-Server

사용자 인터페이스(클라이언트)와 데이터•비즈니스 로직(서버)을 분리하라는 제약이다.
각각은 분리된 역할만 수행한다.

  • 클라이언트: 사용자와의 상호작용을 담당함.
  • 서버: 자원의 상태와 처리 로직을 담당함.

이 분리를 통해 각각은 독립적으로 확장될 수 있다.

  • 서버 구현이 변경되어도 클라이언트는 영향을 최소화할 수 있고,
  • 클라이언트가 다양해져도 서버는 동일한 인터페이스를 유지할 수 있다.

REST는 이를 통해 클라이언트와 서버가 강하게 결합되는 구조를 의도적으로 피한다.


2.2.2 Stateless

Stateless는 REST를 가장 잘 드러내는 제약조건이다.
제약의 의미는 다음과 같다.

  • 서버는 클라이언트의 애플리케이션 상태(Application State)를 저장하지 않는다.
  • 각 요청은 이전 요청과 무관하게 독립적으로 처리되어야 한다.

여기서 애플리케이션의 상태는 클라이언트가 현재 어떤 페이지에 있으며, 다음으로 할 수 있는 것은 주문을 하거나, 장바구니 페이지로 이동하거나를 의미한다.

따라서, 서버는 애플리케이션이 어떤 페이지에 있는지 이전에 어떤 작업을 했는지에 대해 알 필요도 없으며 알 수 없어야한다. 서버는 위와 같은 애플리케이션의 상태에 개입하지 않는다.

이를 통해서 REST는 수평 확장이 쉬워지고, 로드 밸런싱 및 장애 복구에 용이해진다.


2.2.3 Cache

Cache 제약은 응답이 캐시가 가능한지 여부를 명시해야한다는 제약이다.
REST에서는 모든 응답은 캐시가 가능하거나, 캐시가 불가능함을 표현해야한다는 것이다. 이를 통해 얻을 수 있는 효과는 다음과 같다.

  • 네트워크 트래픽 감소
  • 응답 속도 개선
  • 서버 부하 완화

이 제약은 REST가 중간 계층의 개입을 허용하는 아키텍처임을 보여준다.


2.2.4 Uniform Interface

Uniform Interface는 클라이언트와 서버가 상호작용하는 방식이 일관된 인터페이스를 따라야한다는 것을 의미한다.

Uniform Interface는 다음 하위 원칙을 가지고 있으며 각각을 예시로 뜯어보고자 한다.


(1) 자원은 식별 가능해야한다.

  • 자원은 고유하게 식별할 수 있으며, 해당 식별자는 URI(Uniform Resource Identifier)로 표현 되어야 한다.
  • 즉, URI는 행위(무엇을 한다)가 아니라 자원(무엇이다)을 식별할 수 있어야
    잘못된 접근
    /createUser
    /getUserInfo?id=123
    
    잘 된 접근
    /users		-> 사용자라는 자원
    /users/123    -> 특정 사용자라는 자원 

(2) 자원은 Representation을 통해서 조작된다.

  • 클라이언트는 자원 자체를 조작하지 않으며 항상 자원의 표현(representation)을 주고 받는다.
  • 다음 예시 상황을 살펴보자.
    • 자원: 주문(id = 1), 표현: JSON으로 표현된 주문의 상태
    • 주문 상태의 조회
      GET /orders/1
      {
        "orderId": 1,
        "status": "CREATED",
        "totalPrice": 30000
       }
    • 주문 상태의 변경
      PUT /orders/1
      {
        "status": "CANCELED",
       }
  • 이를 통해서 클라이언트는 서버의 내부 구조를 모른 채, 표현만 수정해서 전달하여 자원을 조작할 수 있는 것이다.

(3) 메시지는 자기 설명적(Self-descriptive)이어야한다.

해당 제약 조건은 단순하다.
응답 메시지 하나만 보고도 다음을 알 수 있어야한다는 점이다.

  • 이 메시지가 무엇을 의미하는지
  • 어떻게 처리해야 하는지
  • 어떤 형식인지

즉, 외부 문맥에 의존하지 않아야한다는 것이다.

  • 자기 설명적이지 않은 예시

    // 요청
    POST /users
    Content-Type: application/json
    
    // 응답
    {
      "name": "kim",
      "age": 20
    }
    • 위를 보고 우리는 이 JSON이 어떤 의미인지, 생성인지 수정인지, 어떤 자원의 표현인지를 알 수 없다.
  • 자기 설명적인 예시

    // 요청
    POST /users
    Content-Type: application/json
    
    // 응답
    HTTP/1.1 201 Created
    Location: /users/123
    {
      "name": "kim",
      "age": 20
    }
  • 메시지 자체에 의미, 처리 결과, 다음 행동의 힌트가 포함되어 있는 것을 알 수 있다.


(4) 상태 전이는 하이퍼미디어를 통해 이루어진다.(HATEOAS)

먼저, 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" }
  }
}

클라이언트는 이 응답으로 현재 상태에서 다음과 같은 것이 가능하다는 것을 알 수 있다.

  • 결제 가능
  • 취소 가능

2.2.5 Layered System

다음으로는 중첩 구조로 REST는 시스템이 여러 계층으로 구성될 수 있음을 허용한다.
예시로 다음과 같다.

  • 클라이언트 ↔ 로드 밸런서 ↔ 프록시 ↔ 서버
  • 보안 게이트웨비, 캐시 서버의 중간 개입

위 제약은 다음을 설명한다.

  • 클라이언트는 최종 서버를 알 필요가 없다.
  • 각 계층은 자신의 역할에만 집중한다.

이를 통해 REST는

  • 보안 강화
  • 확장성 향상
  • 운영상의 유연성을
    구조적으로 확보할 수 있게 된다.

2.2.6 Code-on-Demand

위 제약은 서버가 클라이언트에 실행 코드를 전달할 수 있도록 허용하는 제약이다.
대표적으로 JavaScript가 있다.

다만 이 제약은 REST의 유일한 선택적 제약 조건이며, REST를 성립시키기 위해 필수는 아니다.


3. 오늘의 결론, RESTful한 것은 무엇일까?

업로드중..

지금까지 REST가 어떤 배경에서 등장했고,
어떤 제약과 원칙을 통해 정의되었는지를 살펴보았다.
이제 다시 처음의 질문으로 돌아가 보자.

그래서 RESTful한게 무엇인가?

RESTful하다는 것은
어떠한 형식이나 규현 규칙을 따르고 있는것을 묻는 말이 아니다.
REST라는 아키텍처 스타일의 관점을 가지고 설계되었는가를 묻는 것이다.

예시로 다음과 같은 요소들은 REST를 구현할 때 자주 등장하지만,
그 자체가 REST의 본질은 아니다.

  • JSON으로 응답하는가
  • HTTP Status Code를 사용하는가
  • API 명세서 작성 방법

위 내용이 완전히 틀리다고 할 수는 없지만 REST의 본질적 의미와는 다르다고 할 수 있다.

RESTful함을 한 문장으로 정리하면,
나는 다음과 같이 정리해볼 수 있을 것 같다.

시스템의 자원(Resource)을
그 자원의 표현(Representational State)으로 교환함으로써,
클라이언트와 서버 간의 결합을 느슨하게 유지하려는
아키텍처적 원칙을 얼마나 잘 따르고 있는가

만약 면접장에서
“RESTful이 무엇인가요?”라는 질문을 받는다면,
나는 다음과 같이 답할 수 있을 것 같다.

RESTful하다는 것은
시스템의 자원을 표현의 형태로 주고받으며,
분산 환경에서 강한 결합을 피하고
확장성과 변화에 유리한 구조를 만들기 위해
REST가 제시한 제약과 원칙을
얼마나 의식적으로 설계에 반영했는지를 의미합니다.


4. 마치며,,

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가 어떻게 구현되고 있는지를 다음 순서로 살펴보고자 한다.

  • Spring 프레임워크에서 REST
  • RESTful하게 API 명세서 작성하고, 내 프로젝트가 REST한지 검토하고 리팩토링 수행해보기

항상 마지막으로 남기는 말인데,
블로그는 언제나 참고를 위한 자료로 사용하고 공식 문서를 통해 이해하는 것이 더욱 명확하다.
최근에는 GPT로도 어려운 논문을 도와서 읽을 수도 있으니, GPT 등의 생성형 AI를 잘 활용하는 것도 좋아 보인다.

참고 문헌

profile
개발 참 즐겁습니다.

0개의 댓글