본문 바로가기
3. 서재

"대부분의 RESTful하지 않다." 경고를 다시 읽다

by su8y 2023. 6. 11.

최근 Naver D2 노트에서 “REST API는 RESTful하지 않다”는 문장을 보고, 다시금 Roy T. Fielding의 박사 논문『Architectural Styles and the Design of Network-based Software Architectures (2000)』 를 읽어보았습니다.

REST를 만든 그가 말하는 진짜 REST란 무엇이고,
왜 우리가 흔히 사용하는 REST API는 사실 RESTful하지 않은 걸까요?

이 글에서는 논문에 기반해 REST 아키텍처 스타일의 핵심 원칙들을 정리하고,
우리가 실제 개발에서 사용하는 REST API와 비교하며 돌아보려 합니다.


REST는 기술이 아니라 아키텍처 스타일입니다

많은 사람들이 REST를 기술 스택 중 하나로 오해합니다.
하지만 REST는 하나의 표준 기술이 아니라, 디자인 원칙과 제약 조건의 조합으로 구성된 아키텍처 스타일입니다.

HTTP를 기반으로 분산 하이퍼미디어 시스템을 이상적으로 설계하기 위한 철학이며,
우리가 사용하는 REST API는 그 철학을 얼마나 잘 구현하고 있는가에 따라 진짜 RESTful한지 판단할 수 있습니다.


REST 아키텍처 스타일의 6가지 제약 조건

1. Client-Server (관심사의 분리)

서버는 리소스를 관리하고, 클라이언트는 사용자와 상호작용하는 역할을 합니다.
이 구조는 UI와 데이터 저장을 명확히 분리함으로써, 각 구성 요소가 독립적으로 진화할 수 있게 해줍니다.

2. Stateless (무상태성)

서버는 클라이언트의 상태를 저장하지 않습니다.
모든 요청은 자기 완결적(self-contained)이어야 하며, 요청에 필요한 모든 정보는 요청 메시지 안에 포함되어야 합니다.

이로 인해 서버는 확장성과 장애 대응 측면에서 유리해지고, 로드 밸런싱도 쉽게 구현할 수 있습니다.

3. Cacheable (캐시 가능성)

REST 응답에는 캐시 가능 여부를 명시하는 지시자가 포함되어야 합니다.
캐시가 적절히 동작하면 다음과 같은 이점을 얻을 수 있습니다:

  • 서버 부하 감소
  • 네트워크 트래픽 감소
  • 응답 속도 향상

4. Uniform Interface (일관된 인터페이스)

REST를 REST답게 만드는 가장 핵심적인 제약 조건입니다.
모든 리소스와의 상호작용은 일관된 방식으로 이루어져야 하며, 이는 4개의 하위 제약 조건으로 구체화됩니다:

4-1. Resource Identification

모든 자원(Resource)은 고유한 URI로 식별되어야 합니다.

예:

/users/1 /articles/10/comments

4-2. Representation-based Manipulation

리소스는 자체를 직접 조작하는 것이 아니라, 표현(Representation)을 통해 조작합니다.
표현은 일반적으로 JSON 또는 XML과 같은 포맷으로 전달됩니다.

PUT /users/1 Content-Type: application/json { "name": "Su8y", "email": "su8y@example.com" }

4-3. Self-descriptive Messages

모든 메시지는 그 자체만으로 의미를 이해할 수 있어야 합니다.
서버와 클라이언트는 메시지를 해석하기 위해 추가 맥락 정보를 필요로 하지 않아야 하며,
이를 위해 HTTP 헤더와 메시지 본문이 구조화된 정보를 포함해야 합니다.

예:

GET /articles/2 Accept: application/json Authorization: Bearer <token>

4-4. HATEOAS (Hypermedia as the Engine of Application State)

이 제약은 REST의 정체성을 결정짓는 요소로,
클라이언트는 하이퍼미디어 링크를 통해 애플리케이션 상태를 전이해야 합니다.
서버가 제공하는 링크 외의 정보 없이도 다음 행동을 결정할 수 있어야 한다는 의미입니다.

{ 
	"title": "REST 논문 요약",
	"links": [{ "rel": "self", "href": "/articles/2" },
            { "rel": "다음글", "href": "/articles/3" },
            { "rel": "작성자", "href": "/users/5" }] 
}

✅ 이 방식은 클라이언트가 서버 내부 구조를 몰라도, 링크만 따라가며 동작할 수 있게 만들어줍니다.

5. Layered System (계층화 구조)

REST 시스템은 여러 계층(프록시, 게이트웨이, 캐시 등)으로 구성될 수 있으며,
클라이언트는 그 중간 계층의 존재를 인식하지 못해야 합니다.

예:
CDN → API Gateway → Application Server → Database

6. Code-on-Demand (선택 제약)

서버는 클라이언트에게 코드를 전송하여 실행할 수 있습니다. (예: JavaScript)
이는 REST의 선택적 제약 조건으로, 클라이언트의 기능을 동적으로 확장할 수 있게 해줍니다.


대부분의 REST API가 RESTful하지 않은 이유

현대의 대부분 API는 위 제약 조건 중 특히 Uniform Interface – 그 중에서도 HATEOAS를 지키지 않습니다.
대부분의 프론트엔드 코드는 API 경로를 직접 알고 있으며, 링크를 통해 상태를 전이하지 않기 때문에,
냉정하게 보자면 REST라기보다는 단순한 HTTP 기반의 RPC에 가까운 경우가 많습니다.


마무리 – 진짜 REST를 만든다는 것

이 철학과 제약 조건을 이해하고 설계할 때, 우리는 비로소 REST 아키텍처 스타일의 본질에 가까워질 수 있습니다.

 

하지만 현실적으로 모든 제약 조건을 완벽하게 지키는 것은 쉽지 않습니다. 특히 HATEOAS 같은 경우, 클라이언트와 서버 간의 엄격한 계약을 유연하게 가져가야 하고, 프론트엔드 개발 시 동적인 링크 처리에 대한 복잡성이 증가할 수 있어 도입이 망설여지는 경우가 많죠. 촉박한 개발 일정, 기존 시스템과의 호환성 문제, 팀원들의 이해도 차이 등 여러 가지 현실적인 제약이 따르기 마련입니다.

 

그럼에도 불구하고, REST의 핵심 원칙들을 이해하고 이를 최대한 따르려는 노력은 매우 중요합니다. 완벽한 RESTful API를 만들지 못하더라도, 무상태성, 리소스 기반의 일관된 인터페이스, 자기 서술적인 메시지 등 지킬 수 있는 원칙들을 적용하며 점진적으로 개선해 나가는 것이 좋습니다. 이는 API의 확장성, 유지보수성, 그리고 클라이언트 개발 편의성을 높이는 데 크게 기여할 것입니다.