본문 바로가기
IT

실서비스에서 커넥션 풀(hikari Cp) 제대로 이해하기

by urosie 2025. 12. 16.
반응형

이 글은 실서비스 운영 중 발생한 커넥션 풀 이슈를 바탕으로, HikariCP + Spring + MyBatis 환경에서 커넥션 풀이 어떻게 동작하는지, 어떤 설정이 실제로 의미가 있는지 정리한 글이다.


1. 커넥션 풀이 부족해지는 대표적인 원인

실무에서 커넥션 풀 이슈의 원인은 거의 정해져 있다.

  • 커넥션 반환 누락 (close 안 됨)
  • 트랜잭션 범위가 과도하게 큼
  • 오래 걸리는 쿼리로 커넥션 점유 시간이 김
  • 풀 사이즈를 DB 한계보다 크게 설정

중요한 점은 "풀 크기가 작아서" 발생하는 경우는 생각보다 적다는 것이다.


2. SqlSessionTemplate를 쓰고 있다면

@Primary
@Bean
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("node01SessionFactory") SqlSessionFactory ssf) {
return new SqlSessionTemplate(ssf);
}

이 구조는 Spring + MyBatis의 정석적인 구성이다.

  • SqlSessionTemplate이 내부적으로 커넥션을 획득/반환
  • 개발자가 openSession() / close()를 직접 호출하지 않음
  • 정상 구조라면 커넥션 누수가 발생하기 어렵다

따라서 이 환경에서 Connection is not available 에러가 난다면, 원인은 거의 항상 트랜잭션 길이, 쿼리 지연, DB 세션 한계 쪽이다.


3. commit과 커넥션 반환은 전혀 다른 개념

자주 헷갈리는 부분이다.

  • commit: 데이터 변경 확정
  • connection return(close): 커넥션을 풀로 돌려보냄

중요한 사실:

commit을 안 해도, 트랜잭션이 끝나면 커넥션은 반환된다.

Spring의 @Transactional이나 SqlSessionTemplate 환경에서는

  • commit → 성공 시
  • rollback → 실패 시

어느 경우든 메서드 종료 시 커넥션은 풀로 반환된다.

즉, 커넥션 부족 문제는 commit 누락 문제가 아니다.


4. HikariCP 주요 설정 정리

4.1 maximumPoolSize

  • 풀에서 가질 수 있는 최대 커넥션 수
  • 실제 사용량과 반드시 일치하지 않음

실제 사례:

  • maximumPoolSize = 300
  • activeConnections 최대 = 11

→ 풀을 과도하게 크게 잡은 상태

권장 접근:

  • 실제 동시 DB 요청 수 기준으로 설정
  • 대부분 서비스는 30~50 수준이면 충분

4.2 connection-timeout

  • 풀에서 커넥션을 못 구했을 때 기다리는 최대 시간
  • 기본값: 30초 (30000ms)

동작 방식:

  • 커넥션 없음 → 최대 30초 대기
  • 30초 초과 → Connection is not available 예외 발생

너무 길면:

  • 쓰레드가 오래 블로킹됨

너무 짧으면:

  • 순간 트래픽에도 바로 장애

4.3 maxLifetime

로그에서 자주 보이는 메시지:

connection has passed maxLifetime

의미:

  • 설정된 수명을 초과한 커넥션을 정상적으로 폐기하고 재생성
  • 기본값: 30분

문제가 아니라 풀 안정성을 위한 정상 동작 로그다.


5. 풀 통계 로그는 항상 남지 않는다

  • HikariCP는 기본적으로 풀 상태 로그를 남기지 않음
  • 로그 레벨을 올려야 확인 가능
logging.level.com.zaxxer.hikari=DEBUG

또는 JMX를 통해 다음 지표 확인 가능:

  • activeConnections
  • idleConnections
  • totalConnections
  • threadsAwaitingConnection

6. 오라클 / MSSQL에서의 락과 커넥션 점유

Oracle

  • 행 단위 비관적 락: SELECT ... FOR UPDATE
  • 논리적 락: DBMS_LOCK
DBMS_LOCK.REQUEST(...)

MSSQL

  • 행 락: WITH (UPDLOCK)
  • 테이블 락: TABLOCK, TABLOCKX
  • 논리적 애플리케이션 락: sp_getapplock
EXEC sp_getapplock @Resource='ORDER_123', @LockMode='Exclusive'

이런 락들은 트랜잭션이 길어질수록 커넥션 점유 시간을 늘린다.


7. 핵심 결론

  1. 커넥션 부족은 대부분 풀 크기 문제가 아니다
  2. commit 여부와 커넥션 반환은 무관
  3. SqlSessionTemplate 사용 시 누수 가능성은 낮음
  4. 실제 봐야 할 것은:
    • 트랜잭션 길이
    • 쿼리 실행 시간
    • DB 세션 제한
    • 순간 동시 요청 패턴

커넥션 풀 문제는 설정을 키워서 해결되지 않는다. 관측 → 이해 → 줄이기가 정답이다.

반응형

댓글