제시해주신 영상 「아키텍트가 알아야 할 커넥션 풀의 기본과 함정 | 멤버십 영상」 (채널: 코딩하는기술사)의 상세 내용을 빠짐없이 항목별로 정리한 내용입니다.
1. DB 커넥션 풀(Connection Pool)의 개념과 생성 비용
- 기본 개념: DB 커넥션을 미리 생성해 풀(Pool)에 담아두고, 필요할 때 빌려 쓴 뒤 반납하는 방식 [00:18].
- 커넥션 생성 시 발생하는 오버헤드 (비용):
2. 주요 언어/프레임워크 라이브러리의 기본값 비교
| 진영/라이브러리 | 기본 커넥션 풀 수 | 비고 |
|---|---|---|
| Java (Spring Boot 2.0+) | 10개 (HikariCP) | 작게 시작해서 넓혀가는 철학 [03:35] |
| .NET (ADO.NET) | 100개 | MS SQL Server의 Max Connection이 32,000개로 커서 여유있게 시작 [03:56] |
| Node.js (pg-pool) | 10개 | HikariCP와 동일 [04:08] |
| Python (SQLAlchemy) | 5개 (임시 +10개, 최대 15개) | [04:08] |
주의: .NET의 기본값 100개는 권장값이 아닌 안전한 상한선일 뿐이며, 오크로드에 맞춰 조정이 필요함 [05:12]. 100개 이상 지정하는 것은 안티패턴에 해당함 [05:57].
3. 커넥션 수에 대한 오해와 성능 역설 (USL 법칙)
- 흔한 오해: 커넥션 수가 많을수록 동시에 많은 일을 처리하여 처리량(TPS)이 늘어날 것이다 [07:30].
- 실제 동작: 커넥션 수가 일정한 한계를 넘어가면 오히려 성능(TPS)이 급격히 저하되거나 평탄화(Saturation)됨 [07:53].
- 성능이 떨어지는 이유 (유니버설 스케일러빌리티 법칙, USL) [17:49]:
- 벤치마크 참고:
4. 커넥션 풀 크기 결정 공식
① 표준 시작 공식 (PostgreSQL Wiki / HikariCP 가이드)
$$\text{Pool Size} = (\text{물리 CPU 코어 수} \times 2) + \text{Spindle Count}$$
[09:06]
- 물리 코어 수 $\times 2$: Hyper-Threading 논리 코어는 제외하고 물리 코어만 계산 [10:27]. (DB 쿼리는 CPU 연산과 I/O 대기가 번갈아 일어나므로, I/O 대기 시간에 다른 쿼리를 처리하기 위해 2배 적용) [15:06].
- Spindle Count (디스크 회전축 수):
- 2026년 기준 실무 표준 공식:
$$\text{Pool Size} = \text{물리 CPU 코어 수} \times 2$$
[17:26]
② 데드락 회피 공식 (HikariCP)
$$\text{Pool Size} = T_n \times (C_m - 1) + 1$$
[12:53]
- $T_n$: 동시 스레드 수 / $C_m$: 한 스레드가 동시에 점유하는 커넥션 수 [13:04]
- 중첩 트랜잭션 등에서 데드락을 회피하기 위한 최소한의 연결 수를 진단할 때 사용함 [13:04, 14:10].
5. 처리량 진단 도구: 리틀의 법칙 (Little's Law)
$$\text{TPS} = \frac{\text{활성 커넥션 수}}{\text{쿼리 실행 시간}}$$
[20:07]
- 진단 가이드:
6. 다중 WAS (서버) 환경에서의 설정 주의사항
- 실수 패턴: DB 코어 기준 총 적정 풀 수(예: 16개)를 구한 뒤, WAS N대에 각각 16개씩 지정하는 경우 (합산 시 DB가 감당할 수 있는 양의 N배 초과) [24:28].
- 적정 분배 계산:
$$\text{WAS당 Pool Size} = \frac{\text{DB 물리 코어 수} \times 2}{\text{WAS 인스턴스 수}}$$
[25:36] - 안정성 vs 가용성 선택:
- 운영 환경 적용 주의사항:
- Auto-Scaling 환경: WAS 수가 동적으로 변할 때는 PgBouncer나 RDS Proxy 같은 외부 풀러(External Pooler) 사용 권장 [26:54].
7. DB Max Connection과의 관계
- 조건: $\sum (\text{모든 WAS의 Max Pool Size}) < \text{DB Max Connections}$ [29:10].
- PostgreSQL 예시: 기본 max_connections가 100개인 경우, 시스템/관리자 예약을 제외하면 실제 사용 가능 수는 약 90개 수준 (안전마진 0.8 곱 적용 권장) [29:22].
- 설정값이 DB 한계를 초과하면 서버 기동 실패(고정 풀) 또는 피크 타임 트래픽 폭증 시 즉시 시스템 장애 발생(동적 풀) [30:12].
8. 실무에서 마주치는 4가지 함정
- Long Transaction (긴 트랜잭션):
- Time-out Mismatch (타임아웃 불일치):
- HikariCP maxLifetime (기본 30분)이 DB/인프라 레이어(PgBouncer, RDS Proxy, NLB)의 Idle Timeout보다 길면, 이미 끊긴 커넥션을 사용하려다 에러 발생 [31:29, 33:05].
- 해결책: maxLifetime을 DB/인프라 Idle Timeout보다 최소 30초 이상 짧게 설정 [33:47].
- $C_m \ge 2$ 인 코드:
- 한 스레드에서 커넥션을 2개 이상 동시 점유하는 구조는 풀 확장이 아닌 코드 구조 개선(트랜잭션 분리 등)이 우선 [33:56].
- 커넥션 누수 (Leak):
- leakDetectionThreshold 옵션을 약 60초(60000)로 설정하여 60초 이상 반환되지 않는 커넥션을 로그로 확인 및 감지 [34:17].
9. 출근 후 바로 점검할 8가지 체크리스트
- Max Pool Size 시작점 확인: DB 물리 코어 수 $\times 2$ 기준으로 설정되어 있는지 확인 (임의의 50, 100 설정 지양) [36:00].
- 고정 풀(Fixed Pool) 운영: HikariCP 기준 minimumIdle = maximumPoolSize로 동일하게 설정하여 런타임 변동 오버헤드 방지 [36:09].
- Connection Timeout 적정 유지: 너무 길게 잡지 않음 [36:31].
- Leak Detection 설정: leakDetectionThreshold 옵션으로 누수 로그 모니터링 [36:36].
- Long Transaction 제거: 트랜잭션 내 불필요한 로직 및 외부 호출 차단 [36:40].
- 풀 매트릭 대시보드 구축: Active / Waiting 수치 실시간 시각화 [36:48].
- 전체 WAS 풀 합산 검증: $\text{WAS 수} \times \text{Max Pool} < \text{DB Max Connection}$ 준수 여부 점검 (초과 시 PgBouncer 도입) [36:58].
- 부하 테스트를 통한 Saturation Point 도출: 풀 크기를 변경해가며 처리량이 꺾이는 지점(최적 스위트 스팟) 도출 [37:10].