백엔드 면접 용어 사전
Spring·JPAJava Database Connectivity

JDBC

자바가 관계형 DB와 통신하는 표준 API. JPA·MyBatis·jOOQ·JdbcTemplate이 전부 그 위에서 돈다.

자바가 관계형 데이터베이스와 이야기하는 표준 인터페이스(java.sql 패키지). 1997년 JDK 1.1부터 있었다.

"요즘도 쓰나요"에 대한 정확한 답

"안 쓴다"가 아니라 "직접 호출하지 않는다" 가 맞다.

애플리케이션 코드
     ↓
JPA/Hibernate · MyBatis · jOOQ · JdbcTemplate · Spring Data JDBC
     ↓
━━━━━━━━━━━ JDBC (java.sql) ━━━━━━━━━━━   ← 전부 이 위에서 돈다
     ↓
커넥션 풀 (HikariCP)
     ↓
DB 드라이버 (postgresql, mysql-connector, ...)
     ↓
데이터베이스

위의 모든 도구가 내부에서 JDBC를 호출한다. 커넥션 풀도 JDBC 스펙 위의 구현이다. 그래서 N+1이든 커넥션 고갈이든, 사고가 나면 원인은 늘 이 층에 있다.

네 개의 핵심 객체

try (Connection con = dataSource.getConnection();          // ① 연결을 빌린다
     PreparedStatement ps = con.prepareStatement(sql)) {   // ② SQL을 준비한다
    ps.setLong(1, userId);                                 // ③ 파라미터를 바인딩
    try (ResultSet rs = ps.executeQuery()) {               // ④ 결과를 커서로 받는다
        while (rs.next()) { ... }
    }
}   // close() = 풀로 반납 (물리 연결을 닫는 게 아니다)

여기서 가장 자주 헷갈리는 지점 — 풀에서 빌린 Connectionclose()를 부르면 물리 연결이 닫히는 게 아니라 풀로 반납된다. 반납하지 않으면 커넥션 누수가 되고, 쌓이면 풀이 고갈된다.

Statement vs PreparedStatement

// ❌ 문자열을 이어 붙이면 SQL 인젝션에 뚫린다
stmt.executeQuery("SELECT * FROM users WHERE name = '" + input + "'");

// ✅ 파라미터를 값으로 넘기면 SQL 구조가 고정된다 + DB가 실행 계획을 재사용
ps = con.prepareStatement("SELECT * FROM users WHERE name = ?");
ps.setString(1, input);

PreparedStatement는 SQL 뼈대를 먼저 DB에 보내 파싱시켜 두고 값만 나중에 채운다. 그래서 값이 SQL 문법으로 해석될 여지가 없고(인젝션 차단), 같은 쿼리를 반복할 때 실행 계획을 재사용해 빠르다.

가상 스레드 시대의 재평가

"JDBC는 블로킹이라 확장이 안 된다"가 오랫동안 리액티브를 택할 이유였다. 가상 스레드가 블로킹 대기 비용을 없애고 Java 24의 JEP 491이 pinning까지 지우면서, 그 근거가 사라졌다. 대신 새 주의점이 생겼다 — 커넥션 풀이 다음 병목으로 드러난다.

면접 함정

  • "JDBC는 레거시" → 모든 상위 도구의 토대다.
  • "close()하면 연결이 닫힌다" → 풀 환경에서는 반납이다.

대량 처리 — 왕복을 줄인다

// 조회: 기본 fetch size가 작아(드라이버마다 다르나 흔히 10) 왕복이 잦다
ps.setFetchSize(1000);      // 한 번에 1,000행씩 가져온다 (메모리와의 균형)

// 쓰기: 한 건씩 보내면 매번 네트워크 왕복이다
for (var u : users) {
    ps.setString(1, u.name());
    ps.addBatch();                    // 모아 두었다가
}
ps.executeBatch();                    // 한 번에 보낸다
INSERT 10,000건
  건별 실행   왕복 10,000회
  배치 1,000  왕복 10회        → 대개 수십 배 차이

JPA를 쓰더라도 결국 이 층에서 벌어지는 일이라, 배치 설정을 안 켜면 JPA의 saveAll()도 건별 INSERT로 나간다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 모던 자바·스프링 — 가상 스레드·JEP 491·리액티브·jOOQ·Boot 4