콘텐츠로 바로가기

RESTful Architecture & API Design

리소스를 중심으로 통신을 설계하는 REST 아키텍처의 원리와 직관적이고 견고한 API 명세를 설계하기 위한 수리적/논리적 수순을 다루는 학습 노드입니다.

Article
M

Me

hyunyoun's Blog

network-communicationnetworkcommunicationweb-protocolsapi-paradigmsrestful-architectureapi-designapplication-protocols11 min read

1. Overview

RESTful 아키텍처와 API 설계(RESTful Architecture & API Design)는 복잡하고 무거운 SOAP/XML 기반의 기업 간 통신을 박살 내고, HTTP 본연의 동사(Method)와 명사(URI)만으로 세상 모든 자원(Resource)의 생명주기를 지배하게 만든 현대 백엔드의 표준 규약을 해부합니다.

학습자는 단순히 "URL을 예쁘게 짜는 법"이라는 초보적 오해를 넘어, 클라이언트와 서버가 완전히 상태를 분리(Stateless)하여 무한대의 수평 확장(Scale-out)을 가능케 한 **REST의 인프라적 제약 조건(Constraints)**을 뜯어봅니다. 나아가 URI(자원 식별)와 HTTP Method(행위)를 완벽히 분리하고, 적절한 상태 코드(HTTP Status Codes)로 응답하는 실용적 API 디자인 패턴을 장악합니다. 마지막으로, HATEOAS(하이퍼미디어)의 이상과 현실적 타협점, 그리고 버저닝(Versioning) 및 멱등성(Idempotency)을 통한 장애에 강한(Fault-tolerant) 엔터프라이즈 API 설계 역량을 확보합니다.

2. Scope & Boundaries

In-Scope

  • REST Constraints: Client-Server, Stateless, Cacheable, Layered System, Uniform Interface.
  • Resource Design: 명사 기반의 계층적 URI 설계 (/users/123/orders), 컬렉션(Collection)과 도큐먼트(Document).
  • HTTP Methods & Semantics: GET (조회), POST (생성), PUT (전체 교체), PATCH (부분 수정), DELETE (삭제).
  • Idempotency (멱등성): 똑같은 요청을 여러 번 보내도 서버의 상태가 동일하게 유지되어야 하는 속성과 네트워크 재시도(Retry) 설계.
  • HTTP Status Codes: 2xx(성공), 4xx(클라이언트 에러), 5xx(서버 에러)의 시맨틱 매핑.

Out-of-Scope

  • GraphQL 및 gRPC: REST를 대체하거나 보완하는 현대적 대안 쿼리/바이너리 프로토콜 \rightarrow 08-04-04 (또는 별도 API 패러다임) 챕터 영역으로 분리.
  • 서버 내부의 ORM 및 데이터베이스 설계: API를 뒤에서 어떻게 DB에 저장하는가 \rightarrow 11. Database Systems 영역으로 위임.

Boundaries

  • HTTP vs REST: HTTP는 네트워크를 날아다니는 '택배 상자와 운송장(Protocol)'입니다. REST는 그 택배 상자에 내용물을 '어떻게 예쁘게 담고 라벨을 어떻게 적을 것인가'에 대한 '암묵적 룰(Architecture Style)'입니다. REST 규약을 어기고 URL을 /getUser?id=1로 대충 짜고 Method를 무조건 POST로 통일해도 HTTP 통신은 완벽히 동작합니다. 이 문서는 '동작 여부'가 아니라 시스템이 커졌을 때의 유지보수성과 캐싱, 확장을 위한 '약속(Semantics)'에 맹렬히 집중하여 경계를 긋습니다.

