REST API 설계: 자원 지향 아키텍처로 안정적인 인터페이스 만들기

REST는 자원과 URI, HTTP 메서드 의미론, 무상태성과 캐시, 계층화, 하이퍼미디어를 결합한 API 아키텍처 스타일이다. 동시성 제어부터 버전 관리, 오류 모델까지 실무 설계 기준을 정리한다.

2026-08-12 · 최초 발행 2025-11-26

URI에 동사를 넣지 않는 이유

REST(Representational State Transfer)는 분산 시스템에서 자원(Resource)의 상태 표현을 HTTP 표준으로 교환하는 아키텍처 스타일이다. 자원 식별자(URI), 표현(JSON/XML), HTTP 메서드 의미론, 무상태성, 캐시, 계층화, 일관 인터페이스로 구성된다.

서비스를 설계할 때 기본 단위는 세 가지로 나뉜다. 자원(명사)은 URI로 표현하고(/orders, /orders/{id}), 행위(동사)는 HTTP 메서드로 표현하며(GET, POST, PUT, PATCH, DELETE), 표현(컨텐츠 타입)은 JSON/XML 등으로 Content-Type/Accept 헤더를 통해 협상한다. Resource Oriented Architecture(ROA)는 자원 컬렉션과 개별 자원을 명확히 구분하고, URI로 위치·관계를 표현하는 모델이다. 자원 간 링크로 탐색이 가능하도록 설계한다.

URI 설계 원칙은 명사 기반, 복수형 컬렉션(/users), 계층 관계 반영(/users/{id}/orders)이다. 동사는 URI에서 배제하고 HTTP 메서드로 표현한다. 식별자는 표현과 분리해 안정성을 유지한다 — URI는 자원을 가리키고, Accept/Content-Type은 표현 유형을 분리해서 다룬다.

HTTP 메서드 의미론과 무상태성

GET(조회, 안전·멱등), POST(생성/액션, 비멱등), PUT(전체 갱신, 멱등), PATCH(부분 갱신, 비멱등), DELETE(삭제, 멱등)의 의미론을 지키는 것이 REST API의 문법이다. Accept, Content-Type 헤더로 JSON/XML 등 표현을 협상하고, 상태 코드는 2xx/4xx/5xx 범주로 표준화해 클라이언트의 제어 흐름을 단순화한다.

무상태성은 서버가 세션을 보관하지 않는 원칙이다. 상태는 클라이언트가 보유하거나 토큰(JWT 등)으로 전달한다. Cache-Control, ETag/If-None-Match, Last-Modified/If-Modified-Since 같은 캐시 헤더로 캐시 적중률을 높이고 백엔드 부하를 줄인다. 캐시 히트율 60%를 가정하면 백엔드 요청은 40%로 줄어든다.

계층화·보안·하이퍼미디어

API Gateway나 Reverse Proxy를 통한 레이어링으로 확장성과 보안을 강화한다. Rate Limit, Circuit Breaker, Observability를 이 계층에 삽입하기 쉬워진다. TLS를 강제하고 OAuth 2.0/OIDC 기반 인증·인가, 스코프/권한 분리로 최소권한 원칙을 지킨다.

HATEOAS 원칙은 응답 안에 링크(self, next, related)를 제공해 클라이언트가 링크를 따라 상호작용 흐름을 발견하게 한다. HAL/JSON:API 같은 스키마를 채택하면 일관된 응답 구조와 도구 호환성을 확보할 수 있다.

요청이 처리되는 흐름

요청은 인증/인가 → 입력 검증 → 사전 조건(ETag) → 트랜잭션/락 → 도메인 로직 순서로 처리되고, 적절한 상태 코드와 캐시/동시성 헤더를 담아 응답한다.

실패유효성 실패불일치아니오요청 수신URI, Method, Headers,Body인증/인가 검사401/403 응답입력 검증스키마/제약400 응답사전 조건 검사If-Match vs ETag412 Precondition FailedDB 트랜잭션 시작비즈니스 로직락/격리수준 적용성공 여부롤백 - 409/422/500커밋응답 구성2xx, Body, ETag,Cache-Control응답 전송

