ch15_JDBC
통합 문서입니다.
1. JDBC
JDBC
학습 목표
- JDBC의 계층 구조와 표준 실행 흐름을 이해할 수 있다.
Connection,PreparedStatement,ResultSet를 안전하게 사용할 수 있다.- 트랜잭션, 커넥션 풀, DAO 분리 등 실무 핵심 패턴을 적용할 수 있다.
1. JDBC란
JDBC(Java Database Connectivity)는 Java에서 RDBMS에 접근하는 표준 API다.
구성:
- 애플리케이션 코드
- JDBC API
- DB 벤더 드라이버
- 실제 데이터베이스
2. 기본 실행 흐름
DataSource또는DriverManager로Connection획득- SQL 준비 (
PreparedStatement권장) - 파라미터 바인딩
- 실행 (
executeQuery/executeUpdate) - 결과 매핑 (
ResultSet) - 자원 해제
3. Connection과 자동 커밋
기본적으로 JDBC는 auto-commit이 켜져 있다.
conn.setAutoCommit(false);
여러 SQL을 하나의 원자 작업으로 묶으려면 직접 commit/rollback을 관리해야 한다.
4. PreparedStatement (필수)
String sql = "INSERT INTO users(name, age) VALUES(?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, "Kim");
ps.setInt(2, 20);
ps.executeUpdate();
}
장점:
- SQL 인젝션 방지
- 파라미터 바인딩 명확
- SQL 파싱/실행 계획 재사용 가능성
5. ResultSet 매핑
String sql = "SELECT id, name, age FROM users";
try (PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
long id = rs.getLong("id");
String name = rs.getString("name");
int age = rs.getInt("age");
}
}
매핑 시 컬럼명 오타/NULL 처리/타입 매핑 주의가 필요하다.
6. 트랜잭션 제어
conn.setAutoCommit(false);
try {
// SQL 1
// SQL 2
conn.commit();
} catch (Exception e) {
conn.rollback();
throw e;
}
원칙:
- 비즈니스 단위로 트랜잭션 경계 설정
- 실패 시 반드시 롤백
- 예외 원인 로그 보존
7. 자원 관리
Connection, Statement, ResultSet는 반드시 닫아야 한다.
try (Connection conn = ds.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
...
}
try-with-resources가 표준 패턴이다.
8. DAO 계층 분리
권장 구조:
Repository/DAO: SQL 및 매핑Service: 트랜잭션과 비즈니스 규칙Controller: 요청/응답 처리
SQL 접근을 분리하면 테스트/유지보수성이 크게 향상된다.
9. 커넥션 풀(DataSource)
매 요청마다 물리 연결을 새로 만들면 비용이 크다.
실무에서는 HikariCP 같은 커넥션 풀을 사용한다.
효과:
- 연결 재사용
- 지연 감소
- 연결 수 제한/모니터링 가능
10. SQL 예외 처리 전략
- 기술 예외(
SQLException)를 도메인 예외로 변환 - 쿼리/파라미터/트랜잭션 맥락 로그 기록
- 민감 정보는 로그에 직접 노출 금지
11. 보안/성능 체크포인트
- 문자열 연결 SQL 금지 (항상 바인딩)
- N+1 쿼리 패턴 점검
- 인덱스 전략 확인
- 대량 처리 시 배치(
addBatch/executeBatch) 검토
12. 정리
- JDBC 핵심은 안전한 SQL 실행, 자원 해제, 트랜잭션 관리다.
- PreparedStatement + try-with-resources + DataSource는 기본 규칙이다.
- 코드 구조를 DAO/Service로 분리하면 실무 품질이 안정된다.
2. 문제
문제
ch15 범위(Connection/PreparedStatement/ResultSet/Transaction/DAO) 문제입니다.
A. 연결/조회 기초
- JDBC
Connection을 획득하고 연결 정보를 출력하시오. - 단일 테이블
SELECT를 수행해 결과를 콘솔에 출력하시오. - 조회 결과를 DTO 또는 record로 매핑하시오.
B. DML
PreparedStatement로 INSERT를 구현하시오.- UPDATE/DELETE를 각각 구현하시오.
- 영향받은 row 수를 검사해 성공/실패를 판단하시오.
C. 트랜잭션
- 계좌 이체 로직(출금+입금)을 하나의 트랜잭션으로 구현하시오.
- 중간 실패 시 롤백되는지 확인하시오.
- auto-commit on/off 차이를 실험하시오.
D. DAO 분리
UserDao를 작성해 CRUD 메소드를 분리하시오.- 서비스 계층에서 DAO를 사용해 유스케이스를 구성하시오.
- SQLException을 도메인 예외로 변환하시오.
E. 성능/안전
- 문자열 연결 SQL과 바인딩 SQL의 차이를 비교하시오.
executeBatch로 대량 INSERT를 구현하시오.- try-with-resources 누락 시 리소스 누수 문제를 재현하시오.
F. 챌린지
- 페이징 조회 API(
LIMIT/OFFSET)를 구현하시오. - 키워드 검색 조건을 동적으로 조합하되 SQL 인젝션 없이 구현하시오.
- 간단한 커넥션 풀 환경에서 동시 요청 테스트를 수행하시오.
제출 체크리스트
- 모든 SQL이 PreparedStatement 기반인가?
- 트랜잭션 경계가 명확한가?
- 자원 해제가 누락되지 않았는가?
- 예외 로그에 원인/맥락이 충분히 남는가?