TL;DR

  • REST 아키텍처 - 배경부터 핵심까지의 핵심 개념과 사용 범위를 한눈에 정리
  • 등장 배경과 필요한 이유를 짚고 실무 적용 포인트를 연결
  • 주요 특징과 체크리스트를 빠르게 확인

1. 개념

┌─────────────────────────────────────────────────────────────────┐ │ REST 이전의 혼란 │ │ │ │ 1990년대 후반 ~ 2000년대 초반 │ │ │ │ 웹 서비스 통신 방법들: │ │ ├── CORBA (1991): 복잡한 바이너리 프로토콜 │ │ ├── DCOM (1996): Windows 전용, 방화벽 문제 │ │ ├── RMI (1997): Java 전용 │ │ └── SOAP (1998): XML 기반, 엄청나게 복잡 │ │ │ │ SOAP 메시지 예시: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ <?xml version="1.0"?> │ │ │ │ <soap:Envelope │ │ │ │ xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> │ │ │ │ <soap:Header> │ │ │ │ <auth:Credentials>...</auth:Credentials> │ │ │ │ </soap:Header> │ │ │ │ <soap:Body> │ │ │ │ <m:GetUser> │ │ │ │ <m:UserId>123</m:UserId> │ │ │ │ </m:GetUser> │ │ │ │ </soap:Body> │ │ │ │ </soap:Envelope> │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ 문제점: │ │ ├── 너무 복잡하고 무거움 │ │ ├── WSDL (서비스 정의) 작성이 고통 │ │ ├── 모든 요청이 POST (HTTP를 단순 터널로만 사용) │ │ └── 디버깅 어려움 │ │ │ └─────────────────────────────────────────────────────────────────┘

2. 배경

REST 아키텍처 - 배경부터 핵심까지이(가) 등장한 배경과 기존 한계를 정리한다.

3. 이유

이 주제를 이해하고 적용해야 하는 이유를 정리한다.

4. 특징

  • 1 REST 이전의 혼란
  • 2 Roy Fielding과 REST의 등장
  • 1 Client-Server
  • 2 Stateless (무상태)
  • 3 Cacheable (캐시 가능)

5. 상세 내용

작성일: 2026-01-29 카테고리: Backend / Architecture / API Design 포함 내용: REST, RESTful API, Uniform Interface, Stateless, HATEOAS, Richardson 성숙도 모델


1. REST의 탄생 배경

1.1 REST 이전의 혼란

┌─────────────────────────────────────────────────────────────────┐
│                      REST 이전의 혼란                            │
│                                                                   │
│  1990년대 후반 ~ 2000년대 초반                                   │
│                                                                   │
│  웹 서비스 통신 방법들:                                          │
│  ├── CORBA (1991): 복잡한 바이너리 프로토콜                      │
│  ├── DCOM (1996): Windows 전용, 방화벽 문제                      │
│  ├── RMI (1997): Java 전용                                       │
│  └── SOAP (1998): XML 기반, 엄청나게 복잡                        │
│                                                                   │
│  SOAP 메시지 예시:                                               │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  <?xml version="1.0"?>                                   │    │
│  │  <soap:Envelope                                          │    │
│  │    xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> │    │
│  │    <soap:Header>                                         │    │
│  │      <auth:Credentials>...</auth:Credentials>            │    │
│  │    </soap:Header>                                        │    │
│  │    <soap:Body>                                           │    │
│  │      <m:GetUser>                                         │    │
│  │        <m:UserId>123</m:UserId>                          │    │
│  │      </m:GetUser>                                        │    │
│  │    </soap:Body>                                          │    │
│  │  </soap:Envelope>                                        │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  문제점:                                                         │
│  ├── 너무 복잡하고 무거움                                        │
│  ├── WSDL (서비스 정의) 작성이 고통                              │
│  ├── 모든 요청이 POST (HTTP를 단순 터널로만 사용)                │
│  └── 디버깅 어려움                                               │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

1.2 Roy Fielding과 REST의 등장