3. Counterexample

  • 동사형 URL과 POST의 남용 (The RPC Anti-Pattern): 프론트엔드가 회원 탈퇴 API를 짜면서 URI를 POST /deleteUser로 만들고 바디에 {id: 123}을 넣었습니다. 웹 캐시(CDN)는 이 URL이 무슨 자원인지 모르고 POST라서 캐싱도 하지 않습니다. URL만 봐서는 무슨 행위를 하는지 유추할 수 없으며, HTTP 생태계의 규약을 완전히 박살 낸 끔찍한 RPC 스타일의 잔재입니다. (DELETE /users/123이 정답)
  • 멱등성(Idempotency) 무지 결제 참사: 백엔드 개발자가 사용자 포인트 차감 API를 POST /users/123/points/deduct로 짰습니다. 모바일 앱에서 결제를 눌렀는데 타임아웃이 났습니다(서버는 차감 성공했으나 앱은 응답 못 받음). 앱이 불안해서 "재시도(Retry)"를 3번 더 때렸더니 유저 포인트가 4번이나 깎여버렸습니다. 멱등성이 보장되지 않는 POST 요청에 대해, 멱등키(Idempotency Key)나 멱등한 Method(PUT) 설계를 누락하여 터진 치명적 금융 사고입니다.

4. Prerequisites

  • HTTP Request/Response 구조 (Basic): Method, URI, Header, Body의 물리적 구조. (08-01-04 OSI Stack)
  • 소프트웨어 확장성 (Basic): Stateless 아키텍처가 수평 확장(Scale-out)에 유리한 이유. (07-05-01 Scalability)

5. Learning Map

Sequence Core Cluster Objective & Description Evidence (BoK)
1 Statelessness & Constraints 서버에 세션을 저장하지 않아 1,000대의 서버로 무한 증식이 가능해지는 REST의 무상태성 철학과 제약 조건을 쥡니다. P1
2 Resource & URI Design "무엇을 할 것인가"는 동사(Method)에 맡기고, URL은 오직 "어떤 자원(명사)인가"만 표현하는 URI 계층 설계의 미학을 해부합니다. P5
3 Method Semantics & Idempotency 생성(POST)과 교체(PUT/PATCH)의 미묘한 차이를 구분하고, 네트워크 장애로 수십 번 재요청해도 안전한 멱등성 설계를 뜯어봅니다. Industry
4 Status Codes & Versioning 성공(201)과 권한 없음(403), 서버 붕괴(500)를 표준 코드로 응답하여 프론트엔드의 조건문을 깔끔하게 만드는 API 버저닝 통제술을 장악합니다. Industry

6. Learning Topics

Basic

Core Topic 01: 무상태성과 시스템의 확장 (Statelessness & Constraints)

  • Why to Learn: REST가 단순히 URL을 짜는 가이드라인이 아니라, 웹 서버가 클라이언트의 상태(Session)를 기억하지 않게 만들어 인프라 확장을 극대화하는 아키텍처의 근본임을 통찰하기 위함입니다.
  • What to Learn:
    • Concepts: REST (Representational State Transfer), 6 Constraints (Client-Server, Stateless, Cacheable, Layered System, Uniform Interface, Code on Demand).
    • Skills: 세션 기반(Stateful) 로그인과 토큰 기반(Stateless) API 로그인의 인프라적 차이를 분석하고 로드밸런서 설계 시의 이점 도해.
  • How to Learn:
    • 1단계: 상태가 있는(Stateful) 서버의 저주: 클라이언트가 서버 A에 로그인했습니다(세션 메모리 저장). 다음 API 요청이 로드밸런서를 타고 서버 B로 가면 "너 누구야?" 하고 튕깁니다. 이를 막으려면 Sticky Session을 설정하거나 Redis 같은 외부 저장소를 붙여 인프라가 미친 듯이 복잡해집니다.
    • 2단계: 무상태(Stateless) REST: REST API는 서버가 기억상실증에 걸려야 합니다. 클라이언트는 모든 API 요청마다 자기가 누구인지 증명하는 여권(JWT 토큰)을 헤더에 붙여서 던집니다. 서버 A가 죽어서 서버 B로 요청이 가도, 여권을 까보고 바로 승인해 줍니다. 백엔드 서버를 10,000대로 쉽게 복제(Scale-out)할 수 있는 무상태 아키텍처의 힘을 뜯어봅니다.
  • Implement: Stateful vs Stateless 서버 라우팅 렌더링. Stateful: [Req 1: Login] -> Server1(Session=UserA). [Req 2: GetData] -> LB -> Server2 (Error: Not Logged In). Stateless: [Req 1: Login] -> Server1 -> Returns JWT. [Req 2: GetData + JWT] -> LB -> Server2 (Valid JWT -> OK). 서버 간 메모리 결합도(Coupling)가 박살 나는 마이크로서비스 확장의 기본 전제 시각화.

