--- id: backend-graphql-federation title: GraphQL Federation — Apollo / Mesh / Hive category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [backend, graphql, vibe-coding] tech_stack: { language: "TS", applicable_to: ["Backend"] } applied_in: [] aliases: [GraphQL Federation, Apollo Federation, GraphQL Mesh, Hive, supergraph, subgraph] --- # GraphQL Federation > Microservice 가 GraphQL = federation. **Subgraph (per service) → Supergraph (gateway)**. Apollo Federation 가 표준. 작은 system 가 stitching. ## 📖 핵심 개념 - 매 service 가 own schema (subgraph). - Gateway 가 query plan + 분산 실행. - Entity (cross-service type). - Schema composition. ## 💻 코드 패턴 ### Federation 식 ```graphql # users service (subgraph) type User @key(fields: "id") { id: ID! email: String! } # orders service (subgraph) type Order { id: ID! total: Float! user: User! # users service 의 User } extend type User @key(fields: "id") { id: ID! @external orders: [Order!]! # orders 가 추가 } ``` → User 가 두 service 가 정의 (federated). ### Apollo Server (subgraph) ```ts import { ApolloServer } from '@apollo/server'; import { buildSubgraphSchema } from '@apollo/subgraph'; const typeDefs = ` type User @key(fields: "id") { id: ID! email: String! } type Query { users: [User!]! } `; const resolvers = { Query: { users: () => db.users.find() }, User: { __resolveReference: ({ id }) => db.users.findOne({ id }), }, }; const server = new ApolloServer({ schema: buildSubgraphSchema({ typeDefs, resolvers }), }); ``` → `__resolveReference` 가 다른 service 가 reference. ### Apollo Router (gateway) ```yaml # router.yaml supergraph: listen: 0.0.0.0:4000 subgraphs: users: routing_url: http://users:4001 orders: routing_url: http://orders:4002 ``` ```bash router --config router.yaml ``` → Single endpoint, query 가 자동 분산. ### Supergraph composition ```bash # Compose subgraph schemas → supergraph rover supergraph compose --config supergraph.yaml > supergraph.graphql ``` ```yaml # supergraph.yaml subgraphs: users: routing_url: http://users:4001 schema: file: users/schema.graphql orders: routing_url: http://orders:4002 schema: file: orders/schema.graphql ``` ### Apollo Studio / Hive ``` Schema registry: - 매 service 가 schema publish. - Compose 가 검증. - Breaking change 감지. - Performance 가 visualize. → Apollo Studio (paid). Hive (open source, free). ``` ### Entity resolution ```graphql query { orders { id user { email # users service 가 } } } ``` ``` Gateway 가: 1. orders service: orders + user.id 가져옴. 2. users service: User(id: ...) batch. 3. Merge. ``` → N+1 자동 batch (DataLoader). ### Federation directives ```graphql @key(fields: "id") # Entity (cross-service) @external # Field 가 다른 service 가 @requires(fields: "stock") # 다른 service field 필요 @provides(fields: "name") # 이 service 가 줌 @shareable # 여러 service 가 정의 OK @override(from: "old-service") # Migration @inaccessible # Public 안 보임 ``` ### GraphQL Mesh ```yaml # mesh.yaml sources: - name: users handler: openapi: source: https://users/openapi.json - name: orders handler: graphql: endpoint: https://orders/graphql ``` → 매 source (REST, GraphQL, gRPC) 가 unified GraphQL. → Apollo Federation 가 GraphQL only. Mesh 가 다양. ### Schema stitching (legacy) ```ts import { stitchSchemas } from '@graphql-tools/stitch'; const schema = stitchSchemas({ subschemas: [usersSchema, ordersSchema], }); ``` → Federation 의 옛 version. 작은 use case. ### Performance: query plan ```graphql query { user(id: 1) { name orders { total product { name } } } } ``` ``` Plan: 1. users service: user(id: 1) → {id, name}. 2. orders service: orders for user.id 1 → [{id, total, productId}]. 3. products service: products([1, 2, 3]) batch → [{id, name}]. → 3 service 호출, parallel where possible. ``` ### N+1 방지 (DataLoader) ```ts import DataLoader from 'dataloader'; const userLoader = new DataLoader(async (ids: string[]) => { const users = await db.users.find({ id: { $in: ids } }); return ids.map(id => users.find(u => u.id === id)); }); // Resolver User: { id: ({ id }) => userLoader.load(id) } ``` → 매 request 가 자체 loader. Batch. ### Authentication ```ts // Gateway 가 auth header forward const router = new Router({ subgraphs: { users: { routing_url: '...', willSendRequest: ({ request }) => { request.http.headers.set('user-id', context.userId); }}, }, }); // Subgraph 가 user-id header 사용 ``` ### Rate limit ``` Gateway level (Apollo Router): - Query depth limit (5). - Query complexity limit (1000 cost). - Per-user rate. Subgraph level: - Per-resolver rate. ``` ### Caching ``` Apollo Router: - Response cache. - Per-field hint (@cacheControl). - CDN cache. Subgraph: - DataLoader (per-request). - Redis (per-field). ``` ```graphql type User @cacheControl(maxAge: 300) { id: ID! email: String! @cacheControl(maxAge: 60) } ``` ### Tracing ``` - Apollo Studio: query timing. - OpenTelemetry: span 별 service. - Prometheus: metric. → "이 query 가 어디 서비스 가 느림?" visible. ``` ### Schema linting ```bash # Apollo Rover rover graph check my-graph@current --schema schema.graphql ``` → Breaking change 감지. ### Versioning ``` GraphQL = no version (single schema 가 evolve). - Add fields: OK. - Remove field: deprecated → grace period → remove. - Rename: 새 field + 옛 deprecated. → Mobile app 가 옛 client 도 작동. ``` ### Federation 의 alternative ``` - BFF (Backend for Frontend): per-client REST + GraphQL. - API Gateway (REST): 단순. - gRPC + Buf: type-safe. - tRPC: TS-only. → GraphQL Federation 가 큰 system + 다양 client. ``` ### When NOT? ``` - 작은 system (1-2 service): 직접 GraphQL. - Single client: REST 충분. - 매우 high-throughput: gRPC. - Mobile-only + simple: tRPC / REST. ``` ### Migration ``` 1. 1 monolith GraphQL. 2. 1 service split → subgraph. 3. Gateway 추가 (federation 활성). 4. 점진 split. 5. 옛 monolith retire. ``` → Strangler fig. ### Production ``` - Apollo Router (Rust, 빠름). - Hive (open source registry). - Mesh (REST → GraphQL). - ko / pothos / Yoga / Mercurius (subgraph servers). ``` ### Cost / overhead ``` Federation 가 큰 cost: - Gateway latency (10-50ms). - Schema composition complexity. - 매 service 가 federation aware. → 5+ service GraphQL 가 sweet spot. ``` ### Real-world - **Netflix**: 큰 GraphQL Federation. - **Airbnb**: federation 사용. - **Expedia**: federation. - **Walmart**: 큰 multi-team. - **Atlassian**: federation 마이그레이션. ## 🤔 의사결정 기준 | 상황 | 추천 | |---|---| | 단일 GraphQL | 직접 server | | 5+ subgraph | Apollo Federation | | Mixed source | GraphQL Mesh | | 작은 (legacy) | Schema stitching | | Schema registry | Apollo Studio / Hive | | 빠른 gateway | Apollo Router (Rust) | | Simple TS RPC | tRPC | ## ❌ 안티패턴 - **모든 거 federation (작은 system)**: 큰 overhead. - **No DataLoader**: N+1 폭발. - **Schema 무계획 변경**: client 깨짐. - **No cache**: latency. - **Auth gateway 만**: subgraph 도 검증. - **No tracing**: bottleneck 모름. - **Subgraph 가 cross-service join**: federation 의 가치 ↓. ## 🤖 LLM 활용 힌트 - Federation = supergraph + subgraph + entity. - Apollo Router 가 빠름 (Rust). - Hive 가 open source registry. - DataLoader 가 N+1 의 답. ## 🔗 관련 문서 - [[Backend_GraphQL_Server_Patterns]] - [[Backend_GraphQL_Yoga_Pothos]] - [[Backend_API_Gateway_BFF]]