NAT Gateway vs NAT Instance: 프라이빗 서브넷 인터넷 아웃바운드 완전 가이드

프라이빗 서브넷의 EC2 인스턴스가 yum update나 apt-get을 실행했는데 타임아웃이 발생하는 상황 — 대부분의 엔지니어가 처음 VPC를 구성할 때 한 번씩 겪는 문제다. 원인은 단순하다. 프라이빗 서브넷은 인터넷 게이트웨이로 직접 라우팅되지 않기 때문에, 아웃바운드 인터넷 트래픽을 처리할 NAT 계층이 없으면 패킷이 어디로도 가지 못한다. 이 포스트는 NAT Gateway vs NAT Instance 선택 기준을 실제 운영 관점에서 정리한다.

TL;DR — NAT Gateway vs NAT Instance 핵심 비교

항목NAT GatewayNAT Instance
관리 주체AWS 완전 관리형직접 운영 (EC2)
가용성AZ 내 자동 이중화단일 인스턴스 (직접 HA 구성 필요)
대역폭 확장자동 스케일링인스턴스 타입에 종속
소스/목적지 확인자동 비활성화수동으로 비활성화 필요
보안 그룹적용 불가적용 가능
포트 포워딩지원 안 함iptables로 구성 가능
비용 구조시간당 요금 + 데이터 처리 요금EC2 인스턴스 요금
권장 사용 시나리오대부분의 프로덕션 환경비용 최적화가 최우선이거나 커스텀 트래픽 제어가 필요한 경우

NAT가 작동하는 방식 — 먼저 메커니즘을 이해하자

NAT(Network Address Translation)는 프라이빗 IP를 퍼블릭 IP로 변환해서 인터넷으로 내보내고, 응답 패킷을 다시 원래 프라이빗 인스턴스로 돌려보내는 역할을 한다. 핵심은 상태 추적(stateful)이라는 점이다. 아웃바운드 연결의 소스 IP와 포트를 기록해 두었다가, 인바운드 응답이 들어오면 해당 기록을 참조해 올바른 내부 인스턴스로 전달한다.

VPC 라우팅 관점에서 보면, 프라이빗 서브넷의 라우트 테이블에 0.0.0.0/0 대상을 NAT 장치로 지정해야 한다. 인터넷 게이트웨이는 퍼블릭 서브넷 전용이고, 프라이빗 서브넷은 NAT를 통해 간접적으로 인터넷에 접근한다.

graph LR PrivInst["프라이빗 인스턴스 (10.0.1.10)"] NAT["NAT 장치 (퍼블릭 서브넷)"] IGW["인터넷 게이트웨이"] Internet["인터넷"] PrivInst -->|"소스: 10.0.1.10"| NAT NAT -->|"소스: EIP로 변환"| IGW IGW --> Internet Internet -->|"응답 패킷"| IGW IGW --> NAT NAT -->|"상태 테이블 참조 원래 인스턴스로 전달"| PrivInst
  1. 프라이빗 인스턴스가 아웃바운드 패킷을 생성한다. 소스 IP는 프라이빗 IP.
  2. 라우트 테이블의 0.0.0.0/0 규칙에 따라 패킷이 NAT 장치로 전달된다.
  3. NAT 장치가 소스 IP를 자신의 Elastic IP(퍼블릭)로 변환하고 연결 상태를 기록한다.
  4. 변환된 패킷이 인터넷 게이트웨이를 통해 인터넷으로 나간다.
  5. 응답 패킷이 돌아오면 NAT 장치가 상태 테이블을 참조해 원래 프라이빗 인스턴스로 전달한다.

NAT Gateway — 관리형 옵션의 실제 동작

NAT Gateway는 퍼블릭 서브넷에 배치하고 Elastic IP를 할당하는 것으로 설정이 끝난다. AWS가 내부적으로 이중화와 스케일링을 처리하기 때문에 운영자가 신경 쓸 부분이 거의 없다. 단, AZ 단위로 이중화된다는 점을 명확히 이해해야 한다 — NAT Gateway 하나가 전체 리전을 커버하는 게 아니다.

NAT Gateway 생성 및 라우트 테이블 구성

# 1. Elastic IP 할당
aws ec2 allocate-address \
  --domain vpc \
  --region us-east-1

# 2. 퍼블릭 서브넷에 NAT Gateway 생성
# AllocationId는 위 명령의 출력값 사용
aws ec2 create-nat-gateway \
  --subnet-id subnet-0a1b2c3d4e5f67890 \
  --allocation-id eipalloc-0a1b2c3d4e5f67890 \
  --region us-east-1

