본문으로 건너뛰기

AWS 아키텍처

⚠︎ 지난 판 — 2026-07-26. 현재 판은 여기다. 이 문서는 그때의 기록이고 고치지 않는다.

갱신일 2026-07-26 · 기준: infra@0c6f7b0 (main) · server@bf192cc · ai@60ee59a · web@87e0834 Terraform이 만드는 것과 사람이 손으로 하는 것을 갈라 적는다. 앞 절만 코드로 확인된 것이고, 뒤 절은 저장소에 없다.

확인한 사실 — Terraform이 만드는 것

heymoa-infraterraform/environments/prod가 소유하는 범위다. 계정 110080810555, 리전 ap-northeast-2.

리소스근거
VPC · subnet10.30.0.0/16, public 1 + private data 2(AZ 2개). NAT Gateway 없음network.tf
EC2t4g.small ARM64 1대, EIP 고정, lifecycle.ignore_changes = [ami, user_data]application.tf
인바운드80·443만. SSH 22도 8080도 열지 않는다 — 접속은 SSM같은 파일
user_dataSSM Agent 설치·기동뿐. Docker·Git·Nginx·Certbot은 접속 후 사람이 설치같은 파일
RDSheymoa-prod-postgres, db_name = "heymoa", 마스터 유저 heymoa_admin, manage_master_user_password = truedatabase.tf
RDS 접근EC2 보안그룹에서 오는 5432만. IP CIDR 허용 없음같은 파일
IAMEC2 Role에 AmazonSSMManagedInstanceCore + 그 Secret 하나의 GetSecretValueapplication.tf · database.tf
stateS3 heymoa-prod-terraform-state-110080810555, use_lockfile = true, bootstrap이 prevent_destroyversions.tf · bootstrap/main.tf

쓰지 않는 것도 코드가 말한다 — ALB·ACM·NAT Gateway·SSH key·애플리케이션용 S3가 없고, module/tfvars 분리도 하지 않았다.

RDS는 삭제가 쉽게 열려 있다. deletion_protection = false, skip_final_snapshot = true다. infra README가 "실제 사용자 데이터가 생기면 둘 다 반대로 바꾼다"고 조건을 적어 뒀다.

설계 전제

  • 한 대를 손으로 굴린다. EC2 안의 Git·Docker·Nginx·Certbot은 Terraform 밖이고, ignore_changes가 AMI 갱신으로 인스턴스가 교체되는 것을 막는다. CI/CD와 immutable deployment를 도입할 때 이 예외를 걷는다.
  • DB 비밀번호를 코드가 갖지 않는다. RDS가 Secret을 만들고 회전하며, EC2는 IAM Role로 읽는다. 회전 뒤에도 .env에 복사해 쓴다면 값 갱신과 컨테이너 재기동이 필요하다.
  • 공개 진입은 Cloudflare A 레코드 → EIP → EC2의 Nginx 하나뿐이다. 앱 컨테이너는 127.0.0.1에만 바인딩한다(server 포트 8080·actuator 8081이 그렇게 설정돼 있다).
  • MVP 비용 상한을 의도적으로 낮게 잡았다. infra README 기준 월 약 $62이고, Docker 빌드 중 메모리가 부족할 때만 t4g.medium으로 올린다.

미확인 — 저장소에 없는 배포 경로

추정을 사실로 적지 않는다. 아래는 코드로 확인되지 않았고, 값이 확인되면 위 절로 올린다.

무엇지금 아는 것확인 못 한 것어디를 봐야 하나
heymoa-ai가 어디에 뜨나ai 레포에는 로컬 docker-compose.yml만 있고 운영 배포는 "heymoa-infra 소유"라고만 적혀 있다. Terraform에는 ai를 가리키는 리소스가 없다같은 EC2에 함께 올리는지, 인스턴스 수, 이미지가 ARM64로 빌드되는지EC2의 compose 파일
heymoa_ai databaseRDS가 만드는 database는 heymoa 하나다heymoa_ai database를 누가 언제 만드는지, CREATE EXTENSION vector를 어디서 도는지RDS 안의 실제 database 목록
checkpoint 테이블 생성 시점ai가 기동 때 saver.setup()을 부르고, 실패하면 채팅만 죽는다배포 스텝으로 분리했는지배포 절차 문서
마이그레이션 직렬화Alembic이 앱과 분리된 일회성 스텝인 것까지인스턴스가 여럿일 때 동시 실행을 막는 장치배포 스크립트
heymoa-web 호스팅@vercel/analytics·@vercel/speed-insights 의존과 heymoa.app 도메인vercel.json.github/workflows/도 없다 — 빌드·배포 주체와 환경변수 주입 지점Vercel 프로젝트 설정
관측 스택infra 레포에 Prometheus·Loki·Tempo·Grafana compose가 있으나 커밋 메시지가 "이전 서버의 모니터링 템플릿(legacy)"이다지금 운영에 붙어 있는지EC2 실행 중인 컨테이너
Langfuseai는 키가 있을 때만 트레이싱을 붙인다운영에서 키를 넣었는지 (넣으면 전사 원문이 외부로 나간다).env.prod