QueryRunner: JDBC의 복잡함을 덜어주는 효율적인 유틸리티
안녕하세요! 오늘은 자바 데이터베이스 프로그래밍을 할 때 JDBC(Java Database Connectivity)의 번거로운 반복 작업을 획기적으로 줄여주는 Apache Commons DBUtils 라이브러리의 핵심 클래스, QueryRunner에 대해 상세히 알아보겠습니다. 많은 방법들이 있겠지만 이번엔 QueryRunner를 활용하여 작업하는 방법을 볼 것입니다.
1. QueryRunner란 무엇인가?
QueryRunner는 이름 그대로 SQL 쿼리 실행을 도와주는 실행기입니다. 순수 JDBC를 사용할 때 발생하는 Connection 생성, PreparedStatement 설정, ResultSet 처리, 그리고 마지막 close() 호출까지 이어지는 이른바 '상용구 코드(Boilerplate Code)'를 대신 처리해 줍니다.
주요 특징:
- 리소스 관리 자동화: Statement와 ResultSet의 관리를 내부적으로 처리하여 리소스 누수를 방지합니다.
- 간결함: 수십 줄의 JDBC 코드를 단 몇 줄로 줄여줍니다.
- Bean 매핑: 쿼리 결과를 자바 객체(POJO)로 즉시 변환해 주는 Handler 기능을 제공합니다.
2. 핵심 메서드 분석
QueryRunner는 크게 세 가지 형태의 작업을 수행합니다.
① update(): 데이터 변경
INSERT, UPDATE, DELETE 쿼리를 실행할 때 사용합니다.
- 반환값: 영향받은 행(row)의 개수 (int)
- 사용 예: queryRunner.update(conn, sql, params...);
② query(): 데이터 조회
SELECT 쿼리를 실행할 때 사용하며, 결과를 어떻게 받을지 결정하는 ResultSetHandler가 반드시 필요합니다.
- 반환값: Handler가 정의한 타입 (객체, 리스트, Map 등)
- 사용 예: queryRunner.query(conn, sql, handler, params...);
③ batch(): 일괄 처리
동일한 SQL을 여러 번 실행해야 할 때(Bulk Insert 등) 성능 최적화를 위해 사용합니다.
3. ResultSetHandler: 결과 처리의 핵심
QueryRunner의 진가는 다양한 Handler 제공에 있습니다. 쿼리 결과를 어떤 형태로 받을지 선택만 하면 됩니다.
| Handler 클래스 | 설명 |
| BeanHandler | 단일 행을 특정 자바 객체(Bean)로 변환 |
| BeanListHandler | 여러 행을 자바 객체 리스트(List<Bean>)로 변환 |
| MapHandler | 첫 번째 행을 Map<String, Object> 형태로 변환 |
| ScalarHandler | COUNT(*)나 MAX() 같은 단일 컬럼 값을 반환 |
| ArrayListHandler | 각 행을 Object[] 배열로 변환하여 리스트로 반환 |
4. 실제 사용 예시 (코드 가이드)
프로젝트에 commons-dbutils 의존성을 추가한 후, 다음과 같이 코드를 작성할 수 있습니다.
[SELECT 예시: 리스트 조회]
QueryRunner run = new QueryRunner();
String sql = "SELECT * FROM users WHERE status = ?";
// BeanListHandler를 사용하여 User 객체 리스트로 바로 받기
List<User> userList = run.query(conn, sql, new BeanListHandler<>(User.class), "ACTIVE");
[INSERT 예시]
String insertSql = "INSERT INTO users (name, email) VALUES (?, ?)";
int rows = run.update(conn, insertSql, "홍길동", "hong@example.com");
5. 주의사항 및 Tip
- Connection 관리: QueryRunner는 DataSource를 인자로 받아 생성할 수도 있고, 메서드 호출 시마다 Connection을 직접 넘길 수도 있습니다. 트랜잭션 관리가 필요하다면 동일한 Connection을 메서드 파라미터로 전달하는 방식을 권장합니다.
- 가독성 vs 제어권: MyBatis나 JPA 같은 무거운 프레임워크를 쓰기에는 프로젝트 규모가 작거나, SQL의 세밀한 제어가 필요할 때 QueryRunner는 최고의 선택지가 됩니다.
- DB 컬럼명과 필드명: BeanHandler 계열을 사용할 때는 DB의 컬럼명(snake_case)과 자바 객체의 필드명(camelCase)이 일치하거나 적절히 매핑되도록 확인해야 합니다.
QueryRunner는 "최소한의 코드로 최대한의 JDBC 효율"을 내고자 할 때 가장 빛나는 도구입니다. 복잡한 설정 없이 라이브러리 추가만으로 즉시 생산성을 높일 수 있다는 점이 가장 큰 매력입니다.
작성하신 코드에서 반복되는 try-catch-finally와 ResultSet 노다가에 지쳤다면, 지금 바로 도입해 보시는 건 어떨까요?
다음엔 일하거나 공부하며 궁금한 점이나 알아야 할 것에 대해 작성하도록 할 예정입니다. 감사합니다.
'TECH > 웹개발' 카테고리의 다른 글
| [Java/Spring] 현대 인증의 표준, JWT(JSON Web Token) 완벽 가이드 (0) | 2026.03.17 |
|---|---|
| [Java/Spring] 로그인 구현의 클래식, 세션(Session) 인증 방식 A to Z (0) | 2026.03.16 |
| [Spring Boot] API 예외 처리의 정석: @RestControllerAdvice로 클린 코드 만들기 (0) | 2026.03.13 |
| [Java] "돈 계산할 때 double 쓰면 망합니다" — BigDecimal의 필요성과 사용법 (0) | 2026.03.11 |
| [Java] 자바 메모리 구조 완벽 가이드: Stack, Heap, Method Area의 상호작용 (0) | 2026.03.10 |