
자바는 데이터베이스(DB)와 연결하여 데이터를 삽입, 조회, 수정, 삭제(CRUD)할 수 있도록 JDBC(Java Database Connectivity)라는 표준 API를 제공합니다.
이를 통해 데이터베이스 연결, SQL 쿼리 실행, 결과 처리 등의 작업을 수행할 수 있습니다. JDBC는 데이터베이스와의 통신을 추상화하여 DBMS에 종속되지 않고 다양한 DBMS(MySQL, Oracle, PostgreSQL 등)에서 동일한 방식으로 사용할 수 있습니다.
자바는 JDBC를 java.sql과 javax.sql 패키지에 나눠서 제공합니다.

java.sql 패키지
javax.sql 패키지
각 DBMS는 이 인터페이스들을 구현한 .jar 파일(JDBC 드라이버)를 제공합니다.
JDBC 드라이버는 java.sql과 javax.sql에 정의된 인터페이스들을 구현한 클래스 집합으로, 실제로 자바 애플리케이션이 DBMS와 통신할 수 있도록 해주는 역할을 합니다.
JDBC는 크게 다음 두 가지로 구성됩니다.
java.sql, javax.sql 패키지에 정의된 인터페이스 집합.jar 파일Java는 JDBC를 위해 java.sql과 javax.sql 두 패키지를 제공합니다.
java.sql 패키지: 기본 JDBC 인터페이스를 담고 있으며, JDBC의 핵심 기능을 담당합니다.javax.sql 패키지: 확장 JDBC 인터페이스를 담고 있으며, 커넥션 풀, 트랜잭션 관리 등 고급 기능을 담당합니다.각 패키지는 데이터베이스와의 연결, SQL 쿼리 실행, 결과 처리 등을 위한 다양한 인터페이스를 정의합니다.
java.sql 패키지)java.sql은 JDBC의 기본 기능을 담당하는 핵심 인터페이스들을 포함합니다.
Class.forName(...)으로 드라이버 클래스를 로딩하면 자동으로 등록됩니다.Statement, PreparedStatement, CallableStatement 등을 생성할 수 있으며, 트랜잭션을 시작하거나 종료할 수 있습니다.commit(), rollback(), close() 등의 메서드도 포함됩니다.SELECT * FROM user, DELETE FROM boardStatement의 확장 인터페이스로, 파라미터가 포함된 SQL 문을 실행할 수 있습니다.Statement보다 더 많이 사용됩니다.SELECT * FROM user WHERE id = ?CALL get_user(?, ?)rs.next(), rs.getString("name"), rs.getInt(1) 등javax.sql 패키지)javax.sql은 JDBC 기능을 확장하기 위한 고급 인터페이스들을 제공합니다.
이 패키지는 주로 커넥션 풀, 트랜잭션 관리, JNDI 연동, 오프라인 데이터 처리 등에 사용됩니다.
DriverManager를 대체하는 DB 연결 팩토리 인터페이스입니다.DriverManager보다 DataSource를 사용하는 방식이 표준입니다.실무에서는 대부분 DataSource만 직접 사용하며, 나머지는 프레임워크나 라이브러리 내부에서 사용됩니다.
JDBC 드라이버는 자바 애플리케이션과 특정 DBMS 간의 통신을 담당합니다.
각 DBMS는 java.sql 및 javax.sql 인터페이스를 구현한 JDBC 드라이버(.jar 파일)를 제공합니다.
개발자는 JDBC 인터페이스만 사용하고, 실제 DB 연결, SQL 전송, 결과 처리 등의 작업은 드라이버가 수행합니다.
Connection, Statement, ResultSet 등)의 구현체 역할을 합니다.Class.forName(...)을 통해 명시적으로 로딩하거나, 드라이버가 자동으로 로딩되기도 합니다.| DBMS | JDBC 드라이버 이름 | 비고 |
|---|---|---|
| MySQL | mysql-connector-j | Maven 또는 수동 다운로드 가능 |
| Oracle | ojdbc8, ojdbc11 | 자바 버전에 따라 드라이버 선택 필요 |
| PostgreSQL | postgresql-<version>.jar | 오픈소스, PostgreSQL 공식 사이트 제공 |
| MariaDB | mariadb-java-client | MySQL 드라이버와 유사, 대체 가능 |
| SQL Server | mssql-jdbc | Microsoft 공식 제공 |
| SQLite | sqlite-jdbc | 경량형, 커뮤니티 제공(Xerial 등) |
JDBC의 핵심 개념은 다음과 같습니다.
개발자는 인터페이스만 사용하고, 각 DBMS가 제공하는 드라이버가 실제 동작을 수행한다.
개발자는 JDBC를 사용할 때 java.sql 인터페이스만 알면 됩니다.
다음과 같이 코드를 작성하더라도, 실제 동작은 드라이버가 처리합니다.
Connection conn = DriverManager.getConnection(...);
PreparedStatement ps = conn.preparedStatement("SELECT * FROM customer");
ResultSet rs = ps.executeQuery();
예를 들어 MySQL을 사용하는 경우:
Connection conn = DriverManager.getConnection(...);
이 메서드는 내부적으로 MySQL 드라이버(mysql-connector-j.jar)가 등록한 com.mysql.cj.jdbc.Driver 클래스를 통해 동작하며,
반환되는 Connection 객체는 실제로는 com.mysql.cj.jdbc.ConnectionImpl 클래스입니다.
Connection conn = DriverManager.getConnection(...);
// 실제 구현체: com.mysql.cj.jdbc.ConnectionImpl
즉, 개발자는 Connection이라는 인터페이스 타입으로 객체를 다루지만, 실제로는 MySQL 드라이버가 구현한 클래스가 뒤에서 동작하고 있는 것입니다.
이 구조는 자바의 다형성(polymorphism) 덕분에 가능합니다.
Connection conn = new MysqlConnectionImpl(); // 내부적으로는 이렇게 동작함