Core Topic 02: 명사와 행위의 완벽한 분리 (Resource & URI Design)

  • Why to Learn: 행위를 뜻하는 동사를 URL에 덕지덕지 바르는 더러운 관습을 버리고, 전 세계 개발자가 척 보면 구조를 이해하는 직관적인 계층형 식별자(URI)를 설계하기 위함입니다.
  • What to Learn:
    • Concepts: Resource Identifier (URI), Noun-based Routing, Collection (/users), Document (/users/123), Sub-collection (/users/123/orders).
    • Skills: "사용자의 5번 주문 취소"라는 비즈니스 요구사항을 RESTful한 URI(DELETE /users/{id}/orders/5)로 리팩터링하기.
  • How to Learn:
    • 1단계: 동사형 URL의 지옥: /addUser, /updateUser, /getUserList, /deleteUserById. API가 100개가 되면 프론트 개발자는 API 문서를 외울 수가 없어 매번 문서를 뒤적거려야 합니다. URL 자체가 쓰레기통이 됩니다.
    • 2단계: 명사와 컬렉션: URL에는 오직 명사, 자원(Resource)만 씁니다. 복수형(Collection)을 씁니다. /users. 행위는 HTTP Method에 위임합니다.
      • 회원 목록 조회: GET /users
      • 회원 1명 조회: GET /users/123
      • 회원 1명 생성: POST /users (아이디 123은 서버가 생성해서 응답)
      • 회원의 주문 목록: GET /users/123/orders 이처럼 폴더 구조(트리)를 짜듯 완벽한 예측 가능성을 제공하는 API 디자인의 미학을 해부합니다.
  • Implement: 안티 패턴 URL \rightarrow RESTful URL 자동 교정기(파이썬 스크립트). 입력: POST /cancelOrder?orderId=55 엔진 분석: 'cancel'은 삭제(또는 상태변경) 행위, 'Order'는 명사. 출력 제안: [Refactor] DELETE /orders/55 또는 PATCH /orders/55 {status: "cancelled"}. 행위와 자원의 결합을 강제로 찢어버리는 린터(Linter) 시뮬레이션.

Practical

Core Topic 03: 재시도의 방어막, 메소드 멱등성 (Method Semantics & Idempotency)

  • Why to Learn: 네트워크가 끊겨 프론트엔드가 똑같은 API를 10번 재시도(Retry)할 때, 서버의 데이터가 10번 중복 생성되는 참사를 막아내는 시스템적 방어 기제를 장악하기 위함입니다.
  • What to Learn:
    • Concepts: Idempotency (멱등성), Safe Methods (GET, OPTIONS), Idempotent Methods (PUT, DELETE), Non-Idempotent (POST, PATCH), Idempotency Key.
    • Skills: 똑같은 데이터를 2번 전송했을 때, POST의 결과(데이터 2개 생성)와 PUT의 결과(데이터 1개로 유지)가 왜 아키텍처적으로 달라야 하는지 증명하고 방어 로직 짜기.
  • How to Learn:
    • 1단계: 멱등성의 개념 (Idempotency): f(f(x))=f(x)f(f(x)) = f(x). 버튼을 1번 누르나 100번 누르나 서버의 최종 상태가 동일해야 합니다. DELETE /users/123을 10번 보낸다고 유저가 10명 삭제되지 않습니다(멱등함). GET /users/123을 100번 봐도 서버 데이터는 변하지 않습니다(안전함).
    • 2단계: 위험한 POST와 PUT의 차이: POST /articles를 3번 보내면 게시글이 3개 생성됩니다(비멱등적). 모바일 망이 끊겨 앱이 POST를 자동 재시도하면 게시판이 도배됩니다. 반면 PUT /articles/99는 "99번 게시글을 이걸로 완전히 덮어씌워라"입니다. 3번 보내도 결과는 99번 글 1개가 수정될 뿐입니다(멱등함).
    • 3단계: 방어책 (Idempotency Key): 결제(POST)처럼 절대 중복 처리되면 안 되는 API는 클라이언트가 요청 헤더에 Idempotency-Key: uuid-1234를 넣습니다. 서버는 이 키를 캐시(Redis)에 저장해 두고, 1분 안에 똑같은 키가 들어오면 비즈니스 로직을 타지 않고 기존 응답만 뱉어내는 멱등성 강제 주입술을 뜯어봅니다.
  • Implement: 멱등성 필터(Idempotency Middleware) 데모. POST /payments {amount: 100} 요청이 들어옴. 헤더 X-Idempotency-Key: req-555. 서버 로직 1차 통과 \rightarrow DB 100원 결제 승인 \rightarrow Redis에 req-555: 200 OK 저장. 네트워크 끊김(앱이 응답 못 받음) \rightarrow 앱이 똑같은 req-555로 재요청 쏩니다. 미들웨어가 Redis 검사 \rightarrow DB 쿼리 없이 즉시 [Cached] 200 OK 반환. 중복 결제를 원천 차단하는 방어막 렌더링.