┌─────────────────────────────────────────────────────────────────┐
│                    REST의 탄생 (2000년)                          │
│                                                                   │
│  Roy Fielding:                                                   │
│  ├── HTTP/1.0, HTTP/1.1 명세 공동 저자                           │
│  ├── Apache HTTP Server 공동 개발자                              │
│  └── "웹이 왜 이렇게 잘 작동하는지" 분석                         │
│                                                                   │
│  2000년, UC Irvine 박사 논문:                                    │
│  "Architectural Styles and the Design of                        │
│   Network-based Software Architectures"                          │
│                                                                   │
│  핵심 통찰:                                                      │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  "웹(WWW)은 이미 거대하고 성공적인 분산 시스템이다.      │    │
│  │   웹이 성공한 아키텍처 원칙을 API에도 적용하자!"         │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  REST = REpresentational State Transfer                          │
│       = 표현된 상태의 전송                                       │
│       = 리소스의 현재 상태를 표현해서 주고받자                   │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

2. REST의 6가지 제약조건

┌─────────────────────────────────────────────────────────────────┐
│              REST의 6가지 아키텍처 제약조건                      │
│                                                                   │
│  1. Client-Server (클라이언트-서버 분리)                         │
│  2. Stateless (무상태)                                           │
│  3. Cacheable (캐시 가능)                                        │
│  4. Uniform Interface (균일한 인터페이스) ← 가장 중요!           │
│  5. Layered System (계층화 시스템)                               │
│  6. Code on Demand (선택적, 코드 전송)                           │
│                                                                   │
│  이 6가지를 모두 지켜야 "RESTful"                                │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

2.1 Client-Server

┌─────────────────────────────────────────────────────────────────┐
│  1. Client-Server 분리                                           │
│                                                                   │
│  ┌──────────┐                        ┌──────────┐               │
│  │  Client  │ ◄─── HTTP 요청/응답 ──► │  Server  │               │
│  │  (UI)    │                        │  (Data)  │               │
│  └──────────┘                        └──────────┘               │
│                                                                   │
│  핵심:                                                           │
│  ├── 관심사의 분리 (Separation of Concerns)                      │
│  ├── 클라이언트: UI, 사용자 경험                                 │
│  ├── 서버: 데이터 저장, 비즈니스 로직                            │
│  └── 각각 독립적으로 발전 가능                                   │
│                                                                   │
│  예: 모바일 앱 새 버전 출시해도 서버는 그대로                    │
│      서버 DB 교체해도 클라이언트는 모름                          │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

2.2 Stateless (무상태)

┌─────────────────────────────────────────────────────────────────┐
│  2. Stateless (무상태)                                           │
│                                                                   │
│  "서버는 클라이언트의 상태를 기억하지 않는다"                    │
│                                                                   │
│  ❌ Stateful (상태 유지):                                        │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  요청 1: "로그인해줘" (id=kim)                           │    │
│  │  서버: "OK, 너를 기억할게" (세션 저장)                   │    │
│  │                                                          │    │
│  │  요청 2: "내 주문 목록 줘"                               │    │
│  │  서버: "아까 kim이었지? 여기 있어"                       │    │
│  │                                                          │    │
│  │  문제: 서버 여러 대면? 다른 서버로 가면 모름!            │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  ✅ Stateless (무상태):                                          │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  요청 1: "로그인" → 서버: "여기 토큰(JWT)"               │    │
│  │                                                          │    │
│  │  요청 2: "내 주문 목록 줘" + 토큰                        │    │
│  │  서버: "토큰 확인, kim이구나, 여기 있어"                 │    │
│  │                                                          │    │
│  │  장점: 어떤 서버든 처리 가능! (확장성)                   │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  이점:                                                           │
│  ├── 서버 확장 쉬움 (로드밸런서 뒤에 서버 추가)                  │
│  ├── 서버 장애 시 다른 서버가 처리                               │
│  └── 요청 간 의존성 없음                                         │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

2.3 Cacheable (캐시 가능)

┌─────────────────────────────────────────────────────────────────┐
│  3. Cacheable (캐시 가능)                                        │
│                                                                   │
│  "응답이 캐시 가능한지 명시해야 한다"                            │
│                                                                   │
│  ┌──────────┐    ┌───────┐    ┌──────────┐                      │
│  │  Client  │───►│ Cache │───►│  Server  │                      │
│  └──────────┘    └───────┘    └──────────┘                      │
│                       │                                          │
│                       └── 캐시 히트 시 서버 안 감               │
│                                                                   │
│  HTTP 헤더로 캐시 제어:                                          │
│  ├── Cache-Control: max-age=3600 (1시간 캐시)                    │
│  ├── ETag: "abc123" (버전 태그)                                  │
│  └── Last-Modified: ... (마지막 수정 시간)                       │
│                                                                   │
│  GET /users/1 → 캐시 가능 (같은 요청 = 같은 응답)                │
│  POST /users  → 캐시 불가 (매번 다른 결과)                       │
│                                                                   │
│  이점: 성능 향상, 서버 부하 감소                                 │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

