08-theory-and-alternatives
이 챕터가 답하는 질문: GraphQL은 어떤 종류의 도구이고, REST/gRPC/tRPC와 비교했을 때 언제 옳은가? 한 줄 답 (Pyramid Top): “GraphQL은 만능이 아니다 — REST는 리소스가 안정적일 때, gRPC는 서버-서버 강타입일 때, GraphQL은 클라이언트가 모양을 매번 다르게 원할 때 옳다.”
한 문장 답 (Pyramid Top)
*“GraphQL vs REST”*라는 프레임은 거의 항상 잘못이다 — 둘은 서로 다른 축에 있는 도구다. REST는 HTTP 리소스 스타일, GraphQL은 클라이언트 주도 질의 언어, gRPC는 프로토콜 + RPC 프레임워크, tRPC는 TypeScript 모노레포의 함수 타입 공유다. 한 회사가 서버 간엔 gRPC, 클라이언트엔 GraphQL, 공용 API엔 REST, 내부 모노레포엔 tRPC를 동시에 쓰는 그림이 이상하지 않다. 이 챕터는 그 네 도구를 같은 축에 줄 세우려는 충동을 막고, 각자의 적합 자리를 매트릭스로 정리한다.
챕터 지도 (Mermaid)
Why — 왜 이 챕터가 마지막에 오나
00~07을 따라오면서 GraphQL이 무엇이고 어떻게 동작하는지는 충분히 다뤘다. 그러나 production에 올리기 직전, 모든 팀이 같은 질문을 다시 만난다.
“우리 케이스에 진짜 GraphQL이 맞나? REST가 더 단순하지 않나? 서버끼리는 gRPC가 빠르다던데?”
이 질문에 *“GraphQL이 무조건 좋다”*고 답하는 자료는 거의 영업 자료다. 현실의 답은 항상 **“무엇과 무엇을 어떤 축에서 비교하느냐”**부터 정리해야 풀린다. 이 챕터의 7개 문서는 그 축을 하나씩 그어준다.
- 언어로서의 본질:
01— GraphQL은 SQL과 사촌이다, RPC가 아니다 - 흔한 잘못된 비교:
02(REST) ·03(gRPC) ·04(tRPC) ·05(RPC 일반) - 가장 잘 맞는 자리:
06— BFF - 피해야 할 자리:
07— 단순 CRUD, 큰 파일, HTTP 캐시 의존, 운영 경험 0, 1:1 BFF
How — 어떻게 읽나
세 가지 경로가 있다.
| 독자 | 추천 순서 |
|---|---|
| ”GraphQL을 도입할까 고민 중” | 02 → 07 → 06 (현실적 적합성 먼저) |
| “GraphQL 결정은 끝, 다른 도구와 같이 쓸 그림이 궁금” | 06 → 03 → 04 (Polyglot 그림) |
| “이론적으로 GraphQL이 뭐인지 정확히 알고 싶다” | 01 → 05 → 02 (언어 본질부터) |
| # | 파일 | 읽는 데 | 핵심 키워드 |
|---|---|---|---|
| 01 | 01-graphql-as-a-query-language.mdx | 12분 | SQL · declarative · algebraic data type · product/sum |
| 02 | 02-graphql-vs-rest.mdx | 14분 | resource · cacheable · BFF · complementary |
| 03 | 03-graphql-vs-grpc.mdx | 12분 | Protobuf · HTTP/2 · streaming · 서버-서버 |
| 04 | 04-graphql-vs-trpc.mdx | 10분 | end-to-end type · 모노레포 · TypeScript only |
| 05 | 05-graphql-vs-rpc.mdx | 10분 | JSON-RPC · OpenRPC · 함수 호출 vs 그래프 |
| 06 | 06-bff-pattern.mdx | 14분 | BFF · Sam Newman · federation · N 클라이언트 |
| 07 | 07-when-not-to-use-graphql.mdx | 12분 | anti-pattern · 단순 CRUD · file streaming · HTTP cache |
도구 비교 매트릭스 (한 페이지 요약)
| 축 | REST | GraphQL | gRPC | tRPC |
|---|---|---|---|---|
| 본질 | HTTP 리소스 스타일 | 클라이언트 주도 질의 언어 | Protobuf + HTTP/2 RPC | TS 함수 타입 공유 |
| 계약 표현 | OpenAPI(권장) | SDL (의무) | .proto (의무) | TS 타입 (자동) |
| 응답 모양 | 서버가 결정 | 요청이 결정 | 서버가 결정 | 서버가 결정 |
| 전송 | HTTP/1.1·2 | HTTP/WS/SSE | HTTP/2 only | HTTP (보통 HTTP/1.1) |
| 언어 지원 | 사실상 전부 | 사실상 전부 | 10+ 공식 | TS 전용 |
| streaming | SSE/WS 별도 | subscription | bidirectional 내장 | subscription (제한적) |
| HTTP 캐시 | 최고 | 어려움 | 불가 | 어려움 |
| over-fetching | 흔함 | 거의 없음 | 적음 | 적음 |
| under-fetching (N+1 호출) | 흔함 | 한 방에 해결 | 다중 호출 필요 | 다중 호출 필요 |
| introspection | OpenAPI 별도 | spec 의무 | reflection 옵션 | TS 컴파일러 |
| 잘 맞는 자리 | public API · CDN · 파일 | BFF · 가변 모양 클라이언트 | 서버-서버 · 저지연 · streaming | TS 모노레포 풀스택 |
| 안 맞는 자리 | 모양 매번 다른 클라이언트 | 단순 CRUD · 큰 파일 · 캐시 의존 | 브라우저 직접 · public API | non-TS · 외부 팀 |
한 회사는 이 네 가지를 동시에 쓰는 게 보통이다 — 어디서 어떤 도구를 쓰느냐가 진짜 결정.
What — 한 페이지 요약 (모든 문서의 핵심 한 줄)
| 문서 | 한 줄 결론 |
|---|---|
| 01 | GraphQL은 RPC가 아니라 SQL과 같은 family에 속한 declarative query language — 응답의 모양은 쿼리가 type-level로 정의한다. |
| 02 | REST vs GraphQL은 잘못된 프레임이다 — REST는 style, GraphQL은 language. 한 시스템에 둘 다 공존하는 게 정상이다. |
| 03 | gRPC와 GraphQL은 직접 비교 불가능하다 — 한 회사가 서버-서버는 gRPC, 클라이언트엔 GraphQL을 동시에 쓰는 게 가장 흔한 그림. |
| 04 | tRPC는 TS 모노레포 전용의 가장 가벼운 해결책, GraphQL은 언어·팀·플랫폼이 갈라질 때의 일반화된 해결책. |
| 05 | JSON-RPC·OpenRPC는 함수 호출 패러다임이고 GraphQL은 그래프 쿼리 패러다임 — 같은 “RPC” 이름을 써도 다른 모델이다. |
| 06 | BFF는 클라이언트 종류만큼 백엔드를 둔다는 패턴이고, GraphQL은 그 한 BFF가 N 클라이언트를 동시에 받는 자리에 가장 자연스럽다. |
| 07 | GraphQL이 안 맞는 경우: 단순 CRUD · 큰 파일 streaming · 강한 HTTP 캐시 · 운영 경험 0 · 클라이언트 1:1 BFF 가능 — 이 중 하나라도 해당하면 REST/RPC가 더 낫다. |
What-if — 이 챕터를 건너뛰면
- “GraphQL은 무조건 좋다”고 믿으면: 단순 CRUD에 GraphQL을 얹어 learning curve · 운영 부담 · 캐시 손실을 동시에 떠안는다. 6개월 뒤 REST로 롤백.
- “GraphQL은 gRPC와 경쟁한다”고 믿으면: 서버-서버 통신에 GraphQL을 끼우고 성능 · 강타입 · streaming을 모두 잃는다 — 서버-서버는 gRPC가 거의 항상 옳다.
- “BFF는 안 만들어도 된다”고 믿으면: 모바일·웹·TV 클라이언트가 각자 다른 데이터 모양을 원할 때, 백엔드 팀이 모든 모양을 다 만족시키는 REST를 짜다 무너진다.
- “REST는 죽었다”고 믿으면: public API에서 3rd party 개발자가 OpenAPI 한 장 보고 5분 만에 시작하는 매력을 통째로 잃는다.
Insight — 한 단락 이야기
“한 회사 안의 4가지 API”
Netflix는 모바일·TV·웹 클라이언트를 위해 Falcor(자체 BFF)→GraphQL Federation(2021~)로 이동했다. 그러나 그들의 마이크로서비스 내부는 여전히 gRPC를 쓴다. 동시에 그들의 공용 API(파트너용)는 REST다. 그리고 내부 admin tool은 모노레포의 TypeScript 함수를 그냥 import해서 쓴다 — 이게 사실상 tRPC다.
한 시스템 안에 네 가지 도구가 동시에 존재하는 게 정상이다. “무엇을 쓰느냐”가 아니라 “어디에 무엇을 쓰느냐”가 진짜 결정 — 그리고 그 결정의 매트릭스를 이 챕터가 그려준다.
한 단락 요약
GraphQL은 언어로서는 SQL의 사촌(
01)이고, 대안과의 관계에서는 REST(02)·gRPC(03)·tRPC(04)·RPC 일반(05)과 축이 다른 도구다. 가장 자연스러운 자리는 BFF(06)이고, 피해야 할 자리는07이 정리한다. 이 챕터를 끝내면 *“GraphQL이 좋은가”*가 아니라 *“이 자리에 GraphQL이 맞는가”*를 묻게 된다. 다음 챕터(09-real-world-cases)는 이 매트릭스를 실제 회사들이 어떻게 적용했는지를 본다.