대량 배치 안정성을 높이기 위한 구조 개선: Part 3 - 청크 분할과 병렬 처리로 재설계하기
3편. 청크 분할과 병렬 처리로 배치 구조 재설계하기
들어가며
앞선 두 편에서 문제를 정리했다면, 이번 글부터는 “그래서 어떻게 바꿨는가”에 대한 이야기다.
개선의 출발점은 단순했다.
모든 데이터를 한 번에 처리하지 않는다.
이 원칙을 실제 시스템 구조로 옮기는 과정에서 가장 먼저 손을 댄 것이 청크 분할과 병렬 처리였다.
전체를 나누는 순간, 문제가 다르게 보이기 시작했다
기존 구조에서는 데이터가 늘어날수록 선택지는 하나뿐이었다.
- 더 오래 기다리거나
- 더 큰 장애를 감수하거나
하지만 데이터를 작은 단위로 나누자, 문제의 성격 자체가 달라졌다.
- 실패는 전체가 아니라 일부가 되고
- 재시도는 전체가 아니라 특정 범위가 되며
- 성능 개선의 여지가 생기기 시작했다
청크 분할 전략: 얼마나, 어떻게 나눌 것인가
1. 청크 단위의 기준
청크 크기를 정할 때 가장 먼저 고려한 것은 “이 단위가 실패했을 때 감당 가능한가”였다.
- 너무 크면 실패 비용이 커지고
- 너무 작으면 오버헤드가 커진다
결과적으로 다음 기준을 적용했다.
- 하나의 청크는 수 초 내 처리 가능
- 실패 시 재시도가 부담되지 않는 범위
- DB 락을 오래 점유하지 않는 크기
이 기준을 바탕으로 고정 크기 청크를 선택했다.
2. 데이터 경계 명확히 하기
청크 분할에서 중요한 것은 경계가 명확해야 한다는 점이다.
- 범위 기준(ID, 날짜, 해시 등)
- 중복 없이 모든 데이터를 포함
- 병렬 처리 시에도 서로 간섭하지 않도록
이 경계를 명확히 하지 않으면 병렬 처리 자체가 또 다른 정합성 문제를 만든다.
병렬 처리 도입 시 가장 먼저 고려한 것들
병렬 처리는 성능을 끌어올리는 강력한 도구지만, 무작정 스레드를 늘리는 것은 오히려 독이 된다.
1. DB 커넥션 풀 한계
병렬 작업 수는 DB 커넥션 풀 크기를 넘지 않도록 제한했다.
- 배치가 DB를 독점하지 않도록
- 일반 트래픽과의 간섭 최소화
- 최악의 경우에도 시스템 전체가 멈추지 않도록
2. 락 경합과 Deadlock 가능성
병렬 삭제는 특히 위험하다.
- 잘못 설계하면 서로 다른 청크가 같은 인덱스를 두고 경쟁
- 삭제 순서에 따라 Deadlock 발생 가능
이를 피하기 위해:
- 청크 간 데이터 범위가 절대 겹치지 않도록 설계
- 항상 동일한 순서로 락을 획득하도록 쿼리 구조 통일
삭제 쿼리 성능 튜닝: 병렬 처리의 전제 조건
병렬 처리 이전에 반드시 선행되어야 했던 작업이 있다.
삭제 쿼리 자체가 빨라야 한다.
1. 수평 분산 관점의 삭제 설계
대량 삭제를 한 테이블에 몰아 넣는 대신:
- 데이터 분포를 기준으로 수평 분할
- 특정 범위만 선택적으로 삭제
- 불필요한 전체 스캔 제거
이를 통해 각 삭제 작업의 부담을 크게 줄였다.
2. 인덱스 재설계
기존 인덱스는 조회 중심으로 설계되어 있었고, 삭제 조건에는 최적화되어 있지 않았다.
- 삭제 조건을 선두 컬럼으로 재정렬
- 불필요한 복합 인덱스 제거
- 삭제 시 인덱스 업데이트 비용 최소화
이 작업만으로도 단일 청크 삭제 시간이 눈에 띄게 줄었다.
결과: 구조를 바꿨을 뿐인데
청크 분할 + 병렬 처리 + 삭제 쿼리 튜닝을 적용한 결과는 명확했다.
- 전체 삭제 시간 2시간 → 5분
- 배치 실행 중 CPU·메모리 사용량 안정화
- 장기 트랜잭션 제거로 롤백 리스크 사실상 제거
- 실패 시 재처리 범위 최소화
성능 개선도 중요했지만, 무엇보다 큰 변화는 “예측 가능성”이었다.
얻은 교훈
이 과정에서 가장 크게 느낀 점은 하나였다.
대규모 배치에서 중요한 것은 얼마나 빠르냐보다, 얼마나 안전하게 실패할 수 있느냐다.
청크 분할은 단순한 성능 기법이 아니라 실패를 통제 가능한 단위로 바꾸는 설계 선택이었다.
다음 편 예고
다음 글에서는 청크 분할 이후에도 반복적으로 발생하던 문제, 분산 락 환경에서의 Race Condition을 다룬다.
- 락이 있는데도 순서가 깨진 이유
- 장애·타임아웃 상황에서 발생한 실제 시나리오
- 로그 분석을 통한 원인 규명 과정
👉 4편. 분산 락이 있음에도 Race Condition이 발생한 이유에서 이어진다.
댓글
아직 댓글이 없습니다