Public ALB + Private EC2 + RDS 구조의 기본 아키텍처 구상하기

예전에 일했던 회사의 서버구조가 2중화로 구성된 Web + WAS + DB구조였다. 우리 회사의 인프라 담당자에게 물어보니 연습하기에 좋은 구조로 “Public ALB + Private EC2 + RDS”를 추천해줬는데 예전에 담당했던 서비스의 구조와 비슷하다는걸 느꼈다. 그 전에는 잘 알지도 못하면서 AWS 아키텍처 그림을 보면 늘 “대충 이런 느낌이겠지”로 넘겨버리곤 했다. 그래서 2026년 기준으로 가장 흔한 형태이자 연습하기 좋다는 “Public ALB + Private EC2 + RDS” 기본 아키텍처를 머리속에서 정리하고, VPC/라우팅/보안 흐름이 머릿속에서 연결되도록 학습 기록으로 남긴다.

소제목 1 - VPC와 서브넷 설계: 내가 머릿속에 먼저 그린 지도

EC2 + RDS


이 아키텍처를 이해하려면 “리소스를 어디에 둘 것인가”부터 결정해야 했다. 나는 항상 서비스부터 만들고 네트워크는 나중에 맞추려다가 더 헷갈렸는데, 이번엔 반대로 VPC 지도를 먼저 그렸다.
내가 잡은 기본은 VPC 하나(예: 10.0.0.0/16) 안에 서브넷을 최소 4개로 나누는 구성이다. 이유는 고가용성을 위해 AZ를 2개 쓰기 위해서다. 그래서 Public Subnet 2개(AZ A, AZ B), Private Subnet 2개(AZ A, AZ B)로 시작하는 그림을 머리에 넣었다. 퍼블릭/프라이빗은 ‘이름표’가 아니라 라우팅이 결정된다는 것도 이미 여러 번 헷갈려봤기 때문에, 서브넷을 만들고 나서 라우트 테이블을 꼭 같이 떠올리기로 했다.
Public Subnet에는 인터넷과 맞닿아야 하는 리소스가 들어간다. 여기서는 ALB가 대표다. ALB는 외부 사용자의 요청을 받아야 하니까 퍼블릭에 있어야 하고, 보통 가용영역 2개에 걸쳐서 배치된다. 그리고 Private Subnet에는 EC2(앱 서버)와 RDS(DB)를 두는 게 기본이다. 특히 RDS는 인터넷에 노출되면 안 되기 때문에, 퍼블릭에 두지 않는다는 원칙을 내 머리에 박아두었다.
여기서 내가 한 번 더 정리한 포인트는 “Private Subnet이 아무것도 못 하는 공간은 아니다”라는 점이다. Private Subnet의 EC2도 외부 라이브러리 다운로드나 OS 업데이트 같은 아웃바운드가 필요할 수 있다. 그래서 NAT Gateway 또는 VPC Endpoint 같은 요소가 어디에 들어가는지도 같이 생각해야 한다. 나는 비용이 무서워서 NAT를 최소화하고 싶지만, 현실적으로 기본 구성에서는 NAT가 자주 등장한다는 것도 받아들이기로 했다.

소제목 2 - 라우팅 흐름: 인터넷 요청이 들어오고 나가는 길을 문장으로 써보기

나는 AWS 네트워크를 이해할 때 그림보다 “문장”이 더 도움이 됐다. 그래서 이 아키텍처의 트래픽 흐름을 문장으로 써봤다.
1) 사용자가 인터넷에서 내 도메인(예: api.example.com)으로 요청을 보낸다.
2) DNS(Route 53)가 그 도메인을 ALB로 연결해준다.
3) 요청은 IGW(Internet Gateway)를 통해 VPC로 들어온다.
4) Public Subnet에 있는 ALB가 요청을 받고, Target Group으로 Private Subnet의 EC2들에게 전달한다.
5) EC2는 비즈니스 로직을 처리하면서, 필요하면 Private Subnet의 RDS에 연결한다.
6) 응답은 다시 ALB를 통해 사용자에게 돌아간다.
이 흐름을 이해하는 핵심은 “외부에서 직접 EC2로 들어가지 않는다”는 것이다. 외부 트래픽은 ALB까지만 허용하고, EC2는 ALB가 전달하는 트래픽만 받는다. 이 한 줄이 내가 생각하는 이 구조의 본질이다.
라우트 테이블 관점에서 보면 더 명확해진다. Public Subnet 라우트 테이블에는 0.0.0.0/0 -> IGW가 들어가서 인터넷과 직접 통신할 수 있는 조건이 만들어진다. 그래서 ALB는 퍼블릭 영역에서 외부 요청을 받을 수 있다. 반대로 Private Subnet 라우트 테이블에는 보통 0.0.0.0/0 -> NAT가 걸린다. 이렇게 하면 Private Subnet의 EC2가 바깥으로 나가야 할 때(패키지 설치, 외부 API 호출 등)만 NAT를 통해 나갈 수 있고, 외부에서 직접 들어오는 경로는 없다.
그리고 내가 앞으로 실습하면서 꼭 확인해야겠다고 적어둔 게 “리전/가용영역”과 “서브넷-라우트테이블 연결”이다. AWS 콘솔에서 서브넷을 만들고 라우트 테이블 연결을 놓치면, 이름은 Public인데 실제로는 외부로 못 나가는 상황이 생긴다. 나는 이런 실수로 시간을 너무 많이 썼기 때문에, 이번 아키텍처에서는 트래픽 흐름을 머릿속으로 한 번 “왕복”시킨 다음에 설정을 건드리는 방식으로 해보려고 한다.