입력은 URI 경로/쿼리, Method, 헤더(Accept, Content-Type, If-Match 등), Body(JSON 등)로 구성된다. 처리는 인증/인가 → 유효성 검증 → 사전 조건(ETag) → 트랜잭션/락 → 도메인 로직 순서로 진행하고, 출력은 적절한 상태 코드, 에러 세부(문제 상세), 캐시/동시성 헤더를 포함한다.

설계 요소가 운영 지표에 미치는 영향

설계 요소 성능 확장성 일관성 안정성 운영 편의
무상태성 서버 세션 부하 감소 수평 확장 용이 클라이언트 상태 책임 증가 장애 격리 용이 배포/스케일 단순화
캐시 제어(ETag/TTL) 응답 지연 감소 백엔드 트래픽 완화 캐시 불일치 관리 필요 다운스트림 장애 시 완충 캐시 정책으로 운영 제어
멱등성/안전성 준수 재시도 비용 최소화 대규모 재시도에도 부작용 억제 반복 호출 시 결과 일관 네트워크 실패 내성 향상 운영 자동화/재시도 단순화
계층화(API GW/Proxy) 공통 기능 오프로드 라우팅/샤딩 유연 정책 일괄 적용 서킷브레이커로 보호 로깅/모니터링 집중화
하이퍼미디어/표준 스키마 클라이언트 로직 경량 버전 변화 흡수 링크 기반 흐름 일관 프로토콜 진화 안정 문서화/도구 호환 용이

CRUD 설계와 동시성 제어

컬렉션과 개별 자원을 분리해 설계한다: POST /orders, GET /orders/{id}, PUT/PATCH /orders/{id}, DELETE /orders/{id}. ETag 기반 갱신은 If-Match 헤더로 조건부 업데이트를 수행해 레이스 조건을 막는다(불일치 시 412 반환).

아래는 curl 7.x 이상, JSON/UTF-8을 지원하는 서버를 전제로 한 실행 예시다.

# 생성
curl -i -X POST https://api.example.com/orders \
  -H "Content-Type: application/json" \
  -d '{"itemId":"SKU123","qty":2}'

# 조회
curl -i -X GET https://api.example.com/orders/100 \
  -H "Accept: application/json"

# 조건부 갱신(ETag 사용)
curl -i -X PUT https://api.example.com/orders/100 \
  -H "Content-Type: application/json" \
  -H 'If-Match: "etag-abc123"' \
  -d '{"qty":3}'

# 삭제(멱등)
curl -i -X DELETE https://api.example.com/orders/100

페이징부터 오류 모델까지

표준 쿼리 파라미터 page, size, sort, filter를 사용한다(GET /orders?page=2&size=50&sort=createdAt,desc). 응답에는 페이지 메타와 Link 헤더(next, prev)를 제공하고, 대량 데이터는 키셋 페이징을 고려한다(속도·안정성 우수).

버전 관리는 URI 버전(/v1)이 간결하고 캐싱이 쉬우며, 헤더 버전(Accept: application/vnd.example.v2+json)은 더 세밀한 협상이 가능하다. 하위 호환은 추가로만 하고, 파괴적 변경은 새 버전으로 발행하며 공존 기간과 마이그레이션 가이드를 명시한다.

오류 모델은 RFC 7807(problem+json)을 채택해 type, title, status, detail, instance 필드를 통일한다. 상관 ID(Correlation-Id)를 로깅하고 RateLimit 헤더(X-RateLimit-*)를 노출하며, 재시도-지수백오프 가이드를 함께 제공한다.

보안은 OAuth 2.0 Client Credentials/Authorization Code와 스코프 세분화를 적용한다. 입력 검증과 출력 인코딩, 서명된 토큰의 만료·회전 정책, 최소권한과 원천 IP 제한을 병행한다.

REST는 CRUD 중심 업무 도메인에 특히 잘 맞는다. 멱등성, 사전 조건, 표준 오류 모델을 도입하면 운영 신뢰성이 강해지고, 조직 차원의 URI·응답 규약과 버전·보안·관측성 표준을 함께 세우면 일관된 API 시스템을 구축할 수 있다.

RESTAPI 설계HTTP웹 아키텍처동시성 제어