2.4 Layered System (계층화)

┌─────────────────────────────────────────────────────────────────┐
│  5. Layered System (계층화 시스템)                               │
│                                                                   │
│  "클라이언트는 중간 계층을 모른다"                               │
│                                                                   │
│  ┌──────────┐   ┌───────┐   ┌──────┐   ┌──────────┐            │
│  │  Client  │──►│  CDN  │──►│  LB  │──►│  Server  │            │
│  └──────────┘   └───────┘   └──────┘   └──────────┘            │
│       │                                       │                  │
│       └─── 클라이언트는 그냥 요청만 보냄 ────┘                  │
│            중간에 뭐가 있는지 모름                               │
│                                                                   │
│  중간 계층 예시:                                                 │
│  ├── 로드 밸런서                                                 │
│  ├── 캐시 서버 (Redis, Varnish)                                  │
│  ├── API Gateway                                                 │
│  ├── 보안 프록시                                                 │
│  └── CDN                                                         │
│                                                                   │
│  이점: 보안, 확장성, 유연한 아키텍처                             │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

2.5 Code on Demand (선택적)

┌─────────────────────────────────────────────────────────────────┐
│  6. Code on Demand (선택적)                                      │
│                                                                   │
│  "서버가 클라이언트에 실행 가능한 코드 전송"                     │
│                                                                   │
│  예시:                                                           │
│  ├── JavaScript 전송 (웹 페이지)                                 │
│  ├── Java Applet (옛날)                                          │
│  └── Flash (RIP)                                                 │
│                                                                   │
│  유일한 선택적 제약조건                                          │
│  대부분의 REST API에서는 해당 없음                               │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

3. Uniform Interface (균일한 인터페이스) - 가장 중요!

REST를 REST답게 만드는 핵심 제약조건. 4가지 하위 제약으로 구성됨.

┌─────────────────────────────────────────────────────────────────┐
│            Uniform Interface의 4가지 하위 제약                   │
│                                                                   │
│  ① Identification of Resources (리소스 식별)                    │
│  ② Manipulation through Representations (표현을 통한 조작)      │
│  ③ Self-descriptive Messages (자기 서술적 메시지)               │
│  ④ HATEOAS (하이퍼미디어를 통한 상태 전이)                      │
│                                                                   │
│  왜 중요한가?                                                    │
│  ├── 다른 제약은 다른 아키텍처도 가질 수 있음                    │
│  ├── Uniform Interface가 REST를 REST답게 만드는 핵심             │
│  └── Roy Fielding: "REST의 핵심 특징"                            │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

3.1 리소스 식별 (Identification of Resources)

┌─────────────────────────────────────────────────────────────────┐
│          ① 리소스 식별 (Identification of Resources)            │
│                                                                   │
│  핵심: "모든 리소스는 고유한 URI로 식별된다"                     │
│                                                                   │
│  리소스란?                                                       │
│  ├── 명사로 표현되는 "것" (noun)                                 │
│  ├── 사용자, 주문, 상품, 댓글 등                                 │
│  └── 동사가 아닌 명사!                                           │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │                      URI 설계                            │    │
│  │                                                          │    │
│  │  ❌ 나쁜 예 (동사 사용):                                 │    │
│  │  POST /getUsers                                          │    │
│  │  POST /createUser                                        │    │
│  │  POST /deleteUser?id=123                                 │    │
│  │  GET  /getUserOrders?userId=123                          │    │
│  │                                                          │    │
│  │  ✅ 좋은 예 (명사 + HTTP 메서드):                        │    │
│  │  GET    /users           → 사용자 목록                   │    │
│  │  GET    /users/123       → 123번 사용자                  │    │
│  │  POST   /users           → 사용자 생성                   │    │
│  │  DELETE /users/123       → 123번 사용자 삭제             │    │
│  │  GET    /users/123/orders → 123번 사용자의 주문 목록     │    │
│  │                                                          │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  URI 설계 원칙:                                                  │
│  ├── 복수형 사용: /users (not /user)                             │
│  ├── 계층 관계 표현: /users/123/orders/456                       │
│  ├── 소문자 사용: /users (not /Users)                            │
│  ├── 하이픈 사용: /user-profiles (not /user_profiles)            │
│  └── 파일 확장자 없음: /users/123 (not /users/123.json)          │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