Class.forName("com.mysql.cj.jdbc.Driver");
.jar 파일 내부)를 메모리에 로드합니다.java.sql.Driver 인터페이스를 구현하고, 로딩될 때 DriverManager에 자동 등록됩니다.ClassNotFoundException이 발생합니다.Class.forName(...)을 호출하는 것이 학습이나 디버깅을 위해 권장됩니다.Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306:mydb", "user", "password"
);
jdbc:mysql://호스트:포트/DB이름?옵션=값
jdbc:oracle:thin:@호스트:포트:SID
SQLException이 발생합니다.Statement stmt = conn.createStatement();
SELECT * FROM customerPreparedStatement ps = conn.prepareStatment(
"SELECT * FROM customer WHERE id = ?"
);
ps.setInt(1, 101);
실무에서는 PreparedStatment 사용이 권장됩니다.
ResultSet rs = ps.executeQuery();
int result = ps.executeUpdate();
while (rs.next()) {
String name = rs.getString("name");
int age = rs.getInt("age");
}
rs.next()로 커서를 다음 행으로 이동합니다.rs.getXXX(컬럼명 또는 인덱스)로 각 컬럼 값을 가져옵니다.| 메서드 | 설명 |
|---|---|
| next() | 다음 행으로 이동 (없으면 false 반환) |
| getString("컬럼명") | 문자열 반환 |
| getInt(1) | 첫 번째 컬럼의 정수값 반환 |
| getDate(...), getDouble(...) 등 | 다양한 타입 지원 |
rs.close();
ps.close();
conn.close();
try (
Connection conn = DriverManager.getConnection(...);
PreparedStatement ps = conn.preparedStatement(...);
ResultSet rs = ps.executeQuery()
) {
// 실행 및 결과 처리
} catch (SQLException e) {
e.printStackTrace();
}
JDBC를 이해할 때 혼동하기 쉬운 두 가지 개념이 있습니다.
바로 Driver 클래스와 DriverManager 클래스입니다.
이 둘은 이름은 비슷하지만, 역할과 사용 위치가 완전히 다릅니다.
JDBC의 전체 구조를 이해하려면 이 둘을 명확하게 구분할 수 있어야 합니다.
Driver는 JDBC에서 정의한 인터페이스(java.sql.Driver)입니다.
이 인터페이스는 JDBC 드라이버가 반드시 구현해야 하는 규약을 정의합니다.
즉, Driver는 MySQL, Oracle, PostgreSQL 등 DBMS 회사가 구현하는 핵심 인터페이스입니다.
acceptsURL)connect)Driver 클래스를 구현한 클래스를 드라이버의 진입점 클래스(entry-point)라고 합니다.
Driver 객체는 개발자가 직접 생성하거나 호출하지 않습니다.DriverManager만 사용해서 DB에 연결할 뿐입니다.DriverManager는 자바에서 제공하는 JDBC 연결 관리자 클래스입니다.
개발자가 자바에서 직접 사용하는 클래스는 바로 이 DriverManager입니다.
Connection conn = DriverManager.getConnection(url, user, password);
JDBC는 하나의 환경에서 여러 개의 DB 드라이버를 사용할 수 있도록 설계되어 있습니다.
그렇기 때문에 DriverManager는 다음과 같은 방식으로 등록된 드라이버 중 적절한 것을 선택합니다.
개발자가 다음 코드를 실행합니다.
Class.forName("com.mysql.cj.jdbc.Driver");
MySQL 드라이버 클래스 내부에는 다음 코드가 존재합니다.
static {
DriverManager.registerDriver(new Driver());
}
// Connection conn = DriverManager.getConnection("url", "user", "password");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "pass");
MySQL 드라이버의 진입점 클래스는 다음과 같습니다.
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
static {
DriverManager.registerDriver(new Driver());
}
}
jdbc:mysql://...로 시작하면, 이 드라이버가 선택되어 연결을 수행합니다.❗️참고
실제 DB 연결 처리, SQL 실행, 결과 조회 등은 내부의 ConnectionImpl, PreparedStatementImpl, ResultSetImpl 같은 클래스들이 수행합니다.
Driver는 진입과 등록만 담당합니다.
| 항목 | Driver | DriverManager |
|---|---|---|
| 소속 | java.sql.Driver (인터페이스) | java.sql.DriverManager (클래스) |
| 구현 주체 | 각 DBMS 드라이버 제공자 | 자바 표준 라이브러리 |
| 개발자 직접 사용 | ❌ (직접 사용하지 않음) | ✅ (직접 호출) |
| 주요 역할 | DB 연결 수행 클래스 | 드라이버 선택 및 연결 위임 |
| 예시 코드 위치 | com.mysql.cj.jdbc.Driver | DriverManager.getConnection(...) |
Class.forName("드라이버 클래스 이름");
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
// 또는
PreparedStatement ps = conn.preparedStatement("SELECT * FROM customer WHERE id = ?");
ResultSet rs = stmt.executeQuery(sql); // SELECT
int rows = stmt.executeUpdate(sql); // INSERT, UPDATE, DELETE
while (rs.next()) {
// 여러 행인 경우
System.out.println(rs.getString("name"));
}
if (rs.next()) {
// 결과가 1행만 있는 경우
System.out.println(rs.getString("name"));
}
rs.close();
stmt.close();
conn.close();
Class.forName()
→ DriverManager.getConnection()
→ createStatement() or prepareStatment()
→ executeQuery() or executeUpdate()
→ ResultSet 처리
→ close()
| 단계 | 키워드 | 요약 |
|---|---|---|
| 1 | 로딩 | 드라이버 클래스 로딩 및 등록 |
| 2 | 연결 | DB 연결 생성 (Connection) |
| 3 | 준비 | Statement 또는 PreparedStatement 생성 |
| 4 | 실행 | SQL 실행, 결과 ResultSet 또는 쿼리에 영향받은 행 수 반환 |
| 5 | 처리 | rs.next()로 결과 순회 |
| 6 | 정리 | close()로 자원 해제 |
| 단계 | 동작 | 클래스 | 메서드 |
|---|---|---|---|
| 1 | 드라이버 로딩 | Class | forName() |
| 2 | DB 연결 | DriverManager | getConnection() |
| 3 | SQL 실행 객체 생성 | Connection | createStatement() 또는 preparedStatement() |
| 4 | SQL 실행 | Statement, PreparedStatement | executeQuery() 또는 executeUpdate() |
| 5 | 결과 처리 | ResultSet | next(), getString(), getInt() 등 |
| 6 | 자원 해제 | ResultSet, Statement, Connection | close() |