그동안 프로젝트를 진행하면서 가장 어렵고 다가가기 두려웠던게 바로 AWS 였습니다. 인프라쪽 작업을 할때면 블로그를 참고해 시키는것만 따라했지 보안그룹, VPC, 라우팅 테이블.. 어렵고 복잡한 개념으로 다가와 이번기회에 AWS 네트워크 설계부터 다양한 기능들을 이용해보려 합니다.
AWS 네트워크 아키텍처

VPC
먼저, VPC 입니다. VPC 는 AWS 안에 만드는 독립적인 가상 네트워크 공간 입니다. VPC 는 다른 AWS 사용자의 리소스와 완전히 분리하고 IP 대역, 라우팅, 보안등을 직접 설계가 가능합니다. 뿐만 아니라 RDS, EC2 등을 만들때 반드시 필요합니다.
이때 인터넷 게이트 웨이(IGW) 를 VPC 에 연결해줘야 정상적으로 인터넷 -> VPC 또는 VPC -> 인터넷 으로 접속이 가능합니다. 즉 IGW 가 없으면 인터넷과 VPC 가 연결될 수 없기에 반드시 설정해줘야 합니다.
서브넷
서브넷은 VPC를 더 작은 네트워크 단위로 나눈겁니다. 이때 3-Tier 아키텍처를 기반으로 설계할건데, 3-Tier 아키텍처는 프레젠테이션 계층, 애플리케이션 계층, 데이터베이스 계층으로 나눈 아키텍처입니다.
쉽게 말하면 ALB, NAT 등을 할당하는 public(프렌젠테이션) 계층, private(내부 애플리케이션) 계층, DB 계층으로 나눠 각 계층별로 서로 다른 보안그룹을 설정함으로써 강한 보안을 유지할 수 있습니다.
fl-public-subent-a : 10.0.1.0/24
fl-public-subent-c : 10.0.2.0/24
fl-private-subent-a : 10.0.10.0/24
fl-db-subnet-a : 10.0.100.0/24
fl-db-subnet-a : 10.0.200.0/24
3-Tier 아키텍처란?
총 3개의 계층으루 구성된 구조 입니다.
각 계층은 보통 다음과 같이 구성됩니다.
Web Tier -> ALB, Web Server (Nginx 등)
App Tier -> EC2/ECS/Lambda 등 애플리케이션 서버
DB Tier -> RDS, Auror 등 데이터 베이스
라우팅 테이블
라우팅 테이블은 네트워크 트래픽이 어디서 어디로 가야 하는지 정의하는 규칙표 입니다. public 서브넷 라우팅 테이블은 인터넷과 직접 통신이 필요하기 때문에 라우팅 테이블 대상이 IGW(인터넷 게이트 웨이) 로 반드시 설정되어 있어야 합니다.
private 서브넷 라우팅 테이블은 인터넷은 필요하지만 직접 노출되지 않기 때문에 NAT Instance 를 대상으로 설정되어 있어야 합니다. (NAT 관련 설명은 아래에서)
NAT 생성
AWS 네트워크를 설계할때 NAT 사용은 사실상 필수입니다. 보안상 서버들을 외부에서 접근할 수 없고 확인할 수 없도록 해야하기 때문입니다. 그래서 VPC 인프라를 구축할때 public 서브넷, private 서브넷을 각각 만들어 그 안에 EC2 인스턴스를 두고, Bastion Host 를 통해 public 서브넷에서 private 서브넷으로 접속한 후 NAT Gateway 를 통해서 외부 인터넷 소스를 사설망에서 받는 식으로 운용됩니다.
AWS 에서는 NAT Gateway 라는걸 손쉽게 만들고 관리할 수 있게 도와주는데,, 이게 비용이 엄청납니다. 서울리전 기준으로 한시간에 0.06$ 정도가 발생합니다.
그래서 EC2 를 이용해 NAT Gateway 역할을 하는 인스턴스를 만들어 대체한다면 비용적인 측면에서 많은 이점을 가져올 수 있습니다. 하지만, NAT Gateway에 비해 가용성이 많이 떨어진다는 단점이 있지만,, 새로운 서비스를 만들고 시작하기에는 합리적인 방법이라 생각해 NAT 인스턴스를 만들어 운영해보려 합니다.
ALB(Application Load Balancer)
ALB 는 들어오는 트래픽을 여러 대상(EC2)에 분산하고, 애플리케이션 계층에서 동작하는 로드밸런서 입니다. 여러 대상에 분산할 수 있다고 말했지만, 저는 EC2 안에 api 서버와 admin 서버를 같이 띄워 포트만 다르게 설정했습니다. (아직 규모가 크지 않아 EC2 하나로 충분히 운영 가능)
ALB 에 리스너 규칙을 직접 지정할 수 있는데, 저는 경로 기반으로 아래와 같이 라우팅 규칙을 지정했습니다.
/api/* -> EC2:8080(API 서버)
/admin/* -> EC2:8080(API 서버)

ALB 를 사용한 이유는 EC2 가 인터넷에 직접 노출되지 않게 막고, DDoS 와 같은 공격도 ALB 가 1차적으로 막아줄 수 있습니다. 뿐만 아니라 EC2가 죽으면 자동으로 트래픽을 차단하고 복구되면 자동으로 트래픽을 재개 합니다.
Private EC2 접속 방법
private EC2 에 도커 이미지가 잘 띄워졌는지, 또는 로그를 직접 확인하기 위해서는 직접 접근해야 합니다. 원래는 인바운드 규칙에 내 컴퓨터 IP 를 추가해 확인했었는데, 현재 구조로는 불가능합니다. ALB 를 통해서만 private EC2에 접근이 가능하기 때문이죠.
그래서 어떤 방법이 있나 찾아보니 SSM(AWS System Manager) 에서 제공하는 Fleet Manager 를 통해 접근할 수 있습니다. SSM 은 외부에서 EC2 로 들어가는 방식이 아니라, EC2 가 AWS 로 나가는 방식으로 연결됩니다.
AWS Console -> AWS System Manager <- private EC2
여기서 중요한점은 SSH 포트(22) 를 사용하지 않고, 인바운드 보안그룹도 필요 없습니다. EC2 가 아웃바운드로 AWS SSM 서버에 연결하고, 우리는 그 연결을 통해 다양한 명령어를 실행하고 접근할 수 있습니다.
사용자 요청 흐름
1. 사용자가 https://funnyrun.com/api/games 요청
2. DNS → ALB의 공인 IP로 연결
3. ALB가 HTTPS 복호화
4. ALB가 EC2:8080으로 HTTP 요청 전달
5. EC2가 RDS에 쿼리
6. 응답을 역순으로 반환
API 용 EC2 외부 통신 흐름
1. EC2가 docker pull 요청
2. Private Subnet → NAT Instance로 라우팅
3. NAT Instance가 IP 변환 후 Internet Gateway로
4. 인터넷에서 응답
5. 역순으로 EC2에 전달
정리해보면, API 도커 이미지를 실행 중인 EC2는 퍼블릭 인터넷에 직접 노출되지 않으며, 오직 ALB를 통해서만 외부에서 접근이 가능합니다. 또한 해당 EC2가 외부 API 호출, 패키지 다운로드 등 아웃바운드 인터넷 통신이 필요한 경우에는 NAT Instance를 통해서만 외부 인터넷에 접근하도록 구성됩니다. 이와 같은 구조를 통해 EC2는
- 인바운드 트래픽은 ALB로 제한하고
- 아웃바운드 트래픽은 NAT Instance를 경유한 경우에만 허용함으로써
외부로부터의 직접적인 접근을 차단하면서도 필요한 통신만 허용하는 보안성과 통제력이 강화된 네트워크 환경을 구성할 수 있습니다.
추후 개선 방향
현재 하나의 private EC2 안에 총 3개의 도커 이미지(api, admin, redis) 를 띄우고 있습니다. CPU 사용률이 크게 튀지 않아 당장은 auto scaling 이 필요 없다 판단했습니다. 하지만 추후 auto scaling 을 통해 인스턴스를 늘려야 하는 상황이 온다면, 각각 도커 이미지를 띄우도록 인스턴스를 분리해야 할 것 같습니다.
'Devops' 카테고리의 다른 글
| [AWS] ELB 정리 (0) | 2026.01.19 |
|---|---|
| 이벤트 기반 아키텍처(EDA) 도입기 (0) | 2025.12.26 |
| ElasticSearch 를 EC2 에서 실행하기 (0) | 2025.04.27 |
| [Devops] GitHub Container Registry 를 사용한 협업 방법 (2) | 2025.03.16 |
| [Devops] Docker Compose 를 활용한 Redis Ec2 배포 (0) | 2025.01.18 |