AWS 소규모 배포 3가지: EC2, Lightsail, App Runner 비교
앞 글에서 Fargate + RDS + ALB + NAT로 짠 교과서 구성을 뜯어봤습니다. ALB와 NAT Gateway를 빼면 요금이 절반 아래로 떨어진다는 것까지 봤습니다.
그런데 거기서 더 내려갈 수 있습니다. 그리고 상당수의 작은 서비스에는 그쪽이 맞습니다.
흔히 이렇게 이해합니다
AWS에 올린다는 것은 ECS나 App Runner 같은 관리형 서비스에 RDS를 붙여 조합한다는 뜻입니다.
이 이해가 워낙 널리 퍼져 있어서, EC2 인스턴스 한 대에 Docker Compose를 올리는 방식을 두고 "그건 클라우드를 제대로 쓰는 게 아니다"라고 말하는 경우까지 봅니다.
저는 이 구분이 실무에서 과하게 쓰인다고 봅니다. 사용자가 몇 명이고 데이터가 수백 MB인 사내 도구라면, 인스턴스 한 대가 교과서 구성과 똑같이 동작합니다. 차이는 장애 대응과 확장성인데, 그게 필요한 시점이 오기 전까지는 매달 차액이 아무 일도 하지 않는 데 쓰입니다.
다만 요금만 보고 고르면 틀립니다. 세 구성의 진짜 차이는 다른 데 있고, 그건 요금표에 안 나옵니다. 마지막에 다루겠습니다.
EC2 한 대: 지금 쓰는 compose가 그대로 돕니다
가장 단순한 형태입니다. 인스턴스 하나에 Docker Compose를 올리고 앱과 데이터베이스를 같은 곳에서 돌립니다. VPC도 기본 VPC를 그대로 쓰고 서브넷을 나누지 않습니다. 인스턴스 하나와 보안 그룹 하나가 전부입니다.
여기서 챙길 만한 게 몇 가지 있습니다.
Graviton을 쓰면 같은 성능에 20% 정도 쌉니다. t4g 계열이 arm64입니다. 컨테이너를 쓴다면 아키텍처를 맞추는 게 중요한데, 개발 머신이 Apple Silicon이면 이미 arm64라 이미지가 그대로 갑니다. x86 이미지를 arm에서 돌리면 에뮬레이션이 붙어 느려지거나 아예 안 뜹니다. 공식 이미지 대부분은 멀티 아키텍처라 그냥 받으면 맞는 게 옵니다.
버스트 크레딧을 알아 둬야 합니다. t 계열은 기본 성능이 정해져 있고 그 이하로 쓰면 크레딧이 쌓이고 넘게 쓰면 크레딧을 씁니다. 크레딧이 떨어지면 기본 성능으로 묶입니다. 대부분 노는 워크로드에는 잘 맞는데, 몇 시간짜리 배치 작업이 있으면 크레딧이 마릅니다. 그런 작업이 있다면 Unlimited 모드를 켜거나 그 작업만 따로 돌리는 게 낫습니다.
SSH 포트를 열지 않아도 됩니다. SSM Session Manager를 쓰면 SSH 키도, 22번 포트도, 공인 IP도 없이 접속합니다.
aws ssm start-session --target i-0123456789abcdef0인스턴스에 SSM 에이전트와 IAM 역할만 있으면 됩니다. 접속 기록이 CloudTrail에 남는 것도 덤입니다. 보안 그룹에서 22번 규칙을 아예 지울 수 있습니다.
그리고 2024년부터 공인 IPv4 주소는 붙어 있기만 해도 시간당 과금됩니다. 예전의 "인스턴스에 붙어 있으면 무료" 규칙은 없어졌습니다. 액수는 크지 않지만 예전 기준으로 계산하면 어긋납니다.
Lightsail: 요금이 고정입니다
AWS가 만든 단순한 VPS에 가깝습니다. VPC, 서브넷, 라우트 테이블, Elastic IP를 따로 다루지 않습니다. 플랜을 고르면 끝입니다.
진짜 값어치는 예측 가능성입니다. AWS 요금이 무서운 이유는 액수 자체보다 모르는 사이에 늘어난다는 데 있습니다. NAT 데이터 처리, 교차 AZ 전송, CloudWatch 로그 수집, 지운 인스턴스에 남아 있는 스냅샷. 하나하나는 작은데 합치면 어느새 몇 배가 되어 있습니다.
Lightsail은 월 얼마라고 하면 그 값입니다. 데이터 전송이 플랜에 포함되어 있고 고정 IP도 포함입니다. EC2는 전송이 GB당 과금이고 공인 IP가 시간당 과금인데, 여기는 다 들어 있습니다.
한계도 분명합니다. IAM 역할을 인스턴스에 붙여 다른 AWS 서비스를 자연스럽게 부르는 방식이 안 됩니다. 액세스 키를 넣어야 하는데 그건 키 관리 문제를 만듭니다. VPC 통합도 제한적이라 기본 VPC와 피어링은 되지만 프라이빗 서브넷 개념이 없습니다. 오토스케일은 없고, 수직 확장도 스냅샷을 떠서 더 큰 플랜으로 새로 만드는 방식입니다.
다만 막다른 길은 아닙니다. Lightsail 스냅샷은 EC2 AMI로 내보낼 수 있습니다.
aws lightsail export-snapshot --source-snapshot-name my-snapshot그래서 일단 Lightsail로 시작하고 커지면 EC2로 넘어가는 경로가 실제로 있습니다.
App Runner: 요금 구조가 다릅니다
컨테이너 이미지나 소스 저장소를 가리키면 나머지를 다 해줍니다. 로드밸런서, TLS 인증서, 도메인, 오토스케일, 배포가 서비스 안에 들어 있습니다. 교과서 구성에서 직접 조립하던 것들입니다.
여기서 눈여겨볼 건 요금을 세는 방식입니다. 프로비저닝된 메모리와 활성 vCPU를 나눠서 셉니다. 요청이 없으면 메모리 값만 내고, 요청을 처리하는 동안에만 vCPU를 셉니다.
Fargate는 요청이 있든 없든 vCPU를 그대로 냅니다. 그래서 대부분 노는 워크로드에서는 App Runner가 싸고, 트래픽이 꾸준하면 Fargate가 싸집니다. 손익 분기가 있습니다.
그리고 함정이 하나 있습니다. App Runner를 고를 때 가장 자주 밟는 지점입니다.
App Runner는 기본적으로 VPC 밖에서 돕니다. 인터넷은 자유롭게 나가지만 프라이빗 서브넷의 RDS에는 못 닿습니다. 붙이려면 VPC 커넥터를 만드는데, 커넥터를 붙이면 아웃바운드 트래픽이 전부 그 VPC를 타게 됩니다. 그러면 외부 API를 부르기 위해 NAT Gateway가 다시 필요해집니다.
1편에서 본 그 항목입니다. 관리형 서비스를 골라서 인프라를 안 다루려고 했는데, 조용히 최대 비용 항목이 돌아옵니다. 해법은 같습니다. RDS를 퍼블릭 엔드포인트로 두고 보안 그룹으로 막으면 커넥터도 NAT도 필요 없습니다.
콜드 스타트도 있습니다. 최소 인스턴스를 1 이상으로 두면 완화되지만 그만큼 프로비저닝 메모리 요금이 늘어납니다. 0으로 두면 싸지만 첫 요청이 느립니다.
진짜 차이는 요금이 아니라 백업입니다
여기가 이 글의 요점입니다.
세 구성을 요금순으로 늘어놓으면 Lightsail, EC2, App Runner 순입니다. 그런데 그 순서로 고르면 나중에 후회할 가능성이 큽니다. RDS를 쓰느냐 아니냐가 훨씬 큰 갈림길이기 때문입니다.
RDS는 자동 백업과 시점 복구를 인스턴스 요금 안에 포함해서 줍니다. 어제 오후 3시 상태로 되돌리는 게 콘솔에서 몇 번 클릭입니다.
EC2나 Lightsail에서 컨테이너로 데이터베이스를 돌리면 그중 아무것도 없습니다. 직접 만들어야 합니다. 방법은 크게 둘입니다.
볼륨 스냅샷을 뜨는 방식은 설정이 간단하고 AWS Backup으로 일정 관리까지 됩니다. 대신 복구 단위가 볼륨 전체라 특정 테이블만 되돌릴 수 없습니다.
논리 백업은 세밀합니다.
docker compose exec -T postgres pg_dump -U "$USER" "$DB" | gzip | \
aws s3 cp - "s3://버킷/backup/$(date +%F).sql.gz"대신 직접 짜야 하고, 크론에 걸어야 하고, 복구가 실제로 되는지 주기적으로 확인해야 합니다. 마지막 항목이 빠지기 쉬운데, 복구해 본 적 없는 백업은 백업이 아닙니다.
요금표에는 이 차이가 안 나옵니다. 데이터를 잃어 본 적이 있다면 관리형 데이터베이스 값의 의미가 다르게 보일 겁니다.
고정 아웃바운드 IP는 양 끝에만 있습니다
1편에서 다룬 문제가 여기서도 갈림길이 됩니다.
인스턴스 한 대짜리 구성은 그 인스턴스의 공인 IP가 고정입니다. 교과서 구성은 NAT Gateway가 고정해 줍니다. 중간에 있는 것들, 그러니까 App Runner나 NAT 없는 Fargate에는 고정 IP가 없습니다.
외부 API가 IP 화이트리스트를 요구한다면 중간 선택지가 통째로 사라집니다. 요금이나 편의성을 따지기 전에 이것부터 확인하는 게 순서입니다.
어떻게 고를 것인가
질문 순서로 좁히는 편이 빠릅니다.
먼저 외부 API가 IP 등록을 요구하는지 봅니다. 요구하면 인스턴스 한 대짜리이거나 NAT가 있는 구성뿐입니다.
다음으로 데이터를 잃으면 곤란한지 봅니다. 곤란하면 RDS 쪽으로 기울고, 아니면 논리 백업을 반드시 짭니다. "나중에 하지"가 가장 흔한 사고 원인입니다.
그다음이 서버 관리를 하고 싶은지, 트래픽이 늘어날 예정인지입니다. 이 둘은 나중에 바꾸기가 상대적으로 쉽습니다.
옮기기 쉽게 만들어 두면 됩니다
작게 시작하라는 조언이 무책임하지 않으려면 조건이 붙습니다. 나중에 옮기는 비용이 실제로 작아야 합니다.
컨테이너로 만들어 두고 네 가지를 지키면 그렇게 됩니다.
환경변수를 코드 한 곳에서만 읽습니다. Parameter Store로 가든 Secrets Manager로 가든 손댈 자리가 하나입니다.
파일시스템에 영구 상태를 두지 않습니다. Fargate나 App Runner는 컨테이너가 끝나면 디스크가 사라집니다. 업로드나 중간 산출물을 로컬 경로에 쓰면 그 시점에 깨집니다.
배치 작업을 재개 가능하게 만듭니다. 어디까지 처리했는지 기록해서 중단돼도 다시 띄우면 이어서 가게 합니다. 이렇게 해두면 Fargate Spot을 쓸 수 있어서 배치 비용이 크게 줄기도 합니다.
데이터베이스 확장을 늘리지 않습니다. RDS 지원 목록에 없는 확장 하나가 이전 자체를 막습니다.
이 넷을 지키면 구성 사이 이동이 인프라 작업으로 끝나고 앱 코드는 안 바뀝니다.
여기까지가 확실한 부분
요금 비교는 AWS 공식 요금 페이지 기준이고 리전마다 다릅니다. 절대 액수보다 구성 사이의 배수를 보시는 게 낫습니다. 그 배수는 리전이 바뀌어도 크게 흔들리지 않습니다.
어느 구성이 맞느냐는 팀 상황에 달렸습니다. 저는 작은 서비스에 교과서 구성을 처음부터 세우는 건 과하다고 보지만, 운영 인력이 있고 장애 대응 기준이 정해진 조직이라면 이야기가 다릅니다. 혼자 만드는 서비스와 팀이 운영하는 서비스는 같은 요금표를 보고도 다른 답이 나오는 게 맞습니다.
참고 자료는 Amazon EC2 요금, Amazon Lightsail 요금, AWS App Runner 요금 페이지입니다.
함께 읽기
- Fargate 교과서 구성: ALB와 NAT Gateway는 언제 필요할까?AWS 비용 대시보드를 열었는데 NAT Gateway가 Fargate보다 비싼 경우가 있습니다. 앱을 돌리는 값보다 앱이 인터넷으로 나가는 통로 값이 더 나가는 겁니다. 트래픽이 거의 없는 서비스에서도 그렇습니다.
- Zoho Mail 발송 도메인 구성: SMTP·IMAP 연동에서 막힌 지점들애플리케이션에서 메일을 자동으로 보내려고 발송 전용 도메인을 하나 세웠습니다. DNS 레코드를 넣고 인증을 붙이는 작업 자체는 30분쯤 걸렸습니다. 나머지 세 시간은 전부 다른 데서 썼습니다.
- 커널 패치는 왜 재부팅해야 적용될까? Livepatch 와 자동 재부팅새로 만든 서버를 점검하다가 이걸 봤습니다.
- ingress 와 egress: 터널 설정과 청구서에서 만난 두 방향하루에 두 번 이 단어들을 만났습니다. 오전에는 터널 설정 화면에서 ingress 를 봤고, 오후에는 데이터베이스 청구 항목에서 egress 를 봤습니다. 몇 년째 둘 다 쓰고 있었는데, 그날에서야 같은 축의 양쪽이라는 게 눈에 들어왔습니다.
- Cloudflare 무료 플랜과 한국 엣지: TTFB 1초의 원인 분해데모 사이트 하나가 느렸습니다. 첫 바이트까지 1초가 걸렸습니다. 대시보드를 여는 화면이라 무겁긴 한데, 그래도 1초는 이상했습니다. 앱을 뜯어볼 생각으로 시작했다가, 결국 앱은 한 줄도 안 고쳤습니다.