
JDBC는 자바와 데이터베이스(정확히는 표 형태의 데이터)가 상호작용하기 위해 만들어진 API이다.
뭔가 데이터베이스와 자바 애플리케이션과의 통신 인터페이스를 하는거 보니 JPA와 같은 녀석이 아닐까 싶었다. 하지만 굳이 따지자면 JDBC는 직접적으로 데이터베이스와 통신하게되는 저수준 API, JPA는 이를 사용해 애플리케이션을 개발 할 수 있도록 돕는 고수준 API 정도로 이해하면 좋을거 같다.
그래서 얘가 뭘 하냐
- 데이터소스와 연결
- 질의 생성 및 전달
- 질의 결과를 처리하고 전달
을 한다고 한다.
일단 JDBC가 구체적으로 어떠한 구성을 갖고 있는지 알아보자.
우리가 작성하는 코드는 자바로 이루어져있는데 데이터베이스는 사실 서비스마다 다를 수 있다. 하지만 이를 신경쓰지 않고 코드를 잘 작성하기만 데이터베이스에 질의가 잘 전달될 수 있도록 Driver라는 친구를 JDBC가 미리 만들어 두었다. 그리하여 우린 DBMS에 맞는 Driver만 잘 골라주고 사용하면 된다.
설정파일에서 자주 보이던 이녀석이 JDBC Driver 선택이었던 것이다.

드라이버에는 크게 네개의 유형이 있는데,
1. Type 1(Bridge Driver): Bridge Driver는 JDBC와 ODBC(Open Database Connectivity) 간의 브리지 역할을 한다. 요즘은 잘 안쓴다고 한다.
2. Type 2(Native-API Driver): 특정 데이터베이스의 네이티브 API로 변환해주는 드라이버. Type 2보다는 성능상 우수. 클라이언트 시스템에 네이티브 데이터베이스 라이브러리가 설치되어 있어야함. 플랫폼 종속적.
3. Type 3(Network Protocol Driver):JDBC 호출을 미들웨어 서버로 전달하여, 그 서버가 데이터베이스에 연결하도록 하는 방식.
4. Type 4(Thin Driver): JDBC 호출을 데이터베이스 네이티브 프로토콜로 직접 변환해주는 드라이버. Type 2보다 플랫폼 독립적이고 네이티브 API로 변환하는 과정이 없어 성능상 이점이 있기 때문에 현재 가장 많이 사용됨.

이제 JDBC가 클라이언트에 의해 질의를 생성해서 데이터베이스에 전송하고, 그 결과를 전달받아 처리하기까지의 과정을 살펴보자.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/test";
String username = "username";
String password = "password";
try (
Connection connection = DriverManager.getConnection(url, username, password);
PreparedStatement insertStatement = connection.prepareStatement("INSERT INTO users (name, email) VALUES (?, ?)");
PreparedStatement selectStatement = connection.prepareStatement("SELECT id, name, email FROM users")
) {
insertStatement.setString(1, "Yechan");
insertStatement.setString(2, "qkenrdl05@gmail.com");
insertStatement.executeUpdate();
try (ResultSet resultSet = selectStatement.executeQuery()) {
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String email = resultSet.getString("email");
System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
JDBC 드라이버 로드 및 초기화를 진행한다. 이를 위해 Class.forName().newInstance() 메서드를 호출합니다. 이때 JDBC 드라이버는 CLASSPATH에 있어야 한다.
Driver를 통해 Connection 열기:
JDBC Driver를 로드한 후, 애플리케이션은 데이터베이스와 통신하기 위해 JDBC API를 사용한다. 이를 위해 Driver 클래스의 connect() 메서드를 사용하여 데이터베이스에 연결한다. 데이터베이스 연결을 열기 위해서는 인증이 필요하며, 인증 정보는 connect() 메서드의 매개변수로 전달된다. 데이터베이스 연결은 Java 클래스에서 유지될 수 있으며, 연결이 활성화된 상태에서 언제든지 데이터베이스와 통신한다.
질의 실행:
데이터베이스 연결을 얻은 후, 애플리케이션은 Statement, PreparedStatement, 또는 CallableStatement 객체를 사용하여 질의를 실행할 수 있다. JDBC 드라이버는 이러한 인터페이스를 구현하여 기본 기능을 제공한다. 라이브 데이터베이스 연결에서 여러 개의 Statement, PreparedStatement, CallableStatement 객체를 생성할 수 있다. 이후에 ExecuteQuery를 호출하는 시점에 직접 질의문이 전달된다.
결과 처리:
질의가 실행된 후, JDBC 애플리케이션은 ResultSet 및 ResultSetMetaData 인터페이스를 사용하여 데이터베이스로부터 데이터를 가져올 수 있다.
Connection 닫기:
JDBC 애플리케이션의 마지막 단계는 데이터베이스 연결을 닫는 것입니다. Connection 객체의 close() 메서드를 사용하여 데이터베이스 연결 객체를 반환한다.
하지만 위 과정을 잘 보면 질의문을 보낼때마다 Connection을 만들어야 하고, 반복적으로 리소스를 사용하는 모습이 보인다. 문제는 이 Connection이 I/O 작업인지라 자원 소모를 강요하는 작업이다. Connection이 생성되거나 삭제될때마다 많은 자원 소모가 있다는것이다.
그래서 반복적인 자원 사용이 정해진 작업이기 때문에 이를 미리 만들어 사용하는 DBCP(Database Connection Pool)을 사용한다.
https://codingnomads.com/java-301-jdbc-lifecycle
https://steady-coding.tistory.com/564
https://www.ibm.com/docs/ko/i/7.3?topic=driver-getting-started-jdbc