본문으로 건너뛰기

9.3 JdbcTemplate 및 대용량 배치 처리 기초

ORM(JPA) 시대가 도래했어도 전통적인 RDBMS 지향 접근이나 수백만 건의 대량 배치(Batch) Insert 처리에는 JdbcTemplate이 압도적으로 빠르고 확실한 성능을 자랑합니다.

1. JdbcTemplate의 기본 구조​

JdbcTemplate은 JDBC의 복잡한 커넥션 확보, Statement 생성, 자원 해제(try-catch-finally)를 스프링 프레임워크가 대신 템플릿 콜백 패턴으로 처리해 주는 유틸리티 클래스입니다.

@Repository
@RequiredArgsConstructor
public class UserRepositoryJdbc {

private final JdbcTemplate jdbcTemplate;

// 1. 단건 조회 (QueryForObject)
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, userRowMapper(), id);
}

// 2. 다건 조회 (Query)
public List<User> findAll() {
String sql = "SELECT * FROM users";
return jdbcTemplate.query(sql, userRowMapper());
}

// 3. 삽입/수정/삭제 (Update)
public int updateName(Long id, String newName) {
String sql = "UPDATE users SET name = ? WHERE id = ?";
return jdbcTemplate.update(sql, newName, id);
}

// 데이터베이스 결과를 자바 객체로 매핑하는 RowMapper 설정
private RowMapper<User> userRowMapper() {
return (rs, rowNum) -> {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
return user;
};
}
}

2. batchUpdate를 이용한 고속 벌크 연산​

JPA의 영속성 컨텍스트는 수만 건의 데이터를 엑셀에서 읽어 1건씩 Insert할 때 병목(Out of Memory나 성능 지연)이 매우 큽니다. 반면 JdbcTemplate의 batchUpdate를 활용하면 데이터베이스의 Bulk 연산 기능을 끌어내 100배 이상의 성능 향상을 얻을 수 있습니다.

@Repository
@RequiredArgsConstructor
public class BulkUserRepository {

private final JdbcTemplate jdbcTemplate;

@Transactional
public void saveAllBatch(List<User> userList) {
String sql = "INSERT INTO users (name, age) VALUES (?, ?)";

// 1000건 단위로 청크(Chunk)를 나누어 DB로 전송
jdbcTemplate.batchUpdate(sql, userList, 1000,
(PreparedStatement ps, User user) -> {
ps.setString(1, user.getName());
ps.setInt(2, user.getAge());
}
);
}
}
팁

대용량 데이터를 다룰 때 application.yml (또는 DB 접속 URL)에 반드시 rewriteBatchedStatements=true (MySQL/MariaDB 기준) 옵션을 켜야 진정한 의미의 속도 향상(Bulk Insert)이 이루어집니다. 이 옵션이 없으면 batchUpdate를 써도 네트워크를 1건씩 통신합니다.