🔹 1. 데이터베이스 드라이버의 역할과 종류
✅ 드라이버란?
- 애플리케이션과 DB 사이의 중개자 역할을 함.
- 애플리케이션의 JDBC 요청을 DB가 이해할 수 있는 형태로 변환하고, 응답도 다시 자바 객체로 역변환.
✅ 드라이버의 종류
데이터베이스드라이버 클래스명
MySQL | com.mysql.cj.jdbc.Driver |
PostgreSQL | org.postgresql.Driver |
H2 | org.h2.Driver |
Oracle | oracle.jdbc.OracleDriver |
💡 팁: DBMS마다 드라이버가 다르므로 사용 중인 DB에 맞게 드라이버를 지정해야 함.
🔹 2. JDBC란 무엇인가?
✅ JDBC (Java Database Connectivity)
- 자바 애플리케이션에서 DB와 연결하고 SQL을 실행하기 위한 표준 API입니다.
- JDBC는 단순히 인터페이스 집합이며, 실제 동작은 DBMS에 맞는 드라이버 구현체가 수행합니다.
✅ JDBC 드라이버 종류 (Type 1~4)
타입설명특징
Type 1 | JDBC-ODBC 브리지 | 구식, 거의 사용하지 않음 |
Type 2 | 네이티브 API 기반 드라이버 | OS 의존적 |
Type 3 | 네트워크 프로토콜 드라이버 | 중간 서버 필요 |
✅ Type 4 | 순수 Java 드라이버 | 가장 널리 사용됨, OS 독립적 |
🔹 3. Spring Boot의 JDBC 구성
Spring Boot는 JDBC를 사용하는 데 필요한 거의 모든 것을 자동으로 설정해 주는 프레임워크입니다. spring-boot-starter-jdbc를 통해 아래와 같은 기능을 제공합니다
✅ 포함된 핵심 기능
구성 | 요소설명 |
JdbcTemplate | JDBC 작업을 간편하게 처리하도록 도와주는 클래스 (SQL 실행, 결과 조회 등) |
DataSource | 커넥션 풀 또는 단일 커넥션 생성 등 DB 연결에 필요한 자원 관리 |
자동 구성 | application.yml 설정을 바탕으로 자동으로 JDBC 환경을 설정 |
✅ 의존성 추가(주석을 읽어보기!!!!!)
dependencies {
// 애플리케이션이 종료되지 않고 웹 서버를 띄울 수 있도록 도와줍니다. (H2 Console 웹페이지 띄우기)
implementation 'org.springframework.boot:spring-boot-starter-web'
// 스프링 부트 애플리케이션에서 JDBC를 사용하기 위한 모든 필수 의존성을 포함하고 있습니다.
// JDBC API를 통해 데이터베이스와의 연결 및 SQL 쿼리 실행을 쉽게 할 수 있도록 도와줍니다.
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
// H2는 자바 기반의 인메모리 데이터베이스로,
// 로컬 개발 및 테스트 환경에서 DB 서버를 별도로 구축하지 않고 사용할 수 있게 해 줍니다.
// 빠르고 경량이며 설정이 간단하다는 장점이 있습니다.
runtimeOnly 'com.h2database:h2'
}
✅ 포함 요소 상세
구성 요소설명
JdbcTemplate | Spring에서 제공하는 JDBC 간편 도구. 반복되는 Connection, Statement, ResultSet 처리를 자동화. SQL 실행, 조회, 업데이트, 트랜잭션 처리 등에서 매우 유용함. |
DataSource | 커넥션 풀을 관리하거나 DB 연결 정보를 담는 인터페이스. 내부적으로 커넥션 풀 라이브러리(HikariCP 등)를 통해 실제 커넥션을 관리. |
DriverManagerDataSource | 가장 기본적인 DataSource 구현체. 커넥션 풀 없이 매번 새로운 연결을 생성. 학습/테스트 용도로만 권장. 실무에서는 HikariDataSource가 기본. |
자동 구성 | spring.datasource.*로 시작하는 설정 값을 기반으로 Spring Boot가 DataSource, JdbcTemplate, 트랜잭션 매니저 등을 자동 생성해줌. |
✅ Spring Boot JDBC 사용의 장점
1. 자동 구성 기반으로 빠른 개발
- spring-boot-starter-jdbc를 추가하고 application.yml만 작성하면 DB 연결 설정이 완료됩니다.
- 수동으로 드라이버 등록, 커넥션 열기, 닫기 등은 필요 없습니다.
2. 예외 처리 일원화
- JDBC는 SQLException을 직접 처리해야 하지만, Spring은 이를 DataAccessException 계열로 포장해줍니다.
- 예외가 트랜잭션 롤백과 연계되거나, 특정 에러 타입을 쉽게 분기 처리할 수 있음.
3. 코드 간소화 및 가독성 향상
- JdbcTemplate을 사용하면 다음과 같은 중복 코드 제거 가능:
// 기존 JDBC
Connection conn = ...;
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
// JdbcTemplate 방식
String sql = "SELECT * FROM users";
List<User> users = jdbcTemplate.query(sql, new UserRowMapper());
4. 트랜잭션 처리 연동
- Spring Boot는 AOP 기반으로 선언적 트랜잭션 관리가 가능하여, @Transactional 애노테이션만으로도 안전하게 트랜잭션 처리가 가능함.
✨ 팁 요약
팁 1: 실무에서는 DriverManagerDataSource 대신 HikariCP가 기본 제공되며 성능이 훨씬 뛰어납니다.
팁 2: JdbcTemplate은 SQL 실행의 가장 가벼운 방식이며, 성능 및 제어 측면에서 JPA보다 유리한 경우가 있습니다.
팁 3: Spring Boot의 자동 구성은 DataSource, JdbcTemplate, TransactionManager까지 모두 처리해주므로 진입장벽이 매우 낮고 생산성이 높습니다.
🔄 JDBC 실습 흐름
✅ JDBC 작동 순서 & 설명
- 드라이버 로드 (자동)
- 최신 JDBC 드라이버는 JAR만 등록되어 있으면 Class.forName() 없이 자동 로딩됩니다.
- Connection 객체 획득
- DriverManager를 통해 DB와 연결을 맺는 객체 생성.
- 이 연결을 통해 SQL을 실행할 수 있는 준비 상태를 갖춤.
- SQL 실행 객체 생성
- Statement 또는 PreparedStatement를 통해 SQL 실행 객체 생성.
- Statement는 SQL을 문자열로 직접 작성.
- PreparedStatement는 바인딩 방식으로 작성, 보안과 성능에 유리.
- SQL 실행 & 결과 처리
- SELECT 쿼리는 executeQuery()로, 결과는 ResultSet에 저장.
- INSERT, UPDATE, DELETE는 executeUpdate()로 실행.
- ResultSet에서 데이터를 꺼낼 때는 next()로 한 행씩 접근 가능.
-
- 모든 JDBC 객체는 외부 리소스이므로 반드시 닫아야 함.
- Java 7부터는 try-with-resources를 사용하면 자동으로 close() 처리됨.
- 닫아야 할 리소스:
- ResultSet
- Statement / PreparedStatement
- Connection리소스 정리 (try-with-resources)
✅ JDBC 작동 순서도