3.2 표현을 통한 조작 (Manipulation through Representations)

┌─────────────────────────────────────────────────────────────────┐
│      ② 표현을 통한 조작 (Manipulation through Representations)  │
│                                                                   │
│  핵심: "리소스 자체가 아닌 '표현'을 주고받는다"                  │
│                                                                   │
│  리소스 vs 표현:                                                 │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │                                                          │    │
│  │  리소스 (Resource):                                      │    │
│  │  └── DB에 저장된 실제 데이터                             │    │
│  │  └── users 테이블의 id=123 레코드                        │    │
│  │                                                          │    │
│  │  표현 (Representation):                                  │    │
│  │  └── 리소스의 현재 상태를 특정 형식으로 표현한 것        │    │
│  │  └── JSON, XML, HTML, 이미지 등                          │    │
│  │                                                          │    │
│  │  같은 리소스, 다른 표현:                                 │    │
│  │  GET /users/123                                          │    │
│  │  Accept: application/json → {"id":123, "name":"Kim"}     │    │
│  │  Accept: application/xml  → <user><id>123</id>...</user> │    │
│  │  Accept: text/html        → <html>사용자 정보...</html>  │    │
│  │                                                          │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  조작 예시:                                                      │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  1. 조회: 리소스의 "표현"을 받음                         │    │
│  │     GET /users/123                                       │    │
│  │     응답: {"id": 123, "name": "Kim", "email": "..."}     │    │
│  │                                                          │    │
│  │  2. 수정: "표현"을 보내서 리소스 변경                    │    │
│  │     PUT /users/123                                       │    │
│  │     Body: {"id": 123, "name": "Park", "email": "..."}    │    │
│  │     → 서버가 이 표현으로 리소스를 업데이트               │    │
│  │                                                          │    │
│  │  3. 생성: "표현"을 보내서 새 리소스 생성                 │    │
│  │     POST /users                                          │    │
│  │     Body: {"name": "Lee", "email": "..."}                │    │
│  │     → 서버가 이 표현으로 새 리소스 생성                  │    │
│  │                                                          │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  의미:                                                           │
│  ├── 클라이언트는 표현만 다루면 됨 (실제 저장 방식 몰라도 됨)    │
│  ├── 서버 내부 구조가 변해도 표현이 같으면 클라이언트 수정 불필요│
│  └── 콘텐츠 협상 (Content Negotiation) 가능                      │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

3.3 자기 서술적 메시지 (Self-descriptive Messages)

