F-LAB JAVA · 6주차 · Phase 3 · JDBC 표준화의 등장
이 Unit을 끝내면 다음을 답할 수 있어야 한다.
JDBC 는 자바의 DB 접근 표준 API 로, 연결·SQL 실행·결과 처리 방식을 통일하여 DB 를 교체해도 URL 과 드라이버만 바꾸면 나머지 코드는 그대로 동작하며, 이는 5주차의 전략 패턴·인터페이스 추상화와 똑같은 구조다.
JDBC 는 자바의 DB 접근 표준 API 로, 모든 DB 를 같은 방식으로 다룰 수 있게 한다.
덕분에 같은 코드, 다른 DB 가 가능해 —jdbc:mysql://...,jdbc:oracle:thin:@...,jdbc:postgresql://...처럼 URL 과 드라이버만 바꾸면 이후 코드 (DriverManager.getConnection,prepareStatement,executeQuery) 는 동일하다.
JDBC 가 해결한 것은 (1) DB 연결 방식 통일, (2) SQL 실행 방식 통일, (3) 결과 처리 방식 통일이며, DriverManager 가 등록된 드라이버 중 적절한 것을 골라 Connection 을 만들어준다.
이 구조는 5주차의 전략 패턴·인터페이스 추상화 와 똑같다 —Connection,Statement,ResultSet은 인터페이스이고 각 DB 드라이버가 그 구현체로, 애플리케이션은 인터페이스에만 의존한다.
JDBC = 만능 어댑터:
표준 API (만능 어댑터):
- 어느 나라 콘센트든 (DB)
- 같은 플러그 (코드)
- 어댑터만 교체 (드라이버)
같은 코드, 다른 DB:
- 어댑터 헤드만 바꿈 (URL/드라이버)
- 기기 (코드) 그대로
DriverManager (어댑터 관리자):
- 등록된 어댑터들 보관
- URL 보고 맞는 어댑터 선택
- 연결 제공
JDBC 인터페이스 (표준 규격):
- Connection (연결)
- Statement (명령)
- ResultSet (결과)
- 규격만 정의, 구현은 드라이버
5주차 전략 패턴:
- 인터페이스 + 구현 주입
- JDBC 도 같은 구조
→ JDBC = 자바 DB 표준 API, URL/드라이버만 교체, 인터페이스(전략 패턴 구조).
1. JDBC = 표준 API
2. 같은 코드, 다른 DB
3. JDBC가 해결한 것
4. DriverManager
5. 드라이버 로딩
6. 핵심 인터페이스
7. 5주차 패턴과 닮음
8. DB 교체 변경 범위
9. 면접 + 자기 점검
JDBC (Java Database Connectivity):
자바의 DB 접근 표준 API:
- 모든 DB 같은 방식
- 인터페이스 표준
- 구현은 드라이버
표준의 의미:
한 번 배우면:
- 모든 DB 접근
- 같은 코드
- DB 독립
java.sql 패키지:
JDBC 표준 인터페이스:
- Connection
- Statement / PreparedStatement
- ResultSet
- DriverManager
// JDBC 표준 API (ILIC)
public class ShipmentDao {
public Shipment get(Long id) throws Exception {
// 표준 JDBC (DB 무관)
Connection c = DriverManager.getConnection(url, user, pwd);
PreparedStatement ps = c.prepareStatement(
"select * from shipments where id = ?");
ps.setLong(1, id);
ResultSet rs = ps.executeQuery();
// ... 표준 코드
rs.close(); ps.close(); c.close();
return null;
}
String url = "jdbc:mysql://localhost/ilic";
String user = "root";
String pwd = "password";
}
class Shipment {}
JDBC = 자바 DB 접근 표준 API 의 의미는?
답:
1. JDBC:
표준:
패키지:
독립:
// URL 만 다름
// MySQL
String url = "jdbc:mysql://localhost:3306/mydb";
// Oracle
String url = "jdbc:oracle:thin:@localhost:1521:xe";
// PostgreSQL
String url = "jdbc:postgresql://localhost:5432/mydb";
// 이후 코드는 동일!
Connection conn = DriverManager.getConnection(url, user, pwd);
이후 동일:
연결 후:
- prepareStatement (같음)
- executeQuery (같음)
- ResultSet (같음)
→ DB 무관 코드
JDBC URL 형식:
jdbc:<DB종류>:<상세>
- jdbc:mysql://host:port/db
- jdbc:oracle:thin:@host:port:sid
- jdbc:postgresql://host:port/db
// 같은 코드, 다른 DB (ILIC)
public class ShipmentDao {
private final String url; // DB 별로 다름
public ShipmentDao(String url) {
this.url = url;
}
public void add(Shipment s) throws Exception {
Connection c = DriverManager.getConnection(url, "user", "pwd");
// ↓ 이 코드는 DB 무관 (동일)
PreparedStatement ps = c.prepareStatement(
"insert into shipments(id, bl_no) values(?, ?)");
ps.setLong(1, s.getId());
ps.setString(2, s.getBlNo());
ps.executeUpdate();
ps.close(); c.close();
}
}
// 고객사별 (URL 만 다름)
// new ShipmentDao("jdbc:mysql://customerA/ilic")
// new ShipmentDao("jdbc:oracle:thin:@customerB:1521:ilic")
// → add() 코드는 그대로
class Shipment {
Long getId() { return null; }
String getBlNo() { return null; }
}
같은 코드, 다른 DB (URL/드라이버) 는?
답:
1. URL 만 다름:
이후 동일:
URL 형식:
독립:
JDBC 가 해결한 것:
1. DB 연결 방식 통일
2. SQL 실행 방식 통일
3. 결과 처리 방식 통일
+ DB 교체 시 URL/드라이버만
연결 통일:
모든 DB:
- DriverManager.getConnection
- Connection 인터페이스
→ 통일된 연결
실행 통일:
모든 DB:
- prepareStatement
- executeQuery / executeUpdate
→ 통일된 실행
결과 통일:
모든 DB:
- ResultSet
- rs.next(), rs.getXxx()
→ 통일된 결과
// JDBC 가 해결한 3가지 (ILIC)
public class ShipmentDao {
public List<Shipment> findAll() throws Exception {
// 1. 연결 통일
Connection c = DriverManager.getConnection(url, user, pwd);
// 2. 실행 통일
PreparedStatement ps = c.prepareStatement(
"select * from shipments");
ResultSet rs = ps.executeQuery();
// 3. 결과 통일
List<Shipment> result = new ArrayList<>();
while (rs.next()) {
Shipment s = new Shipment();
s.setId(rs.getLong("id"));
s.setBlNo(rs.getString("bl_no"));
result.add(s);
}
rs.close(); ps.close(); c.close();
return result;
}
String url = "jdbc:mysql://localhost/ilic";
String user = "root", pwd = "pwd";
}
class Shipment {
void setId(Long id) {}
void setBlNo(String s) {}
}
// 연결/실행/결과 모두 표준 (DB 무관)
JDBC가 해결한 것 (연결/실행/결과) 은?
답:
1. 3가지 통일:
연결:
실행:
결과:
DriverManager:
드라이버 관리자:
- 등록된 드라이버 관리
- URL 보고 적절한 드라이버 선택
- Connection 생성
DriverManager 역할:
getConnection(url):
- URL 분석 (jdbc:mysql → MySQL)
- 맞는 드라이버 찾음
- 드라이버가 Connection 생성
- 반환
드라이버 선택:
여러 드라이버 등록 시:
- URL 의 DB 종류로
- 적절한 드라이버
- 자동 선택
팩토리 역할:
DriverManager:
- Connection 팩토리
- getConnection (생성)
→ 5주차 팩토리 패턴
// DriverManager (ILIC)
public class ConnectionExample {
public Connection getConnection() throws Exception {
// DriverManager 가:
// 1. URL 분석 (jdbc:mysql → MySQL 드라이버)
// 2. 등록된 MySQL 드라이버 선택
// 3. 드라이버가 Connection 생성
return DriverManager.getConnection(
"jdbc:mysql://localhost/ilic", // URL
"ilic_user", // 계정
"password"); // 비밀번호
}
// 여러 DB 드라이버 등록 시
// jdbc:mysql → MySQL 드라이버
// jdbc:oracle → Oracle 드라이버
// → DriverManager 가 URL 로 자동 선택
}
DriverManager의 역할은?
답:
1. DriverManager:
역할:
선택:
팩토리:
드라이버 로딩:
과거:
- Class.forName 명시
현재 (JDBC 4.0+):
- 자동 로딩 (SPI)
- 의존성만 추가
// 과거 (명시적 로딩)
Class.forName("com.mysql.jdbc.Driver");
Connection c = DriverManager.getConnection(url, user, pwd);
// Class.forName 으로 드라이버 등록
// 현재 (JDBC 4.0+, 자동)
// Class.forName 불필요
Connection c = DriverManager.getConnection(url, user, pwd);
// 의존성에 드라이버 있으면 자동 로딩 (SPI)
SPI (Service Provider Interface):
자동 발견:
- META-INF/services
- 드라이버 자동 등록
→ Class.forName 불필요
// 드라이버 로딩 (ILIC)
// build.gradle 에 드라이버 의존성
// runtimeOnly 'com.mysql:mysql-connector-j'
public class ShipmentDao {
public void add(Shipment s) throws Exception {
// JDBC 4.0+ : Class.forName 불필요 (자동 로딩)
Connection c = DriverManager.getConnection(
"jdbc:mysql://localhost/ilic", "user", "pwd");
// mysql-connector-j 가 SPI 로 자동 등록됨
}
// 과거:
// Class.forName("com.mysql.cj.jdbc.Driver"); // 명시 (불필요)
}
class Shipment {}
드라이버 로딩 방식은?
답:
1. 과거:
현재:
SPI:
의존성:
JDBC 핵심 인터페이스:
- Connection (연결)
- Statement / PreparedStatement (명령)
- ResultSet (결과)
- DriverManager (관리, 클래스)
Connection:
DB 연결:
- 세션 표현
- Statement 생성
- 트랜잭션 제어
PreparedStatement:
미리 컴파일된 SQL:
- 파라미터 (?)
- SQL 인젝션 방어
- 성능 (재사용)
ResultSet:
조회 결과:
- 행 단위 커서
- rs.next() (다음 행)
- rs.getXxx() (컬럼 값)
// 핵심 인터페이스 (ILIC)
public class ShipmentDao {
public Shipment get(Long id) throws Exception {
// Connection (연결)
Connection c = DriverManager.getConnection(url, user, pwd);
// PreparedStatement (명령, 파라미터)
PreparedStatement ps = c.prepareStatement(
"select * from shipments where id = ?");
ps.setLong(1, id); // ? 바인딩 (SQL 인젝션 방어)
// ResultSet (결과)
ResultSet rs = ps.executeQuery();
Shipment s = null;
if (rs.next()) { // 커서 이동
s = new Shipment();
s.setId(rs.getLong("id")); // 컬럼 값
s.setBlNo(rs.getString("bl_no"));
}
rs.close(); ps.close(); c.close();
return s;
}
String url = "jdbc:mysql://localhost/ilic", user = "u", pwd = "p";
}
class Shipment {
void setId(Long id) {}
void setBlNo(String s) {}
}
// 모두 인터페이스 (구현은 드라이버)
JDBC 핵심 인터페이스는?
답:
1. 핵심:
Connection:
PreparedStatement:
ResultSet:
인터페이스 추상화 (5주차):
JDBC:
- Connection (인터페이스)
- 드라이버 (구현)
5주차:
- ConnectionMaker (인터페이스)
- 구현체
→ 같은 추상화
전략 패턴:
JDBC:
- 인터페이스 (전략)
- 드라이버 (구체 전략)
- 런타임 선택 (URL)
→ 5주차 전략 패턴
DIP:
애플리케이션:
- Connection (추상) 의존
- 구체 드라이버 모름
→ 5주차 DIP
OCP:
새 DB 지원:
- 새 드라이버 추가 (확장)
- 애플리케이션 코드 변경 X (닫힘)
→ 5주차 OCP
// JDBC = 5주차 패턴의 실제 구현
// 인터페이스 (추상) — 5주차 ConnectionMaker 처럼
// java.sql.Connection (JDBC 인터페이스)
public class ShipmentDao {
public void add(Shipment s) throws Exception {
// Connection 인터페이스에만 의존 (DIP)
Connection c = DriverManager.getConnection(url);
// c 는 어떤 구현? MySQL? Oracle? 모름 (추상)
// 드라이버가 구현 (전략)
}
String url = "jdbc:mysql://localhost/ilic";
}
class Shipment {}
// 5주차 매핑:
// Connection (인터페이스) = ConnectionMaker (인터페이스)
// MySQL Connection (구현) = NConnectionMaker (구현)
// DriverManager = 팩토리/조립
// → JDBC 가 5주차 원칙의 실제 사례
JDBC가 닮은 5주차 패턴은?
답:
1. 인터페이스 추상화:
전략 패턴:
DIP:
OCP:
DB 교체 변경 범위:
JDBC:
- URL 변경
- 드라이버 변경 (의존성)
- SQL 방언 일부 (다음 Unit)
→ 최소 변경
JDBC 전 vs 후:
전 (Unit 3.1):
- 전체 재작성
후 (JDBC):
- URL/드라이버만
- 코드 그대로
변경 격리:
DB 변경 영향:
- URL (설정)
- 드라이버 (의존성)
- 애플리케이션 코드 X
→ OCP 효과
한계 예고:
JDBC 도 완벽 X:
- SQL 문법 차이 (방언)
- LIMIT vs ROWNUM
- → Unit 3.3
// DB 교체 변경 범위 (ILIC)
// application.yml (설정만)
// spring:
// datasource:
// url: jdbc:mysql://localhost/ilic # MySQL
// # url: jdbc:oracle:thin:@host:1521:ilic # Oracle (변경)
// driver-class-name: com.mysql.cj.jdbc.Driver
// 애플리케이션 코드는 그대로
public class ShipmentDao {
public void add(Shipment s) throws Exception {
Connection c = DriverManager.getConnection(url);
// 이 코드 변경 X (DB 교체해도)
}
String url; // 설정에서 주입
}
class Shipment {}
// DB 교체:
// 1. URL 변경 (설정)
// 2. 드라이버 의존성 추가
// 3. SQL 방언 조정 (일부)
// → 코드 거의 그대로 (JDBC 전과 천지차)
DB 교체 시 변경 범위는?
답:
1. 변경 범위:
전 vs 후:
격리:
한계:
| Q | 핵심 답변 |
|---|---|
| JDBC? | 자바 DB 표준 API |
| 같은 코드 다른 DB? | URL/드라이버만 |
| 해결한 것? | 연결/실행/결과 통일 |
| DriverManager? | 드라이버 선택, Connection |
| 드라이버 로딩? | 자동 (JDBC 4.0+) |
| 핵심 인터페이스? | Connection/Statement/ResultSet |
| 5주차 패턴? | 전략/인터페이스/DIP |
| DB 교체? | URL/드라이버 |
| OCP? | 새 드라이버 확장 |
| PreparedStatement? | 파라미터, 인젝션 방어 |
답:
답:
답:
답:
답:
1. JDBC = 표준 API
2. DriverManager + 인터페이스
3. 5주차 패턴의 실제
이번 Unit에서 JDBC 표준화를 봤다면, 다음은 JDBC 의 한계 (Phase 3 마지막).
💾 Phase 3 — JDBC 표준화의 등장
✅ Unit 3.1 JDBC 없던 시절의 고통
✅ Unit 3.2 JDBC의 표준화 효과 ← 여기
⏭ Unit 3.3 JDBC가 해결하지 않는 것 — Phase 3 완주
🧪 Part A (9 Unit) ✅
💾 Part B — DB 접근의 진화
Phase 3 — JDBC (2/3 진행)
총: 11/28 Unit