✅ JDBC 실습 코드
// JdbcApplication.java
package com.thesun4sky.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JdbcApplication {
public static void main(String[] args) throws SQLException {
// 어플리케이션 실행 컨텍스트 생성
SpringApplication.run(JdbcApplication.class, args);
// 데이터베이스 연결정보
String url = "jdbc:h2:mem:test"; // spring.datasource.url
String username = "sa"; // spring.datasource.username
// connection 얻어오기
try (Connection connection = DriverManager.getConnection(url, username, null)) {
try {
// 테이블 생성 (statement 생성)
String creatSql = "CREATE TABLE USERS (id SERIAL, username varchar(255))";
try (PreparedStatement statement = connection.prepareStatement(creatSql)) {
statement.execute();
}
// 데이터 추가 (statement 생성)
String insertSql = "INSERT INTO USERS (username) VALUES ('teasun kim')";
try (PreparedStatement statement = connection.prepareStatement(insertSql)) {
statement.execute();
}
// 데이터 조회 (statement 생성 후 rs = resultSet 수신 & next() 조회)
String selectSql = "SELECT * FROM USERS";
try (PreparedStatement statement = connection.prepareStatement(selectSql)) {
var rs = statement.executeQuery();
while (rs.next()) {
System.out.printf("%d, %s", rs.getInt("id"), rs.getString("username"));
}
}
} catch (SQLException e) {
if (e.getMessage().equals("ERROR: relation \"account\" already exists")) {
System.out.println("USERS 테이블이 이미 존재합니다.");
} else {
throw new RuntimeException();
}
}
}
}
}