바이브코딩 서비스를 Docker 컨테이너로 실전서비스 론칭하기 · 2부 — 이미지 레지스트리, AWS 인프라(콘솔)

12장. RDS 데이터베이스 생성

11장에서 네트워크 집(VPC)을 지었습니다. 이제 그 집의 가장 안쪽 방 (프라이빗 서브넷)에 첫 입주자를 들입니다. 바로 데이터베이스입니다. 1부에서는 PostgreSQL을 Docker 컨테이너로 내 컴퓨터에 띄웠는데, 실제 서비스에서는 AWS가 대신 운영해 주는 데이터베이스, RDS를 씁니다. 왜 그런지부터 차근차근 봅니다.

[지금 여기]

우리는 22단계를 거쳐 "라이브 투표 서비스"를 직접 만들고, 컨테이너에 담아, AWS 클라우드에 배포합니다. 아래가 그 전체 여정 지도입니다. 지금은 12단계, RDS 데이터베이스를 만들 차례입니다.

  1. 1장개발 환경 준비 (터미널 / Node.js / Git / GitHub / VS Code / Claude Code)
  2. 2장Claude Code 사용법 익히기
  3. 3장무엇을 만들지 기획 (라이브 투표 서비스)
  4. 4장로컬에서 서비스 만들기 (React + Express + PostgreSQL)
  5. 5장Docker 개념
  6. 6장Dockerfile 작성
  7. 7장컨테이너 빌드·실행
  8. 8장AWS 시작 (계정 / IAM / 리전 / 비용)
  9. 9장이미지 태깅
  10. 10장ECR에 이미지 올리기
  11. 11장VPC 네트워크 구성
  12. 12장RDS 데이터베이스 생성
  13. 13장SSM 터널로 RDS 초기화
  14. 14장ECS Fargate + ALB로 배포 (기본 완성)
  15. 15장CI/CD (GitHub Actions)
  16. 16장IaC (Terraform)
  17. 17장배포 자동화 연결
  18. 18장현업 운영 구조 이해
  19. 19장무중단 배포
  20. 20장신규 버전 배포 & 롤백
  21. 21장(심화) 프론트를 Vercel로 분리 배포
  22. 22장마무리 (회고 + 리소스 삭제)

이번 장에서 완성되는 것

한 문장으로: 11장에서 만든 vote-vpc의 프라이빗 서브넷 안에, 인터넷에 노출되지 않는 PostgreSQL 데이터베이스(vote-db)를 만들고, 접속 주소(엔드포인트)를 손에 넣습니다.

이렇게 되면 성공입니다: RDS 콘솔의 데이터베이스 목록에 vote-db가 보이고, 상태가 사용 가능(Available) 이며, 상세 화면에서 vote-db.xxxx.ap-northeast-2.rds.amazonaws.com 형태의 엔드포인트 주소를 복사할 수 있습니다.

사전 조건

이 장은 1~11장까지 따라온 결과물 위에서 시작합니다. 아래가 갖춰져 있어야 합니다. 하나라도 안 돼 있으면 해당 장으로 돌아가세요.

이 세 가지만 확인되면 바로 시작할 수 있습니다.

12.1 왜 DB를 컨테이너가 아닌 RDS로 두는가

"1부처럼 DB도 그냥 컨테이너로 띄우면 안 되나?"라는 의문이 자연스럽게 듭니다. 기술적으로는 가능하지만, 실무에서는 보통 그렇게 하지 않습니다. 이유를 이해하려면 먼저 컨테이너와 데이터의 궁합을 알아야 합니다.

컨테이너는 "언제든 갈아치우는" 것

컨테이너의 장점은 가볍게 만들었다 지웠다 할 수 있다는 것입니다. 새 버전을 배포할 때도 기존 컨테이너를 지우고 새 컨테이너로 갈아 끼웁니다. 그런데 데이터베이스는 정반대의 성질을 가집니다. 데이터는 절대 사라지면 안 되고, 오래오래 쌓여야 합니다. "언제든 갈아치우는 상자" 안에 "절대 잃으면 안 되는 데이터"를 넣는 건 궁합이 나쁩니다.

게다가 데이터베이스를 직접 운영하려면 할 일이 많습니다. 정기 백업, 소프트웨어 보안 패치, 장애 시 복구, 용량 관리… 이걸 전부 직접 하는 건 전문 관리자(DBA)의 일입니다. 그래서 이 궂은일을 AWS에 맡깁니다.

용어

