데이터베이스 커넥션 풀 (Database Connection Pool)

한눈에 보기

데이터베이스 연결을 미리 만들어 재사용하는 커넥션 풀의 동작 원리와 필요성을 다룬다. HikariCP 설정, 풀 크기 계산, 타임아웃과 고갈 문제를 실무 관점에서 정리했다.

최종 업데이트 2026.09.17

커넥션 풀(Connection Pool)은 데이터베이스 연결을 요청할 때마다 새로 만드는 대신, 미리 일정 개수의 연결을 만들어 두고 애플리케이션이 빌려 쓰고 반납하는 방식으로 재사용하는 기법이다. 연결 생성에 드는 네트워크 왕복과 인증 비용을 없애 응답 시간을 줄이고, 데이터베이스에 동시에 맺을 수 있는 연결 수를 일정 범위로 통제하는 역할을 한다. 자바 진영에서는 HikariCP가 사실상 표준 구현으로 쓰인다.

연결 하나를 만드는 데 드는 비용

데이터베이스 연결은 단순한 객체 생성이 아니다. 클라이언트와 서버 사이에 TCP 3방향 핸드셰이크(3-way handshake)가 일어나고, TLS를 쓴다면 암호화 핸드셰이크가 추가되며, 그 위에서 데이터베이스 프로토콜 수준의 인증과 세션 초기화가 이어진다. 이 과정은 수 밀리초에서 수십 밀리초가 걸리는데, 쿼리 자체가 1밀리초 안에 끝나는 경우가 많다는 점을 생각하면 배보다 배꼽이 큰 구조다.

서버 쪽 부담도 크다. 데이터베이스는 연결마다 세션 메모리, 정렬 버퍼, 프로세스나 스레드 같은 자원을 할당한다. 요청이 몰릴 때마다 연결을 새로 만들면 데이터베이스가 연결 폭주만으로 무너질 수 있다. 그래서 연결을 미리 만들어 재사용하고, 동시에 상한을 두어 데이터베이스를 보호하는 커넥션 풀이 필요하다.

풀의 동작 원리

커넥션 풀의 생명 주기는 대여와 반납으로 요약된다. 동작 순서는 다음과 같다.

  1. 애플리케이션 시작 시 풀이 최소 개수의 연결을 미리 만들어 유휴(idle) 상태로 보관한다.
  2. 스레드가 연결을 요청하면 풀은 유휴 연결 하나를 꺼내 건네준다. 이때 연결이 살아 있는지 검증 쿼리나 저수준 확인으로 점검하기도 한다.
  3. 유휴 연결이 없고 최대 개수에 도달하지 않았다면 새 연결을 만들어 준다.
  4. 최대 개수까지 모두 사용 중이면 요청 스레드는 정해진 대기 시간(connection timeout)만큼 블록되고, 그 안에 반납이 없으면 예외를 받는다.
  5. 애플리케이션이 사용을 마치면 연결은 닫히는 것이 아니라 풀로 반납되어 다음 요청에 재사용된다.

개발자가 코드에서 호출하는 close는 실제 연결 종료가 아니라 반납이라는 점이 핵심이다. 풀은 별도로 유휴 시간이 오래된 연결이나 최대 수명(max lifetime)을 넘긴 연결을 조용히 폐기하고 새로 채워, 방화벽이나 데이터베이스가 오래된 연결을 끊어 생기는 문제를 예방한다.

HikariCP가 빠른 이유

HikariCP는 스프링 부트(Spring Boot)의 기본 커넥션 풀로 채택된 경량 구현이다. 성능의 비결은 화려한 기능이 아니라 극단적인 단순화다. 내부적으로 락 경합을 줄이도록 설계된 자료 구조인 ConcurrentBag을 사용해, 스레드가 직전에 쓰던 연결을 우선 다시 잡게 하여 동기화 비용을 줄인다. 또 프록시 생성과 바이트코드 수준 최적화로 연결을 감싸는 오버헤드를 최소화했다. 설정 항목도 의도적으로 적게 유지해 잘못 조합할 여지를 줄였다. 대표 설정은 다음과 같다.

spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.connection-timeout=3000
spring.datasource.hikari.max-lifetime=1800000

HikariCP는 minimum-idle을 maximum-pool-size와 같게 두는 고정 크기 풀을 권장한다. 풀 크기가 수시로 늘었다 줄었다 하면 트래픽이 몰리는 순간마다 연결 생성 비용을 다시 치르기 때문이다.

풀 크기는 어떻게 정하는가

풀을 크게 잡을수록 좋다고 생각하기 쉽지만 실제로는 반대에 가깝다. 데이터베이스 서버가 실제로 동시에 처리할 수 있는 작업 수는 CPU 코어 수와 디스크, 네트워크 대기 시간에 의해 제한된다. 연결이 코어 수보다 훨씬 많으면 컨텍스트 스위칭과 락 경합만 늘어나 오히려 전체 처리량이 떨어진다. HikariCP 문서가 소개하는 경험적 출발점은 다음 공식이다.

pool size = (CPU core 수 * 2) + 유효 디스크 스핀들 수

예를 들어 코어 8개짜리 데이터베이스 서버라면 풀 크기 20 안팎에서 시작해 부하 테스트로 조정하는 식이다. 주의할 점은 이 상한이 데이터베이스 기준이라는 것이다. 애플리케이션 인스턴스가 10대이고 각 풀이 20이면 데이터베이스에는 최대 200개의 연결이 맺힌다. 따라서 인스턴스 수를 곱한 총합이 데이터베이스의 max connections와 실제 처리 능력 안에 들어오도록 설계해야 한다.

풀 고갈 장애 패턴

운영에서 가장 자주 만나는 커넥션 풀 장애는 고갈(exhaustion)이다. 모든 연결이 사용 중이라 새 요청이 대기하다가 타임아웃 예외를 쏟아내는 상황으로, 원인은 대체로 다음 중 하나다.

패턴원인대응
연결 누수예외 경로에서 반납이 누락되어 연결이 영영 돌아오지 않는다try-with-resources 사용, leak detection threshold 설정
느린 쿼리 점유인덱스 없는 쿼리나 락 대기가 연결을 오래 붙잡는다쿼리 튜닝, 쿼리 타임아웃 설정
트랜잭션 안 외부 호출트랜잭션을 연 채로 외부 API를 호출해 응답까지 연결을 점유한다트랜잭션 범위 축소, 외부 호출 분리
순간 트래픽 폭주동시 요청이 풀 크기를 크게 넘는다스케일 아웃, 큐잉, 서킷 브레이커

풀 크기를 늘리는 것은 마지막 수단이다. 누수나 느린 쿼리가 원인이라면 풀을 키워도 고갈 시점만 늦춰질 뿐 같은 장애가 반복된다. 활성 연결 수, 대기 스레드 수, 대여 대기 시간 같은 풀 지표를 모니터링에 반드시 포함해야 원인을 빠르게 좁힐 수 있다.

면접에서 이렇게 물어본다

  • 커넥션 풀을 쓰지 않고 요청마다 연결을 새로 만들면 어떤 문제가 생기는지 설명해 보라.
  • 커넥션 풀의 최대 크기를 무작정 크게 잡으면 왜 성능이 오히려 나빠질 수 있는가.
  • 운영 중 커넥션 풀 고갈로 타임아웃이 발생한다면 어떤 순서로 원인을 좁혀 가겠는가.
  • 트랜잭션 안에서 외부 API를 호출하는 코드가 커넥션 풀에 어떤 영향을 주는가.
  • HikariCP가 다른 풀 구현보다 빠른 이유를 아는 대로 설명해 보라.
데이터베이스 문서 전체 보기

이 개념, 내 코드에서는 어떻게 물어볼까요

데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.

공고 넣고 시작하기