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를 대체하거나 보완하는 현대적 대안 쿼리/바이너리 프로토콜 08-04-04 (또는 별도 API 패러다임) 챕터 영역으로 분리.
- 서버 내부의 ORM 및 데이터베이스 설계: API를 뒤에서 어떻게 DB에 저장하는가 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
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)가 박살 나는 마이크로서비스 확장의 기본 전제 시각화.
Recommended
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)로 리팩터링하기.
- Concepts: Resource Identifier (URI), Noun-based Routing, Collection (
- 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 디자인의 미학을 해부합니다.
- 회원 목록 조회:
- 1단계: 동사형 URL의 지옥:
- Implement: 안티 패턴 URL 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): . 버튼을 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분 안에 똑같은 키가 들어오면 비즈니스 로직을 타지 않고 기존 응답만 뱉어내는 멱등성 강제 주입술을 뜯어봅니다.
- 1단계: 멱등성의 개념 (Idempotency): . 버튼을 1번 누르나 100번 누르나 서버의 최종 상태가 동일해야 합니다.
- Implement: 멱등성 필터(Idempotency Middleware) 데모.
POST /payments {amount: 100}요청이 들어옴. 헤더X-Idempotency-Key: req-555. 서버 로직 1차 통과 DB 100원 결제 승인Redis에 req-555: 200 OK 저장. 네트워크 끊김(앱이 응답 못 받음) 앱이 똑같은req-555로 재요청 쏩니다. 미들웨어가 Redis 검사 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를 물리적으로 분리하여 무중단 마이그레이션을 보장하는 버저닝 전략을 뜯어봅니다.
- 1단계: 200 OK의 함정: 비밀번호가 틀렸는데 서버가 HTTP 상태 코드는
- 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
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) 로직을 구동할 때,
DELETE나PUT이 멱등성(Idempotency)을 보장하여 시스템 상태를 오염시키지 않는 메커니즘을 증명할 수 있는가?
Industry
- 결제 생성(
POST /payments)과 같이 기본적으로 멱등성이 없는 치명적 API에 대해, HTTP 헤더를 이용한Idempotency-Key캐싱 설계를 도입하여 중복 결제를 차단하는 백엔드 방어막을 구축할 수 있는가? - 비즈니스 로직 에러 발생 시, HTTP 상태 코드를
200 OK로 응답하고 Body에만 에러 내역을 싣는 안티 패턴이 앞단의 API Gateway 4xx/5xx 모니터링 알람 및 CDN 캐싱 룰을 어떻게 마비시키는지 논증할 수 있는가?