┌─────────────────────────────────────────────────────────────────┐
│          ③ 자기 서술적 메시지 (Self-descriptive Messages)       │
│                                                                   │
│  핵심: "메시지만 보고 무엇을 해야 하는지 완전히 알 수 있어야 함" │
│                                                                   │
│  ❌ 자기 서술적이지 않은 메시지:                                 │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  GET /users/123 HTTP/1.1                                 │    │
│  │  Host: api.example.com                                   │    │
│  │                                                          │    │
│  │  응답:                                                   │    │
│  │  HTTP/1.1 200 OK                                         │    │
│  │                                                          │    │
│  │  {"id": 123, "name": "Kim"}                              │    │
│  │                                                          │    │
│  │  문제: 이게 JSON인지 어떻게 알아?                        │    │
│  │        이 숫자들의 의미는?                               │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  ✅ 자기 서술적인 메시지:                                        │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  GET /users/123 HTTP/1.1                                 │    │
│  │  Host: api.example.com                                   │    │
│  │  Accept: application/json                                │    │
│  │                                                          │    │
│  │  응답:                                                   │    │
│  │  HTTP/1.1 200 OK                                         │    │
│  │  Content-Type: application/json; charset=utf-8           │    │
│  │  Cache-Control: max-age=3600                             │    │
│  │  ETag: "abc123"                                          │    │
│  │                                                          │    │
│  │  {                                                       │    │
│  │    "id": 123,                                            │    │
│  │    "name": "Kim",                                        │    │
│  │    "email": "kim@example.com"                            │    │
│  │  }                                                       │    │
│  │                                                          │    │
│  │  이제 알 수 있는 것:                                     │    │
│  │  ├── 형식: JSON (Content-Type)                           │    │
│  │  ├── 캐시: 1시간 가능 (Cache-Control)                    │    │
│  │  ├── 버전: abc123 (ETag)                                 │    │
│  │  └── 문자셋: UTF-8                                       │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  더 완벽한 자기 서술 (엄격한 해석):                              │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  Content-Type: application/vnd.myapi.user+json; v=1      │    │
│  │                                                          │    │
│  │  → 커스텀 미디어 타입으로 스키마 정보까지 포함           │    │
│  │  → 이 타입의 명세를 보면 필드 의미를 알 수 있음          │    │
│  │  → 현실에서는 거의 안 함 (OpenAPI/Swagger로 대체)        │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
│  실무에서 자기 서술성:                                           │
│  ├── Content-Type 필수                                           │
│  ├── 적절한 HTTP 상태 코드 사용                                  │
│  ├── 에러 응답에 명확한 메시지 포함                              │
│  └── OpenAPI(Swagger) 문서로 보완                                │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

HTTP 상태 코드로 자기 서술

┌─────────────────────────────────────────────────────────────────┐
│                 HTTP 상태 코드 = 자기 서술                       │
│                                                                   │
│  ┌──────────┬────────────────────────────────────────────────┐  │
│  │ 코드     │ 의미 (메시지 안 봐도 알 수 있음)               │  │
│  ├──────────┼────────────────────────────────────────────────┤  │
│  │ 200 OK   │ 성공                                           │  │
│  │ 201 Created│ 새 리소스 생성됨                             │  │
│  │ 204 No Content│ 성공, 응답 본문 없음                      │  │
│  │ 400 Bad Request│ 클라이언트 요청 오류                     │  │
│  │ 401 Unauthorized│ 인증 필요                               │  │
│  │ 403 Forbidden│ 권한 없음                                  │  │
│  │ 404 Not Found│ 리소스 없음                                │  │
│  │ 409 Conflict│ 충돌 (중복 등)                              │  │
│  │ 422 Unprocessable│ 검증 실패                              │  │
│  │ 500 Internal Error│ 서버 오류                             │  │
│  └──────────┴────────────────────────────────────────────────┘  │
│                                                                   │
│  상태 코드만 봐도 결과를 알 수 있다 = 자기 서술적               │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

3.4 HATEOAS (하이퍼미디어를 통한 상태 전이)

┌─────────────────────────────────────────────────────────────────┐
│     ④ HATEOAS (Hypermedia As The Engine Of Application State)  │
│                                                                   │
│  핵심: "응답에 다음에 할 수 있는 행동의 링크를 포함"             │
│                                                                   │
│  왜 필요한가?                                                    │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │                                                          │    │
│  │  일반 API (HATEOAS 없음):                                │    │
│  │  ─────────────────────────                               │    │
│  │  GET /users/123                                          │    │
│  │  응답: {"id": 123, "name": "Kim"}                        │    │
│  │                                                          │    │
│  │  클라이언트: "이 사용자 삭제하려면 어디로 요청하지?"     │    │
│  │            → 문서 보거나 코드에 하드코딩해야 함          │    │
│  │            → API 변경되면 클라이언트도 수정 필요         │    │
│  │                                                          │    │
│  │  HATEOAS 적용:                                           │    │
│  │  ─────────────                                           │    │
│  │  GET /users/123                                          │    │
│  │  응답:                                                   │    │
│  │  {                                                       │    │
│  │    "id": 123,                                            │    │
│  │    "name": "Kim",                                        │    │
│  │    "_links": {                                           │    │
│  │      "self": {"href": "/users/123"},                     │    │
│  │      "delete": {"href": "/users/123", "method": "DELETE"}│    │
│  │      "orders": {"href": "/users/123/orders"},            │    │
│  │      "update": {"href": "/users/123", "method": "PUT"}   │    │
│  │    }                                                     │    │
│  │  }                                                       │    │
│  │                                                          │    │
│  │  클라이언트: 링크만 따라가면 됨!                         │    │
│  │            → URL 하드코딩 불필요                         │    │
│  │            → API 변경되어도 링크만 따라가면 됨           │    │
│  │                                                          │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

