DBCP(DataBase Connection Pooling) 개념
DBCP(DataBase Connection Pooling)는 데이터베이스와 애플리케이션 간의 연결을 효율적으로 관리하기 위한 기술입니다. 데이터베이스 연결은 생성과 종료에 상당한 리소스와 시간이 소요되기 때문에, 연결을 재사용하는 풀(pool)을 만들어 성능을 개선하는 방식입니다.
기존의 DB 연결 방식
기존 방식에서는 애플리케이션이 데이터베이스 작업을 수행할 때마다 새로운 연결을 생성하고 작업이 끝난 후 연결을 종료합니다.
* 동작 방식
1. 데이터베이스 연결 생성 (Connection 객체 생성)
2. SQL 실행
3. 연결 종료 (Connection 객체 닫기)
* 특징
매 요청마다 연결 생성: 데이터베이스와 통신할 때마다 새로운 연결(TCP/IP)을 생성합니다.
연결 해제 후 소멸: 작업이 끝난 후 연결을 종료해 더 이상 재사용되지 않습니다.
* 문제점
1. 높은 연결 비용
- 연결 생성 및 종료는 시간이 많이 걸리는 작업입니다.
- 특히 고성능 애플리케이션에서 많은 연결이 빈번하게 이루어질 경우 큰 병목이 발생합니다.
2. 낮은 효율성
- 매번 새 연결을 생성하는 것은 자원의 낭비입니다.
- 동일한 연결이 반복적으로 필요할 때도 매번 새로 만들어야 합니다.
3. 성능 저하
- 대량의 동시 요청이 들어오면 데이터베이스가 과부하 상태에 빠질 수 있습니다.
4. 코드 복잡성
- 연결 생성 및 종료 로직을 매번 작성해야 하며, 누수(Connection Leak)를 방지하려면 더 많은 코드가 필요합니다.
DBCP 방식
DBCP는 데이터베이스 연결을 미리 생성해 풀(pool)에 저장해 두고, 필요할 때 재사용하는 방식입니다.
* 동작 방식
1. 애플리케이션 시작 시 일정 수의 연결을 생성해 Pool에 저장
2. 애플리케이션 요청 시 Pool에서 사용 가능한 연결 제공
3. 작업이 끝난 후 연결은 닫지 않고 Pool로 반환 (재사용)
* 특징
연결 재사용: 기존 연결을 재사용하므로 매번 새로운 연결을 생성하지 않습니다.
자동 연결 관리: 사용하지 않는 연결은 Pool에서 자동으로 정리하거나 유휴 상태를 모니터링합니다.
* 장점
1. 성능 향상
- 연결 생성 및 종료 비용이 제거되어 응답 속도가 빨라집니다.
2. 자원 최적화
- 제한된 연결을 효율적으로 관리하여 데이터베이스 과부하를 방지합니다.
3. 코드 간소화
- 개발자는 연결 관리에 신경 쓰지 않아도 되고, DBCP가 모든 작업을 처리합니다.
4. 동시성 처리
- 다수의 요청을 효율적으로 처리할 수 있으며, 멀티스레드 환경에서도 안전합니다.
고객 입장에서 본 기존 DB 연결 방식의 문제
기존의 데이터베이스 연결 방식은 고객이 사용하는 서비스의 품질과 경험에 직접적인 영향을 미칠 수 있습니다. 고객의 입장에서 이 방식이 초래하는 문제는 다음과 같습니다.
1. 응답 속도 지연
문제: 각 요청마다 새로운 DB 연결을 생성하므로 처리 시간이 증가합니다.
영향: 고객이 웹사이트나 앱을 사용할 때 페이지 로드 시간이 길어지고, 버튼 클릭 후 결과가 나타나는 데 시간이 오래 걸립니다.
결과: 느린 응답 시간은 고객 만족도를 저하시킬 수 있습니다.
2. 트래픽 증가 시 서비스 중단
문제: 다수의 고객이 동시에 서비스를 사용할 경우, 각 요청마다 새 연결을 생성하면서 데이터베이스의 연결 수 제한에 도달할 수 있습니다.
영향:데이터베이스 연결 실패로 인해 고객 요청이 처리되지 않음."서비스를 사용할 수 없습니다."와 같은 에러 메시지를 볼 가능성이 높아짐.
결과: 트래픽 급증 시 서비스 불안정성이 증가하여 고객의 신뢰를 잃을 수 있습니다.
3. 비일관된 사용자 경험
문제: 데이터베이스 연결이 불안정하거나 과부하 상태가 되면 요청 처리 속도가 불규칙해집니다.
영향:같은 작업을 수행해도 한 번은 빠르고, 다른 한 번은 느려질 수 있습니다.데이터 저장/조회가 실패할 가능성이 있음.
결과: 고객은 서비스가 신뢰할 수 없다고 느끼게 됩니다.
4. 데이터 처리 오류
문제: 연결 누수(Connection Leak)로 인해 오래된 연결이 유지되거나 새로운 연결을 생성하지 못할 수 있습니다.
영향:요청 처리 중 에러가 발생하거나 데이터가 손실될 수 있음.고객이 입력한 정보가 제대로 저장되지 않거나, 조회 시 잘못된 데이터를 볼 수 있음.
결과: 중요한 데이터가 유실되면 고객 불만으로 이어지며, 서비스의 신뢰도를 떨어뜨립니다.
5. 확장성 부족
문제: 기존 방식은 다수의 동시 요청을 처리하기 위한 효율적인 자원 관리 체계가 없습니다.
영향:고객 수가 늘어날수록 성능 문제가 심화됩니다.프로모션, 세일, 이벤트 등으로 트래픽이 급증하면 서비스가 멈출 수 있습니다.
결과: 새로운 고객을 유치하는 데 실패하거나 기존 고객을 잃게 됩니다.
6. 신뢰성 및 안정성 문제
문제: 시스템이 예측할 수 없는 방식으로 작동할 수 있습니다(예: 연결 실패, 처리 지연).
영향: 고객이 기대하는 수준의 안정적이고 신뢰할 수 있는 서비스를 제공하지 못함.
결과: 고객 이탈률 상승 및 브랜드 이미지 훼손.
* 고객이 느끼는 최종적인 문제
느린 응답 시간과 서비스 오류는 고객이 서비스를 지속적으로 이용하는 데 방해가 됩니다.스트레스: 작업 실패, 데이터 손실 등은 고객에게 직접적인 불만을 야기합니다.서비스 불신: 반복되는 문제는 고객이 해당 서비스를 신뢰하지 못하게 만듭니다.
기존 방식의 문제를 해결하기 위해 DBCP 같은 Connection Pool 기법을 도입하면 고객 요청 처리 속도 향상, 데이터베이스 연결의 안정적 관리, 트래픽 증가 시에도 서비스 확장성 유지, 일관되고 신뢰할 수 있는 사용자 경험 제공이 가능합니다. 이로 인해, 고객 만족도와 서비스 품질이 전반적으로 개선됩니다.
Spring Boot에서 권장하는 DBCP 방식
Spring Boot 2.x와 Spring Boot 3.x에서는 기본적으로 데이터베이스 Connection Pool을 효율적으로 관리하기 위해 HikariCP를 권장하고 기본 설정으로 사용합니다. 성능과 안정성 면에서 가장 뛰어난 선택으로 간주됩니다.
HikariCP란?
HikariCP는 경량화된 고성능 데이터베이스 Connection Pool입니다. 다음과 같은 특징을 가지고 있습니다.
1. 빠른 성능
- 다른 DBCP 구현체보다 더 빠르고 효율적입니다.
- 낮은 연결 생성/사용/반환 오버헤드
2. 낮은 메모리 소비
- 효율적인 메모리 관리로 자원 사용량이 적습니다.
3. 강력한 안정성
- 연결 누수 탐지, 빠른 복구, 대규모 트래픽 처리에 유리
4. 쉬운 설정Spring Boot에서 기본적으로 통합되며, 간단한 설정으로 사용 가능
Spring Boot에서 HikariCP 기본 설정
Spring Boot는 기본적으로 HikariCP를 데이터베이스 Connection Pool로 사용하며, 별도로 설정하지 않으면 자동으로 적용됩니다.
application.properties 또는 application.yml에 명시하지 않아도, spring-boot-starter-data-jpa나 유사한 의존성을 추가하면 HikariCP가 기본 Connection Pool로 동작합니다.
예제: application.yml
spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: root password: secret hikari: maximum-pool-size: 10 minimum-idle: 2 idle-timeout: 10000 connection-timeout: 30000 max-lifetime: 1800000
* maximum-pool-size
- 최대 연결 수 (기본값: 10)
- 애플리케이션의 동시 요청 수를 고려해 설정
* minimum-idle
- 유지할 최소 유휴 연결 수
- 사용량이 적을 때도 빠른 응답을 위해 최소한의 연결을 유지.
* idle-timeout
유휴 연결이 제거되기까지의 시간(밀리초, 기본값: 600,000ms)
유휴 상태를 오래 유지할 필요가 없을 경우 줄이는 것이 좋음
* connection-timeout
연결 대기 시간(밀리초, 기본값: 30,000ms)
지정된 시간 내에 연결을 가져오지 못하면 예외 발생
* max-lifetime
각 연결의 최대 수명(밀리초, 기본값: 1,800,000ms)
연결이 오래 유지되면, 데이터베이스 서버의 연결 문제를 예방하기 위해 정기적으로 새 연결로 교체
Thread 수와 Connection Pool 수의 관계
WAS (Web Application Server)의 Thread 수와 Connection Pool 수는 밀접하게 관련이 있습니다. 이들은 서버 성능, 자원 사용량, 그리고 응답 속도에 중요한 영향을 미칩니다.
1. Thread 수: WAS에서 Thread는 클라이언트 요청을 처리하기 위해 생성되는 작업 단위입니다. 각 요청마다 별도의 스레드가 할당되며, 이 스레드는 요청을 처리하고 응답을 반환합니다. 서버의 최대 스레드 수는 동시 처리 가능한 요청의 수를 제한합니다. 만약 이 수가 너무 적으면 동시 요청 처리 능력이 부족해져서 성능이 저하될 수 있고, 너무 많으면 자원 낭비가 발생할 수 있습니다.
2. Connection Pool 수: Connection Pool은 데이터베이스와의 연결을 효율적으로 관리하기 위한 메커니즘입니다. 이 Pool에는 일정 수의 데이터베이스 연결이 미리 생성되어 있으며, 클라이언트 요청에 따라 Pool에서 연결을 빌려옵니다. Pool의 크기는 동시에 처리할 수 있는 데이터베이스 연결의 수를 결정합니다. 너무 작은 Pool은 연결이 부족해져 데이터베이스 작업을 처리하는 데 병목 현상을 일으킬 수 있습니다.
* Thread 수와 Connection Pool 수의 관계
Thread 수와 Connection Pool 수의 관계는 간단히 말해 동시 요청 처리 능력에 관한 것입니다. WAS에서 클라이언트 요청을 처리하려면 Thread가 필요하고, Thread가 데이터베이스와 연결해야 할 경우 데이터베이스 연결이 필요합니다. 예를 들어, 하나의 요청을 처리하기 위해 Thread가 데이터베이스와 연결을 생성해야 한다면, Thread 수와 Connection Pool 수가 적절히 맞아야 성능이 최적화됩니다. 만약 Thread 수가 많고 Connection Pool 수가 적다면, 많은 요청이 대기 상태에 들어가거나 성능 저하가 발생할 수 있습니다. 반대로 Connection Pool 수가 많고 Thread 수가 적으면, 데이터베이스 연결이 충분히 있더라도 Thread 부족으로 요청을 처리하지 못할 수 있습니다.
* 최적화 방법
Thread 수와 Connection Pool 수는 서버의 성능을 최적화하기 위해 적절히 조정해야 합니다. 이를 위해 애플리케이션의 요청 처리 패턴을 분석하고, 데이터베이스 성능과 서버의 하드웨어 자원도 고려해야 합니다. 또한, Thread Pool과 Connection Pool을 설정할 때는 최대 Thread 수가 최대 Connection Pool 수를 초과하지 않도록 설정하는 것이 좋습니다.
결론적으로, WAS의 Thread 수와 Connection Pool 수는 서버 성능을 결정하는 중요한 요소로, 이들의 균형을 잘 맞추는 것이 필요합니다.
Thread Pool과 Connection Pool 설정
Thread Pool과 Connection Pool을 설정하는 계산 방법은 여러 요인에 따라 달라질 수 있지만, 일반적으로 서버의 성능, 애플리케이션의 특성, 그리고 데이터베이스의 처리 능력 등을 고려해야 합니다.
1. Thread Pool 설정
Thread Pool의 크기는 주로 다음 요소들에 따라 결정됩니다
- 동시 사용자 수: 동시에 요청을 보내는 사용자 수
- 요청 처리 시간: 각 요청을 처리하는 데 걸리는 시간
- 하드웨어 자원: CPU와 메모리
* Thread Pool 크기 계산 방법
- 동시 요청 수: 서버가 동시에 처리할 수 있는 요청의 수를 결정합니다. 예를 들어, 동시에 100개의 요청을 처리해야 한다면 최소한 100개의 Thread가 필요합니다.
- 요청 처리 시간: 요청을 처리하는 데 걸리는 평균 시간이 짧으면 Thread Pool 크기를 상대적으로 작게 설정할 수 있습니다. 처리 시간이 길면 그만큼 많은 Thread가 필요할 수 있습니다.
- 서버 하드웨어: 서버의 CPU 코어 수와 메모리 용량도 중요한 요소입니다. CPU가 여러 코어를 갖추고 있다면, 더 많은 Thread를 사용할 수 있습니다.
* 일반적으로 추천되는 공식은 다음과 같습니다
최대 스레드 수 = (CPU 코어 수 × 2) + (동시 요청 수 / 요청 처리 시간)
* 예시
서버 CPU 코어 수: 8
동시 요청 수: 200 요청 처리 시간: 0.5초 (즉, 한 Thread가 요청을 처리하는 데 0.5초가 걸린다고 가정)
최대 Thread 수 = (8 × 2) + (200 / 0.5) = 16 + 400 = 416
따라서, Thread Pool의 크기는 약 416개가 적당할 수 있습니다.
2. Connection Pool 설정
Connection Pool의 크기는 데이터베이스와의 연결을 효율적으로 관리하는 데 중요한 역할을 합니다. 데이터베이스 연결은 비용이 많이 들고 시간이 걸리므로, 연결을 재사용할 수 있도록 설정하는 것이 중요합니다.
* Connection Pool 크기 계산 방법
- 동시 요청 수: 데이터베이스 연결을 요청하는 동시 클라이언트의 수
- 쿼리 처리 시간: 각 쿼리를 처리하는 데 걸리는 평균 시간
- 데이터베이스 성능: 데이터베이스의 최대 동시 연결 수
- Thread Pool 크기: 각 Thread는 하나 이상의 데이터베이스 연결을 필요로 하므로, Thread 수에 비례하여 설정할 수 있습니다.
* 일반적으로 Connection Pool의 크기는 다음과 같은 방식으로 설정할 수 있습니다:
Connection Pool 크기 = (Thread Pool 크기 × 평균 DB 연결 필요 수) 또는 (동시 요청 수 × 평균 DB 연결 필요 수)
* 예시
Thread Pool 크기: 416개
각 Thread가 한 번에 처리하는 평균 DB 연결 수: 1
평균 DB 쿼리 처리 시간: 0.5초
Connection Pool 크기 = 416 (Thread Pool 크기) × 1 (각 Thread가 사용하는 DB 연결 수) = 416
따라서, Connection Pool의 크기는 416개가 적당할 수 있습니다.
Thread Pool의 크기를 Connection Pool 크기보다 약간 더 크게 설정하는 것이 좋습니다. 이유는, 스레드가 반드시 DB 연결을 사용하는 것이 아니기 때문에, DB 연결을 사용하지 않는 Thread가 존재할 수 있기 때문입니다. 예를 들어, 일부 요청은 데이터베이스와의 연결 없이 처리될 수 있습니다.
따라서, Thread Pool 크기를 Connection Pool보다 +10개 정도 더 설정하는 것은 충분히 합리적입니다. 이 추가적인 Thread는 데이터베이스 연결이 사용되지 않는 비동기 작업을 처리하거나, DB 연결을 기다리고 있는 다른 Thread를 효율적으로 대기시킬 수 있게 합니다. +10개의 Thread는 과도하지 않으며, 서버가 자원을 효율적으로 활용할 수 있도록 도와줍니다. 다만, 최적화는 환경에 따라 달라지므로 모니터링을 통해 성능을 지속적으로 분석하고, 필요에 따라 조정하는 것이 중요합니다.
참고
DB 커넥션 풀(DBCP)은 왜 쓰는가?(HikariCP)
Commons DBCP 이해하기
데이터베이스 커넥션 풀 (Connection Pool)과 HikariCP
'DB' 카테고리의 다른 글
[SQLD] 자격증 합격 후기 (경력자) (4) | 2024.06.20 |
---|---|
[DB] MySQL IN과 EXISTS 차이 (0) | 2023.09.24 |
[DB] SQL 쿼리 튜닝 시 고려사항 (0) | 2023.09.18 |
[DB] MySQL 해시 조인(hash join) 개념 (0) | 2023.09.12 |
[DB] MySQL 스토리지 엔진 종류 및 특징 (0) | 2023.09.03 |