Spring Boot/Connection Pooling

Connection Pooling

재윤 2025. 8. 28. 17:51
반응형

Connection Pooling이 없을 때의 DB 연결 방법

 

1. TCP 연결

  • 애플리케이션이 “DB 서버야, 연결해줘” 하고 요청
  • DB 서버가 “좋다” 하고 응답
  • 네트워크에서 SYN → SYN/ACK → ACK 왕복

2. TLS/SSL 핸드셰이크

  • 암호화 연결을 쓸 경우 서로 열쇠 교환해서 보안 통로 확보

3. 인증

  • 클라이언트가 아이디/비밀번호를 보냄
  • DB서버는 “비번, 권한 전부 체크 후 들어와”하고 허락

4. 세션 초기화

  • DB 서버가 새로운 “세션(대화방)”을 만들어줌
  • 기본 설정들을 관리
    • 사용할 DB
    • 문자셋/ 시간대
    • autocommit 모드, isolation level 등

5. 준비 완료

  • 첫 쿼리를 실행할 수 있음

6. 커넥션 닫기

  • Connection.close() 호출 → TCP 연결도 종료
  • 서버는 “이 세션 끝!” 하고 정리
  • 네트워크 리소스(TIME_WAIT)도 소모

이 과정의 비용이 비쌈

  • 위 과정이 요청마다 반복되면 네트워크 왕복 + 인증 + 세션 생성 비용이 매번 듦
  • 빠른 로컬 DB라도 수 ms~수십 ms는 기본, TLS 켜면 더 커짐
  • 요청이 몰리면 성능 병목 발생

이렇기에 커넥션 풀 등장

  • 앱 시작 시 미리 여러 개 커넥션을 열어둠 (위 1~4번을 선행)
  • 요청이 오면 → 바로 빌려줌(0.x ms 수준)
  • 사용 후 close() 해도 실제론 닫지 않고 풀에 반환해서 재사용

쉽게 말하면,

  • 풀 없이: 손님 올 때마다 테이블/의자 새로 사옴 → 비싸고 느림
  • 풀 쓰면: 미리 테이블/의자 준비해둠 → 손님 오면 바로 안내, 쓰고 나가면 다음 손님 재사용

 

Connection Pooling 개념 및 동작 방식

DB 연결을 미리 여러 개 만들어주고, 요청이 오면 빌려주고 끝나면 다시 돌려받아 재사용하는 창고

 

 

동작 방식

 

 

1. 웜업 == DB 접속

  • 앱이 뜰 때 또는 트래픽에 맞춰 초기 커넥션을 여러 개 만들어 둠
  • (Hikrai : minimun-idle 개수 만큼 유휴 연결 유지)

2. 빌리기 - getConnection() == DB 접속

  • 요청 들어옴 → 풀에 놀고 있는 커넥션이 있으면 즉시 반환
  • 없으면
    • 아직 maximum-pool-size 미만이면 새 연결 생성
    • 이미 꽉 찼으면 대기 (최대 connection-timeout까지만)
    • 시간 내 못 빌리면 시간초과 예외(풀 고갈)

3. 사용(In-use) == 트랜잭션 시작, SQL 실행, 트랜잭션 종료

  • 스프링 트랜잭션이 시작되면 풀에서 빌린 커넥션에 옵션을 세팅
    • autoCommit=false, readOnly, isoaltion 등
  • JPA/Hibernate가 이 커넥션으로 SQL 실행
  • 트랜잭션 종료 시 커밋/롤백

4. 반납(Return) - Close() == 트랜잭션 닫기

  • 애플리케이션에서 close()를 호출해도 실제로 소켓을 닫지 않고 커넥션을 풀에 되돌림(상태 초기화 후 유휴 상태로)
  • Hikrai가 세션 상태를 리셋해서 다음 요청이 깨끗한 환경으로 쓰게 함

5. 유지/교체(Maintain) == 트랜잭션 닫기

  • 너무 오래된 커넥션은 교체(max-lifetime)
  • 오랫동안 안 쓰인 유휴 연결은 정리(idle-timeout)
  • 연결이 죽었는지 헬스 체크(JDBD isValid()/keepalive)

 

튜닝 포인트

# 기본 크기/대기
spring.datasource.hikari.minimum-idle=10        # 유휴(최소) 유지 개수
spring.datasource.hikari.maximum-pool-size=20   # 동시에 빌릴 수 있는 최대
spring.datasource.hikari.connection-timeout=30000  # 빌릴 때 최대 대기(ms)

# 수명/정리
spring.datasource.hikari.idle-timeout=600000    # 유휴 연결 정리(ms)
spring.datasource.hikari.max-lifetime=1800000   # 연결 교체 주기(ms) ← DB wait_timeout보다 살짝 짧게
spring.datasource.hikari.keepalive-time=0       # 필요 시 주기적 keepalive(ms)

# (옵션) 누수 탐지
spring.datasource.hikari.leak-detection-threshold=20000  # 빌리고 안 돌려주면 경고(ms)

스프링/트랜잭션과의 연결

  • @Transactional 시작 → 풀에서 커넥션 1개를 빌려 현재 스레드에 바인딩
  • 메서드 끝(정상/예외) → commit/rollback 수행 → 풀에 반납
  • 같은 트랜잭션 동안엔 항상 같은 커넥션을 사용 (일관성 보장)

 

initial / max / idle / pooling time 매핑 (Hikari 설정)

그림의 개념 의미 Hikari 속성 (Spring Boot) 설명/팁

그림의 개념 의미 Hikari 속성 (Spring Boot) 설명/팁
initial 서버 시작/운영 중 미리 확보해 둘 유휴 커넥션 개수 spring.datasource.hikari.minimum-idle “최소 유휴 개수”. 이 수만큼은 항상 놀고 있게 유지 → 첫 요청 지연 감소(웜업 효과)
max 동시에 빌릴 수 있는 최대 커넥션 spring.datasource.hikari.maximum-pool-size 동시 트래픽 상한. 너무 작으면 대기/타임아웃, 너무 크면 DB가 힘들어짐
idle 유휴(놀고 있는) 커넥션 수 (상동, minimum-idle) + 회수 주기: idle-timeout 사용 안 하는 연결을 몇 개 유지할지 + 오랫동안 놀면 정리하는 시간(ms)
pooling time 커넥션 대기 한도(풀 꽉 찼을 때 얼마나 기다릴지) spring.datasource.hikari.connection-timeout 이 시간 안에 못 빌리면 예외(풀 고갈). SLA에 맞춰 짧게 잡아 장애를 빨리 인지
반응형