HATEOAS 실제 예시

// 주문 조회 응답 (HATEOAS 적용)
{
  "id": 456,
  "status": "PENDING",
  "total": 50000,
  "items": [
    {"productId": 1, "name": "키보드", "quantity": 1}
  ],
  "_links": {
    "self": {
      "href": "/orders/456"
    },
    "cancel": {
      "href": "/orders/456/cancel",
      "method": "POST",
      "title": "주문 취소"
    },
    "pay": {
      "href": "/orders/456/payment",
      "method": "POST",
      "title": "결제하기"
    },
    "customer": {
      "href": "/users/123"
    }
  }
}

// 주문 완료 후에는 cancel, pay 링크가 사라짐
{
  "id": 456,
  "status": "COMPLETED",
  "total": 50000,
  "_links": {
    "self": {"href": "/orders/456"},
    "receipt": {"href": "/orders/456/receipt"},
    "refund": {"href": "/orders/456/refund", "method": "POST"}
  }
}

HATEOAS의 현실

┌─────────────────────────────────────────────────────────────────┐
│                    HATEOAS의 현실                                │
│                                                                   │
│  이상:                                                           │
│  ├── 클라이언트가 URL을 몰라도 됨                                │
│  ├── 링크만 따라가면 모든 기능 사용 가능                         │
│  ├── API 변경에 클라이언트가 자동 적응                           │
│  └── 웹 브라우저처럼 동작!                                       │
│                                                                   │
│  현실:                                                           │
│  ├── 구현 복잡도 증가                                            │
│  ├── 응답 크기 증가                                              │
│  ├── 대부분의 클라이언트가 링크를 활용 안 함                     │
│  ├── 프론트엔드 개발자: "그냥 URL 주세요"                        │
│  └── 거의 대부분 API가 HATEOAS 미적용                            │
│                                                                   │
│  Roy Fielding의 불만:                                            │
│  "HATEOAS 없으면 REST가 아니야!"                                 │
│  → 그래서 대부분 "RESTful" (REST스러운)이라고 부름               │
│                                                                   │
│  그래도 가치 있는 곳:                                            │
│  ├── 공개 API (GitHub, Stripe 일부 적용)                         │
│  ├── 장기 유지보수 필요한 API                                    │
│  └── 다양한 클라이언트 지원 필요 시                              │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

4. Richardson 성숙도 모델

┌─────────────────────────────────────────────────────────────────┐
│                  REST 성숙도 모델 (Richardson)                   │
│                                                                   │
│  Level 3: HATEOAS                    ← 진정한 REST               │
│           (하이퍼미디어 컨트롤)           (거의 없음)            │
│                │                                                 │
│  Level 2: HTTP Methods               ← 대부분 여기               │
│           (GET, POST, PUT, DELETE)       "RESTful API"          │
│                │                                                 │
│  Level 1: Resources                  ← 리소스 URI만 있음         │
│           (/users, /orders)                                      │
│                │                                                 │
│  Level 0: POX (Plain Old XML)        ← SOAP 스타일               │
│           (하나의 엔드포인트에 모든 것)                          │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

각 레벨 예시

Level 0 (POX):
┌─────────────────────────────────────────────────────────────────┐
│  POST /api                                                       │
│  Body: {"action": "getUser", "userId": 123}                      │
│                                                                   │
│  POST /api                                                       │
│  Body: {"action": "createUser", "name": "Kim"}                   │
│                                                                   │
│  → 모든 요청이 같은 엔드포인트, action으로 구분                  │
│  → RPC 스타일                                                    │
└─────────────────────────────────────────────────────────────────┘

Level 1 (Resources):
┌─────────────────────────────────────────────────────────────────┐
│  POST /users/123                                                 │
│  Body: {"action": "get"}                                         │
│                                                                   │
│  POST /users                                                     │
│  Body: {"action": "create", "name": "Kim"}                       │
│                                                                   │
│  → 리소스 URI는 있지만, 여전히 POST만 사용                       │
└─────────────────────────────────────────────────────────────────┘

