데이터베이스(DB) 연결은 애플리케이션과 DB 간의 통신을 가능하게 하는 수단이다. 이를 위해 데이터베이스 드라이버와 데이터베이스 연결 정보를 포함하는 URL이 필요하다. 자바의 DB 연결에는 주로 JDBC(Java Database Connectivity)가 사용되며, 이는 URL 형식을 사용한다.
데이터베이스 연결 구조에는 2Tier와 3Tier 두 가지가 있다.
JDBC는 Java Database Connectivity의 약어로, 다양한 종류의 관계형 데이터베이스에 접속하고 SQL 문을 수행할 때 사용되는 표준 SQL 인터페이스 API이다. 각 DBMS에 맞는 JDBC 드라이버를 이용하면 다양한 DBMS(MySQL, MsSQL, Oracle, PostgreSQL 등)와 쉽게 연동할 수 있다.
자바 애플리케이션에서 데이터베이스에 접근하기 위해서는 다음과 같은 구조로 동작한다: Java (Web) Application -> JDBC API -> JDBC Driver -> DB
JDBC 드라이버는 자바 프로그램의 요청을 DBMS가 이해할 수 있는 프로토콜로 변환해 주는 클라이언트 측 어댑터이다. 각 DBMS 제공자는 자신에게 알맞은 JDBC 드라이버를 제공한다.
JDBC를 이용한 데이터베이스 연결 및 쿼리 수행의 기본적인 순서는 다음과 같다:
1. DB 벤더에 맞는 드라이버 로드
2. DB 서버의 IP, ID, PW 등을 DriverManager
클래스의 getConnection()
메소드를 사용하여 Connection 객체 생성
3. Connection에서 PreparedStatement
객체를 생성
4. executeQuery
를 수행하고 ResultSet
객체를 받아 데이터를 처리
5. 사용했던 ResultSet
, PreparedStatement
, Connection
을 close
하여 자원을 반납
매번 사용자가 요청할 때마다 JDBC 드라이버를 로드하고 연결 객체를 생성하는 것은 비효율적이다. 이를 해결하기 위해 커넥션 풀(Connection Pool)을 사용한다.
connection pool은 웹 컨테이너(WAS)가 실행될 때 일정량의 Connection 객체를 미리 만들어서 pool에 저장한다. 클라이언트 요청이 오면 Connection 객체를 빌려주고, 임무가 완료되면 다시 Connection 객체를 pool에 반환한다.
동시 접속자가 많을 경우나 너무 많은 DB 접근이 발생할 경우, connection은 한정되어 있기 때문에 쓸 수 있는 connection이 발납될 때까지 기다려야 한다. 이때, 너무 많은 connection을 생성하면 메모리 소모가 크고 프로그램의 성능을 떨어뜨릴 수 있다. 따라서 사용량에 따라 적정량의 connection 객체를 생성해 두어야 한다.
Connection Pool의 크기를 무한정 늘리면 성능이 좋아질까? 그렇지 않다. Connection의 주체는 Thread이므로 Thread와 함께 고려해야 한다.
Thread Pool 크기가 Connection Pool 크기보다 작으면 남는 Connection은 메모리 공간만 차지하게 됩니다. 반면에 Thread Pool 크기와 Connection Pool 크기가 동시에 증가하면 더 많은 Context Switching이 발생하여 성능에 부정적인 영향을 미칠 수 있다.
Connection Pool의 크기를 어떻게 설정해야 적절한가에 대해 Hikari CP의 공식 문서에서는 아래의 공식을 제시하고 있다.
1 connections = ((core_count) * 2) + effective_spindle_count
여기서 core_count는 현재 서버에서 사용하는 CPU 개수를 나타내고, effective_spindle_count는 DB 서버가 처리할 수 있는 동시 I/O 요청 수를 나타냅니다. 이 공식에 따르면, CPU 속도가 Disk I/O 보다 월등히 빠르므로, Thread가 Disk 작업에서 블로킹되는 시간에 다른 Thread의 작업을 처리할 수 있는 여유가 생긴다는 점을 반영하고 있다.
JDBC는 자바 애플리케이션이 데이터베이스에 접근할 수 있도록 만든 JAVA에서 제공하는 API이며, connection pool은 JDBC 실행 과정 중에서 생성되어야 할 Connection 객체를 미리 만들어 저장해두는 기법이다. 이로 인해 불필요한 과정(Connection 객체 생성,삭제)을 줄여 성능을 향상시킬 수 있다.
그러나 Connection Pool의 크기를 크게 설정하면 메모리 소모가 크며, 많은 사용자가 대기 시간이 줄어들지만, 반대로 작게 설정하면 대기 시간이 길어집니다. 따라서 사용량에 따라 적정량의 Connection 객체를 생성해 두어야 한다.
아주 유용한 정보네요!