# 3. NAT Gateway가 available 상태가 될 때까지 대기
aws ec2 wait nat-gateway-available \
  --nat-gateway-ids nat-0a1b2c3d4e5f67890 \
  --region us-east-1

# 4. 프라이빗 서브넷 라우트 테이블에 기본 경로 추가
aws ec2 create-route \
  --route-table-id rtb-0a1b2c3d4e5f67890 \
  --destination-cidr-block 0.0.0.0/0 \
  --nat-gateway-id nat-0a1b2c3d4e5f67890 \
  --region us-east-1

멀티 AZ 구성 — 이게 빠지면 단일 장애점이 생긴다

AZ-a의 프라이빗 서브넷 라우트 테이블이 AZ-b의 NAT Gateway를 가리키고 있으면, AZ-b에 장애가 발생했을 때 AZ-a의 아웃바운드 트래픽도 함께 끊긴다. 각 AZ의 프라이빗 서브넷은 같은 AZ에 있는 NAT Gateway를 사용하도록 라우트 테이블을 분리해야 한다.

graph TD subgraph AZA["AZ-a"] PrivA["프라이빗 서브넷 A"] PubA["퍼블릭 서브넷 A"] NATA["NAT Gateway A (EIP-a)"] PrivA -->|"0.0.0.0/0"| NATA NATA --- PubA end subgraph AZB["AZ-b"] PrivB["프라이빗 서브넷 B"] PubB["퍼블릭 서브넷 B"] NATB["NAT Gateway B (EIP-b)"] PrivB -->|"0.0.0.0/0"| NATB NATB --- PubB end IGW["인터넷 게이트웨이"] NATA --> IGW NATB --> IGW IGW --> Internet["인터넷"]
  1. AZ-a 프라이빗 서브넷의 라우트 테이블은 AZ-a NAT Gateway를 가리킨다.
  2. AZ-b 프라이빗 서브넷의 라우트 테이블은 AZ-b NAT Gateway를 가리킨다.
  3. 각 NAT Gateway는 같은 AZ의 퍼블릭 서브넷에 위치하고 별도의 Elastic IP를 사용한다.
  4. 한 AZ에 장애가 발생해도 다른 AZ의 아웃바운드 트래픽은 영향받지 않는다.

NAT Instance — EC2로 직접 NAT를 구성할 때

NAT Instance는 AWS가 제공하는 커뮤니티 AMI를 사용하거나, 일반 Amazon Linux 2 인스턴스에 직접 IP 포워딩과 iptables masquerade 규칙을 설정하는 방식으로 구성한다. 관리형 NAT Gateway가 등장하기 전에 주로 사용하던 방식이지만, 포트 포워딩이나 트래픽 필터링 같은 커스텀 요구사항이 있을 때는 여전히 유효한 선택지다.

소스/목적지 확인 비활성화 — 반드시 해야 하는 설정

EC2 인스턴스는 기본적으로 자신이 소스이거나 목적지인 패킷만 처리한다. NAT 역할을 하려면 다른 인스턴스의 트래픽을 대신 전달해야 하므로, 이 확인을 비활성화해야 한다. 이걸 빠뜨리면 NAT Instance를 통과하는 패킷이 모두 드롭된다 — 그리고 로그에는 아무것도 남지 않는다.

# NAT Instance로 사용할 EC2의 소스/목적지 확인 비활성화
aws ec2 modify-instance-attribute \
  --instance-id i-0a1b2c3d4e5f67890 \
  --no-source-dest-check \
  --region us-east-1

# 설정 확인
aws ec2 describe-instance-attribute \
  --instance-id i-0a1b2c3d4e5f67890 \
  --attribute sourceDestCheck \
  --region us-east-1

Amazon Linux 2에서 NAT 설정

🔽 NAT Instance 커널 설정 및 iptables 규칙 (클릭하여 펼치기)
# NAT Instance에 SSH 접속 후 실행

# 1. IP 포워딩 활성화
sudo sysctl -w net.ipv4.ip_forward=1

# 재부팅 후에도 유지되도록 설정
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf

# 2. iptables MASQUERADE 규칙 추가
# eth0은 인터넷 방향 인터페이스 (퍼블릭 서브넷 ENI)
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# 3. iptables 규칙 저장 (Amazon Linux 2)
sudo service iptables save

# 4. 설정 확인
sudo iptables -t nat -L -n -v

NAT Instance 보안 그룹 설정

NAT Instance는 보안 그룹을 적용할 수 있다는 점에서 NAT Gateway와 다르다. 프라이빗 서브넷의 CIDR에서 오는 트래픽을 인바운드로 허용하고, 아웃바운드는 인터넷으로 나가는 트래픽을 허용해야 한다.

