AWS Lambda와 RDS 연동 시 'Too Many Connections' 에러 완벽 방어: RDS Proxy 아키텍처
트래픽이 터지자마자 데이터베이스가 죽었다? 서버리스 Lambda의 역습과 RDS 커넥션 고갈 에러
"운영 서버를 관리할 필요가 없다는 말에 혹해서 AWS Lambda(서버리스)로 백엔드 API를 구축했습니다. 그런데 이벤트 첫날 트래픽이 몰리자마자 FATAL: Too many connections 에러를 뿜으며 데이터베이스(RDS)가 장렬하게 전사해버렸습니다."
서버리스(Serverless)의 환상에 빠진 클라우드 아키텍트 주니어들이 가장 크게 겪는 대참사입니다. AWS Lambda는 유저가 늘어나면 무한대에 가깝게 자동으로 인스턴스를 복제(Scale-out)하며 트래픽을 처리합니다. 겉보기엔 완벽한 시스템 같습니다.
하지만 그 뒤에 버티고 있는 RDBMS(MySQL, PostgreSQL 등)는 무한대가 아닙니다. 데이터베이스는 연결(Connection)을 맺을 때마다 막대한 메모리를 소모하며, 물리적인 최대 커넥션 한계가 존재합니다. 본 가이드에서는 Lambda의 폭주가 어떻게 DB의 숨통을 끊어놓는지 그 구조적 결함을 해체하고, AWS RDS Proxy를 도입하여 철벽의 방어막을 치는 엔터프라이즈 아키텍처를 단호하게 제시합니다.
📌 이 글의 핵심 포인트
- Lambda 콜드 스타트와 컨테이너 복제가 유발하는 DB 커넥션 폭탄의 원리
- 기존 Connection Pooling(HikariCP 등) 기법이 서버리스 환경에서 무용지물인 이유
- AWS RDS Proxy를 통한 중앙 통제형 커넥션 재사용(Multiplexing) 구축법
1단계: 원인 분석 - 무한 복제와 고갈의 늪
일반적인 EC2 웹 서버는 백엔드 애플리케이션(Spring, Node.js)이 켜질 때 미리 50~100개의 DB 커넥션을 맺어두고(Connection Pool), 유저들이 이를 돌려씁니다. 따라서 아무리 유저가 만 명이 몰려와도 DB 입장에서는 100개의 커넥션만 유지하면 되므로 평화롭습니다.
반면, Lambda는 함수가 호출될 때마다 독립적인 마이크로 컨테이너가 뜹니다. 트래픽이 폭주하여 Lambda 인스턴스가 1,000개가 동시에 실행되면, 각각의 Lambda가 DB에 1개씩 새로운 연결을 시도합니다. 1,000개의 망치가 동시에 DB의 문을 두드리는 꼴입니다. RDS의 max_connections 허용치를 가볍게 초과하며 데이터베이스는 뻗어버립니다.
2단계: 1차 방어선 - 람다 핸들러(Handler) 외부 초기화
초보자들이 흔히 하는 실수는 Lambda의 handler 함수 내부에서 DB를 연결하는 것입니다. 이렇게 하면 함수가 실행될 때마다 연결과 종료(TCP Handshake)를 반복하므로 속도도 느리고 지연이 극심해집니다.
const mysql = require('mysql2/promise');
// ❌ 람다가 켜질 때마다 무조건 새로운 DB 연결을 맺는 최악의 패턴
exports.handler = async (event) => {
const connection = await mysql.createConnection({ ... });
// 로직 처리...
};
// ✅ 핸들러 외부(글로벌 공간)에 선언하여 컨테이너 재사용(Warm Start) 시 커넥션을 공유함
let dbConnection = null;
exports.handler = async (event) => {
if (!dbConnection) {
dbConnection = await mysql.createConnection({ ... });
}
// 로직 처리...
};
이 코드 한 줄로 기존에 켜져 있던 람다 컨테이너(Warm Start)는 DB 연결을 재사용하게 됩니다. 하지만 트래픽이 급증하여 새로운 람다가 수천 개 뜨는 상황(Scale-out)까지 막아주지는 못합니다.
3단계: 엔터프라이즈 완벽 해결책 - AWS RDS Proxy 도입
서버리스와 RDBMS의 태생적 궁합 문제를 완벽하게 해결하기 위해 아마존이 내놓은 무기가 바로 RDS Proxy입니다.
아키텍처를 변경하여 Lambda가 RDS(데이터베이스)를 직접 바라보게 하지 마십시오. 중간에 RDS Proxy라는 거대한 교통경찰을 세워둡니다. Lambda는 무조건 Proxy에게 연결을 시도합니다. 1,000개의 람다가 몰려와도 Proxy는 뒤에 있는 RDS와 단 100개의 안전한 커넥션 풀만 유지한 채, 람다들의 요청을 잘게 쪼개서(Multiplexing) 100개의 파이프로 우아하게 통과시킵니다.
당신의 코드를 바꿀 필요는 전혀 없습니다. 그저 AWS 콘솔에서 RDS Proxy를 생성하고, 환경변수의 DB_HOST 주소를 RDS의 엔드포인트에서 RDS Proxy의 엔드포인트로 글자 몇 개만 교체하면 끝납니다. DB 고갈 에러는 영원히 소멸합니다.
🙋♂️ 자주 묻는 질문 (FAQ)
Q. NoSQL(DynamoDB)을 쓰면 이런 에러가 없나요?
A. 맞습니다. DynamoDB는 커넥션 기반이 아니라 HTTP API 호출 기반이므로 커넥션 풀링 문제가 아예 존재하지 않습니다. 그래서 서버리스 아키텍처(Lambda)를 구축할 때는 가급적 DynamoDB를 사용하는 것이 베스트 프랙티스(Best Practice)입니다.
💡 핵심 정리 및 마무리
클라우드 기술이 진보하여 서버 관리가 사라졌다고 해서, 인프라의 물리적 법칙까지 무시할 수는 없습니다. 확장의 무한함을 자랑하는 컴퓨팅 파워(Lambda)와, 정합성을 위해 제약을 감수해야 하는 저장소(RDBMS) 사이의 극심한 패러다임 충돌을 직시하십시오. 이 두 세계를 우아하게 연결하는 프록시(Proxy) 아키텍처를 도입하는 순간, 당신의 서비스는 트래픽 폭주 앞에서도 결코 무너지지 않을 것입니다.
댓글
댓글 쓰기