Spring Batch JdbcPagingItemReader, JdbcBatchItemWriter 쿼리 읽고 bulk 하는 프로세스
JdbcPagingItemReader 내부 동작
Spring Batch에서 페이징 처리를 하려면 바로 JdbcPagingItemReader 가 있습니다. 그런데 이 친구 막상 써보려 하면 쿼리는 누가 짜주고, 페이지는 어떻게 나뉘는지 궁금하지 않을 수 없습니다.
이번 JdbcPagingItemReader 의 동작 원리와 내부 구조를 한 방에 이해할 수 있도록 정리해보겠습니다.
1. 초기 설정
afterPropertiesSet() 메서드에서 이 모든 준비가 시작됩니다.
afterPropertiesSet() 내부에서 queryProvider.init(dataSource)가 호출하면
- 첫 페이지용 쿼리: generateFirstPageQuery()
- 이후 페이지용 쿼리: generateRemainingPagesQuery()
우리가 쿼리를 직접 쓰지 않아도, Oracle, MySQL, SQL Server 등에 맞는 SQL을 queryProvider가 알아서 생성해줍니다.
내부적으로는 StringBuilder로 SQL을 조립해 최종 문자열을 만들죠.
쿼리 작성은 queryProvider 가 알아서 다 해주게됩니다.
2. 데이터 읽기
doReadPage()
데이터를 한 페이지씩 읽을 때 doReadPage()가 실행됩니다.
여기서 페이지 구분은 어떻게 하느냐?
- 첫 번째 페이지 → 기본 파라미터로 SQL 실행
- 두 번째 페이지부터 → 이전 페이지에서 읽은 정렬 키 값을 기준으로 다음 데이터를 가져옵니다.
afterPropertiesSet 에서 가져온 쿼리를 첫 페이지와 이후 페이지 쿼리가 다르게 실행됩니다.
이 방식이 바로 Keyset Paging입니다.
예를 들어, 내가 마지막으로 읽은 id가 105니까, 다음 페이지 id > 105 부터 읽어와 입니다.
즉, 첫번째 이후 페이지는 startAfterValues 기반으로 keyset paging 동작으로 내부적으로 현재 정렬 key 값을 기억하고 있습니다. (→ Cursor 방식과 유사하다.)
3. 정렬 키 기준 페이징 (PagingRowMapper)
keyset paging이 되려면, 현재 페이지의 마지막 row 에서 정렬 키 값을 기억해둬야겠죠?
keyset paging 을 구현하려면 마지막으로 조회된 정렬 키 값을 추적해야 합니다. 현재 페이지에서 마지막으로 조회된 정렬 키 값을 추적해야 합니다.
PagingRowMapper는 각 Row를 매핑하면서
queryProvider.getSortKeys()에서 정의된 필드들(id, created_at 등)의 값을
startAfterValues에 저장해둡니다.
이 값이 다음 페이지 쿼리에 쓰이는 조건이 됩니다.
WHERE id > :_id
4. 파라미터조합
getParameterMap
쿼리 실행에 필요한 파라미터는 두 가지가 섞여있습니다.
구분 | 설명 | 예시 |
일반 파라미터 | 상태, 날짜, 사용자 ID 등 필터 조건 | status = 'ACTIVE' |
정렬 키 | 페이징 기준 값 | id > 105 |
위에 있는걸 하나의 Map으로 합쳐주는 게 getParameterMap() 입니다.
5. 정리
JdbcPagingItemReader는 내부적으로 PagingQueryProvider를 통해 페이지 단위 SQL을 생성하고 실행합니다.
1. 첫 페이지는 기본 파라미터로 실행된 SQL:
SELECT ... FROM table ORDER BY id ASC LIMIT 10
2. 다음 페이지는 마지막 읽은 row의 key를 기억해서 실행된 SQL:
SELECT ... FROM table WHERE id > ? ORDER BY id ASC LIMIT 10
정렬 키가 중요한 이유는
JdbcPagingItemReader는 반드시 정렬 키(sort key)를 필요한데, 이 키가 있어야 다음 페이지를 안전하게 이어서 읽을 수 있고, 고정된 결과 순서를 유지할 수 있기 때문입니다.
→ 정렬 키는 실행 중 RowMapper에서 추출되어 다음 SQL 조건으로 쓰이게 됩니다.
'IT' 카테고리의 다른 글
개발자로서 다시 읽는 책, 개발자 기술 면접 노트 (5) | 2025.06.29 |
---|---|
LeetCode 3085. Minimum Deletions to Make String K-Special — 그리디가 틀리는 이유 (0) | 2025.06.22 |
spring batch 기본 내용 정리 (2) | 2025.06.01 |
가상 면접 사례로 배우는 대규모 시스템 설계 기초 4장 (2) | 2025.05.11 |
zipkin 내용 정리 (1) | 2025.05.05 |
댓글
이 글 공유하기
다른 글
-
개발자로서 다시 읽는 책, 개발자 기술 면접 노트
개발자로서 다시 읽는 책, 개발자 기술 면접 노트
2025.06.29 -
LeetCode 3085. Minimum Deletions to Make String K-Special — 그리디가 틀리는 이유
LeetCode 3085. Minimum Deletions to Make String K-Special — 그리디가 틀리는 이유
2025.06.22 -
spring batch 기본 내용 정리
spring batch 기본 내용 정리
2025.06.01 -
가상 면접 사례로 배우는 대규모 시스템 설계 기초 4장
가상 면접 사례로 배우는 대규모 시스템 설계 기초 4장
2025.05.11