HikariCP 커넥션 풀 설정, 숫자의 근거 정리
결론부터. Spring Boot는 HikariCP를 기본 커넥션 풀로 내장하고 있어서, 대부분 application.yml을 한 줄도 안 건드리고 기본값(maximum-pool-size: 10)으로 운영한다. 문제는 이 기본값이 모든 서비스에 맞는 숫자가 아니라는 점이다. 무작정 풀 크기를 키우면 오히려 느려질 수 있다.
커넥션 풀이 하는 일
매 요청마다 DB에 새로 연결하면 TCP 핸드셰이크와 인증 과정이 반복돼 느리다. 커넥션 풀은 미리 연결을 여러 개 만들어두고 재사용하는 방식으로 이 비용을 없앤다. HikariCP는 이 중에서도 가볍고 빠르기로 정평이 나 있어 Spring Boot 2.0부터 기본값으로 채택됐다.
spring:
datasource:
hikari:
maximum-pool-size: 10
minimum-idle: 10
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000풀 크기는 클수록 좋지 않다
직관적으로 "동시 요청이 많으니 풀도 크게" 잡고 싶지만, DB 서버의 CPU 코어 수는 유한하다. 커넥션 수가 코어 수를 넘어서면 각 커넥션이 컨텍스트 스위칭을 기다리며 경쟁하게 되고, 처리량이 오히려 떨어진다. HikariCP 위키가 제시하는 공식은 다음과 같다.
connections = (core_count × 2) + effective_spindle_count
SSD 기준으로는 spindle_count를 사실상 0으로 보고, (코어 수 × 2) + 1 정도를 출발점으로 삼는 게 실무적이다. 예를 들어 DB 서버가 4코어라면 (4×2)+1 = 9, 즉 10 언저리가 적정선이다. Spring Boot의 기본값 10이 우연이 아니라 이 계산과 맞닿아 있는 셈이다.
⚠️ 핵심은 애플리케이션 서버가 아니라 DB 서버의 자원 기준으로 정한다는 점이다. 인스턴스 3대 × 풀 10개 = DB에는 30개 커넥션이 몰리는 셈이므로, 스케일아웃 환경에서는 인스턴스당 풀 크기를 오히려 줄여야 한다.
타임아웃 값들, 각각 무슨 역할인가
| 설정 | 기본값 | 의미 |
|---|---|---|
connection-timeout |
30000ms | 풀에서 커넥션을 기다리는 최대 시간. 초과 시 예외 발생 |
idle-timeout |
600000ms | 유휴 커넥션을 풀에서 제거하기까지의 시간 |
max-lifetime |
1800000ms | 커넥션 최대 수명. DB 서버 타임아웃보다 짧아야 함 |
max-lifetime은 특히 중요하다. MariaDB나 방화벽·로드밸런서가 일정 시간 이상 유휴 커넥션을 강제로 끊는 경우가 있는데, HikariCP가 그 시점보다 먼저 커넥션을 교체하지 않으면 "죽은 커넥션을 정상으로 착각하고 쓰다가 예외가 나는" 상황이 생긴다.
-- MariaDB의 현재 wait_timeout 확인
SHOW VARIABLES LIKE 'wait_timeout';운영 중 점검 방법
풀이 부족한지 넉넉한지는 추측하지 말고 지표로 확인한다. Micrometer와 연동하면 아래 지표를 노출한다.
management:
endpoints:
web:
exposure:
include: metricshikaricp.connections.pending — 커넥션을 기다리는 스레드 수. 지속적으로 0보다 크면 풀이 부족한 신호
hikaricp.connections.active — 실제 사용 중인 커넥션 수. 이 값이 maximum-pool-size에 자주 붙으면 증설 검토
✅ pending이 간헐적으로만 튀는 정도라면 정상 범위다. 상시 대기가 걸린다면 그때 풀을 키우되, 먼저 DB 서버 코어 수와 다른 애플리케이션의 풀 크기를 함께 계산해야 한다.
마무리. HikariCP 튜닝의 핵심은 "얼마나 크게"가 아니라 "DB 서버가 감당할 수 있는 한도 안에서"다. 기본값 10은 생각보다 합리적인 출발점이므로, 실측 지표 없이 숫자부터 올리는 것은 피하는 게 좋다. pending 지표를 먼저 모니터링에 추가하고, 실제로 대기가 쌓일 때 코어 수 공식을 기준으로 조정하는 순서를 권한다.
테크커런트 · toyeka-kor.tistory.com
'Programming > Spring' 카테고리의 다른 글
| Spring @TransactionalEventListener AFTER_COMMIT 함정: 저장 로직이 반영되지 않는 이유 (0) | 2026.07.27 |
|---|---|
| @Transactional 실전 함정 정리 — 셀프 호출부터 롤백까지 (0) | 2026.07.22 |
| 스프링 MVC와 DispatcherServlet 내부 동작: 모든 요청은 여기로 집결! (0) | 2025.08.24 |
| 🌱 스프링(Spring)의 탄생과 철학 – Rod Johnson의 한 줄기 ‘봄’ (0) | 2022.11.21 |
| 📌Lombok 어노테이션 총정리: Getter부터 @Data까지 코드가 줄어든다! (0) | 2022.11.02 |