# NAT Instance용 보안 그룹 생성
aws ec2 create-security-group \
  --group-name nat-instance-sg \
  --description 'Security group for NAT Instance' \
  --vpc-id vpc-0a1b2c3d4e5f67890 \
  --region us-east-1

# 프라이빗 서브넷 CIDR에서 오는 모든 트래픽 허용 (인바운드)
aws ec2 authorize-security-group-ingress \
  --group-id sg-0a1b2c3d4e5f67890 \
  --protocol all \
  --cidr 10.0.0.0/8 \
  --region us-east-1

# 아웃바운드 전체 허용 (기본값이지만 명시적으로 확인)
aws ec2 authorize-security-group-egress \
  --group-id sg-0a1b2c3d4e5f67890 \
  --protocol all \
  --cidr 0.0.0.0/0 \
  --region us-east-1

실제 장애 패턴 — 잘못된 진단과 실제 원인

NAT Instance를 새로 구성하고 프라이빗 인스턴스에서 curl https://example.com을 실행했는데 연결이 안 됐다. 처음엔 보안 그룹 문제라고 생각해서 인바운드 규칙을 열고 또 열었다. 아무 변화가 없었다.

실제 원인은 소스/목적지 확인이 여전히 활성화된 상태였다. AWS 콘솔에서 비활성화했다고 생각했는데, 인스턴스를 잘못 선택해서 다른 인스턴스에 적용한 것이었다. 패킷은 NAT Instance에 도달했지만, 인스턴스가 '이 패킷은 내 것이 아니다'라고 판단해서 드롭했다. 네트워크 ACL 로그도, 보안 그룹 거부 로그도 없었다 — 그냥 조용히 사라졌다.

진단 순서는 이렇게 잡아야 한다:

# 1. 프라이빗 인스턴스에서 라우트 확인
ip route show
# 0.0.0.0/0이 NAT 장치 방향으로 설정되어 있는지 확인

# 2. NAT Instance의 소스/목적지 확인 상태 검증
aws ec2 describe-instance-attribute \
  --instance-id i-0a1b2c3d4e5f67890 \
  --attribute sourceDestCheck \
  --region us-east-1
# 'Value'가 false여야 정상

# 3. NAT Instance에서 IP 포워딩 활성화 여부 확인
sysctl net.ipv4.ip_forward
# 1이어야 정상

# 4. iptables MASQUERADE 규칙 존재 여부 확인
sudo iptables -t nat -L POSTROUTING -n -v

소스/목적지 확인 비활성화는 콘솔과 CLI 모두에서 적용 대상 인스턴스를 반드시 재확인해야 한다. 이 설정이 빠지면 나머지 모든 설정이 올바르더라도 트래픽은 통과하지 않는다.

NAT Gateway vs NAT Instance 선택 기준

graph TD Start(["NAT 방식 선택"]) Q1{"포트 포워딩 또는 커스텀 트래픽 제어 필요?"} Q2{"비용이 최우선 제약 조건인가?"} Q3{"트래픽 볼륨이 매우 낮은가?"} NATInst["NAT Instance 선택"] NATGW["NAT Gateway 선택"] Start --> Q1 Q1 -->|"예"| NATInst Q1 -->|"아니오"| Q2 Q2 -->|"아니오"| NATGW Q2 -->|"예"| Q3 Q3 -->|"예 (소형 인스턴스가 저렴)"| NATInst Q3 -->|"아니오"| NATGW
  1. 포트 포워딩이나 커스텀 트래픽 제어가 필요하면 NAT Instance가 유일한 선택지다.
  2. 비용이 최우선 제약이고 트래픽이 매우 낮다면 소형 EC2 인스턴스 비용이 더 저렴할 수 있다.
  3. 그 외 대부분의 프로덕션 환경에서는 NAT Gateway가 운영 부담 대비 합리적인 선택이다.
  4. 멀티 AZ 환경에서는 어떤 방식을 선택하든 AZ별 NAT 장치를 분리해야 한다.

NAT Gateway 비용 최적화 — 데이터 처리 요금을 놓치지 말 것

NAT Gateway는 시간당 요금 외에 처리된 데이터 GB당 요금이 별도로 부과된다. 같은 VPC 내 인스턴스 간 트래픽이 NAT Gateway를 경유하도록 잘못 라우팅되면 불필요한 데이터 처리 요금이 발생한다. S3나 DynamoDB 같은 AWS 서비스에 접근할 때는 VPC 엔드포인트를 사용하면 NAT Gateway를 경유하지 않아 비용을 절감할 수 있다.

