REST API 기초

REST의 탄생 배경

SOAP/WSDL (XML 기반)  →  REST (HTTP 기반)
      ↓                        ↓
  엄격한 규칙              유연한 구조
  복잡한 명세              간단한 인터페이스

SOA에서 REST로의 진화

구분SOAP/WSDLREST
기반XMLHTTP
규칙엄격한 스키마유연한 구조
학습 곡선높음낮음
적합 환경기업 내부 시스템분산 서비스, 모바일, 웹

REST 기본 철학

┌─────────────────────────────────────────────────────────────┐
│                    REST 4대 원칙                             │
├─────────────────────────────────────────────────────────────┤
│  1. 모든 리소스는 URI로 식별                                  │
│  2. 리소스는 다양한 형태(JSON, XML 등)로 표현 가능             │
│  3. HTTP 표준 메소드로 리소스 조작 (GET, POST, PUT, DELETE)   │
│  4. 서버는 상태를 저장하지 않음 (Stateless)                   │
└─────────────────────────────────────────────────────────────┘

무상태성 (Statelessness)의 장점

특성설명예시
가시성요청만 보고 전체 맥락 파악 가능모니터링/디버깅 용이
신뢰성장애 발생 시 체크포인트 불필요서버 재시작해도 문제 없음
확장성서버 증설만으로 처리량 증가로드밸런서로 분산 처리

리차드슨 성숙도 모델 (RMM)

REST의 성숙도를 4단계로 구분

Level 3: HATEOAS        ← 하이퍼미디어 링크 포함
    ↑
Level 2: HTTP Verbs     ← GET, POST, PUT, DELETE 활용
    ↑
Level 1: Resources      ← URI로 리소스 구분
    ↑
Level 0: POX            ← 단순 HTTP 전송 (POST만 사용)

각 레벨 상세

Level 0: 원격 프로시저 호출

POST /api HTTP/1.1
Content-Type: application/xml

<getUser><id>123</id></getUser>

Level 1: REST 리소스

POST /api/users/123 HTTP/1.1

Level 2: HTTP 메소드 활용

GET    /api/users/123    # 조회
POST   /api/users        # 생성
PUT    /api/users/123    # 수정
DELETE /api/users/123    # 삭제

Level 3: HATEOAS

{
  "id": 123,
  "name": "John",
  "links": [
    { "rel": "self", "href": "/api/users/123" },
    { "rel": "orders", "href": "/api/users/123/orders" },
    { "rel": "delete", "href": "/api/users/123", "method": "DELETE" }
  ]
}

HTTP 메소드 특성

안전성과 멱등성

┌──────────┬──────────┬──────────┬─────────────────────────────┐
│  메소드   │  안전성  │  멱등성  │           설명              │
├──────────┼──────────┼──────────┼─────────────────────────────┤
│  GET     │    O     │    O     │ 조회, 캐시 가능              │
│  HEAD    │    O     │    O     │ 헤더만 조회                  │
│  POST    │    X     │    X     │ 생성, 매번 새 리소스 생성 가능│
│  PUT     │    X     │    O     │ 전체 수정, 반복해도 결과 동일 │
│  PATCH   │    X     │    X     │ 부분 수정                    │
│  DELETE  │    X     │    O     │ 삭제, 반복해도 결과 동일      │
└──────────┴──────────┴──────────┴─────────────────────────────┘
  • 안전(Safe): 서버 상태를 변경하지 않음
  • 멱등(Idempotent): 여러 번 실행해도 결과가 동일

RESTful URI 설계

URI 설계 원칙

✅ 좋은 예시                    ❌ 나쁜 예시
────────────────────────────────────────────────────
/v1/users                      /v1/getUsers
/v1/users/123                  /v1/user?id=123
/v1/users/123/orders           /v1/getUserOrders?userId=123
/v1/users/123/orders/456       /v1/deleteOrder?id=456

URI 설계 규칙

규칙설명예시
명사 사용동사 대신 명사로 리소스 표현/users (O), /getUsers (X)
복수형컬렉션은 복수형으로/users, /orders
계층 구조슬래시로 계층 표현/users/123/orders
소문자URI는 소문자로 통일/api/users
하이픈단어 구분은 하이픈 사용/user-profiles

실제 설계 예시

도서관 API 설계

