--- id: api-gateway-kong-envoy title: API Gateway — Kong / Envoy / Tyk category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [api, gateway, infrastructure, vibe-coding] tech_stack: { language: "Lua / YAML", applicable_to: ["Backend", "Infrastructure"] } applied_in: [] aliases: [API gateway, Kong, Envoy, Tyk, Apigee, Krakend, Traefik] --- # API Gateway > 모든 API request 의 entry point. **Auth, rate limit, transform, route, observability** 한 곳. Kong / Envoy / Tyk / Krakend / Apigee. ## 📖 핵심 개념 - L7 proxy + plugins. - Service discovery + routing. - Cross-cutting concern (auth, rate, log). - Backend service 가 비즈니스만. ## 💻 코드 패턴 ### Kong (declarative) ```yaml # kong.yaml _format_version: "3.0" services: - name: user-api url: http://users:8080 routes: - name: user-route paths: [/api/users] plugins: - name: rate-limiting config: { minute: 100 } - name: jwt - name: prometheus ``` ```bash # DB-less mode kong start -c kong.conf --vv ``` → DB-less = config file. DB mode = postgres / cassandra. ### Kong Konnect / Enterprise - Managed control plane - Multi-region - Plugin marketplace - DevPortal ### Envoy (xDS) ```yaml # envoy.yaml static_resources: listeners: - address: socket_address: { address: 0.0.0.0, port_value: 8080 } filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager route_config: virtual_hosts: - name: backend domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: backend } http_filters: - name: envoy.filters.http.jwt_authn - name: envoy.filters.http.ratelimit - name: envoy.filters.http.router clusters: - name: backend load_assignment: cluster_name: backend endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: backend, port_value: 8080 } ``` → Istio / service mesh 의 데이터 plane. ### Tyk ```bash curl -H "X-Tyk-Authorization: $KEY" \ -X POST http://gateway:8080/tyk/apis \ -d @api.json curl -X POST http://gateway:8080/tyk/reload ``` → API 별 JSON config + hot reload. ### Krakend (declarative, fast) ```json { "version": 3, "endpoints": [ { "endpoint": "/api/user/{id}", "method": "GET", "backend": [ { "url_pattern": "/users/{id}", "host": ["http://users:8080"] } ], "extra_config": { "qos/ratelimit/router": { "max_rate": 100, "client_max_rate": 10 } } } ] } ``` → Aggregator (여러 backend 합쳐 1 response). ### Plugin / filter ``` - Authentication (JWT, OAuth, API key) - Rate limiting - Request / response transform - Logging / tracing - Caching - CORS - Body validation - IP filtering - Bot detection ``` ### JWT validation (Kong) ```yaml plugins: - name: jwt config: uri_param_names: [token] claims_to_verify: [exp] ``` ```bash # Consumer 등록 curl -X POST http://kong:8001/consumers -d "username=alice" curl -X POST http://kong:8001/consumers/alice/jwt -d "key=alice-key" ``` ### Rate limiting (Kong) ```yaml plugins: - name: rate-limiting config: second: 5 minute: 30 hour: 1000 policy: redis redis_host: redis ``` → Local (per node) vs cluster (redis). ### Request transform ```yaml - name: request-transformer config: add: headers: ["X-User: $(jwt.sub)"] remove: headers: ["Authorization"] ``` ### gRPC gateway ```yaml # Envoy - name: envoy.filters.http.grpc_web - name: envoy.filters.http.grpc_json_transcoder typed_config: proto_descriptor: "/etc/proto.pb" services: ["user.UserService"] ``` → gRPC 가 REST / web 으로. ### Canary deploy ```yaml # Envoy weighted_clusters routes: - match: { prefix: "/" } route: weighted_clusters: clusters: - { name: backend-v1, weight: 90 } - { name: backend-v2, weight: 10 } ``` → 10% 트래픽 v2. ### A/B test (header / cookie) ```yaml routes: - match: prefix: "/" headers: [{ name: "x-user-segment", exact_match: "beta" }] route: { cluster: backend-beta } - match: { prefix: "/" } route: { cluster: backend-prod } ``` ### Observability ``` - Access log → ELK / Loki - Metrics → Prometheus (RED / USE) - Tracing → Jaeger / Zipkin / OTel - Audit log (auth events) → Gateway 가 모두 한 곳. ``` ### Hot reload ```bash # Envoy envoy --hot-restart # Kong kong reload ``` → Config 변경 — connection drop X. ### mTLS ```yaml # Service mesh (Istio + Envoy) mtls: mode: STRICT ``` → Service-to-service 자동 TLS. ### Header injection (request 추적) ```yaml - name: correlation-id config: header_name: X-Request-ID generator: uuid echo_downstream: true ``` ### CORS ```yaml - name: cors config: origins: ["https://app.com"] methods: ["GET", "POST"] credentials: true max_age: 3600 ``` ### Bot / DDoS ```yaml - name: ip-restriction config: deny: ["192.168.1.0/24"] - name: bot-detection config: deny: - "(?i)(bot|crawler|spider)" ``` ### Body / response cache ```yaml - name: proxy-cache config: response_code: [200] request_method: [GET] content_type: ["application/json"] cache_ttl: 300 strategy: memory ``` ### GraphQL ```yaml - name: graphql-rate-limiting config: cost_strategy: node_quantifier # query complexity max_cost: 1000 ``` ### AWS API Gateway ```yaml # Serverless framework functions: api: handler: handler.api events: - http: path: users/{id} method: get cors: true authorizer: aws_iam ``` → Managed, Lambda 친화. 큰 traffic 비쌈. ### Cloudflare Workers + WAF ```ts // Cloudflare Worker = edge gateway export default { async fetch(req: Request) { if (await isBot(req)) return new Response('blocked', { status: 403 }); return fetch('https://backend' + new URL(req.url).pathname, req); }, }; ``` → Edge 의 가벼운 gateway. ### NGINX (간단 gateway) ```nginx upstream backend { server backend:8080; } location /api/ { auth_jwt "Realm" token=$arg_token; auth_jwt_key_file /etc/nginx/jwt.key; limit_req zone=api burst=10; proxy_pass http://backend/; } ``` → NGINX Plus = enterprise feature. ### Service mesh vs gateway ``` Gateway: north-south (외부 → 내부) Service mesh: east-west (서비스 간) → 큰 system 가 둘 다. Service mesh = Istio / Linkerd / Consul. ``` ### Custom gateway (Hono / Bun) ```ts import { Hono } from 'hono'; const app = new Hono(); app.use('*', async (c, next) => { // JWT validate const token = c.req.header('authorization')?.replace('Bearer ', ''); if (!verifyJwt(token)) return c.text('unauthorized', 401); await next(); }); app.use('*', rateLimit({ max: 100, window: 60 })); app.all('/api/users/*', async (c) => { return fetch('http://users:8080' + c.req.path, c.req.raw); }); ``` → 작은 / 특화 gateway. ### Cost / 선택 ``` Kong: 큰 ecosystem, 가장 인기 Envoy: 가장 빠름, complex config Tyk: 좋은 UI, dashboard Krakend: simple, 빠름, declarative Traefik: K8s 친화, automatic NGINX: legacy 강함 AWS API Gateway: serverless 친화 Cloudflare: edge ``` ## 🤔 의사결정 기준 | 상황 | 추천 | |---|---| | 일반 API | Kong / Tyk | | 가장 빠름 | Envoy / Krakend | | Service mesh | Istio (Envoy) | | K8s 친화 | Traefik / Kong K8s | | Serverless | AWS API Gateway | | Edge | Cloudflare Workers | | 작은 / custom | Hono / NGINX | | Aggregator | Krakend / Apollo gateway | ## ❌ 안티패턴 - **모든 logic 가 gateway**: 비즈니스 분리. - **No rate limit**: DDoS 취약. - **No auth at gateway**: 매 service 다. - **Hot reload 없음**: 매번 down. - **No observability**: blind. - **DB mode + single Postgres**: SPOF. - **Plugin 너무 많음**: latency 누적. ## 🤖 LLM 활용 힌트 - Kong / Envoy 가 default 후보. - Auth + rate + log = baseline plugin. - Hot reload 필수 (zero-downtime). - Service mesh 가 east-west. ## 🔗 관련 문서 - [[Backend_API_Gateway_BFF]] - [[DevOps_Service_Mesh_Deep]] - [[Backend_Rate_Limiting]]