VPC 네트워크 구축 - 정답 및 해설
이 문서의 내용
- 각 실습 단계의 웹 콘솔 상세 절차와 AWS CLI 명령어
- 각 단계별 해설 (왜 이렇게 하는지)
- 검증 스크립트로 학생들의 작업 결과 확인
- 학생들이 자주 겪는 트러블슈팅 가이드
답안 개요
이 챕터에서 생성하는 AWS 리소스의 최종 상태입니다:
| 리소스 | 이름 | 주요 설정 |
|---|---|---|
| VPC | ShopEasy-VPC | CIDR: 10.0.0.0/16 |
| 퍼블릭 서브넷 | ShopEasy-Public-A | 10.0.1.0/24, ap-northeast-2a, 자동 IP 할당 ON |
| 퍼블릭 서브넷 | ShopEasy-Public-C | 10.0.2.0/24, ap-northeast-2c, 자동 IP 할당 ON |
| 프라이빗 서브넷 | ShopEasy-Private-A | 10.0.100.0/24, ap-northeast-2a |
| 프라이빗 서브넷 | ShopEasy-Private-C | 10.0.101.0/24, ap-northeast-2c |
| 인터넷 게이트웨이 | ShopEasy-IGW | ShopEasy-VPC에 연결됨 |
| NAT Gateway | ShopEasy-NAT | ShopEasy-Public-A에 위치, 탄력적 IP 할당됨 |
| 라우트 테이블 | ShopEasy-Public-RT | 0.0.0.0/0 → IGW, 퍼블릭 서브넷 2개 연결 |
| 라우트 테이블 | ShopEasy-Private-RT | 0.0.0.0/0 → NAT GW, 프라이빗 서브넷 2개 연결 |
AWS CLI 명령어를 사용하려면 사전에 aws configure로 자격 증명이 설정되어 있어야 합니다.
리전은 ap-northeast-2로 설정하세요.
CLI 방법은 학생들에게 웹 콘솔 실습이 끝난 후 보충 학습으로 제공하는 것을 권장합니다.
Step 1: VPC 생성
정답
- AWS 콘솔 상단 검색창에 "VPC" 입력 → VPC 서비스 클릭
- 왼쪽 메뉴에서 "VPC" 클릭
- 오른쪽 상단 "VPC 생성" 버튼 클릭
- 설정 입력:
- 생성할 리소스: "VPC만" 선택
- 이름 태그:
ShopEasy-VPC - IPv4 CIDR 블록: "IPv4 CIDR 수동 입력" 선택
- IPv4 CIDR:
10.0.0.0/16 - IPv6 CIDR 블록: "IPv6 CIDR 블록 없음" (기본값)
- 테넌시: "기본값" (기본값)
- "VPC 생성" 버튼 클릭
- VPC ID가 생성되었는지 확인 (예:
vpc-0abc1234def56789)
"VPC 등" 옵션을 선택하면 서브넷, IGW, NAT GW까지 한 번에 만들어져서 학습 효과가 떨어집니다. 반드시 "VPC만"을 선택하도록 안내하세요.
# 1. VPC 생성
aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=ShopEasy-VPC}]' \
--region ap-northeast-2
응답에서 VpcId를 확인하고, 이후 명령어에서 사용합니다.
# VPC ID를 변수에 저장 (이후 명령어에서 활용)
VPC_ID=$(aws ec2 describe-vpcs \
--filters "Name=tag:Name,Values=ShopEasy-VPC" \
--query "Vpcs[0].VpcId" \
--output text \
--region ap-northeast-2)
echo "VPC ID: $VPC_ID"
# DNS 호스트 이름 활성화 (EC2 인스턴스에 DNS 이름 부여)
aws ec2 modify-vpc-attribute \
--vpc-id $VPC_ID \
--enable-dns-hostnames '{"Value":true}' \
--region ap-northeast-2
해설
VPC는 AWS 계정 내에서 논리적으로 격리된 가상 네트워크입니다.
10.0.0.0/16 CIDR 블록은 RFC 1918 프라이빗 IP 주소 범위에 해당하며,
65,536개의 IP 주소를 제공합니다. 이는 여러 서브넷을 생성하고 리소스를 배치하기에 충분한 크기입니다.
VPC 생성 시 자동으로 기본 라우트 테이블, 기본 NACL, 기본 보안 그룹이 함께 생성됩니다. 하지만 우리는 명시적으로 라우트 테이블을 생성하여 사용할 것입니다.
Step 2: 퍼블릭 서브넷 2개 생성
정답
- VPC 대시보드 왼쪽 메뉴에서 "서브넷" 클릭
- "서브넷 생성" 버튼 클릭
- VPC 선택:
ShopEasy-VPC - 첫 번째 서브넷 설정:
- 서브넷 이름:
ShopEasy-Public-A - 가용 영역:
ap-northeast-2a - IPv4 서브넷 CIDR 블록:
10.0.1.0/24
- 서브넷 이름:
- "새 서브넷 추가" 버튼 클릭
- 두 번째 서브넷 설정:
- 서브넷 이름:
ShopEasy-Public-C - 가용 영역:
ap-northeast-2c - IPv4 서브넷 CIDR 블록:
10.0.2.0/24
- 서브넷 이름:
- "서브넷 생성" 버튼 클릭
퍼블릭 IP 자동 할당 활성화
- 서브넷 목록에서 ShopEasy-Public-A 체크박스 선택
- 상단 "작업" 드롭다운 → "서브넷 설정 편집"
- "퍼블릭 IPv4 주소 자동 할당 활성화" 체크
- "저장" 클릭
- ShopEasy-Public-C도 동일하게 반복
# 퍼블릭 서브넷 A 생성
SUBNET_PUB_A=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--availability-zone ap-northeast-2a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=ShopEasy-Public-A}]' \
--query 'Subnet.SubnetId' \
--output text \
--region ap-northeast-2)
echo "Public Subnet A: $SUBNET_PUB_A"
# 퍼블릭 서브넷 C 생성
SUBNET_PUB_C=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.2.0/24 \
--availability-zone ap-northeast-2c \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=ShopEasy-Public-C}]' \
--query 'Subnet.SubnetId' \
--output text \
--region ap-northeast-2)
echo "Public Subnet C: $SUBNET_PUB_C"
# 퍼블릭 IP 자동 할당 활성화
aws ec2 modify-subnet-attribute \
--subnet-id $SUBNET_PUB_A \
--map-public-ip-on-launch \
--region ap-northeast-2
aws ec2 modify-subnet-attribute \
--subnet-id $SUBNET_PUB_C \
--map-public-ip-on-launch \
--region ap-northeast-2
해설
서브넷을 두 개의 가용 영역(AZ-a, AZ-c)에 분산 배치하는 이유는 고가용성입니다. AWS의 가용 영역은 물리적으로 분리된 데이터센터 그룹이므로, 한 AZ에 장애가 발생해도 다른 AZ에서 서비스를 계속할 수 있습니다.
"퍼블릭 IPv4 주소 자동 할당"을 활성화하면, 이 서브넷에 생성되는 EC2 인스턴스가 자동으로 공인 IP 주소를 받습니다. 이 설정을 하지 않으면 인스턴스에 수동으로 탄력적 IP(EIP)를 할당해야 합니다.
- 퍼블릭 IP 자동 할당을 잊는 경우가 많습니다. Chapter 02에서 EC2 생성 시 공인 IP가 없으면 접속이 불가합니다.
- CIDR 블록이 VPC 범위(10.0.0.0/16)를 벗어나면 오류가 발생합니다.
- 같은 AZ에 두 서브넷을 모두 만드는 실수가 있습니다. AZ를 꼭 확인시키세요.
Step 3: 프라이빗 서브넷 2개 생성
정답
- VPC 대시보드 → "서브넷" → "서브넷 생성"
- VPC 선택:
ShopEasy-VPC - 첫 번째 서브넷 설정:
- 서브넷 이름:
ShopEasy-Private-A - 가용 영역:
ap-northeast-2a - IPv4 서브넷 CIDR 블록:
10.0.100.0/24
- 서브넷 이름:
- "새 서브넷 추가" 클릭
- 두 번째 서브넷 설정:
- 서브넷 이름:
ShopEasy-Private-C - 가용 영역:
ap-northeast-2c - IPv4 서브넷 CIDR 블록:
10.0.101.0/24
- 서브넷 이름:
- "서브넷 생성" 클릭
프라이빗 서브넷의 리소스는 공인 IP가 필요 없으므로, "퍼블릭 IPv4 주소 자동 할당"을 활성화하지 않습니다. 기본값(비활성화)을 그대로 두세요.
# 프라이빗 서브넷 A 생성
SUBNET_PRIV_A=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.100.0/24 \
--availability-zone ap-northeast-2a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=ShopEasy-Private-A}]' \
--query 'Subnet.SubnetId' \
--output text \
--region ap-northeast-2)
echo "Private Subnet A: $SUBNET_PRIV_A"
# 프라이빗 서브넷 C 생성
SUBNET_PRIV_C=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.101.0/24 \
--availability-zone ap-northeast-2c \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=ShopEasy-Private-C}]' \
--query 'Subnet.SubnetId' \
--output text \
--region ap-northeast-2)
echo "Private Subnet C: $SUBNET_PRIV_C"
해설
프라이빗 서브넷의 CIDR을 100번대(10.0.100.0/24, 10.0.101.0/24)로 설정한 것은
네이밍 컨벤션입니다. 퍼블릭은 1~99번대, 프라이빗은 100번대 이상을 사용하면
IP 주소만 보고도 네트워크 유형을 즉시 파악할 수 있어 운영 및 디버깅이 편리합니다.
RDS는 DB 서브넷 그룹 생성 시 최소 2개의 AZ에 걸친 서브넷을 요구합니다. Chapter 03에서 RDS를 생성할 때 이 두 프라이빗 서브넷을 사용합니다.
Step 4: 인터넷 게이트웨이 생성 및 VPC에 연결
정답
4-1. 인터넷 게이트웨이 생성
- VPC 대시보드 왼쪽 메뉴 → "인터넷 게이트웨이"
- "인터넷 게이트웨이 생성" 버튼 클릭
- 이름 태그:
ShopEasy-IGW - "인터넷 게이트웨이 생성" 클릭
4-2. VPC에 연결
- 생성 완료 후 상단에 표시되는 초록색 배너의 "VPC에 연결" 링크 클릭
(또는 IGW 선택 → 작업 → "VPC에 연결") - 사용 가능한 VPC:
ShopEasy-VPC선택 - "인터넷 게이트웨이 연결" 클릭
- 상태가 "Attached"로 변경되었는지 확인
# 인터넷 게이트웨이 생성
IGW_ID=$(aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=ShopEasy-IGW}]' \
--query 'InternetGateway.InternetGatewayId' \
--output text \
--region ap-northeast-2)
echo "IGW ID: $IGW_ID"
# VPC에 인터넷 게이트웨이 연결
aws ec2 attach-internet-gateway \
--internet-gateway-id $IGW_ID \
--vpc-id $VPC_ID \
--region ap-northeast-2
echo "IGW $IGW_ID attached to VPC $VPC_ID"
해설
인터넷 게이트웨이는 VPC당 1개만 연결할 수 있습니다. 이미 다른 VPC에 연결된 IGW를 사용하려 하면 오류가 발생합니다.
IGW는 네트워크 주소 변환(NAT)을 수행합니다: VPC 내부의 프라이빗 IP를 퍼블릭 IP로 변환하여 인터넷과 통신합니다. 이 과정은 자동으로 처리됩니다.
IGW를 생성하고 VPC에 연결했다고 해서 바로 인터넷이 되는 것은 아닙니다. 라우트 테이블에 IGW로의 경로를 추가해야 비로소 해당 서브넷이 인터넷에 연결됩니다. (Step 6에서 수행)
Step 5: NAT Gateway 생성
정답
- VPC 대시보드 왼쪽 메뉴 → "NAT 게이트웨이"
- "NAT 게이트웨이 생성" 버튼 클릭
- 설정 입력:
- 이름:
ShopEasy-NAT - 서브넷:
ShopEasy-Public-A(반드시 퍼블릭 서브넷!) - 연결 유형:
퍼블릭(기본값) - 탄력적 IP 할당 ID: "탄력적 IP 할당" 버튼 클릭 (새 EIP 자동 생성)
- 이름:
- "NAT 게이트웨이 생성" 클릭
- 상태가 "Pending"에서 "Available"로 변경될 때까지 대기 (약 2~3분)
NAT Gateway의 상태가 "Available"이 된 후에 Step 7의 프라이빗 라우트 테이블을 설정해야 합니다. "Pending" 상태에서도 라우트 추가는 가능하지만, 트래픽이 정상적으로 흐르지 않습니다.
# 탄력적 IP 할당
EIP_ALLOC=$(aws ec2 allocate-address \
--domain vpc \
--tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=Name,Value=ShopEasy-NAT-EIP}]' \
--query 'AllocationId' \
--output text \
--region ap-northeast-2)
echo "Elastic IP Allocation ID: $EIP_ALLOC"
# NAT Gateway 생성 (퍼블릭 서브넷 A에 배치)
NAT_GW_ID=$(aws ec2 create-nat-gateway \
--subnet-id $SUBNET_PUB_A \
--allocation-id $EIP_ALLOC \
--tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=ShopEasy-NAT}]' \
--query 'NatGateway.NatGatewayId' \
--output text \
--region ap-northeast-2)
echo "NAT Gateway ID: $NAT_GW_ID"
# NAT Gateway가 Available 상태가 될 때까지 대기
aws ec2 wait nat-gateway-available \
--nat-gateway-ids $NAT_GW_ID \
--region ap-northeast-2
echo "NAT Gateway is now available!"
해설
NAT(Network Address Translation) Gateway는 프라이빗 서브넷의 리소스가 인터넷에 아웃바운드 연결을 할 수 있게 해줍니다. 하지만 인터넷에서 NAT Gateway를 통해 프라이빗 서브넷으로 인바운드 연결을 시작하는 것은 불가능합니다.
NAT Gateway를 퍼블릭 서브넷에 배치하는 이유: NAT Gateway 자체가 인터넷과 통신해야 프라이빗 서브넷의 트래픽을 중계할 수 있기 때문입니다. 퍼블릭 서브넷은 IGW 경로가 있으므로 NAT Gateway가 인터넷에 접근할 수 있습니다.
학생들에게 반드시 NAT Gateway의 비용을 안내하세요:
- 시간당 $0.059 (서울 리전 기준)
- 처리 데이터 GB당 $0.059
- 월 상시 가동 시 약 $43 (데이터 전송 제외)
- 탄력적 IP는 NAT GW에 연결되어 있는 동안 무료, NAT GW 삭제 후 미해제 시 과금
실습 종료 후 NAT Gateway 삭제 → 탄력적 IP 해제 순서로 정리해야 합니다.
Step 6: 퍼블릭 라우트 테이블 생성 및 설정
정답
6-1. 라우트 테이블 생성
- VPC 대시보드 왼쪽 메뉴 → "라우트 테이블"
- "라우트 테이블 생성" 버튼 클릭
- 설정:
- 이름:
ShopEasy-Public-RT - VPC:
ShopEasy-VPC
- 이름:
- "라우트 테이블 생성" 클릭
6-2. 인터넷 라우트 추가
- 생성된 ShopEasy-Public-RT 선택
- 하단의 "라우트" 탭 클릭
- "라우트 편집" 버튼 클릭
- "라우트 추가" 버튼 클릭
- 설정:
- 대상:
0.0.0.0/0 - 대상: "인터넷 게이트웨이" 선택 →
ShopEasy-IGW
- 대상:
- "변경 사항 저장" 클릭
6-3. 퍼블릭 서브넷 연결
- ShopEasy-Public-RT 선택 상태에서 "서브넷 연결" 탭 클릭
- "서브넷 연결 편집" 클릭
- ShopEasy-Public-A와 ShopEasy-Public-C 체크
- "연결 저장" 클릭
# 퍼블릭 라우트 테이블 생성
PUB_RT_ID=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=ShopEasy-Public-RT}]' \
--query 'RouteTable.RouteTableId' \
--output text \
--region ap-northeast-2)
echo "Public Route Table ID: $PUB_RT_ID"
# 인터넷 게이트웨이로의 라우트 추가
aws ec2 create-route \
--route-table-id $PUB_RT_ID \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id $IGW_ID \
--region ap-northeast-2
# 퍼블릭 서브넷 2개를 라우트 테이블에 연결
aws ec2 associate-route-table \
--route-table-id $PUB_RT_ID \
--subnet-id $SUBNET_PUB_A \
--region ap-northeast-2
aws ec2 associate-route-table \
--route-table-id $PUB_RT_ID \
--subnet-id $SUBNET_PUB_C \
--region ap-northeast-2
echo "Public subnets associated with Public RT"
해설
라우트 테이블은 서브넷에서 나가는 트래픽의 경로를 결정합니다.
VPC 생성 시 자동으로 만들어진 기본(Main) 라우트 테이블에는
10.0.0.0/16 → local 라우트만 있어 VPC 내부 통신만 가능합니다.
우리가 추가한 0.0.0.0/0 → IGW 라우트는
"VPC 내부가 아닌 모든 목적지로의 트래픽은 인터넷 게이트웨이로 보내라"는 의미입니다.
이 라우트가 연결된 서브넷이 바로 "퍼블릭 서브넷"이 됩니다.
트래픽의 목적지가 10.0.100.5라면:
10.0.0.0/16(local) - 매칭됨! (/16 = 16비트 일치)0.0.0.0/0(IGW) - 매칭됨! (/0 = 0비트 일치)
더 구체적인(긴 접두사) 규칙이 우선하므로 /16 > /0,
따라서 local 라우트가 적용됩니다. VPC 내부 트래픽은 IGW를 거치지 않습니다.
Step 7: 프라이빗 라우트 테이블 생성 및 설정
정답
7-1. 라우트 테이블 생성
- VPC 대시보드 → "라우트 테이블" → "라우트 테이블 생성"
- 설정:
- 이름:
ShopEasy-Private-RT - VPC:
ShopEasy-VPC
- 이름:
- "라우트 테이블 생성" 클릭
7-2. NAT Gateway 라우트 추가
- 생성된 ShopEasy-Private-RT 선택
- 하단의 "라우트" 탭 → "라우트 편집"
- "라우트 추가" 클릭
- 설정:
- 대상:
0.0.0.0/0 - 대상: "NAT 게이트웨이" 선택 →
ShopEasy-NAT
- 대상:
- "변경 사항 저장" 클릭
7-3. 프라이빗 서브넷 연결
- ShopEasy-Private-RT 선택 → "서브넷 연결" 탭
- "서브넷 연결 편집" 클릭
- ShopEasy-Private-A와 ShopEasy-Private-C 체크
- "연결 저장" 클릭
# 프라이빗 라우트 테이블 생성
PRIV_RT_ID=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=ShopEasy-Private-RT}]' \
--query 'RouteTable.RouteTableId' \
--output text \
--region ap-northeast-2)
echo "Private Route Table ID: $PRIV_RT_ID"
# NAT Gateway로의 라우트 추가
aws ec2 create-route \
--route-table-id $PRIV_RT_ID \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id $NAT_GW_ID \
--region ap-northeast-2
# 프라이빗 서브넷 2개를 라우트 테이블에 연결
aws ec2 associate-route-table \
--route-table-id $PRIV_RT_ID \
--subnet-id $SUBNET_PRIV_A \
--region ap-northeast-2
aws ec2 associate-route-table \
--route-table-id $PRIV_RT_ID \
--subnet-id $SUBNET_PRIV_C \
--region ap-northeast-2
echo "Private subnets associated with Private RT"
해설
프라이빗 라우트 테이블의 0.0.0.0/0 → NAT Gateway 라우트는
프라이빗 서브넷의 리소스가 인터넷으로 나가는 것만 허용합니다.
NAT Gateway가 출발지 IP를 자신의 탄력적 IP로 변환(SNAT)하므로,
외부에서는 요청의 원래 출발지(프라이빗 IP)를 알 수 없습니다.
이 설정이 완료되면, 프라이빗 서브넷의 RDS가 OS 패치나 소프트웨어 업데이트를 인터넷에서 다운로드할 수 있습니다. 하지만 인터넷에서 프라이빗 서브넷의 리소스에 직접 접속하는 것은 여전히 불가능합니다.
검증 스크립트
학생들의 실습 결과를 한 번에 확인할 수 있는 스크립트입니다:
전체 리소스 확인 스크립트
#!/bin/bash
# ShopEasy VPC 네트워크 검증 스크립트
REGION="ap-northeast-2"
echo "========================================="
echo " ShopEasy VPC 네트워크 검증"
echo "========================================="
# 1. VPC 확인
echo ""
echo "[1] VPC 확인"
VPC_ID=$(aws ec2 describe-vpcs \
--filters "Name=tag:Name,Values=ShopEasy-VPC" \
--query "Vpcs[0].VpcId" \
--output text --region $REGION)
if [ "$VPC_ID" = "None" ] || [ -z "$VPC_ID" ]; then
echo " [FAIL] ShopEasy-VPC가 존재하지 않습니다!"
exit 1
else
CIDR=$(aws ec2 describe-vpcs --vpc-ids $VPC_ID \
--query "Vpcs[0].CidrBlock" --output text --region $REGION)
echo " [OK] VPC: $VPC_ID (CIDR: $CIDR)"
fi
# 2. 서브넷 확인
echo ""
echo "[2] 서브넷 확인"
for SUBNET_NAME in ShopEasy-Public-A ShopEasy-Public-C ShopEasy-Private-A ShopEasy-Private-C; do
SUBNET_ID=$(aws ec2 describe-subnets \
--filters "Name=tag:Name,Values=$SUBNET_NAME" "Name=vpc-id,Values=$VPC_ID" \
--query "Subnets[0].SubnetId" --output text --region $REGION)
SUBNET_CIDR=$(aws ec2 describe-subnets --subnet-ids $SUBNET_ID \
--query "Subnets[0].CidrBlock" --output text --region $REGION 2>/dev/null)
SUBNET_AZ=$(aws ec2 describe-subnets --subnet-ids $SUBNET_ID \
--query "Subnets[0].AvailabilityZone" --output text --region $REGION 2>/dev/null)
if [ "$SUBNET_ID" = "None" ] || [ -z "$SUBNET_ID" ]; then
echo " [FAIL] $SUBNET_NAME 없음"
else
echo " [OK] $SUBNET_NAME: $SUBNET_ID ($SUBNET_CIDR, $SUBNET_AZ)"
fi
done
# 3. 퍼블릭 서브넷 자동 IP 할당 확인
echo ""
echo "[3] 퍼블릭 IP 자동 할당 확인"
for SUBNET_NAME in ShopEasy-Public-A ShopEasy-Public-C; do
SUBNET_ID=$(aws ec2 describe-subnets \
--filters "Name=tag:Name,Values=$SUBNET_NAME" "Name=vpc-id,Values=$VPC_ID" \
--query "Subnets[0].SubnetId" --output text --region $REGION)
AUTO_IP=$(aws ec2 describe-subnets --subnet-ids $SUBNET_ID \
--query "Subnets[0].MapPublicIpOnLaunch" --output text --region $REGION 2>/dev/null)
if [ "$AUTO_IP" = "True" ]; then
echo " [OK] $SUBNET_NAME: 자동 IP 할당 활성화"
else
echo " [WARN] $SUBNET_NAME: 자동 IP 할당 비활성화!"
fi
done
# 4. 인터넷 게이트웨이 확인
echo ""
echo "[4] 인터넷 게이트웨이 확인"
IGW_ID=$(aws ec2 describe-internet-gateways \
--filters "Name=tag:Name,Values=ShopEasy-IGW" "Name=attachment.vpc-id,Values=$VPC_ID" \
--query "InternetGateways[0].InternetGatewayId" --output text --region $REGION)
if [ "$IGW_ID" = "None" ] || [ -z "$IGW_ID" ]; then
echo " [FAIL] ShopEasy-IGW가 VPC에 연결되지 않았습니다!"
else
echo " [OK] IGW: $IGW_ID (VPC에 연결됨)"
fi
# 5. NAT Gateway 확인
echo ""
echo "[5] NAT Gateway 확인"
NAT_ID=$(aws ec2 describe-nat-gateways \
--filter "Name=tag:Name,Values=ShopEasy-NAT" "Name=state,Values=available" \
--query "NatGateways[0].NatGatewayId" --output text --region $REGION)
if [ "$NAT_ID" = "None" ] || [ -z "$NAT_ID" ]; then
echo " [FAIL] ShopEasy-NAT가 Available 상태가 아닙니다!"
else
NAT_SUBNET=$(aws ec2 describe-nat-gateways --nat-gateway-ids $NAT_ID \
--query "NatGateways[0].SubnetId" --output text --region $REGION)
echo " [OK] NAT GW: $NAT_ID (서브넷: $NAT_SUBNET)"
fi
# 6. 라우트 테이블 확인
echo ""
echo "[6] 라우트 테이블 확인"
for RT_NAME in ShopEasy-Public-RT ShopEasy-Private-RT; do
RT_ID=$(aws ec2 describe-route-tables \
--filters "Name=tag:Name,Values=$RT_NAME" "Name=vpc-id,Values=$VPC_ID" \
--query "RouteTables[0].RouteTableId" --output text --region $REGION)
if [ "$RT_ID" = "None" ] || [ -z "$RT_ID" ]; then
echo " [FAIL] $RT_NAME 없음"
else
ROUTES=$(aws ec2 describe-route-tables --route-table-ids $RT_ID \
--query "RouteTables[0].Routes[?DestinationCidrBlock=='0.0.0.0/0'].{Target:GatewayId||NatGatewayId}" \
--output text --region $REGION)
ASSOC_COUNT=$(aws ec2 describe-route-tables --route-table-ids $RT_ID \
--query "length(RouteTables[0].Associations[?!Main])" --output text --region $REGION)
echo " [OK] $RT_NAME: $RT_ID (0.0.0.0/0 -> $ROUTES, 서브넷 ${ASSOC_COUNT}개 연결)"
fi
done
echo ""
echo "========================================="
echo " 검증 완료!"
echo "========================================="
트러블슈팅
자주 발생하는 문제 & 해결 방법
AWS 계정에는 리전당 VPC 생성 제한이 있습니다 (기본 5개). 해결: 사용하지 않는 VPC를 삭제하거나, AWS Support에 한도 증가를 요청합니다. 기본 VPC를 삭제하지 않도록 주의하세요.
같은 VPC 내에서 서브넷 CIDR 블록이 겹치면 생성할 수 없습니다. 해결: 이미 생성된 서브넷의 CIDR 블록을 확인하고 겹치지 않는 범위를 사용합니다. 잘못 만든 서브넷은 삭제 후 다시 생성하세요.
IGW가 이미 다른 VPC에 연결되어 있거나, 해당 VPC에 다른 IGW가 연결된 경우입니다. 해결: VPC당 IGW는 1개만 가능합니다. 기존 연결을 해제(Detach)하거나 새 IGW를 생성하세요.
계정당 탄력적 IP 수가 제한되어 있습니다 (기본 5개). 해결: 사용하지 않는 탄력적 IP를 해제(Release)합니다. EC2 → 네트워크 & 보안 → 탄력적 IP에서 확인할 수 있습니다.
NAT Gateway 생성에는 보통 2~3분이 소요됩니다. 5분 이상 Pending이면 문제가 있을 수 있습니다. 해결: NAT Gateway를 삭제하고 다시 생성합니다. 서브넷이 퍼블릭 서브넷인지, IGW가 VPC에 연결되어 있는지 확인하세요.
NAT Gateway가 아직 "Available" 상태가 아니거나, 다른 VPC의 NAT Gateway일 수 있습니다. 해결: NAT Gateway가 같은 VPC에 있는지, 상태가 "Available"인지 확인합니다. 올바른 NAT Gateway를 선택하세요.
모든 서브넷은 항상 하나의 라우트 테이블에 연결되어 있습니다. 명시적으로 연결하지 않으면 VPC의 기본(Main) 라우트 테이블에 암시적으로 연결됩니다. 해결: 이것은 정상입니다. 새 라우트 테이블에 연결하면 기존 연결이 자동으로 해제됩니다.
실습을 다른 리전에서 진행하면 이후 챕터와의 연결이 끊어집니다. 해결: AWS 콘솔 오른쪽 상단의 리전 선택기에서 "아시아 태평양 (서울)"을 선택합니다. 다른 리전에 만든 리소스는 삭제하세요.
강의 팁
- (10분) 건물 비유로 VPC 개념 설명 - 화이트보드에 건물 그림을 그리며 설명하면 효과적
- (5분) CIDR 표기법 간단 설명 - /16, /24 의 IP 개수만 이해하면 충분
- (5분) 아키텍처 다이어그램 설명 - 학생용 가이드의 다이어그램 활용
- (20분) 실습 진행 - 학생들이 직접 따라하도록 순회 지도
- (5분) 체크리스트로 결과 확인 - 빠진 설정이 없는지 점검
- "기본 VPC랑 뭐가 다른가요?" - 기본 VPC는 AWS가 자동 생성한 것으로, 실습에는 우리가 직접 만든 VPC를 사용해야 구조를 이해할 수 있습니다.
- "VPC 등으로 한 번에 만들면 안 되나요?" - 가능하지만, 하나씩 만들어야 각 리소스의 역할과 관계를 이해할 수 있습니다.
- "NAT Gateway 없으면 어떻게 되나요?" - 프라이빗 서브넷의 리소스가 인터넷에 접근할 수 없습니다. 패키지 업데이트 등이 불가합니다.
- "서브넷이 왜 2개씩 필요한가요?" - RDS, ALB 등이 최소 2개 AZ를 요구합니다. 한 AZ 장애 시 서비스 연속성을 위함입니다.
- 학생들이 "VPC 등" 옵션으로 한 번에 만들지 않도록 미리 안내
- NAT Gateway 생성에 시간이 걸리므로, 대기 시간 동안 개념 복습 진행
- 퍼블릭 서브넷의 자동 IP 할당을 빠뜨리지 않도록 강조
- 라우트 테이블에서 퍼블릭 RT의 타겟이 IGW인지, 프라이빗 RT의 타겟이 NAT GW인지 혼동하지 않도록 주의