Advanced

Core Topic 04: 에러의 규격화와 생태계 통제 (Status Codes & Versioning)

  • Why to Learn: 모든 API 응답을 200 OK로 주고 바디 안에 {code: "ERROR_01"}을 숨기는 최악의 설계(안티 패턴)를 버리고, HTTP 인프라가 에러를 자동 인지할 수 있도록 생태계 규약을 장악하기 위함입니다.
  • What to Learn:
    • Concepts: HTTP Status Codes (2xx, 3xx, 4xx, 5xx), HATEOAS, API Versioning (URI vs Header).
    • Skills: 유저가 없는 리소스를 요청했을 때 404 Not Found, 권한이 없을 때 403 Forbidden, 서버 DB가 죽었을 때 500 Internal Server Error를 구분하여 던지고 클라이언트 예외 처리 분기 짜기.
  • How to Learn:
    • 1단계: 200 OK의 함정: 비밀번호가 틀렸는데 서버가 HTTP 상태 코드는 200 OK를 주고, 본문에 {status: "fail", msg: "Wrong PW"}를 줍니다. 앞에 있는 로드밸런서나 브라우저 캐시는 상태 코드가 200이니 "아, 정상 응답이네?" 하고 덜컥 에러 메시지를 캐싱해버립니다. 다음 정상 유저까지 그 캐싱된 에러를 봅니다.
    • 2단계: HTTP 인프라와의 대화: 비즈니스 에러도 철저히 HTTP 상태 코드로 매핑해야 합니다. 클라이언트가 잘못 찌르면 무조건 4xx, 서버 쪽 예외가 터지면 무조건 5xx를 던져야, 앞단에 있는 L7 로드밸런서, WAF, Datadog 모니터링 툴들이 "아, 이 서버 500 에러 폭주하네. 죽이자!"라고 인프라 레벨의 방어가 가능해지는 아키텍처를 해부합니다.
    • 3단계: API 진화 (Versioning): 시스템이 엎어졌을 때 구버전 앱 사용자들을 위해 /v1/users/v2/users를 물리적으로 분리하여 무중단 마이그레이션을 보장하는 버저닝 전략을 뜯어봅니다.
  • Implement: API 에러 매핑 모사기. 입력 Request: DELETE /users/admin. 비즈니스 룰: 어드민은 삭제 불가. 잘못된 설계 출력: HTTP 200 OK, Body: {err: "Cannot delete admin"}. RESTful 설계 출력: HTTP 403 Forbidden, Body: {err_code: 901, detail: "Admin protection"}. 이후 APM(모니터링) 에이전트가 200은 무시하고 403을 [ALERT] Authorization Failure Spike로 집계하는 인프라 연동 효과 렌더링.

7. Terminology