관리형 서비스(Managed Service) 설치·백업·업데이트·장애 복구 같은 운영 궂은일을 클라우드 업체가 대신 해 주는 서비스입니다. 나는 "사용"에만 집중하면 됩니다. 월세 집에서 보일러가 고장 나면 집주인이 고쳐 주는 것과 비슷합니다.

용어

RDS(Relational Database Service) AWS의 관리형 데이터베이스 서비스입니다. PostgreSQL, MySQL 같은 데이터베이스를 클릭 몇 번으로 만들어 주고, 백업·패치·복구를 AWS가 대신 관리해 줍니다. 우리는 1부와 같은 PostgreSQL을 RDS로 만듭니다.

정리하면 이렇습니다.

이 분리가 실무 배포 구조의 기본 틀입니다. 3부에서 앱을 마음껏 배포하고 롤백할 수 있는 것도, 데이터가 앱과 분리되어 RDS에 안전하게 있기 때문입니다.

[활용 사례] 관리형 데이터베이스는 실무에서 이렇게 쓰인다

관리형 DB(RDS)는 우리 투표 서비스에만 쓰는 특별한 도구가 아닙니다. 현업에서 데이터를 다루는 거의 모든 서비스가 비슷한 이유로 이걸 씁니다. 몇 가지 대표적인 장면을 봅시다.

  1. 백업·패치·복구를 사람 대신 클라우드가 한다. 스타트업에 DBA가 따로 없어도, RDS는 매일 자동으로 백업을 뜨고, DB 소프트웨어의 보안 패치를 정해진 시간에 대신 적용합니다. "어제 밤 12시 상태로 되돌려 주세요" 같은 시점 복구도 콘솔 클릭 몇 번이면 됩니다. 직접 서버에 PostgreSQL을 깔아 운영하면 이 모든 걸 사람이 챙겨야 합니다.
  2. 장애가 나도 서비스가 안 멈추게(다중 AZ 고가용성). 쇼핑몰이나 은행 앱처럼 잠깐도 멈추면 안 되는 서비스는 RDS의 "다중 AZ(Multi-AZ)" 기능을 켭니다. 똑같은 예비 DB를 다른 가용영역(다른 데이터센터)에 하나 더 두고, 주 DB에 장애가 나면 몇십 초 안에 예비로 자동 전환합니다. 사람이 새벽에 깨서 손쓸 필요가 없습니다.
  3. 트래픽이 늘면 성능만 키운다. 이용자가 늘어 DB가 버거워지면, 콘솔에서 인스턴스 등급(성능)만 한 단계 올리거나, 읽기 전용 복제본을 추가해 부하를 나눕니다. 데이터를 옮기거나 새로 설치할 필요가 없습니다.
  4. 왜 굳이 컨테이너가 아니라 관리형인가. 넷플릭스·에어비앤비 같은 회사도 애플리케이션(앱)은 컨테이너로 수시로 배포·교체하지만, 데이터를 담는 DB는 이렇게 관리형 서비스에 맡겨 분리합니다. "자주 갈아치우는 앱"과 "절대 잃으면 안 되는 데이터"를 떼어 두는 것이 안정적인 서비스의 기본 공식이기 때문입니다.

이처럼 관리형 DB는 "운영 부담을 클라우드에 넘기고, 우리는 서비스 로직에 집중한다"는 목적으로 널리 쓰입니다. 우리도 같은 이유로 RDS를 씁니다.

[맛보기] RDS 콘솔 둘러보기

실제로 만들기 전에, RDS 콘솔이 어떻게 생겼는지 눈으로 한 번 둘러봅시다. 이 맛보기에서는 아무것도 만들지 않습니다. 화면만 열어 봅니다.

  1. AWS 콘솔 오른쪽 위 리전이 서울(ap-northeast-2) 인지 확인합니다.
  2. 상단 검색창에 RDS를 입력하고, 나온 RDS 서비스를 클릭해 들어갑니다.
  3. RDS 대시보드가 열립니다. 왼쪽 메뉴에서 데이터베이스(Databases) 를 눌러 보세요. 지금은 만든 게 없어 목록이 비어 있습니다. (이 목록에 잠시 뒤 vote-db가 생깁니다.)
  4. 오른쪽 위 데이터베이스 생성(Create database) 버튼을 눌러 봅니다. 생성 화면 맨 위에 엔진 옵션(Engine options) 이 나오는데, Aurora, MySQL, PostgreSQL, MariaDB, Oracle, SQL Server 등 AWS가 관리해 주는 여러 데이터베이스 종류가 카드로 보입니다. "관리형으로 고를 수 있는 DB가 이렇게 많구나" 하고 눈에 익혀 두세요.
  5. 지금은 여기까지만 둘러보고, 아직 생성하지 마세요. 화면을 그대로 둔 채 다음 12.2절로 넘어가, 우리 프로젝트용 값을 하나씩 채워 실제로 만듭니다.

