이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- RDS Proxy나 Cloud SQL 커넥션 풀링은 어떤 문제를 줄여주는가?
- 애플리케이션 풀과 DB 프록시는 어떤 관계인가?
- 인프라 인력은 DB 연결 폭주를 왜 부담스러워하는가?
개요
클라우드 환경에서는 애플리케이션 인스턴스가 늘고 줄면서 DB 연결 수가 크게 변한다. 서버리스, 오토스케일링, 짧은 수명의 컨테이너는 연결 폭주를 만들 수 있다.
AWS RDS Proxy, Google Cloud SQL의 커넥션 관리와 풀링 기능은 이런 문제를 줄이는 데 도움을 준다. 그러나 프록시가 DB 한계를 없애는 것은 아니다. 애플리케이션 풀, 프록시, DB max connections, 트랜잭션 특성을 함께 이해해야 한다.
원리
일반 연결 흐름은 다음과 같다.
Application HikariCP
DB connection
Database프록시를 두면 다음처럼 된다.
Application HikariCP
Proxy connection
RDS Proxy 또는 Cloud SQL Pooling
DB backend connection
Database프록시는 애플리케이션의 많은 연결을 DB의 더 적은 backend connection으로 효율적으로 관리하려고 한다. 특히 연결 생성 비용과 폭주를 줄이는 데 도움이 된다.
다만 프록시가 항상 connection을 마음대로 multiplexing할 수 있는 것은 아니다. 트랜잭션, 세션 변수, prepared statement, temporary table 같은 세션 상태가 있으면 특정 client connection이 backend connection에 묶이는 현상이 생길 수 있다. 서비스가 어떤 DB 기능을 쓰는지에 따라 프록시 효율이 달라진다.
프록시가 해결하는 것과 못 하는 것
프록시가 도와줄 수 있는 것:
- 연결 생성 비용 감소
- 갑작스러운 연결 폭주 완화
- DB failover 시 연결 관리 개선
- 서버리스 환경의 connection storm 완화
프록시가 해결하지 못하는 것:
- 느린 쿼리
- 잘못된 인덱스
- 긴 트랜잭션
- lock wait와 deadlock
- DB CPU와 I/O 한계
- hot row 병목
프록시를 붙였는데도 쿼리가 10초 걸리면 DB backend connection은 그 시간 동안 일한다. 프록시는 마법의 성능 계층이 아니다.
따라서 프록시 도입 후에도 다음 지표를 함께 본다.
- proxy client connections
- proxy backend/database connections
- borrow/acquire latency
- pinned session 또는 session state 관련 지표
- DB active session과 CPU/I/O
- failover 중 에러율과 재연결 시간
애플리케이션 풀과의 관계
프록시를 쓰더라도 애플리케이션 풀을 무제한으로 키우면 안 된다. 애플리케이션 풀은 여전히 요청 스레드와 동시 DB 작업 수를 제한하는 장치다.
spring.datasource.url=jdbc:postgresql://my-rds-proxy.proxy-xxx.ap-northeast-2.rds.amazonaws.com:5432/app
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.connection-timeout=2000프록시 뒤에 DB가 있다고 해서 maximumPoolSize=100을 각 인스턴스에 설정하면 애플리케이션은 너무 많은 동시 SQL을 프록시로 보낸다. 프록시는 일부를 backend connection에 매핑하지만, DB 작업 자체가 많으면 병목은 그대로다.
애플리케이션 pool은 여전히 bulkhead다. 프록시가 있더라도 API 서버가 동시에 보낼 SQL 수를 제한해야 하고, batch/export는 별도 제한을 두는 편이 안전하다.
인프라/DBA의 고충
인프라 담당자는 DB를 단순히 “연결만 받는 서버”로 보지 않는다. 연결 폭주는 다음 문제를 만든다.
- DB 메모리 사용 증가
- 인증과 세션 생성 비용 증가
- failover 시 재연결 폭주
- max connections 초과
- 모니터링과 원인 분석 어려움
- 정상 운영자 접속까지 막힘
개발자가 배포로 인스턴스 수를 늘리거나 batch를 추가할 때 DB 연결 예산을 공유하지 않으면 인프라 입장에서는 갑자기 DB 앞에 트래픽이 몰린다. 그래서 변경 전 “인스턴스 수 x pool size x 배치 동시성”을 함께 알려주는 개발자가 협업을 훨씬 쉽게 만든다.
개인 프로젝트 기준
개인 프로젝트에서는 RDS Proxy까지 항상 필요하지는 않다. 대신 다음은 챙긴다.
- pool size를 작게 명시한다.
- DB max connections를 확인한다.
- local, dev, prod 설정을 분리한다.
- connection timeout과 query timeout을 둔다.
- 배치와 API가 동시에 DB를 압박하지 않게 한다.
작은 프로젝트에서도 이 기준을 문서화하면 운영 감각이 드러난다.
실전 팁
- 서버리스나 급격한 오토스케일링 환경에서는 DB 프록시를 적극 검토한다.
- 프록시 도입 후에도 slow query와 lock wait는 별도로 해결한다.
- failover 테스트에서 애플리케이션 pool이 어떻게 반응하는지 본다.
- 프록시 지표와 DB 지표를 함께 대시보드에 둔다.
- 인프라에 변경을 요청할 때는 예상 연결 수와 트랜잭션 특성을 같이 설명한다.
- transaction pooling/multiplexing이 세션 상태 때문에 제한되는지 공식 문서와 실제 지표로 확인한다.
- 프록시 도입 전후로 connection storm, failover, pool pending, query latency를 비교한다.
- ORM/JDBC가 세션 변수나 prepared statement를 어떻게 쓰는지 인프라와 공유한다.
위험 신호!
- 프록시를 붙였으니 pool size를 크게 늘려도 된다고 생각한다.
- 서버리스 함수가 요청마다 직접 DB에 연결한다.
- failover 상황에서 모든 인스턴스가 동시에 재연결한다.
- DB max connections에 운영 접속 여유가 없다.
- 프록시 도입 후 느린 쿼리 분석을 중단한다.
- 프록시가 있으니 long transaction과 session state가 문제가 되지 않는다고 생각한다.
- proxy 지표는 보지 않고 DB 지표만 보거나, 반대로 DB active session 없이 proxy 연결 수만 본다.
- failover 테스트 없이 프록시가 재연결을 알아서 처리한다고 믿는다.
확인 질문
- DB 프록시가 주로 완화하는 문제는 무엇인가?
- 연결 생성 비용과 연결 폭주, failover 시 연결 관리 문제를 완화한다.
- DB 프록시가 느린 쿼리를 해결하지 못하는 이유는 무엇인가?
- SQL 실행 자체는 여전히 DB backend connection과 DB 엔진이 처리하므로 쿼리 비용은 사라지지 않기 때문이다.
- 인프라/DBA와 pool 변경을 논의할 때 전달해야 할 정보는 무엇인가?
- 인스턴스 수, 인스턴스별 pool size, batch 동시성, 예상 트래픽, query timeout, transaction 특성, failover 요구사항이다.
- DB 프록시를 도입해도 애플리케이션 pool이 필요한 이유는 무엇인가?
- 프록시는 연결 관리를 돕지만 애플리케이션에서 동시에 보낼 SQL 수와 요청 스레드 점유를 제한하지 못하므로, 앱 pool은 DB 보호와 장애 격리 장치로 계속 필요하기 때문이다.