MyBatis를 사용하면서 수만 건 이상의 데이터를 처리할 때 성능 저하를 겪어본 적 있으습니다.
단순한 반복문(Loop)으로 insert나 update를 호출하면 매번 데이터베이스와 통신(Network Round-trip)이 발생하여 속도가 급격히 떨어집니다.
이때 MyBatis의 ExecutorType 설정을 변경하는 것만으로도 상당한 성능 개선을 이룰 수 있습니다.
1. ExecutorType.REUSE: Statement 재사용
REUSE 모드는 이름 그대로 PreparedStatement를 재사용하는 방식입니다.
- 동작 원리: 동일한 SQL 문을 실행할 때, 매번 새로운 Statement 객체를 생성하지 않고 이전에 생성된 객체를 캐싱하여 다시 사용합니다.
- 장점: SQL 파싱 비용과 Statement 생성 비용을 절감할 수 있습니다.
- 한계: 객체는 재사용하지만, 실행 시마다 DB와 네트워크 통신이 발생합니다. 따라서 통신 비용이 큰 대용량 처리에서는 성능 향상 폭이 제한적입니다.
2. ExecutorType.BATCH: 일괄 처리 (강력 추천)
대용량 INSERT/UPDATE가 목적이라면 반드시 고려해야 할 모드입니다.
- 동작 원리: JDBC의 addBatch() 기능을 활용합니다. SQL 실행 명령을 즉시 DB로 보내지 않고 메모리에 모아두었다가 한꺼번에 전송합니다.
- 장점: 네트워크 왕복 횟수를 획기적으로 줄여주기 때문에 REUSE보다 훨씬 빠릅니다.
- 주의사항:
- 실행 직후 영향받은 행 수(Row count)를 알 수 없습니다. (상수값 반환)
- 메모리 부하를 방지하기 위해 일정 단위(예: 1,000건)마다 flushStatements()를 호출해야 합니다.
3. 한눈에 비교하는 차이점
| 구분 | REUSE | BATCH |
| 핵심 목적 | Statement 객체 생성 비용 절감 | 네트워크 통신 횟수(Round-trip) 최소화 |
| DB 전송 시점 | 메서드 호출 즉시 | 커밋(Commit) 또는 Flush 호출 시 |
| 반환값 | 영향받은 행 수 (int) | 성공 여부 확인 불가 (특수 상수 반환) |
| 추천 상황 | 동일 쿼리 반복 + 결과 확인 필요 | 수십만 건 이상의 대용량 벌크 작업 |
4. 설정 및 구현 방법
방법 1. 전역 설정 (mybatis-config.xml)
애플리케이션 전체에 적용하고 싶을 때 사용하지만, BATCH 모드의 특성상 전역 설정보다는 필요한 곳에서만 호출하는 방식을 권장합니다.
XML
<settings>
<setting name="defaultExecutorType" value="BATCH"/>
</settings>
방법 2. Java 코드에서 직접 지정 (추천)
대용량 처리가 필요한 로직에서만 SqlSession을 BATCH 모드로 열어 사용합니다.
Java
// ExecutorType.BATCH로 세션 오픈
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
BoardMapper mapper = session.getMapper(BoardMapper.class);
for (int i = 0; i < dataList.size(); i++) {
mapper.insertData(dataList.get(i));
// 1000건마다 DB로 전송하여 메모리 관리
if ((i + 1) % 1000 == 0) {
session.flushStatements();
}
}
session.commit();
}
Copyright 2026. [버미] all rights reserved.