Level 2 (HTTP Methods):
┌─────────────────────────────────────────────────────────────────┐
│  GET    /users/123                                               │
│  POST   /users      Body: {"name": "Kim"}                        │
│  PUT    /users/123  Body: {"name": "Park"}                       │
│  DELETE /users/123                                               │
│                                                                   │
│  → HTTP 메서드로 행위 표현 (대부분의 REST API)                   │
└─────────────────────────────────────────────────────────────────┘

Level 3 (HATEOAS):
┌─────────────────────────────────────────────────────────────────┐
│  GET /users/123                                                  │
│  {                                                               │
│    "id": 123, "name": "Kim",                                     │
│    "_links": {                                                   │
│      "self": {"href": "/users/123"},                             │
│      "orders": {"href": "/users/123/orders"}                     │
│    }                                                             │
│  }                                                               │
│                                                                   │
│  → 응답에 다음 행동 링크 포함 (진정한 REST)                      │
└─────────────────────────────────────────────────────────────────┘

5. REST의 실질적 장점

┌─────────────────────────────────────────────────────────────────┐
│                  REST가 주는 실질적 이점                         │
│                                                                   │
│  1. 단순함                                                       │
│     ├── HTTP만 알면 됨 (이미 다 알고 있음)                       │
│     ├── WSDL, 복잡한 스펙 필요 없음                              │
│     └── curl로 바로 테스트 가능                                  │
│                                                                   │
│  2. 확장성                                                       │
│     ├── Stateless → 서버 추가 쉬움                               │
│     ├── 캐싱 → 부하 분산                                         │
│     └── 계층화 → 중간 서버 추가 쉬움                             │
│                                                                   │
│  3. 독립성                                                       │
│     ├── 클라이언트/서버 독립 개발                                │
│     ├── 언어/플랫폼 무관                                         │
│     └── 어떤 클라이언트든 같은 API 사용                          │
│                                                                   │
│  4. 가시성                                                       │
│     ├── URL만 봐도 뭐하는지 알 수 있음                           │
│     ├── GET /users/123 → 123번 사용자 조회                       │
│     └── 디버깅 쉬움                                              │
│                                                                   │
│  5. 웹 인프라 활용                                               │
│     ├── 기존 HTTP 캐시, 프록시, CDN 그대로 사용                  │
│     └── 웹 생태계의 모든 도구 활용 가능                          │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

6. 정리

┌─────────────────────────────────────────────────────────────────┐
│                       REST 핵심 정리                             │
│                                                                   │
│  REST의 본질:                                                    │
│  "웹이 성공한 아키텍처 원칙을 API에 적용하자"                    │
│                                                                   │
│  6가지 제약조건:                                                 │
│  ├── 1. Client-Server: 관심사 분리                               │
│  ├── 2. Stateless: 서버가 상태 안 기억 (확장성)                  │
│  ├── 3. Cacheable: 캐시 가능 (성능)                              │
│  ├── 4. Uniform Interface: 일관된 인터페이스 (핵심!)             │
│  ├── 5. Layered System: 계층화 (유연성)                          │
│  └── 6. Code on Demand: 코드 전송 (선택적)                       │
│                                                                   │
│  Uniform Interface (가장 중요):                                  │
│  ├── ① 리소스 식별: URI로 리소스 식별 (/users/123)              │
│  ├── ② 표현으로 조작: JSON/XML로 상태 표현                      │
│  ├── ③ 자기 서술적: 메시지만 보고 이해 가능                     │
│  └── ④ HATEOAS: 응답에 다음 행동 링크 (거의 안 함)              │
│                                                                   │
│  현실:                                                           │
│  ├── 대부분 "Level 2 REST" (HTTP 메서드 활용)                    │
│  ├── HATEOAS까지 하는 곳 거의 없음                               │
│  └── 그래도 SOAP보다 훨씬 나음!                                  │
│                                                                   │
│  핵심 가치:                                                      │
│  단순함 + 확장성 + 웹 표준 활용                                  │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

관련 키워드

REST, RESTful, Uniform Interface, Stateless, HATEOAS, Richardson 성숙도, HTTP 메서드, 리소스, 표현, 자기 서술적 메시지