GET    /v1/books                    # 전체 도서 목록
GET    /v1/books/isbn/978-1234      # ISBN으로 도서 조회
POST   /v1/books                    # 새 도서 등록
PUT    /v1/books/isbn/978-1234      # 도서 정보 전체 수정
PATCH  /v1/books/isbn/978-1234      # 도서 정보 일부 수정
DELETE /v1/books/isbn/978-1234      # 도서 삭제

GET    /v1/users/123/books          # 특정 유저의 대출 도서
GET    /v1/users/123/books/count    # 대출 도서 수

HTTP 메소드 상세

GET - 리소스 조회

GET /v1/users/123 HTTP/1.1
Host: api.example.com
Accept: application/json
// Response: 200 OK
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com"
}

POST - 리소스 생성

POST /v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "name": "Jane Doe",
  "email": "jane@example.com"
}
// Response: 201 Created
// Location: /v1/users/124
{
  "id": 124,
  "name": "Jane Doe",
  "email": "jane@example.com"
}

PUT vs POST

특성POSTPUT
URI 결정서버가 결정클라이언트가 지정
멱등성X (매번 새 리소스)O (동일 결과)
용도생성생성 또는 전체 교체
# POST: 서버가 ID 생성
POST /v1/users
→ 201 Created, Location: /v1/users/124

# PUT: 클라이언트가 ID 지정
PUT /v1/users/124
→ 201 Created (없으면 생성)
→ 200 OK (있으면 교체)

PUT vs PATCH

# PUT: 전체 교체 (모든 필드 필요)
PUT /v1/users/123
{
  "name": "John Updated",
  "email": "john@example.com",
  "age": 30,
  "address": "Seoul"
}

# PATCH: 부분 수정 (변경할 필드만)
PATCH /v1/users/123
{
  "name": "John Updated"
}

API 테스트

cURL 기본 사용법

# GET 요청
curl https://api.example.com/v1/users

# 헤더 포함
curl -H "Authorization: Bearer token123" \
     https://api.example.com/v1/users

# 응답 헤더 확인
curl -i https://api.example.com/v1/users

# POST 요청 (JSON)
curl -X POST \
     -H "Content-Type: application/json" \
     -d '{"name":"John","email":"john@example.com"}' \
     https://api.example.com/v1/users

# PUT 요청
curl -X PUT \
     -H "Content-Type: application/json" \
     -d '{"name":"John Updated","email":"john@example.com"}' \
     https://api.example.com/v1/users/123

# DELETE 요청
curl -X DELETE https://api.example.com/v1/users/123

cURL 주요 옵션

옵션설명예시
-XHTTP 메소드 지정-X POST
-H헤더 추가-H "Content-Type: application/json"
-d요청 본문-d '{"key":"value"}'
-i응답 헤더 포함 출력curl -i URL
-v상세 정보 출력curl -v URL
-o파일로 저장-o output.json

설계 베스트 프랙티스

URI 설계

✅ 권장사항
────────────────────────────────────
- 명사 + HTTP 메소드로 행위 표현
- 서브리소스는 URI 계층으로 표현
- 필터/검색은 쿼리 파라미터 사용
- 버전은 URI에 포함 (/v1/, /v2/)

응답 설계

✅ 권장사항
────────────────────────────────────
- 기본 응답 포맷: JSON
- 필드명: camelCase 또는 snake_case (일관성 유지)
- 카운트 API 제공: /users/count
- 상세한 응답으로 추가 요청 최소화
- 페이지네이션: ?page=1&limit=20
- 필드 선택: ?fields=id,name,email

쿼리 파라미터 활용

# 필터링
GET /v1/users?status=active&role=admin

# 정렬
GET /v1/users?sort=created_at&order=desc

# 페이지네이션
GET /v1/users?page=2&limit=20

# 필드 선택 (Sparse Fieldsets)
GET /v1/users?fields=id,name,email

# 검색
GET /v1/users?q=john

# 조합
GET /v1/users?status=active&sort=name&page=1&limit=10&fields=id,name

핵심 용어 정리

용어설명
RESTRepresentational State Transfer
리소스URI로 식별되는 모든 것
표현형리소스의 특정 시점 상태 (JSON, XML 등)
무상태성서버가 클라이언트 상태를 저장하지 않음
멱등성여러 번 실행해도 결과가 동일한 특성
HATEOAS응답에 다음 가능한 액션 링크 포함
RMMRichardson Maturity Model (성숙도 모델)