C.W.K.
Stream
Lesson 01 of 07 · published

Resource vs RPC — 두 mental model, 둘 다 유효

~11 min · rest-design, resources-vs-rpc, mental-model

Level 0HTTP Newbie
0 XP0/46 lessons0/12 achievements
0/120 XP to next level120 XP to go0% complete
"오늘날 ship 되는 대부분 'REST API' 가 HTTP 의상 입은 RPC 야. 모욕 아냐 — 유용한 관찰. 질문은 '어느 게 옳아' 가 아니라 '실제 어느 mental model 쓰고 있어, 그게 도움 돼?'"

두 설계 중심

API 설계 앉을 때 첫 결정이 따라오는 모든 걸 모양 잡아: API 가 뭘 중심으로 조직됐어?

Resource-oriented (REST 본격). 세계가 thing 으로 만들어짐 — user, order, payment, conversation. 각 thing 이 URI 에 살아. 일곱 HTTP method 가 그것들에 작용. 읽기는 GET; collection 에 POST 로 create; 교체는 PUT; 삭제는 DELETE. Verb 가 미리 정의; 명사만 설계.

RPC (Remote Procedure Call). 세계가 operation 으로 만들어짐 — createUser, processPayment, finalizeCouncil. 각 operation 이 procedure 이름과 argument 가짐. Payload 를 POST 해서 invoke. 명사가 procedure 이름에 사라짐; verb 가 무한 (필요한 대로 새로 만듦).

둘 다 동작. 둘 다 production ship. 결정은 어느 mental model 이 도메인과 팀 습관에 맞는지.

리트머스 테스트 — URI 세기

아무 API URI 목록 봐. 대부분 URI 가 thing 이름 (/users/42, /orders/abc, /payments/xyz) 이면 resource-oriented. 대부분 URI 가 operation 이름 (/createUser, /processOrder, /getPaymentStatus) 이면 RPC.

2026년의 잘 알려진 API 빠른 survey:

  • Resource-leaning: Stripe (대부분), GitHub REST, AWS S3, Kubernetes API. URI 가 thing 이름.
  • RPC-leaning: Slack Web API (chat.postMessage, users.list), 대부분 gRPC service, OpenAI Chat Completions (POST /v1/chat/completions). URI 가 operation 이름.
  • Hybrid: 대부분 진짜 API. 명백한 명사엔 resource URI, 안 맞는 operation 엔 action endpoint (POST /payments/{id}/refund, POST /jobs/{id}/cancel). cwkPippa 가 이 양동이.

각 모델 빛나는 때

Resource-oriented 이기는 때:

  • 도메인에 명확한 명사. CRUD 무거운 application (admin panel, content management, e-commerce catalog) 이 깔끔하게 매핑.
  • Cache friendliness 중요. GET 주도 접근이 CDN 이 만들어진 그거.
  • Client 가 다양 (브라우저, 모바일, 제 3자 통합). 일곱 verb 가 보편 이해; 새 명사 배우는 게 새 procedure 배우는 것보다 쉬워.
  • 발견 가능성과 convention 노출 원함. /users/{id}/orders 가 self-explanatory; getOrdersForUser(userId) 는 docs 읽어야.

RPC-leaning 이기는 때:

  • 도메인이 operation 무거움. AI 채팅 ("이 prompt 완료"), workflow orchestration, transcoding, ML inference — 다 자연스럽게 "이 args 로 X 해" 로 읽힘.
  • Client 와 server 둘 다 엄밀 통제. gRPC/Protobuf 가 canonical 예: typed contract, generated stub, code-first.
  • Operation 이 명사에 자연스럽게 매핑 안 됨. "이 user 들한테 이 channel 에 이 severity 로 notification 보내" 는 resource 로 어색; procedure 로 깔끔.
일관성이 순수성 이김. 잘 정당화된 action endpoint 셋 가진 resource-oriented API 괜찮음. 모든 operation 을 resource shape 으로 고문하는 '순수 REST' API 는 수수께끼 됨. 설계 중심 골라; 대안이 일탈보다 나쁠 때만 일탈해.

실전 하이브리드

대부분 production API 가 어색한 operation 에 action sub-resource 가진 resource-oriented 에 도착. 패턴: 최상위에 명사 (/orders, /payments), 특정 resource 아래 sub-path 로 action (POST /orders/42/cancel, POST /payments/xyz/refund). Action 이 이름 붙고, verb 가 POST (action 은 보통 협조 없이 idempotent 아님), target 이 parent resource.