# S3용 게이트웨이 VPC 엔드포인트 생성 (NAT Gateway 우회)
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0a1b2c3d4e5f67890 \
  --service-name com.amazonaws.us-east-1.s3 \
  --route-table-ids rtb-0a1b2c3d4e5f67890 \
  --vpc-endpoint-type Gateway \
  --region us-east-1
NAT Gateway를 경유하는 S3 트래픽은 데이터 처리 요금이 부과된다. 게이트웨이 엔드포인트는 추가 비용 없이 S3와 DynamoDB 트래픽을 VPC 내부로 직접 라우팅한다 — 이 조합은 거의 항상 설정할 가치가 있다.

IAM — NAT 관련 작업에 필요한 최소 권한

NAT Gateway 생성과 라우트 테이블 수정에는 별도의 IAM 권한이 필요하다. 최소 권한 원칙에 따라 필요한 작업만 허용하도록 구성한다.

🔽 NAT Gateway 관리용 IAM 정책 예시 (클릭하여 펼치기)
{
  'Version': '2012-10-17',
  'Statement': [
    {
      'Effect': 'Allow',
      'Action': [
        'ec2:CreateNatGateway',
        'ec2:DeleteNatGateway',
        'ec2:DescribeNatGateways',
        'ec2:AllocateAddress',
        'ec2:ReleaseAddress',
        'ec2:DescribeAddresses',
        'ec2:CreateRoute',
        'ec2:DeleteRoute',
        'ec2:DescribeRouteTables',
        'ec2:AssociateRouteTable'
      ],
      'Resource': '*'
    }
  ]
}

NAT Gateway vs NAT Instance — 운영 체크리스트

어떤 방식을 선택하든, 배포 전에 다음 항목을 확인한다:

  • [ ] 프라이빗 서브넷 라우트 테이블에 0.0.0.0/0 → NAT 장치 경로가 설정되어 있는가
  • [ ] NAT 장치가 퍼블릭 서브넷에 위치하고 있는가
  • [ ] 퍼블릭 서브넷 라우트 테이블에 0.0.0.0/0 → 인터넷 게이트웨이가 설정되어 있는가
  • [ ] (NAT Instance) 소스/목적지 확인이 비활성화되어 있는가
  • [ ] (NAT Instance) IP 포워딩과 iptables masquerade가 설정되어 있는가
  • [ ] 멀티 AZ 환경에서 AZ별 NAT 장치가 분리되어 있는가
  • [ ] S3/DynamoDB 트래픽에 VPC 게이트웨이 엔드포인트가 적용되어 있는가

마무리 — NAT Gateway vs NAT Instance 선택 요약

대부분의 프로덕션 환경에서 NAT Gateway는 운영 복잡도를 낮추는 합리적인 선택이다. 소스/목적지 확인 설정, iptables 규칙, 인스턴스 패치 같은 작업을 직접 관리할 필요가 없다. 반면 포트 포워딩이나 세밀한 트래픽 제어가 필요하거나, 비용 구조상 소형 EC2 인스턴스가 유리한 환경이라면 NAT Instance가 여전히 유효하다.

멀티 AZ 구성에서 AZ별 NAT 장치 분리와 S3/DynamoDB용 VPC 엔드포인트 적용은 어떤 방식을 선택하든 기본으로 챙겨야 할 항목이다.

핵심 용어 정리

용어설명
NAT (Network Address Translation)프라이빗 IP를 퍼블릭 IP로 변환해 인터넷 통신을 가능하게 하는 기술
Elastic IPAWS 계정에 할당되는 고정 퍼블릭 IPv4 주소. NAT Gateway에 연결해 고정 아웃바운드 IP로 사용
소스/목적지 확인 (Source/Dest Check)EC2가 자신이 소스 또는 목적지인 패킷만 처리하도록 하는 기본 설정. NAT Instance에서는 반드시 비활성화 필요
VPC 엔드포인트 (Gateway 타입)S3, DynamoDB 트래픽을 NAT Gateway 없이 AWS 내부 네트워크로 직접 라우팅하는 기능
라우트 테이블서브넷의 트래픽 경로를 정의하는 VPC 구성 요소. 프라이빗 서브넷의 기본 경로를 NAT 장치로 지정해야 함

Related Posts

댓글

이 블로그의 인기 게시물

EC2 SSH 연결 타임아웃 완전 해결 가이드: Security Group 인바운드 규칙부터 라우팅까지

EC2 SSH 연결 시간 초과: 확인해야 할 보안 그룹(Security Group) 규칙

IAM User vs IAM Role 차이점 완전 정리 — EC2에서 S3 접근 시 무엇을 써야 하는가