[Spring] DB 커넥션 풀

icebox127·2026년 6월 4일

갑자기 프론트에서 API 사용이 안 된다고해서 배포서버 로그를 확인했다.

사용 가능한 커넥션 풀이 없다고 나왔다.
근데 커넥션 풀이 뭘까..?

커넥션 풀

애플리케이션이 DB에 접근하려면, 먼저 네트워크를 통해 DB 서버와 연결(Connection)을 맺어야 한다. 이 연결이 쿼리를 생성할때마다 일어나면 성능이 매우 떨어지기에, 한 번 만들어두고 재사용을 하게 된다.
즉 커넥션 풀은 DB 커넥션을 미리 만들어두고, 필요할 때 빌려 쓰는 풀(pool)이다.

동작 원리

  1. 애플리케이션 시작 시, 설정된 크기만큼 커넥션을 미리 생성한다
  2. 요청이 들어오면, 풀에서 하나를 빌린다
  3. 쿼리 실행 후, 해당 커넥션을 닫지 않고 다시 풀에 반납한다
  4. 요청이 많을 경우, 대기열에 쌓이거나 에러가 발생한다(최대 풀 크기 초과 시)

커넥션 풀 고갈의 원인

① 커넥션 누수 (Connection Leak)
코드 내부에서 DB 커넥션을 가져간 뒤, 어떤 이유로든 반납(close())하지 않고 계속 붙잡고 있는 경우
Spring Boot와 JPA(Spring Data JPA)를 쓰면 기본적으로 트랜잭션이 끝날 때 커넥션을 알아서 반납하지만, Transaction 범위를 벗어난 곳에서 Lazy Loading을 과도하게 시도하거나 외부 API 호출처럼 시간이 오래 걸리는 작업이 트랜잭션 내부(또는 OSIV 구조)에 묶여 있을 때 발생 가능

② 느린 쿼리 (Slow Query)와 병목
특정 API가 실행하는 쿼리가 너무 느려서 커넥션을 수초 동안 붙잡고 있는 경우
인덱스가 타지 않는 대량의 조인 쿼리나 전체 테이블 스캔이 발생하면, 하나의 요청이 커넥션을 오래 점유하게 되고, 뒤이은 요청들이 줄줄이 대기하다가 풀이 고갈됨

③ 데드락 (Deadlock)
두 개 이상의 트랜잭션이 서로가 가진 데이터 락(Lock)이 풀리기를 기다리며 무한 대기에 빠지는 상황

내 경우는 아마 1번인것 같다.

설정

application.yaml에 hikari 설정을 추가했다.

spring:
  main:
    allow-bean-definition-overriding: true
  datasource:
    url: ${DB_URL}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 10
      minimum-idle: 10
      idle-timeout: 300000
      max-lifetime: 480000
      keepalive-time: 240000
      connection-test-query: "SELECT 1"
      validation-timeout: 3000

참고 자료

데이터베이스-DB-커넥션-풀Connection-Pool의-의미

CS공부-흔히-발생하는-실수-DB-커넥션-풀

profile
감자의 공부기록🥔

0개의 댓글