게이트웨이
Gateway
서로 다른 네트워크를 연결하는 장치. API Gateway는 마이크로서비스의 단일 진입점 역할.
Gateway
서로 다른 네트워크를 연결하는 장치. API Gateway는 마이크로서비스의 단일 진입점 역할.
게이트웨이(Gateway)는 서로 다른 네트워크, 프로토콜, 또는 시스템을 연결하는 '관문' 역할을 하는 장치나 소프트웨어입니다. 가정에서 사용하는 공유기도 게이트웨이의 일종으로, 내부 사설 네트워크(192.168.x.x)와 외부 인터넷을 연결합니다. 게이트웨이는 OSI 7계층 모든 레벨에서 동작할 수 있어 라우터보다 더 상위 개념입니다.
라우터와 게이트웨이의 핵심 차이점은 프로토콜 변환 능력입니다. 라우터는 동일한 프로토콜(주로 IP) 내에서 패킷을 전달하지만, 게이트웨이는 서로 다른 프로토콜 간 변환이 가능합니다. 예를 들어, HTTP를 MQTT로 변환하거나, IPv4를 IPv6로 변환하는 것이 게이트웨이의 역할입니다. 실무에서 Default Gateway는 패킷이 로컬 네트워크를 벗어날 때 거치는 첫 번째 라우터를 의미합니다.
클라우드 환경에서 게이트웨이는 더욱 중요해졌습니다. AWS에서 Internet Gateway(IGW)는 VPC를 인터넷에 연결하고, NAT Gateway는 프라이빗 서브넷의 인스턴스가 외부 인터넷에 접근할 수 있게 합니다. IGW는 양방향 통신을 허용하고 비용이 무료인 반면, NAT Gateway는 아웃바운드만 허용하며 시간당 약 $0.045 + 데이터 처리 비용이 발생합니다.
API Gateway는 마이크로서비스 아키텍처에서 모든 API 요청의 단일 진입점 역할을 합니다. Kong, AWS API Gateway, Azure API Management 등이 대표적이며, 인증/인가, 속도 제한(Rate Limiting), 요청 라우팅, 프로토콜 변환, 로깅/모니터링 등의 기능을 제공합니다. Netflix는 Zuul에서 Spring Cloud Gateway로 전환하여 하루 수십억 개의 API 요청을 처리합니다.
import boto3
import netifaces
# 로컬 시스템의 기본 게이트웨이 확인
gateways = netifaces.gateways()
default_gw = gateways['default'][netifaces.AF_INET]
print(f"기본 게이트웨이: {default_gw[0]}") # 192.168.1.1
print(f"인터페이스: {default_gw[1]}") # eth0
# AWS: Internet Gateway 생성 및 연결
ec2 = boto3.client('ec2', region_name='ap-northeast-2')
# Internet Gateway 생성
igw = ec2.create_internet_gateway()
igw_id = igw['InternetGateway']['InternetGatewayId']
print(f"IGW 생성됨: {igw_id}")
# VPC에 연결
ec2.attach_internet_gateway(
InternetGatewayId=igw_id,
VpcId='vpc-12345678'
)
# NAT Gateway 생성 (퍼블릭 서브넷에 배치)
# 먼저 Elastic IP 할당
eip = ec2.allocate_address(Domain='vpc')
nat_gw = ec2.create_nat_gateway(
SubnetId='subnet-public-12345',
AllocationId=eip['AllocationId'],
TagSpecifications=[{
'ResourceType': 'natgateway',
'Tags': [{'Key': 'Name', 'Value': 'prod-nat-gw'}]
}]
)
print(f"NAT Gateway 생성됨: {nat_gw['NatGateway']['NatGatewayId']}")
# 라우팅 테이블 업데이트 (프라이빗 서브넷 → NAT Gateway)
ec2.create_route(
RouteTableId='rtb-private-12345',
DestinationCidrBlock='0.0.0.0/0',
NatGatewayId=nat_gw['NatGateway']['NatGatewayId']
)
# 로컬 시스템 게이트웨이 확인
# Linux/macOS
ip route | grep default # default via 192.168.1.1 dev eth0
netstat -rn | grep default # 라우팅 테이블 전체
# Windows
route print | findstr "0.0.0.0"
ipconfig | findstr "게이트웨이"
# AWS CLI: Internet Gateway 생성
aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=prod-igw}]'
# VPC에 IGW 연결
aws ec2 attach-internet-gateway \
--internet-gateway-id igw-12345678 \
--vpc-id vpc-12345678
# NAT Gateway 생성 (Elastic IP 필요)
aws ec2 allocate-address --domain vpc # EIP 할당
aws ec2 create-nat-gateway \
--subnet-id subnet-public-12345 \
--allocation-id eipalloc-12345678 \
--tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=prod-nat}]'
# NAT Gateway 상태 확인 (available까지 2-3분 소요)
aws ec2 describe-nat-gateways \
--nat-gateway-ids nat-12345678 \
--query 'NatGateways[0].State'
# 프라이빗 서브넷 라우팅 테이블에 NAT Gateway 경로 추가
aws ec2 create-route \
--route-table-id rtb-private-12345 \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id nat-12345678
# Transit Gateway (여러 VPC 연결)
aws ec2 create-transit-gateway \
--description "Multi-VPC Hub" \
--options "AutoAcceptSharedAttachments=enable"
// Express.js API Gateway 패턴 구현
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const rateLimit = require('express-rate-limit');
const jwt = require('jsonwebtoken');
const app = express();
// Rate Limiting (분당 100 요청)
const limiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
message: { error: 'Too many requests, please try again later' }
});
app.use(limiter);
// JWT 인증 미들웨어
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token provided' });
try {
req.user = jwt.verify(token, process.env.JWT_SECRET);
next();
} catch (err) {
res.status(403).json({ error: 'Invalid token' });
}
};
// 마이크로서비스 라우팅
const services = {
users: 'http://user-service:3001',
orders: 'http://order-service:3002',
products: 'http://product-service:3003'
};
// 각 서비스로 프록시
Object.entries(services).forEach(([path, target]) => {
app.use(`/api/${path}`, authMiddleware, createProxyMiddleware({
target,
changeOrigin: true,
pathRewrite: { [`^/api/${path}`]: '' },
onProxyReq: (proxyReq, req) => {
// 사용자 정보를 헤더에 추가
proxyReq.setHeader('X-User-Id', req.user.id);
proxyReq.setHeader('X-Request-Id', crypto.randomUUID());
},
onError: (err, req, res) => {
console.error(`Proxy error: ${err.message}`);
res.status(502).json({ error: 'Service unavailable' });
}
}));
});
// Health Check
app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.listen(3000, () => console.log('API Gateway running on :3000'));
"프라이빗 서브넷에서 외부 API 호출이 필요하니까 NAT Gateway를 붙여야 합니다. 다만 NAT Gateway는 AZ당 하나씩 필요하고, 월 $35 + 데이터 처리 비용이 발생하니까 비용 최적화가 필요하면 NAT Instance나 VPC Endpoint를 고려해보세요."
"EC2 인스턴스가 인터넷 연결이 안 되는 이유를 보니, 퍼블릭 서브넷인데 Internet Gateway가 VPC에 연결 안 되어 있네요. IGW 연결하고 라우팅 테이블에 0.0.0.0/0 → IGW 경로를 추가하면 됩니다."
"마이크로서비스가 10개 넘어가니까 API Gateway 도입이 필요합니다. Kong이나 AWS API Gateway로 통합 인증, Rate Limiting, 로깅을 중앙화하면 각 서비스에서 중복 구현할 필요가 없어요. 또 클라이언트는 단일 엔드포인트만 알면 되니까 관리가 쉬워집니다."
IGW는 퍼블릭 서브넷용(양방향, 무료), NAT Gateway는 프라이빗 서브넷용(아웃바운드만, 유료)입니다. 프라이빗 서브넷에 IGW 경로를 추가해도 인터넷 연결은 되지 않습니다. 반드시 NAT Gateway나 NAT Instance를 사용하세요.
NAT Gateway는 AZ 장애 시 함께 다운됩니다. 프로덕션 환경에서는 각 AZ마다 NAT Gateway를 배치하고, 해당 AZ의 프라이빗 서브넷이 같은 AZ의 NAT Gateway를 사용하도록 라우팅하세요.
모든 트래픽이 API Gateway를 통과하므로 장애 시 전체 시스템 다운됩니다. 다중 AZ 배포, 헬스체크, Auto Scaling을 필수로 설정하고, 서킷 브레이커 패턴을 적용하세요.
퍼블릭 서브넷: IGW 연결 + 퍼블릭 IP 할당. 프라이빗 서브넷: 각 AZ별 NAT Gateway 배치. API Gateway: 멀티 AZ + Rate Limiting + 타임아웃(29초 이하) 설정. Transit Gateway로 VPC 간 연결 중앙화.