Term (EN / ko, abbr) 1문장 정의 단계(기본/권장/실무/심화) 역할/맥락 관련 개념 유사/대비/함께 사용 오해 포인트 Evidence(Primary/Secondary/Industry) Flags(core)
REST (Representational State Transfer) 자원(명사)은 URI로, 행위(동사)는 HTTP Method로 철저히 분리하여, 서버와 클라이언트가 '무상태(Stateless)'로 통신하게 만드는 웹 아키텍처 디자인 규약입니다. 기본 자원 기반 HTTP 통신 설계 Resource / Stateless SOAP / RPC (행위 기반) 단순히 URL을 예쁘게 짜는 법이 아니라, 캐시를 돕고 서버 확장을 쉽게 만드는 인프라 최적화 철학의 모음임 P1:CS2023 core
URI (Uniform Resource Identifier) 인터넷 상의 수많은 데이터(자원) 중 특정 컬렉션(/users)이나 도큐먼트(/users/123)를 정확히 가리키는 유일한 명사형 주소 체계입니다. 기본 자원 식별 체계 URL / Resource HTTP Method URI 안에 create, delete 같은 동사를 넣는 순간 REST의 근본 철학(행위 분리)이 즉시 박살 남 P5:SFIA core
Idempotency (멱등성) 네트워크 타임아웃으로 인해 클라이언트가 똑같은 API 요청(예: PUT, DELETE)을 수십 번 반복해서 때려도, 서버의 최종 데이터 상태는 딱 1번 때렸을 때와 동일하게 유지되는 시스템적 내성입니다. 권장 네트워크 재시도에 대한 데이터 무결성 Safe Method / Idempotency Key Non-Idempotent (POST) POST는 기본적으로 비멱등적이므로, 결제 API처럼 치명적인 POST 요청에는 클라이언트가 '멱등 키'를 강제로 껴넣어 중복 생성을 막아야 함 Industry core
HTTP Status Codes (HTTP 상태 코드) 응답의 본문(Body)을 까보지 않아도 앞단의 CDN이나 모니터링 툴이 에러 여부를 즉시 파악할 수 있도록, 웹 인프라 생태계가 합의한 성공(2xx), 클라이언트 에러(4xx), 서버 에러(5xx) 규약입니다. 실무 글로벌 에러 핸들링 표준 HTTP Response Header Body 에러 코드 (비표준) 에러가 났음에도 상태 코드를 무조건 200 OK로 응답하면, 로드밸런서가 그 에러 페이지를 "성공이네!" 하고 영원히 캐싱해버리는 참사가 터짐 Industry core

8. References

Primary

  • [P1] CS2023 - Networking and Communication (NC) - HTTP and Application Layer Protocols
  • [P5] SFIA - Software Design (SWDN) - RESTful Architecture

Secondary

  • [Architectural Styles and the Design of Network-based Software Architectures] Roy Thomas Fielding - REST (Chapter 5)
  • [REST API Design Rulebook] Mark Masse - URI Design and HTTP Methods

Industry

  • [Microsoft Azure Architecture Center] - RESTful web API design
  • [Google Cloud API Design Guide] - Standard Methods and Error Model

9. Final Checklist

Primary

  • 서버가 클라이언트의 이전 상태(세션)를 기억하지 않는 무상태성(Stateless) 제약 조건이, 로드밸런서 뒤에 수백 대의 백엔드 서버를 수평 확장(Scale-out)할 수 있게 만드는 핵심 원리임을 설명할 수 있는가?
  • GET /deleteUser?id=5와 같은 구시대적 RPC 스타일의 안티 패턴을 지적하고, 이를 명사 중심의 자원(Resource) 식별과 HTTP Method(DELETE)가 분리된 RESTful 구조(/users/5)로 리팩터링할 수 있는가?

Secondary

  • POST(새 리소스 생성)와 PUT/PATCH(기존 리소스 수정)의 차이를 시맨틱(의미론) 관점에서 구분하고, 부분 업데이트(Patch)와 전체 교체(Put)의 설계 트레이드오프를 평가할 수 있는가?
  • 불안정한 모바일 네트워크 환경에서 클라이언트가 API 응답을 받지 못해 재시도(Retry) 로직을 구동할 때, DELETEPUT이 멱등성(Idempotency)을 보장하여 시스템 상태를 오염시키지 않는 메커니즘을 증명할 수 있는가?

Industry

  • 결제 생성(POST /payments)과 같이 기본적으로 멱등성이 없는 치명적 API에 대해, HTTP 헤더를 이용한 Idempotency-Key 캐싱 설계를 도입하여 중복 결제를 차단하는 백엔드 방어막을 구축할 수 있는가?
  • 비즈니스 로직 에러 발생 시, HTTP 상태 코드를 200 OK로 응답하고 Body에만 에러 내역을 싣는 안티 패턴이 앞단의 API Gateway 4xx/5xx 모니터링 알람 및 CDN 캐싱 룰을 어떻게 마비시키는지 논증할 수 있는가?

Application Protocols & API Paradigms

2 / 5