코딩일상

Spring Boot HikariCP 본문

카테고리 없음

Spring Boot HikariCP

solutionMan 2025. 10. 21. 21:58
반응형

Spring Boot HikariCP & R2DBC 커넥션 풀 총정리

 

 

1️⃣ HikariCP 역사와 도입 배경

 

  • 초기 Spring Boot / Spring에서는 기본 커넥션 풀로 Commons DBCP, C3P0, Tomcat JDBC Pool 사용
  • 문제점:
    • 성능이 느림 (과도한 synchronized)
    • 커넥션 누수, stale connection 문제
    • 멀티스레드 환경 불안정
  • 2012년, Brett Wooldridge가 성능과 안정성을 높인 HikariCP 개발
    • 이름: 일본어 光(Hikari) = “빛”, 경량 & 고속 의미
    • 설계 철학: 최소 동기화, lock-free 구조, JDBC 표준 준수
  • Spring Boot 2.x부터 공식 기본 커넥션 풀로 채택
    • 이유: 성능, 안정성, 낮은 메모리 오버헤드, 유지보수 신뢰성

 

2️⃣ HikariCP 구조

 ┌─────────────────────────────┐
 │         HikariDataSource    │ ← 사용자 접근
 └───────────────┬─────────────┘
                 │
       ┌─────────▼─────────┐
       │ HikariPool          │ ← 풀 관리 핵심
       └─────────┬─────────┘
                 │
   ┌─────────────┴─────────────┐
   │ PooledConnection[]         │ ← 실제 JDBC Connection 배열
   └───────────────────────────┘

 

  • HikariDataSource: Spring Boot에서 DataSource로 사용
  • HikariPool: 커넥션 풀 관리
  • PooledConnection: 실제 JDBC Connection을 Proxy로 감싸 재활용

 

3️⃣ 커넥션 요청 처리

 

1) Fast-path & Slow-path

경로의미특징

Fast-path idle 커넥션 충분 시 즉시 반환, lock-free
Slow-path idle 없음 또는 경합 발생 시 새 커넥션 생성, connectionTimeout 동안 대기
flowchart TD
    A[사용자 요청: getConnection()] --> B{ConcurrentBag에서 idle 커넥션 존재?}
    B -- YES --> C[Fast-path: 상태 IN_USE로 변경 → 반환]
    B -- NO --> D{총 커넥션 < maximumPoolSize?}
    D -- YES --> E[새 커넥션 생성 → 반환]
    D -- NO --> F[connectionTimeout 동안 대기 → 없으면 Exception]
    C --> G[사용 후 connection.close() → IDLE 상태로 반환]
    E --> G
    F --> G

 

  • ConcurrentBag: idle 커넥션 관리, lock-free 구조
  • Proxy Connection: 반환 시 실제 닫지 않고 재활용
  • Lazy 생성: 요청 시 필요한 만큼만 커넥션 생성

 

2) 최소 idle vs 최대 풀 동적 증가

 

  • minimumIdle: 풀 시작 시 미리 생성, 항상 유지 → Fast-path 확보
  • maximumPoolSize: 풀 최대치, DB 과부하 방지
  • 요청 증가 시:
    1. idle 부족 → Slow-path
    2. 총 커넥션 < maximumPoolSize → 새 커넥션 생성
    3. 최대치 도달 → connectionTimeout 동안 대기
  •  
  • idleTimeout: idle 상태 오래된 커넥션 폐기, minimumIdle 유지
flowchart TD
    A[애플리케이션 시작] --> B[minimumIdle 커넥션 생성]
    B --> C[커넥션 요청 발생]
    C --> D{idle 커넥션 존재?}
    D -- YES --> E[Fast-path 반환]
    D -- NO --> F{총 커넥션 < maximumPoolSize?}
    F -- YES --> G[새 커넥션 생성 → 반환]
    F -- NO --> H[connectionTimeout 대기 → 없으면 Exception]
    E --> I[connection.close() → IDLE 상태]
    G --> I
    H --> I
    I --> J{idleTimeout 초과?}
    J -- YES --> K[커넥션 폐기]
    J -- NO --> L[idle 유지, minimumIdle 보장]

 

4️⃣ HikariCP 성능 고려 사항

 

  1. Fast-path 활용 → idle 충분히 확보
  2. Slow-path 발생 시:
    • 커넥션 생성 시간 (JDBC 연결, 인증, SSL 등) 때문에 지연 가능
  3. 연관 문제
    • minimumIdle 낮음 → Slow-path 폭주
    • 커넥션 반환 지연 (close() 호출 지연)
    • DB 최대 커넥션 제한 낮음 → 풀 확장 지연
  4. 해결 방법
  • minimumIdle 증가, maximumPoolSize 확인
  • DB 연결 최적화 (네트워크, 인증, SSL)
  • 코드 최적화: 사용 후 즉시 close()
  • 필요 시 connectionTimeout 조정

 

5️⃣ R2DBC 개요

 

  • R2DBC (Reactive Relational Database Connectivity)
    • 비동기, 논블로킹 방식의 리액티브 JDBC API
    • Spring WebFlux 등 Reactive 시스템에서 사용
  • 특징
    • Flux/Mono 기반 → Reactor 지원
    • 커넥션 풀 사용 가능 (r2dbc-pool)
    • 기존 JDBC와 달리 스레드 블로킹 없음

항목JDBCR2DBC

방식 동기, 블로킹 비동기, 논블로킹
스레드 사용 쿼리 대기 시 블록 블록 없음
리액티브 호환 ✅ (Reactor, RxJava)
적합 환경 Spring MVC Spring WebFlux, Reactive API

 

6️⃣ 결론 요약

  • HikariCP
    • 최소 idle 유지 → 빠른 반환
    • 요청 증가 시 최대 풀까지 점진적 확장
    • Fast-path / Slow-path 구조로 동시성 최적화
  • 성능 지연 원인
    • DB 연결 자체 지연
    • minimumIdle 낮음
    • 커넥션 반환 지연
  • R2DBC
    • Reactive 환경에서 논블로킹 DB 접근
    • 동기 JDBC 환경에서는 여전히 HikariCP 최적
반응형
Comments