이게 동작하는 이유: 발견 가능성 보존 (/orders/42 찾고 그것에 뭘 할 수 있는지 봄), resource-oriented mental model 유지, 진짜 안 맞는 operation ("refund" 는 명사 아니라 payment 에 하는 거) 이 깔끔한 집 얻음.

cwkPippa 의 mix

cwkPippa 가 하이브리드. backend/routes/ 대부분이 resource-oriented: /api/conversations, /api/folders, /api/messages, /api/artifacts 다 GET/POST/PUT/PATCH/DELETE 가진 resource 처럼 동작. 근데 POST /api/council/{id}/finalize, POST /api/council/{id}/inject, POST /api/heartbeat/cron/{id}/run-now 가 action endpoint — 기존 resource 에 대한 operation 이지 create 아니라 resource 모델 안 맞아서. Mix 가 의도적; council finalization 을 'finalizations' resource 로 강제 끼우는 건 ceremony 위한 ceremony.

Code

하이브리드 action endpoint 가진 resource-oriented·text
# Resource-oriented 설계 — 명사 세기
GET    /users                      # resource 나열
POST   /users                      # resource 생성 (server 가 ID 할당)
GET    /users/{id}                 # resource 하나 읽기
PUT    /users/{id}                 # 교체
PATCH  /users/{id}                 # 부분 update
DELETE /users/{id}                 # 제거

GET    /users/{id}/orders          # nested resource — user 에 속한 order
POST   /users/{id}/orders          # user 아래 order 생성

# Action endpoint (실용적 하이브리드 탈출구)
POST   /orders/{id}/cancel         # action — POST + 이름 붙은 sub-path
POST   /payments/{id}/refund       # action — 같은 패턴
RPC-스타일: 모든 URI 가 verb, 모든 method 가 POST·text
# 순수 RPC 설계 — verb 세기
POST   /users.list                 # user 나열 (Slack 스타일)
POST   /users.create               # user 생성
POST   /users.get                  # 하나 읽기
POST   /users.update               # update
POST   /users.delete               # delete
POST   /orders.cancel              # action
POST   /payments.refund            # action

# 주목: 모든 URI 가 operation, 모든 method 가 POST.
# Status code 는 여전히 동작하지만 protocol 의 일곱 verb 가 하나로 붕괴.
같은 로직, 두 설계 중심 — 선호하는 비용 골라·python
# 같은 비즈니스 로직, 두 방식. 둘 다 동작; tradeoff 다름.
from fastapi import FastAPI

app = FastAPI()

# ============= Resource-oriented =============
@app.get('/orders/{oid}')
async def get_order_resource(oid: str):
    return await load_order(oid)

@app.post('/orders/{oid}/cancel', status_code=202)
async def cancel_order_resource(oid: str):
    return await cancel(oid)

# ============= RPC-스타일 ===================
@app.post('/orders.get')
async def get_order_rpc(payload: dict):
    return await load_order(payload['order_id'])

@app.post('/orders.cancel')
async def cancel_order_rpc(payload: dict):
    return await cancel(payload['order_id'])

# Resource-oriented 가 cacheable GET, conditional request, optimistic locking 공짜로 줘.
# RPC 가 더 단순한 계약 설계와 더 쉬운 코드 생성 줘. 지불하고 싶은 비용 골라.

External links

Exercise

써본 API 아무거나 (Stripe, GitHub, Slack, OpenAI, cwkPippa). URI 10개 봐. 각각에 대해 URI 가 THING 이름 (resource-oriented) 인지 OPERATION 이름 (RPC) 인지 분류. 비율 계산. API 가 대부분 resource-oriented 야, 대부분 RPC 야, 하이브리드야? 보너스: 현재 RPC-스타일로 하는 API operation 하나 골라서 resource-oriented 로 재설계 (혹은 반대). 뭘 얻었어? 뭘 포기했어?
Hint
Slack URI 는 users.list, chat.postMessage 처럼 보임 — operation. RPC. GitHub 는 /repos/{owner}/{repo}/issues 처럼 — thing. Resource. OpenAI /v1/chat/completions 는 operation 이름 — RPC. cwkPippa 는 하이브리드. 재설계 연습이 각 모델이 묵시적으로 비용 치거나 지불하는 게 뭔지 가르쳐. 맞는 답 없음; 연습은 tradeoff articulate 하는 데 있어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.