"REST 가 하나 architectural style. 대부분 경우에 충분히 좋고 infrastructure-friendly 라서 지배. 근데 작업 카테고리 셋이 더 좋은 대안 있고, 아닌 척하는 게 낭비 노력."
REST 가 잘못된 경우들
1. Typed 내부 service-to-service 트래픽 → gRPC. Control 하는 두 service 가 높은 볼륨으로 서로 말하면 typed 계약, generated stub (손수 만든 client 없음), JSON overhead 없는 HTTP/2 multiplexing 원함. gRPC + Protobuf 가 이거 깔끔히 함. Kubernetes, 모든 주요 cloud provider 의 내부 mesh, microservice estate — 다 안에 gRPC.
2. Rich client 가 깊은 schema 에서 필드 고름 → GraphQL. 여러 client type (web, mobile, partner 앱) 이 관련 데이터의 다른 조각 원함 — 제품 + 리뷰 + 저자 + 유사 제품, 근데 각 client 가 다른 부분집합 원함 — REST endpoint 가 확산하거나 너무 많이 돌려줌. GraphQL 이 client 가 query 쓰게.
3. 자연 procedural operation → RPC-over-HTTP. 일부 operation 이 resource 에 자연 매핑 안 됨. "이 코드 컴파일," "이 비디오 transcode," "이 prompt 완료" — verb, 명사 아님. Rich payload 가진 action endpoint POST (OpenAI 의 /v1/chat/completions) 가 정직히 RPC. REST 인 척이 강제됨.
gRPC — Typed, Binary, HTTP/2
gRPC 가 service 를 Protobuf .proto 파일로 정의; tool 이 10+ 언어의 typed client 와 server 생성. Wire format 이 HTTP/2 위 binary Protobuf. 승리:
- Typed 모든 거. "그 필드가 string 인지 number 인지?" 없음 — .proto 가 말함.
- Generated stub. Go, Python, Java, TypeScript 의 client — 다 같은 .proto 에서, 다 type-checked.
- HTTP/2 multiplexing 내장. 한 연결에 여러 동시 호출.
- 양방향 streaming. 양 측이 stream 가능; WebSocket framing 보다 훨씬 단순.
비용: binary wire 가 브라우저 DevTools 에서 못 읽음; CDN 지원 제한 (gRPC-Web 이 우회); proto 진화가 규율 필요. 내부 service mesh 엔 가치; 소비자 다양한 공개 API 엔 가치 거의 없음.
GraphQL — Client-Chosen Shape
GraphQL 이 client 가 원하는 정확한 필드 묘사하는 GraphQL 문법의 query 보내는 단일 endpoint (보통 POST /graphql) 노출:
{
user(id: "u_42") {
name
email
orders(limit: 3) {
id
total
items { name }
}
}
}
Server 가 각 필드 독립 resolve. Client 가 요청한 거 정확히 받음. 승리:
- Over-fetch / under-fetch 해결. Mobile 이 작은 payload; web admin 이 큰 거 — 같은 endpoint.
- 관련 데이터 위한 round trip 하나. Client-쪽 N+1 없음.
- 강한 typing GraphQL schema 통해.
비용: caching 어려움 (모든 query 다름); 복잡 query 가 resolver 조심히 안 쓰면 DB 두드림; request shape 호출 당 다양해서 intermediary (CDN, proxy) 최적화 어려움.
RPC — Operation 에 명사 없을 때
진짜 procedural operation 엔 RPC-over-HTTP (JSON payload 가진 action endpoint 에 POST) 가 정직. POST /complete, POST /transcode, POST /sign. OpenAI Chat Completions API 가 정확히 이거 — 그리고 REST 인 척이 charade.
현대 RPC 패턴: tRPC (TypeScript-only, end-to-end typed), JSON-RPC 2.0, plain POST-with-JSON. 맞는 operation 에 RPC 선택이 'REST 포기' 아님; protocol 을 트래픽 shape 에 매칭.
결정 heuristic
- 내부 service mesh, 양 측 typed → gRPC.
- 다른 필드 부분집합 원하는 많은 다양 client → GraphQL.
- 명백한 명사 없는 operation-shaped 트래픽 → HTTP 위 RPC.
- 공개 CRUD, 통합, 브라우저 앱 → REST.
- Real-time 양방향 → WebSocket (혹은 내부엔 gRPC streaming).
- Server-push 된 event, one-way → SSE.
대부분 production system 이 이 중 2-3 씀. cwkPippa 가 REST + SSE + WebSocket. 전형적 SaaS 가 REST + GraphQL + gRPC (공개엔 REST, rich web app 엔 GraphQL, 내부엔 gRPC). 하이브리드가 정상; mono-style 이 드묾.
cwkPippa 의 선택, 재방문
POST /api/council/{id}/finalize). Mix 가 의도적; 한 style 로 모든 거 시도가 엔지니어링 위 ideology.