소제목 3 - 보안 설정: SG로 ‘ALB→EC2→RDS’만 통과시키는 습관

이 구조의 장점은 보안 규칙을 비교적 단순하게 만들 수 있다는 점이라고 느꼈다. 내가 목표로 잡은 보안 원칙은 딱 하나였다. “ALB → EC2 → RDS” 외에는 열지 않는다. 그리고 이건 대부분 Security Group(SG)으로 구현할 수 있다.
먼저 ALB용 SG를 만든다. 인바운드는 80/443을 0.0.0.0/0에서 받게 열 수도 있고(운영이라면 443 중심), 학습용으로는 80만 열고 시작할 수도 있다. 중요한 건 ALB가 외부 요청을 받을 수 있어야 한다는 점이다. 아웃바운드는 기본적으로 대상(EC2)으로 나가야 한다.
다음은 EC2용 SG다. 여기서 핵심은 인바운드를 “ALB SG에서 오는 트래픽만 허용”하는 것이다. 즉, 80 또는 8080 같은 앱 포트를 열되, 소스는 0.0.0.0/0이 아니라 ALB의 SG로 제한한다. 이렇게 하면 외부에서 EC2로 직접 접속하는 길이 막힌다. SSH 접속이 필요하면 Bastion을 두거나 SSM(Session Manager)을 쓰는 방식이 더 안전하다고 들었는데, 나는 아직 초보라서 이번 학습에서는 “가능하면 SSH 자체를 최소화”하는 방향으로 가고 싶다.
마지막은 RDS용 SG다. DB 포트(예: MySQL 3306, PostgreSQL 5432)를 열되, 소스는 EC2 SG로 제한한다. 이것도 0.0.0.0/0으로 열면 바로 사고다. 나는 이 규칙을 “DB는 특정 서버 그룹에서만 접근 가능”으로 외웠다.
NACL은 이번 기본 아키텍처에서는 필수까지는 아니라고 들었지만, 서브넷 단위로 특정 IP를 막아야 하는 요구가 있으면 유용하다고 정리해뒀다. 다만 나는 아직 SG도 자주 헷갈리기 때문에, 초반에는 SG를 확실히 다지고 NACL은 최소로 두는 게 현실적이라고 생각한다.
추가로 비용/운영 측면에서 NAT Gateway가 들어오면 비용이 발생할 수 있으니, 가능하다면 S3/DynamoDB 같은 접근은 VPC Endpoint로 바꿔서 NAT 의존도를 줄이는 것도 나중 과제로 적어두었다. 이건 보안 강화에도 도움이 된다고 하니까, “기본 구성 → 비용 최적화 버전”으로 확장하는 흐름이 내 학습 루트에 잘 맞을 것 같다.

“Public ALB + Private EC2 + RDS” 구조를 내가 이해한 한 문장은 “외부 트래픽은 ALB까지만, 앱/DB는 사설망에서만”이다. VPC 안에 public/private 서브넷을 AZ별로 나누고, public은 IGW, private은 NAT로 라우팅하며, SG로 ‘ALB→EC2→RDS’만 열어두면 기본 뼈대가 완성된다. 나는 아직 네트워크가 약하지만, 트래픽 흐름을 문장으로 왕복시키고 설정하면 실수가 줄어드는 걸 느꼈다. 다음 단계로는 이 구성을 실제로 만들어보고, 내가 어디서 막혔는지(라우트테이블/SG/서브넷 연결 실수 같은 것)를 그대로 기록해볼 생각이다.

댓글

이 블로그의 인기 게시물

JOIN 기초: users와 point_history를 합쳐 ‘회원별 요약(잔액/최근 활동)’ 만들기

점검 SQL: “원장 합계(SUM) vs balance” 불일치를 찾아내고 원인을 좁히는 방법

EXPLAIN 기초: 점검/리포트 쿼리가 느려질 때 “왜 느린지” 확인하는 방법