이렇게 콘솔의 전체 모양을 먼저 봐 두면, 다음 절에서 설정 항목이 많아도 덜 낯섭니다.

12.2 우리 프로젝트의 RDS 인스턴스 만들기

이제 방금 열어 둔 생성 화면에서, 우리 투표 서비스용 값을 채워 만듭니다. 설정 항목이 많지만, 우리가 신경 쓸 것만 짚어 가며 진행합니다.

용어

DB 인스턴스(DB Instance) RDS로 만드는 데이터베이스 서버 한 대를 부르는 말입니다. "인스턴스"는 AWS에서 "실행 중인 서버 하나"를 가리키는 흔한 표현입니다.

[콘솔] RDS 생성

주의

시작 전에 오른쪽 위 리전이 서울(ap-northeast-2) 인지 다시 한번 확인하세요. 리전이 다르면 11장에서 만든 vote-vpc가 보이지 않습니다.

맛보기에서 열어 둔 데이터베이스 생성(Create database) 화면에서 이어 갑니다. (닫았다면 RDS → 데이터베이스 → 데이터베이스 생성으로 다시 엽니다.) 위에서부터 차례로 설정합니다.

  1. 데이터베이스 생성 방식: 표준 생성(Standard create) 을 선택합니다.
    • 손쉬운 생성(Easy create)은 설정이 숨겨져 있어, 배우는 지금은 표준으로 하나씩 보며 갑니다.
  2. 엔진 옵션(Engine options): PostgreSQL 을 선택합니다.
    • [용어] 엔진(Engine): 데이터베이스의 종류를 말합니다. 1부 로컬에서 쓴 것과 같은 PostgreSQL을 고릅니다.
    • 엔진 버전은 기본으로 표시되는 최신 버전을 그대로 두면 됩니다.
  3. 템플릿(Templates): 프리 티어(Free tier) 또는 Sandbox 를 선택합니다.
    • [참고] 계정 유형에 따라 이 항목의 이름이 다르게 표시됩니다. 예전 방식의 무료 플랜 계정에는 프리 티어로, 최근 개편된 계정에는 Sandbox(샌드박스) 로 나타납니다. 어느 쪽이든 비용이 적게 나오는 설정들(가장 작은 인스턴스, 단일 AZ 등)이 자동으로 잡힙니다. 둘 다 안 보이면 개발/테스트(Dev/Test) 를 고르고, 아래 인스턴스 구성에서 가장 작은 크기를 직접 선택하세요.
  4. 설정(Settings) 을 입력합니다.
    • DB 인스턴스 식별자(DB instance identifier): vote-db 라고 입력합니다. (이 DB 서버의 이름입니다.)
    • 마스터 사용자 이름(Master username): postgres (기본값 그대로 둡니다.)
    • 자격 증명 관리(Credentials management): 자체 관리(Self managed) 를 선택하고, 그 아래 마스터 암호(Master password)암호 확인에 내가 정한 비밀번호를 직접 입력합니다.
      • [주의] 이 암호는 DB의 최고 관리자 비밀번호입니다. 안전한 곳에 그대로 적어 두세요. 잠시 뒤 접속 정보 표에 넣고, 13장 터널링 접속과 14장 배포에서 씁니다. 나중에 다시 볼 수 없으니 지금 기록하는 게 중요합니다.
      • [참고] 바로 위에 AWS Secrets Manager에서 관리 옵션도 보입니다. 실무에서 더 안전한 방식인데, 추가 요금이 붙습니다. 그게 무엇인지는 12.5에서 개념으로 설명하고, 이번 실습은 개념부터 익히기 위해 "자체 관리"로 진행합니다.
  5. 인스턴스 구성(Instance configuration): 프리 티어/Sandbox 템플릿이면 가장 작은 크기(예: db.t3.micro 또는 db.t4g.micro)가 자동 선택돼 있습니다. 그대로 둡니다.
    • [용어] 인스턴스 크기: DB 서버의 성능(CPU·메모리) 등급입니다. micro는 가장 작은, 학습·테스트용 크기입니다.
  6. 연결(Connectivity)이 부분이 이 장에서 가장 중요합니다. 천천히 봅니다.
    • 컴퓨팅 리소스에 연결: EC2 컴퓨팅 리소스에 연결 안 함(Don't connect to an EC2 compute resource) 을 선택합니다. (아직 붙일 서버가 없습니다. 연결은 14장에서 ECS로 합니다.)
    • VPC: 11장에서 만든 vote-vpc 를 선택합니다.
      • [주의] 기본(Default) VPC가 아니라, 우리가 만든 vote-vpc를 골라야 합니다. 여기를 놓치면 엉뚱한 네트워크에 DB가 생깁니다.
    • DB 서브넷 그룹(DB subnet group): 자동 생성되는 항목을 그대로 둡니다. (이게 뭔지는 다음 12.3에서 설명합니다.)
    • 퍼블릭 액세스(Public access): 반드시 아니요(No) 를 선택합니다.
      • [주의] 이 실습에서 가장 중요한 보안 설정입니다. "예"로 하면 DB가 인터넷에 직접 노출됩니다. 11장에서 설계한 대로, DB는 프라이빗 서브넷에 숨기고 우리 서버만 접근하게 합니다.
    • VPC 보안 그룹(VPC security group): 새로 생성(Create new) 을 선택하고, 새 VPC 보안 그룹 이름vote-db-sg 라고 입력합니다.
      • 11장에서 설계했던 "RDS 보안 그룹"이 여기서 실제로 만들어집니다. "누구를 들여보낼지"(ECS에서만 허용) 규칙은 14장에서 ECS를 만든 뒤 연결합니다.
    • 가용 영역(Availability Zone): 기본 설정 없음(No preference) 그대로 둡니다.
  7. 추가 구성(Additional configuration) 을 펼칩니다. (연결 항목 아래에 접혀 있는 "추가 구성"을 클릭하면 열립니다.)
    • 초기 데이터베이스 이름(Initial database name): voteapp 이라고 입력합니다.
      • [주의] 이 항목은 접혀 있는 "추가 구성" 안에 있어서 놓치기 쉽습니다. 반드시 펼쳐서 입력하세요.
      • [참고] 이걸 비워 두면 DB 서버만 생기고 그 안에 담을 데이터베이스가 없어서, 나중에 직접 만들어야 합니다. 지금 입력해 두면 13장에서 바로 표를 만들 수 있습니다.
    • 백업·모니터링 등 나머지 설정은 기본값 그대로 둡니다.
  8. 맨 아래 월별 추정 요금(Estimated monthly costs) 을 한번 훑어보고, 데이터베이스 생성(Create database) 버튼을 누릅니다.
  9. 데이터베이스 목록으로 돌아옵니다. vote-db의 상태가 생성 중(Creating) 으로 표시되고, 사용 가능(Available) 이 될 때까지 보통 5~10분 정도 걸립니다.
확인

데이터베이스 목록에서 vote-db의 상태가 사용 가능(Available) 이 되면 성공입니다. 기다리는 동안 다음 12.3절을 읽어 두세요.

12.3 DB 서브넷 그룹과 보안 그룹 — 방금 무슨 일이 있었나

생성 화면에서 그냥 지나친 항목 두 가지를 이해하고 갑시다. 11장 개념과 바로 이어집니다.

용어

DB 서브넷 그룹(DB Subnet Group) "RDS를 어느 서브넷들에 둘 수 있는지"를 정한 목록입니다. RDS는 규칙상 서로 다른 AZ에 있는 서브넷 2개 이상을 요구합니다. 11장에서 우리가 AZ 2개에 프라이빗 서브넷을 만들어 둔 덕분에, 이 조건이 자연스럽게 충족됐습니다. (사전 조건에서 확인한 그 2개입니다.)

왜 서브넷이 2개나 필요할까요? 지금 우리 DB는 한 대지만, 앞의 활용 사례에서 본 "다중 AZ(Multi-AZ)" 기능 때문입니다. 예비 DB를 다른 AZ에 하나 더 두고, 주 DB에 장애가 나면 자동으로 예비로 전환하는 기능인데, 그 예비가 들어갈 자리를 미리 확보해 두는 것이 서브넷 그룹입니다. (우리는 비용 때문에 다중 AZ를 켜지 않지만, 실무 운영에서는 켜는 것이 일반적입니다.)

보안 그룹은 어떨까요? 방금 vote-db-sg를 만들었지만, 아직 "누구를 들여 보낼지" 규칙이 완성되지 않았습니다. 11장 설계를 다시 보면:

그런데 ECS는 아직 만들지 않았으니(14장), 지금은 가리킬 대상이 없습니다. 그래서 이 규칙은 14장에서 ECS를 만든 뒤 완성합니다. 지금 기억할 것은 하나입니다. DB는 지금 프라이빗 서브넷에 있고, 보안 그룹이 아직 아무도 들여보내지 않아 완전히 잠긴 상태라는 것. 안전하게 잠가 두고 시작하는 것이 올바른 순서입니다.

12.4 접속 정보 확인 — 엔드포인트

DB가 "사용 가능" 상태가 되면, 접속에 필요한 정보를 확인해 둡시다.

용어

엔드포인트(Endpoint) DB 서버의 접속 주소입니다. vote-db.xxxxxxxx.ap-northeast-2.rds.amazonaws.com 같은 형태입니다. 10장 ECR에서 본 "주소"처럼, IP 주소 대신 이 이름을 쓰면 AWS가 내부적으로 알아서 실제 서버로 연결해 줍니다.

[콘솔] 접속 정보 확인

  1. RDS 콘솔의 데이터베이스 목록에서 vote-db를 클릭합니다.
  2. 연결 및 보안(Connectivity & security) 탭에서 확인합니다.
    • 엔드포인트(Endpoint): vote-db.xxxx.ap-northeast-2.rds.amazonaws.com 형태의 주소. 복사해 두세요.
    • 포트(Port): 5432 (PostgreSQL의 기본 포트입니다.)

이로써 앱이 DB에 접속하는 데 필요한 다섯 가지가 모두 준비됐습니다. 아래 표를 채워 안전한 곳에 적어 두세요.

항목
호스트(주소) 엔드포인트 (위에서 복사한 것)
포트 5432
데이터베이스 이름 voteapp
사용자 이름 postgres
비밀번호 12.2에서 정한 마스터 암호

이 다섯 가지가 4장에서 .env로 분리했던 바로 그 값들의 "AWS 버전"입니다. 13장에서 이 값으로 DB에 접속해 표를 만들고, 14장에서 컨테이너를 띄울 때 이 값들을 환경변수로 넣어 줍니다.

주의

이 접속 정보(특히 비밀번호)는 코드나 GitHub에 절대 올리지 마세요. 1부에서 배운 원칙 그대로입니다.

12.5 DB 자격 증명 관리 — Secrets Manager

12.2에서 지나친 "AWS Secrets Manager에서 관리" 옵션을 개념으로 소개합니다.

용어

Secrets Manager(시크릿 매니저) 비밀번호 같은 민감한 값을 AWS가 금고처럼 보관해 주는 서비스입니다. 앱은 비밀번호를 직접 들고 있지 않고, 실행될 때 이 금고에서 꺼내 씁니다. 비밀번호를 주기적으로 자동 교체해 주는 기능도 있습니다.

.env 파일과 비교하면 이렇습니다. .env는 값을 파일로 들고 다니는 방식이라, 파일이 새어 나가면 끝입니다. Secrets Manager는 값이 AWS 금고 안에만 있고 필요한 순간에만 꺼내 쓰므로 더 안전합니다. 실무에서는 RDS 생성 시 자격 증명 관리에서 "AWS Secrets Manager에서 관리"를 선택해 처음부터 금고에 넣기도 합니다. (12.2에서 우리가 안 고른 그 옵션입니다.)

이 실습에서는 개념을 익히는 것이 먼저라 자체 관리(비밀번호 직접 입력) 방식으로 진행하고, 14장에서 환경변수로 전달합니다. "실무에서는 금고(Secrets Manager)에 맡기는 것이 더 안전하다"는 것만 기억해 두세요.

[확인]

이번 장이 제대로 끝났는지 눈으로 확인합니다.

여기까지 됐다면, 데이터베이스는 프라이빗 서브넷 안에 안전하게 자리 잡았습니다. 그런데 지금은 너무 꽁꽁 잠가 둔 탓에 우리조차도 이 DB에 들어갈 길이 없습니다. 보안 그룹이 아무도 들여보내지 않고, 퍼블릭 액세스도 꺼 놨으니까요. 바로 이 잠긴 방에 우리만 잠깐 들어가 표를 만드는 일이, 여정 지도의 바로 다음 칸인 13장(SSM 터널로 RDS 초기화)에서 할 일입니다.

막히면

이 장에서 자주 나는 오류와 대처법입니다.

[체크리스트]

아래가 모두 됐는지 확인하세요. 하나라도 안 됐다면 해당 절로 돌아갑니다.

모두 체크됐다면, 잠긴 데이터베이스가 프라이빗 서브넷에 준비된 것입니다.