🗄️ 데이터베이스

커넥션 풀

Connection Pool

DB 연결을 재사용하는 기법. 오버헤드 감소.

상세 설명

커넥션 풀(Connection Pool)은 데이터베이스 연결을 미리 생성해두고 재사용하는 기법입니다. DB 연결은 TCP 핸드셰이크, 인증, 세션 초기화 등으로 비용이 높은 작업이므로, 매 요청마다 연결을 생성하고 닫는 대신 풀에서 가져다 쓰고 반환합니다.

커넥션 풀은 최소/최대 연결 수, 유휴 연결 타임아웃, 연결 검증 등을 설정할 수 있습니다. 적절한 크기 설정이 중요한데, 너무 작으면 대기가 발생하고, 너무 크면 DB 서버에 부담이 됩니다. 일반적으로 (CPU 코어 수 * 2) + 유효 스핀들 수가 권장됩니다.

애플리케이션 레벨(HikariCP, DBCP)과 미들웨어 레벨(pgBouncer, ProxySQL)에서 구현할 수 있습니다. 서버리스 환경에서는 연결 급증 문제가 있어 PgBouncer 같은 외부 풀러나 AWS RDS Proxy를 사용하기도 합니다.

코드 예제

# Python - SQLAlchemy 커넥션 풀 설정
from sqlalchemy import create_engine

engine = create_engine(
    'postgresql://user:password@localhost/mydb',
    pool_size=10,           # 기본 풀 크기
    max_overflow=20,        # 최대 추가 연결 수
    pool_timeout=30,        # 연결 대기 타임아웃 (초)
    pool_recycle=1800,      # 연결 재활용 주기 (초)
    pool_pre_ping=True      # 연결 상태 확인
)

# Java - HikariCP 설정
# application.yml
spring:
  datasource:
    hikari:
      minimum-idle: 5
      maximum-pool-size: 20
      idle-timeout: 300000      # 5분
      max-lifetime: 1800000     # 30분
      connection-timeout: 30000 # 30초
      validation-timeout: 5000
      leak-detection-threshold: 60000

# Node.js - pg Pool 설정
const { Pool } = require('pg');

const pool = new Pool({
    host: 'localhost',
    database: 'mydb',
    user: 'user',
    password: 'password',
    max: 20,                    // 최대 연결 수
    idleTimeoutMillis: 30000,   // 유휴 타임아웃
    connectionTimeoutMillis: 10000
});

// 커넥션 사용
const client = await pool.connect();
try {
    const result = await client.query('SELECT * FROM users WHERE id = $1', [userId]);
    return result.rows;
} finally {
    client.release();  // 풀에 반환 (닫지 않음!)
}

// Django - 커넥션 풀 설정
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'HOST': 'localhost',
        'NAME': 'mydb',
        'CONN_MAX_AGE': 600,    # 연결 유지 시간 (초)
        'CONN_HEALTH_CHECKS': True,
    }
}

실무 대화 예시

백엔드 개발자: 트래픽 급증할 때 "too many connections" 에러가 나요.

DBA: 커넥션 풀 max_pool_size가 몇이에요? DB의 max_connections는요?

백엔드 개발자: 풀은 서버당 50개인데, 서버가 10대라서 500개고, max_connections는 200이에요.

DBA: 그럼 당연히 초과하죠. pgBouncer로 커넥션 풀링하거나, 애플리케이션 풀 크기를 줄여야 해요.

면접관: 적절한 커넥션 풀 크기는 어떻게 정하시나요?

지원자: HikariCP 공식에서는 (CPU 코어 수 * 2) + 유효 스핀들 수를 권장합니다. SSD라면 대략 코어 수의 2~3배 정도요. 하지만 실제로는 부하 테스트로 최적값을 찾아야 합니다. 쿼리 특성에 따라 달라지거든요.

면접관: 커넥션 풀 관련해서 주의할 점은요?

지원자: 연결을 반드시 반환해야 합니다. try-finally나 using 패턴으로 누수를 방지하고, leak detection 설정으로 문제를 조기에 발견해야 합니다.

시니어: 여기 connection.close()가 finally 블록 안에 없네요.

주니어: 예외 안 나면 닫히지 않나요?

시니어: 중간에 예외 나면 연결이 반환 안 돼서 풀이 고갈됩니다. 항상 finally에서 반환하거나 with 문을 쓰세요. 커넥션 누수는 찾기 어려운 버그예요.

주의사항

관련 용어

더 배우기