커넥션 풀

미리 일정 수의 DB 커넥션을 생성해 풀(Pool)에 보관하고, 요청 시 재사용하여 연결 생성/해제 비용을 줄이는 기법입니다.

동작 원리

[커넥션 풀 없이]
요청 → 커넥션 생성 → SQL 실행 → 커넥션 해제 → 응답
        (TCP 3-way handshake + 인증)  (매번 반복, 느림)

[커넥션 풀 사용]
애플리케이션 시작 시 커넥션 N개 미리 생성

요청1 → 풀에서 커넥션 빌림 → SQL 실행 → 풀에 반납 → 응답
요청2 → 풀에서 커넥션 빌림 → SQL 실행 → 풀에 반납 → 응답
         (생성/해제 비용 없음, 빠름)
[ Connection Pool ]
┌──────────────────────────────────┐
│  ● 사용 중    ○ 대기 중(idle)      │
│                                  │
│  ● conn1 → [요청 A 처리 중]       │
│  ● conn2 → [요청 B 처리 중]       │
│  ○ conn3 → [대기]                │
│  ○ conn4 → [대기]                │
│  ○ conn5 → [대기]                │
│                                  │
│  요청 C 도착 → conn3 빌려감        │
│  요청 A 완료 → conn1 반납          │
└──────────────────────────────────┘

커넥션 풀이 필요한 이유

문제풀 미사용풀 사용
연결 생성 비용매 요청마다 TCP handshake + 인증 (수십 ms)최초 1회만 생성, 이후 재사용
자원 고갈동시 요청 폭증 시 커넥션 무한 생성 → DB 과부하최대 커넥션 수 제한으로 DB 보호
응답 시간연결 생성 지연이 매번 발생즉시 사용 가능
메모리 사용커넥션마다 DB 측 메모리 할당/해제 반복고정된 수만 유지하여 안정적

Java 예시 (HikariCP — Spring Boot 기본)

설정

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: secret
    hikari:
      minimum-idle: 5          # 최소 유지 커넥션 수
      maximum-pool-size: 10    # 최대 커넥션 수
      connection-timeout: 3000 # 커넥션 획득 대기 시간 (ms)
      idle-timeout: 600000     # 유휴 커넥션 유지 시간 (ms)
      max-lifetime: 1800000    # 커넥션 최대 수명 (ms)
      leak-detection-threshold: 2000  # 커넥션 누수 감지 (ms)

직접 생성

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("secret");
config.setMaximumPoolSize(10);
config.setMinimumIdle(5);
config.setConnectionTimeout(3000);

HikariDataSource dataSource = new HikariDataSource(config);

// 커넥션 사용
try (Connection conn = dataSource.getConnection()) {
    PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
    ps.setLong(1, 1L);
    ResultSet rs = ps.executeQuery();
    // 처리 로직
}  // try-with-resources → 자동으로 풀에 반납 (close ≠ 해제, 반납)

주요 설정 값 가이드

설정설명권장 값
maximum-pool-size풀이 보유할 최대 커넥션 수10~20 (서버 규모에 따라 조절)
minimum-idle유휴 상태로 유지할 최소 커넥션 수maximum-pool-size와 동일 권장
connection-timeout풀에서 커넥션을 얻기까지 대기 시간3000ms (3초)
idle-timeout유휴 커넥션이 풀에서 제거되기까지 시간600000ms (10분)
max-lifetime커넥션의 최대 수명 (DB wait_timeout보다 짧게)1800000ms (30분)

적정 풀 사이즈 공식

최적 풀 사이즈 = CPU 코어 수 × (1 + DB 대기시간 / CPU 처리시간)

HikariCP 공식 권장:

pool size = (core_count * 2) + effective_spindle_count

예: 4코어, SSD 1개
→ (4 × 2) + 1 = 9~10

주의: 풀 사이즈를 무작정 늘리면 오히려 성능이 저하됩니다. DB 커넥션은 공유 자원이므로 과도한 커넥션은 컨텍스트 스위칭, 메모리 낭비, DB 부하를 유발합니다.

커넥션 풀 동작 흐름

요청 도착
    │
    ▼
풀에 유휴 커넥션 있는가? ──── YES ──→ 커넥션 빌려줌 → SQL 실행 → 반납
    │
    NO
    │
    ▼
현재 커넥션 수 < max-pool-size? ── YES ──→ 새 커넥션 생성 → 빌려줌
    │
    NO
    │
    ▼
connection-timeout까지 대기
    │
    ├── 대기 중 반납된 커넥션 있음 → 빌려줌
    └── 타임아웃 초과 → ConnectionTimeoutException 발생

주요 커넥션 풀 라이브러리 비교

항목HikariCPDBCP2Tomcat Pool
성능가장 빠름보통보통
Spring Boot 기본O (2.0+)XX
모니터링JMX, Micrometer 지원JMXJMX
커넥션 검증경량 (Connection.isValid)쿼리 기반쿼리 기반
바이트코드 최적화O (FastList, ConcurrentBag)XX

실무 팁: 커넥션 누수는 장애의 주요 원인입니다. leak-detection-threshold를 설정하여 커넥션을 빌린 후 일정 시간 내 반납하지 않으면 경고 로그를 남기도록 하고, 반드시 try-with-resources로 커넥션 반납을 보장하세요.

CSLOG에서 보기