https://claude.ai/public/artifacts/d3a9a17c-2daa-4621-91c1-fbc4db36c321

| VPC | - |
|---|---|
| IPv4 CIDR | 10.0.0.0/16 |
| 리전 | us-east-2(오하이오) |
| 역할 | 모든 AWS 리소스를 논리적으로 격리하는 가상 네트워크. 서브넷, 라우팅 테이블, 보안 그룹의 기반 단위 |
예시 1: 스타트업이 하나의 서비스를 운영하는 경우
신규 쇼핑몰 서비스를 론칭하는 스타트업이 있다고 가정한다. 이 회사는 아직 서비스가 하나뿐이므로 VPC 1개(10.0.0.0/16)를 생성하고, 이 안에 WEB/WAS/DB 서브넷을 배치한다. 개발 환경과 운영 환경을 분리하고 싶다면, 개발용 VPC(10.1.0.0/16)를 별도로 만들어 *VPC Peering으로 연결할 수 있다. 이렇게 하게 되면 개발자가 실수로 운영 DB에 접근하는 사고를 네트워크 레벨에서 차단할 수 있다.
예시 2: 중견 기업이 여러 서비스를 운영하는 경우
한 기업이 쇼핑몰, 사내 ERP, 고객 DRM 세 가지 시스템을 운영한다면, 각 시스템별로 별도 VPC를 생성하는 것이 권장된다. 쇼핑몰 VPC(10.0.0.0/16), ERP VPC(10.1.0.0/16), CRM VPC(10.2.0.0/16)로 분리하면 한 시스템에 침해 사고를 당해도 다른 시스템으로의 Lateral Movement를 방지할 수 있다. 시스템 간 통신이 필요하다면 *AWS Transit Gateway를 통해 허용된 트래픽만 선별적으로 통과시킨다.
*VPC Peering :
*AWS Transit Gateway :
예시 1: 블랙프라이데이 세일 기간의 쇼핑몰
대규모 할인 이벤트 기간에 한쪽 AZ(us-east-2a)의 데이터센터에 물리적 장애가 발생했다고 가정한다. 2개 AZ에 서브넷이 분산되어 있으므로, us-east-2c의 web-sub-2에 있는 Apache 서버와 was-sub-2의 Tomcat 서버가 즉시 모든 트래픽을 처리한다. 고객은 서비스 중단을 체감하지 못하고 주문을 계속 진행할 수 있다. 만일 단일 AZ에만 배치했다면 그 AZ 장애 시 전체 서비스가 다운된다.
예시 2: 금융 규제를 받는 핀테크 서비스
금융 서비스에서는 규제 기관이 "결제 처리 서버는 인터넷에서 직접 접근할 수 없어야 한다"는 요건을 요구한다. 이 경우 WAS를 프라이빗 서브넷(was-sub-1/2)에 배치하고, DB를 별도 프라이빗 서브넷(rds-sub-1/2)에 배치하여 인터넷 라우팅 경로를 완전히 차단한다. 감사(Audit) 시 "WAS가 DB가 프라이빗 서브넷에 있고, 라우팅 테이블에 인터넷 경로가 없음"을 증적으로 제출할 수 있어 규제 준수를 입증할 수 있다.
| 서브넷 이름 | IPv4 CIDR | 가용영역 | 유형 | 역할 |
|---|---|---|---|---|
| web-sub-1 | 10.0.0.0/24 | us-east-2a | Public | 웹 서버(Apache) 배치, ALB 연결 |
| web-sub-2 | 10.0.1.0/24 | us-east-2c | Public | 웹 서버(Apache) 배치, ALB 연결 |
| was-sub-1 | 10.0.4.0/24 | us-east-2a | Private | WAS(Tomcat) 배치, NLB 연결 |
| was-sub-2 | 10.0.5.0/24 | us-east-2c | Private | WAS(Tomcat) 배치, NLB 연결 |
| rds-sub-1 | 10.0.8.0/24 | us-east-2a | Private | Oracle RDS 배치 |
| rds-sub-2 | 10.0.9.0/24 | us-east-2c | Private | Oracle RDS 배치 |
- 3-Tier 분리 설계: WEB(Public) → WAS(Private) → RDS(Private) 구조로 각 계층을 분리하여 보안성을 높임.
- 각 계층을 2개의 가용 영역(AZ)에 분산 배치하여 고가용성(HA) 확보.
퍼블릭 서브넷(web-sub-1/2)이 인터넷과 통신할 수 있도록 VPC에 연결하는 관문. VPC당 1개만 연결 가능.
예시 1: 글로벌 고객을 대상으로 하는 웹 서비스
전 세계 고객이 접속하는 쇼핑몰에서 IGW는 고객의 브라우저 요청이 VPC 내부의 ALB와 Apache 서버에 도달할 수 있는 유일한 진입점이다. IGW가 없으면 아무리 퍼블릭 IP를 할당해도 인터넷 트래픽이 VPC 안으로 들어올 수 없다. 중요한 점은, 프라이빗 서브넷(WAS, RDS)에는 IGW 경로가 없으므로 외부에서 WAS나 DB에 직접 접근하는 것은 불가능하다.
예시 2: 내부 전용 시스템에서의 IGW 제거
사내에서만 사용하는 ERP 시스템이라면 IGW 자체를 VPC에 연결하지 않고, *AWS Direct Connect나 VPN으로만 접근하도록 구성한다. 이렇게 하면 VPC 내 모든 서브넷이 프라이빗이 되어, 인터넷을 통한 공격 벡터를 원천적으로 제거할 수 있다.
*AWS Direct Connect:
예시 1: WAS 서버에 외부 API 호출이 필요한 경우
쇼핑몰의 WAS까 결제 대행사(PG) API를 호출해야 한다면, 프라이빗 서브넷의 WAS가 인터넷에 접근해야 한다. 이때 NAT Gateway를 퍼블릭 서브넷에 배치하고, pri-rt에 0.0.0.0/0 → NAT Gateway 경로를 추가한다. WAS는 NAT Gateway를 통해 외부 API를 호출할 수 있지만, 외부에서 WAS로의 직접 접근은 여전히 불가능하다. 현재 아키텍처에서는 NAT Gateway가 없으므로, WAS가 외부 API를 호출해야 하는 비즈니스 요건이 생기면 이를 추가해야 한다.
예시 2: 잘못된 라우팅으로 인한 보안 사고 방지
운영자가 실수로 pri-rt에 0.0.0.0/0 → IGW 경로를 추가하면, RDS가 배치된 프라이빗 서브넷이 사실상 퍼블릭 서브넷이 된다. DB가 인터넷에 노출되어 SQLi 등의 공격에 직접적으로 취약해질 수 있다. 이를 방지하기 위해 *AWS Config 규칙을 설정하여 "프라이빗 서브넷의 라우팅 테이블에 IGW 경로가 추가되면 즉시 알림"이 가도록 모니터링하는 것이 실무에서 권장된다.
*AWS Config:
pub-rt
- 퍼블릭 라우팅 테이블.
- 0.0.0.0/0 → IGW 경로를 추가하여 web-sub-1, web-sub-2에 연결.
- 인터넷 트래픽을 IGW로 전달.
pri-rt
- 프라이빗 라우팅 테이블.
- was-sub-1/2, rds-sub-1/2에 연결.
- 인터넷 경로 없음 → WAS/RDS를 외부 접근으로부터 보호.
예시 1: 쇼핑몰 메인 페이지 로딩 최적화
쇼핑몰 메인 페이지에 접속하면, 로고 이미지, CSS 파일, JavaScript 파일 등 정적 리소스가 약 30~50개 요청된다. Apache가 이 정적 파일들을 직접 서빙하고, 상품 목록 조회(동적 데이터)만 Tomcat으로 전달하면 WAS의 부하가 크게 줄어든다. 만약 Apache 없이 Tomcat이 모든 요청을 처리하면, 정적 파일 서빙에도 Java 스레드가 소모되어 동시 사용자 500명만 되어도 응답 지연이 발생할 수 있다. Apahce를 앞에 두면 동일 조건에서 2000명 이상을 처리 가능하다.
예시 2: Apache를 리버스 프록시로 활용한 보안 강화
외부 공격자가 Tomcat의 관리 콘솔(/manager)에 직접 접근하려는 시도가 빈번하다. Apache가 앞에 있으면, Apache의 VirtualHost 설정에서 /manager 경로에 대한 접근을 차단(Deny)하거나, mod_jk의 JkMount 설정에서 해당 경로를 프록시하지 않도록 제외할 수 있다. 이렇게 하면 Tomcat 관리 콘솔이 인터넷에서 완전히 은닉되어, Tomcat 취약점을 노린 공격을 사전에 차단한다.
| web-ec2 | - |
|---|---|
| AMI | Ubuntu Server 22.04 LTS (HVM) |
| 인스턴스 유형 | t3.micro |
| 키 페어 | web-key (.pem, RSA) |
| 서브넷 | web-sub-1 (10.0.0.0/24) |
| 보안 그룹 | web-sg |
| 퍼블릭 IP | 탄력적 IP 할당 (18.129.123.241) |
| 역할 | Apache2 웹 서버 운영. libapache2-mod-jk를 통해 WAS(Tomcat)에 AJP 프로토콜로 요청 프록시. Oracle Instant Client 설치로 DB 직접 접속 가능. |
| 설치 소프트웨어 | Apache2, libapache2-mod-jk, Oracle Instant Client 19.16, SQL*Plus |
예시 1: 쇼핑몰 주문 처리 흐름에서의 WAS 역할
고객이 "주문하기" 버튼을 클릭하면 다음 흐름이 발생한다. Apache가 HTTP 요청을 수신하고, mod_jk가 AJP로 Tomcat에 전달한다. Tomcat의 서블릿이 주문 정보를 검증(재고 확인, 가격 계산, 쿠폰 적용)하고, JDBC로 Oracle RDS에 INSERT 쿼리를 실행하여 주문 데이터를 저장한 뒤, 결과를 JSP 페이지로 렌더링하여 Apache를 통해 고객에게 반환된다. 이 모든 비즈니스 로직이 WAS에서 처리된다.
예시 2: Windows Server를 WAS로 선택한 상황과 고려사항
이 아키텍처에서는 WAS에 Windows Server 2019를 사용하고 있는데, 이는 Eclipse IDE를 GUI 환경에서 사용하여 개발/배포를 직접 수행하기 위한 선택이다. 실제 운영 환경에서는 Linux(Amazon Linux 2 또는 Ubuntu)를 사용하는 것이 일반적이다. Linux는 라이선스 비용이 없어 t3.medium 기준 Windows 대비 월 약 20~30% 비용이 절감되고, SSH를 통한 자동화(CI/CD 파이프라인, 스크립트 배포)가 훨씬 용이하다. 실무에서는 Jenkins나 CodeDeploy로 WAR 파일을 자동 배포하는 것이 표준이다.
| was-ec2 | - |
|---|---|
| AMI | Microsoft Windows Server 2019 Base |
| 인스턴스 유형 | t3.medium (2vCPU, 4GB RAM) |
| 키 페어 | was-key (.pem, RSA) |
| 서브넷 | was-sub-1 (10.0.4.0/24) |
| 보안 그룹 | was-sg |
| 접속 방법 | RDP (Port 3389) |
| 역할 | Apache Tomcat 9.0.12 위에서 Java EE 웹 애플리케이션(쇼핑몰) 운영. Eclipse로 ROOT.war 빌드 후 배포. |
| 설치 소프트웨어 | Apache Tomcat 9.0.12, JRE 1.8.0_202, Eclipse IDE for Enterprise Java, Chrome |
| 방화벽 개방 포트 | 8009(AJP), 8080(HTTP), 8443(HTTPS) |
WEB-WAS 연동 구성 (Apache mod_jk)
- worker.properties 설정
- worker.ajp13_worker.host=was-ec2 Private IP (→ 후에 NLB DNS로 교체), port=8009
- 000-default.conf 수정
- JKMount/* ajp13_worker 추가 → 모든 경로를 AJP로 Tomcat에 전달
- Auto Scaling 적용 후 NLB DNS로 교체
- worker.ajp13_worker.host=was-as-nlb DNS 이름 → NLB가 WAS 인스턴스로 부하 분산
예시 1: *Multi-AZ 페일오버 시 서브넷 그룹의 역할
rds-sub-gp에 rds-sub-1(us-east-2a)과 rds-sub-2(us-east-2c)가 포함되어 있으므로, Multi-AZ를 활성화하면 AWS는 Primary를 us-east-2a에, Standby를 us-east-2c에 자동 배치한다. us-east-2a에 장애가 발생하면 Standby가 Primary로 승격되고, RDS의 엔드포인트(DNS)가 자동으로 us-east-2c의 인스턴스를 가리키도록 변경된다. WAS는 엔드포인트(DNS)로 연결하므로 코드 변경없이 자동으로 새 Primary에 연결된다.
예시 2: 서브넷 그룹을 잘못 구성한 경우의 문제
만약 서브넷 그룹에 rds-sub-1(us-east-2a)만 포함하고 rds-sub-2를 빠뜨렸다면, Multi-AZ 활성화 시 AWS가 다른 AZ에서 Standby를 배치할 서브넷을 찾지 못해 생성에 실패한다. 또한, 서브넷 그룹에 퍼블릭 서브넷(web-sub)을 넣고 퍼블릭 액세스를 "예"로 설정하면 DB가 인터넷에 노출되는 심각한 보안 사고가 발생할 수 있다. 반드시 DB 전용 프라이빗 서브넷만 포함시켜야 한다.
*Multi-AZ 페일오버:
| jm-rds | - |
|---|---|
| DB 엔진 | Oracle Enterprise Edition 19.0.0.0 |
| 버전 | Oracle 19.0.0.0.ru-2022-07.r1 |
| 인스턴스 클래스 | db.t3.small (2vCPU, 2GB RAM) |
| 스토리지 | 마그네틱 20GB |
| DB 인스턴스 식별자 | jm-rds |
| 초기 db 이름 | chmdb |
| 마스터 사용자 | chmainadmin |
| 서브넷 그룹 | rds-sub-gp (rds-sub-1 + rds-sub-2) |
| 퍼블릭 엑세스 | 아니요 (VPC 내부에서만 접근) |
| 포트 | 1521 (Oracle 기본 포트) |
| 자동 백업 | 비활성화 |
| 암호화 | 비활성화 |
| 다중 AZ | 단일 인스턴스 생성 |
| 역할 | 쇼핑몰의 상품, 회원, 주문 데이터 영구 저장. WAS(Tomcat)에서 JDBC를 통해 연결. |
DB 서브넷 그룹 - rds-sub-gp
rds-sub-gp - 포함 서브넷 rds-sub-1 (10.0.8.0/24) + rds-sub-2 (10.0.9.0/24) 가용 영역 us-east-2a, us-east-2c 역할 RDS가 배포될 수 있는 서브넷 범위 정의. 다중 AZ 구성 시 자동으로 2개 AZ에 배포 가능.
예시 1: 애플리케이션 업데이트 배포 전략
쇼핑몰에 새로운 결제 기능을 추가한 ROOT.war v2를 배포해야 한다. 기존 was-ec2에 v2를 배포하고 정상 동작을 확인한 후, 이 인스턴스를 중지하고 새로운 AMI(was-ami-v2)를 생성한다. was-as의 시작 템플릿을 was-ami-v2로 업데이트한 후, 인스턴스 새로 고침(Instance Refresh)을 실행하면 기존 인스턴스가 순차적으로 새 AMI 기반 인스턴스로 교체된다. 문제가 발생하면 시작 템플릿을 이전 AMI(was-ami-v1)로 되돌려 롤백할 수 있다.
예시 2: 재해 복구(DR) 시나리오에서의 AMI 활용
us-east-2 리전 전체에 장애가 발생하는 극단적 상황에 대비하여, AMI를 다른 리전(ex: us-west-2)으로 복사해둘 수 있다. 재해 발생 시 오레곤 리전에서 복사된 AMI를 사용하여 동일한 web-ec2, was-ec2를 빠르게 재구성하고, RDS 크로스 리전 읽기 복제본을 Primary로 승격시켜 서비스를 복구한다. 전체 복구 시간(RTO)을 수 시간에서 30분 이내로 단축할 수 있다.
was-ami (WAS AMI)
- Tomcat + 애플리케이션(ROOT.war)이 배포된 was-ec2를 중지 후 이미지화.
Auto Scaling 그룹이 동일한 환경의 인스턴스를 자동 생성하는 데 사용.
web-ami (WEB AMI)
- Apache + mod_jk가 설치, 설정된 web-ec2를 이미지화.
- web-as Auto Scaling 그룹이 동일하나 웹 서버 인스턴스를 자동 생성하는 데 사용.
예시 1: AJP 프로토콜에 NLB를 사용하는 이유
AJP는 HTTP가 아닌 이진(binary) 프로토콜이므로 ALB(L7)로는 처리할 수 없다. ALB는 HTTP/HTTPS만 이해하기 때문에 AJP 패킷을 수신하면 해석에 실패하고 502 Bad Gateway를 반환한다. NLB는 TCP 레벨에서 패킷을 그대로 전달하므로 AJP, 데이터베이스 프로토콜, 커스텀 TCP 프로토콜 등 어떤 프로토콜이든 처리할 수 있다. 따라서 Apache ↔ Tomcat 간의 AJP 통신에는 NLB가 필수 선택이다.
예시 2: Internal NLB로 WAS를 외부에서 완전히 은닉
NLB를 Internal으로 설정했으므로, NLB의 DNS 이름은 VPC 내부의 프라이빗 IP로만 해석된다. 인터넷에서 was-as-nlb의 DNS를 조회해도 접근할 수 없다. Apache의 worker.properties에서 worker.ajp13_worker.host를 NLB DNS로 설정하면, NLB가 was-sub-1과 was-sub-2에 분산된 Tomcat 인스턴스들에 TCP 레벨로 요청을 자동 분배한다. 특정 Tomcat 인스턴스가 다운되면 NLB의 TCP 헬스 체크가 이를 감지하고 해당 인스턴스로의 트래픽을 자동 차단한다.
| was-as-nlb | (WAS 내부 로드 밸런서) |
|---|---|
| 유형 | Network Load Balancer (NLB) |
| 체계 | Internal (내부용 - VPC 내에서만 접근) |
| 가용 영역 | was-sub-1, was-sub-2 |
| 리스너 프로토콜/포트 | TCP / 8009 (AJP) |
| 대상 그룹 | was-tg (TCP:8009) |
| 역할 | web-ec2(Apache)에서 AJP 요청을 was-as Auto Scaling 인스턴스들에 TCP 레벨에서 부하분산. 초저지연, 고처리량 환경에 적합한 L4 로드 밸런서. |
예시 1: 경로 기반 라우팅으로 마이크로서비스 분리
쇼핑몰이 성장하여 "상품 서비스"와 "회원 서비스"를 별도 서버 그룹으로 분리하고 싶다면, ALB의 경로 기반 라우팅을 활용할 수 있다. /products/ 요청은 상품 서버 대상 그룹으로, /members/ 요청은 회원 서버 대상 그룹으로 라우팅하도록 규칙을 설정한다. 하나의 ALB로 여러 서비스를 관리할 수 있어 비용 효율적이며, 각 서비스를 독립적으로 스케일링할 수 있다.
예시 2: HTTPS 적용과 SSL 오프로딩
실제 서비스에서는 ALB에 SSL/TLS 인증서(AWS Certificate Manager 무료 인증서)를 적용하여 HTTPS(443)로 리스너를 구성한다. ALB가 SSL 암호화/복호화를 처리(*SSL Offloading)하므로, 뒤쪽의 Apache 서버는 HTTP(80)로만 통신하면 된다. 이렇게 하면 각 Apache 서버에 인증서를 개별 설치할 필요가 없고, 인증서 갱신도 ALB에서 한 번만 하면 된다. HTTP(80)로 들어오는 요청은 ALB 리스너 규칙에서 HTTPS(443)로 301 리다이렉트를 설정하여 모든 통신을 암호화한다.
*SSL Offloading:
| web-as-alb | (WEB 외부 로드 밸런서) |
|---|---|
| 유형 | Application Load Balancer (ALB) |
| 체계 | Internet-facing (인터넷 연결) |
| 가용 영역 | web-sub-1, web-sub-2 |
| 리스너 프로토콜/포트 | HTTP / 80 |
| 대상 그룹 | web-tg (HTTP:80) |
| 보안 그룹 | web-alb-sg |
| 역할 | 인터넷에서 들어오는 HTTP 요청을 web-as Auto Scaling 인스턴스(Apache)에 HTTP 레벨에서 분산. URL 기반 라우팅, 헬스 체크 등 L7 기능 제공. |
예시 1: 쇼핑몰 타임 세일로 트래픽이 급증하는 상황
평소 동시 접속자가 500명인 쇼핑몰에서 오후 2시에 타임 세일을 진행하여 동시 접속자가 3000명으로 급증한다. web-as와 was-as 그룹의 CPU 사용률이 70%를 넘기면, 대상 추적 스케일링 정책이 트리거되어 새 인스턴스가 자동 생성된다. web-as는 web-ami로부터 Apache가 설치된 인스턴스를, was-as는 was-ami로부터 Tomcat+ROOT.war가 배포된 인스턴스를 약 2-3분 내에 생성하고, ALB/NLB의 대상 그룹에 자동 등록된다. 세일이 끝나고 트래픽이 줄어들면 인스턴스가 축소된다.
예시 2: 인스턴스 장애 시 자동 복구(Self-Healing)
새벽 3시에 web-sub-1의 Apache 인스턴스가 *OS 커널 패닉으로 다운되었다고 가정한다. ALB의 헬스 체크가 해당 인스턴스의 비정상을 감지하고, Auto Scaling 그룹이 "현재 인스턴스 수(1개)가 원하는 인스턴스 수(2개)보다 적다"는 것을 인식한다. ASG는 자동으로 새 인스턴스를 web-ami로부터 생성하여 정상 상태로 복구한다. 운영자가 잠든 사이에도 서비스가 자동으로 복구되므로, 새벽 장애에 대한 대응 부담이 크게 줄어든다.
*OS 커널 패닉:
was-as (WAS Auto Scaling 그룹)
- 시작 템플릿: was-tmp (was-ami, t3.medium, was-key, was-sg)
- 서브넷: was-sub-1, was-sub-2
- 원하는/최소/최대: 2 / 1 / 3
- 정책: 평균 CPU 70% 초과 시 확장 (대상 추적), 축소 비활성화
web-as (WEB Auto Scaling 그룹)
- 시작 템플릿: web-tmp (web-ami, t3.micro, web-key, web-sg)
- 서브넷: web-sub-1, web-sub-2
- 원하는/최소/최대: 2 / 1 / 3
- 정책: 평균 CPU 70% 초과 시 확장 (대상 추적), 축소 비활성화
예시 1: 보안 그룹 체이닝으로 계층 간 접근 통제
이 아키텍처의 보안 그룹 설계는 *"체이닝(Chaining)" 패턴을 따른다. web-alb-sg는 인터넷(0.0.0.0/0)에서 80/443을 수신하고 WEB 서브넷으로만 전달한다. web-sg는 ALB에서 온 80 트래픽을 수신하고 WAS 서브넷으로 8009만 송신한다. was-sg는 WEB 서브넷에서 8009를 수신하고 RDS 서브넷으로 1521만 송신한다. rds-sg는 WAS 서브넷에서 1521만 수신한다. 이렇게 하면 공격자가 Apache 서버를 장악하더라도 RDS에 직접 접근할 수 없고, 반드시 WAS를 거쳐야만 한다. 공격자의 횡적 이동 경로를 크게 제한하는 효과가 있다.
예시 2: SSH 접근 제한 강화
현재 web-sg의 SSH(22) 인바운드가 0.0.0.0/0(모든 IP)으로 열려 있는데, 이는 실습 편의를 위한 것이다. 실제 비즈니스 환경에서는 회사 사무실의 고정 IP(ex. 203.0.113.10/32)로만 SSH를 허용해야 한다. 더 나은 방법은 SSH 포트를 완전히 닫고, *AWS Systems Manager Session Manager를 사용하여 IAM 인증 기반으로 인스턴스에 접근하는 것이다. 이렇게 하면 SSH Brute Force attack을 원천 차단할 수 있다.
*Chaining: *AWS Systems Manager Session Manager:
- 보안 그룹 특징:
상태 저장(Stateful) 방화벽.
인바운드 허용 시 응답 트래픽은 자동 허용.
허용 규칙만 정의 (거부 규칙 없음).
web-sg - 웹 서버 보안 그룹
▼ Inbound - ▲ Outbound - SSH 22 0.0.0.0/0 TCP 8009 10.0.4.0/23 (WAS) HTTP 80 0.0.0.0/0 HTTPS 443 0.0.0.0/0
- Apache 웹 서버 및 Auto Scaling으로 생성된 web 인스턴스에 적용.
- HTTP.HTTPS 인바운드 허용.
- AJP(8009)만 WAS 서브넷으로 아웃바운드.
was-sg - WAS 서버 보안 그룹
▼ Inbound - ▲ Outbound - TCP 8009 10.0.4.0/23 (WAS) Oracle 1521 10.0.8.0/23 (RDS) TCP 8009 10.0.0.0/23 (WEB) TCP 8009 10.0.4.0/23 (WAS)
- Tomcat WAS 인스턴스에 적용.
- AJP(8009)는 WEB/WAS 서브넷에서만 수신.
- Oracle은 RDS 서브넷으로만 송신.
rds-sg - RDS 보안 그룹
▼ Inbound - ▲ Outbound - Oracle 1521 10.0.4.0/23 (WAS) 전체 삭제 기본 규칙 제거
- Oracle RDS에 적용.
- WAS 서브넷(10.0.4.0/23)에서의 1521 포트 접속만 허용.
- 아웃바운드 기본 규칙 완전 삭제로 최소 권한 원칙 적용.
was-alb-sg - ALB 전용 보안 그룹
▼ Inbound - ▲ Outbound - HTTP 80 0.0.0.0/0 HTTP 80 10.0.0.0/23 (WEB) HTTPS 443 0.0.0.0/0 HTTPS 443 10.0.0.0/23 (WEB)
- web-as-alb ALB에 전용으로 적용.
- 인터넷에서 80/443 수신.
- WEB 서브넷으로만 포워딩.
- Network ACL 특징:
상태 비저장(Stateless) 방화벽.
번호 순서대로 규칙 평가.
허용/거부 모두 정의 가능.
응답 트래픽을 위해 임시 포트(1024-65535)를 별도 허용해야 함.
예시 1: 특정 IP 대역의 차단(거부 규칙 활용)
보안 모니터링에서 중국 IP 대역(ex. 123.45.0.0/16)으로부터 대량의 SQL Injection 공격이 탐지되었다고 가정한다. 보안 그룹에는 거부 규칙을 설정할 수 없지만, NACL에서는 가능하다. web-nacl의 인바운드에 규칙 번호 50으로 123.45.0.0/16 → DENY를 추가하면(기존 허용 규칙 번호 100보다 낮은 번호), 해당 IP 대역의 모든 트래픽이 서브넷 진입 전에 차단된다. 이것이 보안 그룹만으로는 불가능하고, NACL이 필요한 대표적인 상황이다.
예시 2: Stateless 특성으로 인한 임시 포트 설정 필수
was-nacl에서 인바운드로 AJP(8009)를 허용했지만, 아웃바운드에 임시 포트(1024~65535)를 허용하지 않으면 Tomcat의 응답 패킷이 서브넷을 빠져나가지 못한다. 이는 보안 그룹(Stateful)에서는 자동 처리되지만, NACL(Statelss)에서는 수동으로 설정해야 한다. 실무에서 NACL을 처음 구성할 때 가장 흔히 발생하는 실수가 바로 이 임시 포트 허용을 빠뜨리는 것으로, 모든 것이 정상인데 통신이 안 되는 원인 모를 장애로 이어진다.
web-nacl (WEB 서브넷)
- 연결: web-sub-1, web-sub-2
- 인바운드: SSH(22), HTTP(80), HTTPS(443), 임시 TCP(1024-65535) - 0.0.0.0/0 허용
- 아웃바운드: HTTP(80), HTTPS(443), AJP(8009→WAS), 임시 TCP 허용
was-nacl (WAS 서브넷)
- 연결: was-sub-1, was-sub-2
- 인바운드: AJP 8009 (WEB서브넷), 임시TCP(RDS, WAS 대역) 허용
- 아웃바운드: 임시TCP (WEB 대역), Oracle 1521 (RDS 대역) 허용
rds-nacl (RDS 서브넷)
- 연결: rds-sub-1, rds-sub-2
- 인바운드: Oracle 1521 (WAS 서브넷 10.0.4.0/23) 허용
- 아웃바운드: 임시TCP 1024-65535 (WAS 서브넷) 허용
예시 1: 팀별 권한 분리
쇼핑몰을 운영하는 팀이 개발팀, 인프라팀, DBA팀으로 나뉘어 있다고 가정한다. 개발팀 IAM 그룹에는 EC2(Read), S3(Read/Write), CloudWatch(Read) 권한만 부여한다. 인프라팀에는 VPC, EC2, ALB, Auto Scaling 등의 Full Access를 부여한다. DBA팀에는 RDS Full Access만 부여한다. 이렇게 하면 개발자가 실수로 VPC 설정을 변경하거나, 인프라 엔지니어가 RDS를 삭제하는 사고를 IAM 레벨에서 방지할 수 있다.
예시 2: MFA 적용과 루트 계정 보호
현재 설정에서는 MFA가 비활성화되어 있는데, 실무에서는 모든 IAM 사용자에게 MFA(Multi-Factor Authentification)를 필수로 적용해야 한다. 특히 루트 계정은 하드웨어 MFA 키(YubiKey 등)로 보호하고, 일상적인 작업에는 절대 사용하지 않는다. 2019년 Capital One 해킹 사건에서 IAM 역할의 과도한 권한이 핵심 원인이었으며, 이후 AWS는 IAM 정책을 최소 권한으로 설정할 것을 강력히 권고하고 있다.
예시 1: DNS 레코드와 EIP 연동
Auto Scaling 적용 전, 쇼핑몰 도메인의 A 레코드를 web-ec2의 EIP로 설정한다. 서버를 점검을 위해 중지했다가 다시 시작해도 IP가 바뀌지 않으므로, DNS 변경 없이 서비스를 재개할 수 있다. 단, Auto Scaling을 적용한 이후에는 ALB의 DNS 이름으로 CNAME 또는 Route 53 Alias 레코드를 설정하는 것이 올바른 방식이며, 개별 인스턴스의 EIP는 더 이상 필요하지 않다.
1. 3-Tier 아키텍처
2. 고가용성 (HA)
3. 심층 보안 (Defenses in Depth)
4. 이중 로드 밸런싱
5. AJP 프로토콜 연동
6. AMI 기반 불변 인프라
미완이긴 한데 추후 시간이 된다면 마저 보완해서 수정하겠습니다.