EC2 3대로 서비스 운영하기 - 애플리케이션 분리
2대의 서버에서 웹/애플리케이션, 데이터베이스로 나누었습니다. 3대의 서버에서는 웹에서 애플리케이션을 분리 해서 3대의 서버에 각각 사용합니다

1. 아키텍처 다이어그램
사용자
↓
Web EC2
└ Nginx / Squid Proxy
↓
Application EC2
└ Next.js / Redis
↓
Database EC2
└ PostgreSQL2. 2-Tier에서 3-Tier로 확장하는 이유
Web/Application EC2
↓
Database EC2- 웹 서버와 애플리케이션 서버의 역할을 분리하고 싶은 경우
- 애플리케이션의 CPU나 메모리 사용량이 증가하는 경우
- 애플리케이션만 별도로 확장하고 싶은 경우
- 외부에 노출되는 영역을 최소화하고 싶은 경우
- 배포나 장애 발생 시 Web과 App의 영향을 분리하고 싶은 경우
- 향후 Load Balancer나 Auto Scaling으로 확장할 계획이 있는 경우
[2-Tier]
Web + Application
↓
Database
↓ 확장
[3-Tier]
Web
↓
Application
↓
Database3. 아키텍처 살펴보기
Client
↓
Internet Gateway
↓
Nginx
↓
Next.js
↓
PostgreSQL여기서 중요한 특징은 공인 IP가 Web EC2에만 존재한다는 점입니다.
4. [1] VPC - Default
- VPC에는 Internet Gateway가 연결되어 있습니다.
- 기본 VPC에는 가용 영역별 Public Subnet이 생성되어 있습니다.
- 그림에서는 2a, 2c 두 개의 가용 영역을 사용합니다.
- EC2 간 통신은 Public IP가 아닌 Private IP를 사용합니다.
- 같은 VPC 내부에서는 Private IP를 이용하여 직접 통신할 수 있습니다.
5. [2] EC2 - Web Server
- Amazon Linux 2023 사용
- Elastic IP 또는 Public IPv4 연결
- Nginx 설치
- Reverse Proxy 구성
- Squid Proxy 구성
- HTTPS 인증서 설치
User
↓
HTTPS :443
↓
Nginx
↓
Application EC2 :3000Application Server의 Next.js 포트는 인터넷에 공개할 필요가 없습니다.
6. Squid Proxy의 역할
- 외부 API 호출
- GitHub 접근
- npm 패키지 다운로드
- 외부 인증 서비스 연결
- 외부 결제 API 호출
- 특정 고정 IP 기반 API 연동
Application EC2
Private IP
↓
Squid Proxy
Web EC2
↓
Elastic IP
↓
Internet이 방식의 장점은 Application EC2에 별도의 Public IPv4를 할당하지 않으면서 외부 인터넷 통신을 사용할 수 있다는 것입니다.
7. EC2 - Application Server
- Amazon Linux
- Next.js
- Redis
- Private IP만 사용
Web EC2
10.x.x.x
↓
Application EC2
10.x.x.x:3000Application EC2에는 Public IPv4를 할당하지 않습니다.
Application Security Group
TCP 3000
Source: Web Security Group이렇게 하면 Web Server에서 들어오는 요청만 Application Server가 받을 수 있습니다.
8. Redis를 Application Server에 구성
그림에서는 Redis도 Application EC2에 함께 구성되어 있습니다.
Redis는 일반적으로 다음과 같은 용도로 사용할 수 있습니다.
- 로그인 세션
- 캐시
- API 응답 캐시
- 임시 데이터
- Rate Limit
- Queue
- 반복 조회 데이터
EC2 3대 규모의 소규모 3-Tier 환경에서는 Redis를 별도의 서버로 분리하기보다는 Application Server에 함께 설치하여 사용할 수 있습니다.
Application EC2
Next.js
↕
Redis서비스 규모가 커진다면 이후 Redis 전용 EC2 또는 Amazon ElastiCache로 분리할 수 있습니다.
9. [4] EC2 - Database Server
세 번째 EC2는 데이터 저장을 담당하는 Database Server입니다.
그림에서는 PostgreSQL을 사용합니다.
주요 특징은 다음과 같습니다.
- Amazon Linux 기반 EC2
- PostgreSQL 설치
- Private IP만 사용
- Application EC2에서만 접근
- Public IPv4 사용하지 않음
Application EC2의 Next.js는 Database EC2의 Private IP를 이용하여 PostgreSQL에 연결합니다.
예를 들어 다음과 같습니다.
Application EC2
172.31.x.x
↓
TCP 5432
↓
Database EC2
172.31.x.xDB 서버의 Public IP를 사용할 필요가 없습니다.
Security Group도 다음과 같이 구성하는 것이 좋습니다.
Database Security Group
TCP 5432
Source: Application Security Group이렇게 하면 Application Server에서만 PostgreSQL에 연결할 수 있습니다.
10. Public Subnet인데 왜 App과 DB는 인터넷에서 접근할 수 없을까요?
이번 구성에서 조금 특이하게 느껴질 수 있는 부분입니다.
Web, App, DB EC2 모두 Public Subnet에 위치합니다.
하지만 Public Subnet에 있다고 해서 모든 EC2가 자동으로 인터넷에 노출되는 것은 아닙니다.
IPv4 기준으로 EC2가 Internet Gateway를 통해 인터넷과 직접 통신하려면 Public IPv4 또는 Elastic IP가 필요합니다.
이번 구성에서는 다음과 같이 사용합니다.
Web EC2
Private IP + Elastic IP
→ 인터넷 통신 가능
Application EC2
Private IP only
→ 인터넷 직접 통신 불가
Database EC2
Private IP only
→ 인터넷 직접 통신 불가따라서 App과 DB는 Public Subnet에 있어도 Public IPv4를 할당하지 않는다면 인터넷에서 직접 접근할 수 없습니다.
다만 Private Subnet과는 차이가 있습니다.
Private Subnet은 Route Table 자체에 Internet Gateway 경로가 없기 때문에 네트워크 계층에서 한 번 더 인터넷 접근을 제한할 수 있습니다.
따라서 이번 구성은 비용과 구조를 단순화한 소규모 3-Tier 구성으로 볼 수 있고, 보안을 더 강화하려면 이후 App과 DB를 Private Subnet으로 이동할 수 있습니다.
11. 2-Tier와 무엇이 달라졌을까요?
2-Tier에서는 다음과 같이 구성했습니다.
EC2 #1
Nginx + Next.js
↓
EC2 #2
PostgreSQL3-Tier에서는 Web과 Application을 다시 분리합니다.
EC2 #1
Nginx
↓
EC2 #2
Next.js + Redis
↓
EC2 #3
PostgreSQL가장 큰 차이는 역할별 리소스를 독립적으로 사용할 수 있다는 점입니다.
2-Tier에서는 Nginx와 Next.js가 같은 CPU와 메모리를 사용합니다.
애플리케이션의 CPU 사용률이 증가하거나 메모리 사용량이 급증하면 Nginx에도 영향을 줄 수 있습니
다.
3-Tier에서는 Web Server와 Application Server가 각각 독립적인 EC2이기 때문에 리소스 영향도를 줄일 수 있습니다.
또한 향후 Application Server만 더 높은 사양으로 변경하거나 여러 대로 늘리는 것도 쉬워집니다.
12. 3-Tier로 분리했을 때의 장점
3-Tier 구조에서는 각 서버의 책임이 명확해집니다.
Web
사용자 요청 처리 / Reverse Proxy
Application
서비스 로직 처리
Database
데이터 저장운영 관점에서도 장점이 있습니다.
- 서버별 CPU와 메모리 분리
- 애플리케이션 배포 시 Web Server 영향 감소
- DB 리소스 독립
- App 서버만 별도 확장 가능
- 계층별 Security Group 설정 가능
- App/DB 직접 인터넷 노출 방지
- 향후 ALB, Auto Scaling, RDS로 확장하기 쉬움
특히 애플리케이션의 처리량이 증가하면 Web이나 DB는 그대로 유지하면서 Application EC2만 확장할 수 있습니다.
13. Security Group도 3단계로 분리합니다
3-Tier에서는 Security Group도 서버 역할별로 분리하는 것이 좋습니다.
예를 들어 다음과 같이 구성할 수 있습니다.
Web Security Group
HTTP 80
Source: 0.0.0.0/0
HTTPS 443
Source: 0.0.0.0/0
SSH 22
Source: 관리자 IPApplication Security Group
Next.js 3000
Source: Web Security GroupDatabase Security Group
PostgreSQL 5432
Source: Application Security Group전체 흐름은 다음과 같습니다.
Internet
↓ 443
Web SG
↓ 3000
Application SG
↓ 5432
Database SG즉 외부 사용자는 Application이나 Database로 직접 접근할 수 없습니다.
14. 배포 과정 살펴보기
서버가 3대로 분리되면서 각 서버에 필요한 환경을 별도로 구성해야 합니다.
(1) EC2 3대 생성
- Web Server EC2 생성
- Application Server EC2 생성
- Database Server EC2 생성
- 필요한 EBS 스토리지 설정
- 역할별 Security Group 생성
Public IPv4는 Web EC2에만 사용합니다.
(2) Web EC2 구성
- SSH 접속
- Nginx 설치
- Reverse Proxy 구성
- Squid Proxy 설치
- Elastic IP 연결
- SSL 인증서 설치
- Application EC2 Private IP로 Proxy Pass 설정
예를 들어:
Nginx
↓
http://10.x.x.x:3000형태로 Application EC2에 요청을 전달합니다.
(3) Application EC2 구성
- Node.js LTS 설치
- PM2 설치
- Next.js 프로젝트 배포
- Redis 설치
- 환경변수 설정
- PostgreSQL 연결 정보 설정
- Squid Proxy 설정
Application EC2는 Private IP만 사용합니다.
(4) Database EC2 구성
- PostgreSQL 설치
- 서비스 DB 생성
- DB 사용자 생성
- PostgreSQL 외부 연결 설정
- Application EC2에서만 접속하도록 Security Group 제한
- 데이터 백업 구성
(5) Next.js와 PostgreSQL 연결
Next.js의 DB 연결 정보는 Database EC2의 Private IP 기준으로 설정합니다.
예를 들어:
DB_HOST=172.31.x.x
DB_PORT=5432형태로 설정합니다.
Public IP를 사용할 필요가 없습니다.
(6) Squid Proxy 연결
Application EC2에서 외부 인터넷이 필요한 경우 Web EC2의 Private IP를 Proxy 주소로 설정합니다.
예를 들어 구조는 다음과 같습니다.
Application EC2
↓
Web EC2 Squid Proxy
↓
Elastic IP
↓
External APISquid Proxy는 Application EC2에서만 접근할 수 있도록 Security Group과 ACL을 제한하는 것이 좋습니다.
(7) 도메인 연결
- Web EC2에 Elastic IP 연결
- DNS A 레코드 등록
- Nginx Virtual Host 설정
- SSL 인증서 설치
- HTTPS 접속 확인
(8) 전체 테스트
마지막으로 전체 요청 흐름을 확인합니다.
Client
↓
Internet Gateway
↓
Web EC2 / Nginx
↓
Application EC2 / Next.js
↓
Database EC2 / PostgreSQL그리고 Application EC2의 외부 통신도 확인합니다.
Application
↓
Squid Proxy
↓
Internet15. 운영 관리도 서버별로 나눕니다
EC2가 3대로 늘어나면 관리해야 할 대상도 증가합니다.
Web Server에서는 다음을 확인합니다.
- Nginx 로그
- SSL 인증서
- Squid Proxy 상태
- 네트워크 트래픽
Application Server에서는 다음을 관리합니다.
- Next.js 로그
- PM2 프로세스 상태
- CPU 및 메모리
- Redis 메모리 사용량
- 애플리케이션 배포
Database Server에서는 다음을 관리합니다.
- PostgreSQL 로그
- CPU와 메모리
- EBS 디스크 사용량
- DB Backup
- EBS Snapshot
특히 Database Server는 서비스의 핵심 데이터를 보관하기 때문에 애플리케이션 백업과 별도로 PostgreSQL 백업을 관리하는 것이 중요합니다.
16. 월 예상 비용
EC2가 2대에서 3대로 증가했기 때문에 비용도 증가합니다.
예를 들어 다음과 같이 구성한다고 가정할 수 있습니다.
EC2 t3.micro × 3
EBS 10 GiB × 3
Public IPv4 × 1여기서 중요한 점은 Public IPv4를 Web Server에만 하나 사용한다는 것입니다.
Application과 Database EC2는 Private IP만 사용하기 때문에 별도의 Public IPv4 비용이 발생하지 않습니다.
또한 이번 구조에서는 별도의 NAT Gateway를 사용하지 않고 Web EC2의 Squid Proxy를 이용하기 때문에 NAT Gateway 비용도 발생하지 않습니다.
다만 실제 비용은 다음 조건에 따라 달라질 수 있습니다.
- AWS 리전
- EC2 인스턴스 타입
- EBS 용량
- Public IPv4 가격
- 인터넷 데이터 전송량
- 환율
- Savings Plans 적용 여부
17. 이 구성의 장점과 한계
이번 3-Tier 구성의 가장 큰 장점은 Web, Application, Database 역할을 모두 분리하면서도 비교적 낮은 비용으로 구성할 수 있다는 것입니다.
특히 다음과 같은 특징이 있습니다.
- Public IPv4 하나만 사용
- App과 DB 인터넷 직접 노출 방지
- NAT Gateway 없이 Squid Proxy 사용
- 서버별 역할 분리
- Application과 DB 리소스 독립
- Security Group 단계별 제한 가능
- 향후 확장하기 쉬운 구조
반면 한계도 있습니다.
먼저 App과 DB가 Public Subnet에 존재합니다.
Public IPv4를 할당하지 않았기 때문에 현재는 인터넷에 직접 노출되지 않지만, Private Subnet에 배치한 것만큼 네트워크 계층의 격리가 강한 구조는 아닙니다.
또한 EC2 3대가 각각 단일 서버이기 때문에 여전히 Single Point of Failure가 존재합니다.
예를 들어 Application EC2가 장애가 나면 Web Server와 Database Server가 정상이어도 서비스는 동작하지 않습니다.
18. 다음 단계에서는 어떻게 확장할 수 있을까요?
이번 구조는 소규모 서비스에서 3-Tier 구조를 이해하고 실제 운영에 적용해보는 단계로 적합합니다.
서비스가 성장하면 다음과 같이 발전시킬 수 있습니다.
먼저 App과 DB를 Private Subnet으로 이동할 수 있습니다.
Public Subnet
└─ Web
Private App Subnet
└─ Application
Private DB Subnet
└─ Database그다음 Web Server의 역할을 ALB로 변경할 수도 있습니다.
Internet
↓
ALB
↓
Application EC2
↓
RDSApplication Server를 여러 대로 구성하면 Auto Scaling도 적용할 수 있습니다.
Redis는 Amazon ElastiCache로 변경하고 PostgreSQL은 Amazon RDS로 변경할 수 있습니다.
결국 다음과 같은 형태로 발전할 수 있습니다.
Internet
↓
ALB
↓
Application Auto Scaling
↓
ElastiCache
↓
RDS Multi-AZ19. 마무리
이번 구성에서는 EC2 3대를 이용하여 Web / Application / Database를 각각 분리한 3-Tier 아키텍처를 살펴봤습니다.
전체 구조는 다음과 같이 정리할 수 있습니다.
User
↓
Internet Gateway
↓
Web EC2
└─ Nginx / Squid Proxy
↓
Application EC2
└─ Next.js / Redis
↓
Database EC2
└─ PostgreSQL2-Tier에서는 Web과 Application이 하나의 서버를 사용했다면, 이번에는 두 역할까지 분리하면서 서버별 책임을 더욱 명확하게 만들었습니다.
또한 Web EC2에만 Public IPv4를 사용하고 Application과 Database는 Private IP만 사용하여 외부에서 직접 접근할 수 없도록 구성했습니다.
Application Server에서 인터넷 연결이 필요한 경우에는 Web EC2의 Squid Proxy를 통해 외부로 연결할 수 있기 때문에 별도의 Public IPv4나 NAT Gateway 없이도 비교적 저렴하게 구성할 수 있습니다.
이 구조는 2-Tier에서 한 단계 확장하면서 Web / App / DB 역할 분리, Security Group 간 통신, Private IP 기반 서버 연결, Proxy를 이용한 아웃바운드 통신을 함께 경험할 수 있는 구성입니다.
다만 아직 각 역할의 서버가 한 대씩만 존재하기 때문에 완전한 고가용성 구조는 아닙니다.
다음 단계에서는 App과 DB를 Private Subnet으로 이동하거나, ALB + Auto Scaling + RDS + ElastiCache 구조로 확장하면서 보다 일반적인 AWS 상용 아키텍처로 발전시킬 수 있습니다.
