DevLog

엔지니어링 블로그를 한 곳에서 탐색하고, 최근 발행 흐름을 빠르게 파악할 수 있는 서비스 입니다.

Quick Links

  • Latest Feed
  • Engineering Directory

Support

  • 소개
  • 개인정보처리방침

Contribute

  • 원하는 블로그 추가 (준비 중)
  • Feedback

© 2026 DevLog Inc. All rights reserved.

본 사이트는 공개 RSS 피드를 통해 콘텐츠를 수집하며, 모든 콘텐츠의 저작권은 원저작자에게 있습니다.

Back to Feed
Read Original

Contents

Continue Reading

  • More from 카카오페이
  • Related reads#SpringBatch
#Backend

수억 건의 데이터, 맛있게 쪼개 먹는 방법 (with. Partitioning)

수억 건의 데이터, 맛있게 쪼개 먹는 방법 (with. Partitioning)
01

Summary

수억 건의 데이터도 순식간에! Spring Batch 성능을 10배 올리는 시니어의 비밀 레시피

OOM의 늪에서 탈출하여 대규모 데이터를 맛있게 쪼개 먹는 파티셔닝과 커서 기반 최적화 전략

카카오페이 정산플랫폼팀의 실제 장애 해결 사례를 통해 대규모 배치 처리의 정석을 보여주는 아티클입니다. 단순한 병렬 처리를 넘어 MongoDB의 내부 동작 원리를 고려한 Reader와 Writer 최적화 기법을 심도 있게 다룹니다. 성능 측정 지표를 통해 실제 아키텍처 개선이 가져오는 압도적인 효율성을 증명합니다.

  • 01Local Partitioning을 활용해 작업을 독립적인 스레드로 분할하여 병렬 처리 극대화
  • 02Paging 방식의 O(N²) 성능 저하를 해결하는 Cursor 기반 스트리밍 조회 기법 적용
  • 03Bulk Operations 도입으로 네트워크 I/O를 최소화하고 쓰기 성능 1,000% 향상
  • 04서버 코어 수와 작업 특성을 고려한 최적의 gridSize 및 ThreadPool 튜닝 가이드
  • 05메모리 효율성과 시스템 안정성을 동시에 잡는 실무 관점의 아키텍처 설계

+RECOMMENDATION

Spring Batch를 사용하면서 대량 데이터 처리 시 OOM을 겪고 있거나 배치 수행 시간 단축이 절실한 개발자에게 강력히 추천합니다. 특히 MongoDB를 저장소로 사용하는 환경에서 Cursor와 Bulk 연산을 어떻게 조합해야 하는지 명확한 가이드를 제공합니다.

The Problem

수억 건에 달하는 대용량 원장 데이터를 Spring Batch로 처리하는 과정에서 데이터를 한꺼번에 메모리에 적재하며 OOM(Out of Memory) 이슈가 발생했습니다. 또한, 기존의 페이징 기반 ItemReader는 데이터가 뒤로 갈수록 skip() 연산에 따른 성능 저하가 심화되는 병목 현상을 보였습니다.

The Solution

전체 작업을 월/일 단위로 나누는 2단계 파티셔닝(Local Partitioning) 전략을 도입하여 병렬성을 확보했습니다. 메모리 효율을 위해 Paging 대신 Cursor 기반의 MongoCursorItemReader로 스트리밍 조회를 적용하고, Bulk Operations를 통해 쓰기 성능을 최적화했습니다.

The Result

500만 건의 데이터 처리 기준으로 기본 방식 대비 약 10.9배의 속도 향상(97분에서 9분으로 단축)을 달성했습니다. 커서 기반 조회를 통해 메모리 사용량을 일정하게 유지함으로써 수억 건의 데이터 환경에서도 OOM 없이 안정적인 시스템을 구축했습니다.

Trade-off

파티셔닝 도입으로 인해 gridSize 및 ThreadPool 설정 등 구성 복잡도가 증가하며, 병렬 스레드 수 증가에 따른 DB 커넥션 풀 고갈 위험이 존재합니다. 본문에 구체적으로 명시되지는 않았으나, 파티셔닝 작업 간의 데이터 정합성 보장을 위한 추가적인 관리 비용이 발생할 수 있습니다.

03

Key Concepts

Concept · 01

Local Partitioning

단일 JVM 내에서 대량 데이터를 논리적인 조각으로 나누고, 각 파티션을 별도의 스레드에서 독립적인 Worker Step으로 실행하는 병렬 처리 모델입니다.

  • Manager Step이 Partitioner를 통해 작업 범위를 결정하고 ExecutionContext를 생성
  • 각 Worker Step은 독립적인 Reader, Processor, Writer 인스턴스를 가져 경합 방지
Concept · 02

MongoCursorItemReader

MongoDB의 서버 사이드 커서를 사용하여 데이터를 스트리밍 방식으로 한 건씩 읽어오는 ItemReader로, 페이징 방식의 한계를 극복합니다.

  • skip() 연산 없이 다음 문서로 바로 이동하여 대용량에서도 일정한 O(1) 성능 유지
  • 메모리 사용량을 일정하게 관리하여 대규모 데이터 로드 시 OOM 방지
Concept · 03

Bulk Operations

여러 개의 쓰기 요청을 하나의 메시지로 패키징하여 한 번의 네트워크 왕복으로 처리하는 일괄 쓰기 방식입니다.

  • N번의 네트워크 요청을 1번으로 줄여 I/O 오버헤드와 서버 부하를 획기적으로 감소
  • UNORDERED 모드 설정을 통해 순서에 상관없는 병렬 쓰기 최적화 수행
Continue reading · same source

카카오페이More from 카카오페이

View all posts from 카카오페이
  • 2025 TAM CONNECT: 카카오페이 x 토스, 기술지원의 미래를 함께 그리다

    Technical Account ManagementTAMOperational Excellence
    1개월 전
  • 공통 컴포넌트를 건강하게 기르기 위한 고민

    ReactComponent LifecycleHeadless UI
    3개월 전
  • 2026년 카페개페, AI와 함께한 현장 스케치

    카카오페이DevRel개발자페스티벌
    3개월 전
  • SDD (spec-kit) 에이전트 코딩 실전기

    SDDSpec-kit에이전틱 코딩
    4개월 전
  • 그때는 맞고 지금은 틀리다. Yarn Berry에서 pnpm으로 패키지 매니저 전환기

    pnpmYarn BerryZero-installs
    4개월 전

Related reads#SpringBatch

Explore #SpringBatch
무신사·Java Flight Recorder

의심했던 범인은 알리바이가 있었다.

#SpringBatch4일 전
올리브영·Kafka

옴니채널 재고 정합성 한계에 대응하는 인벤토리 데이터 파이프라인 구축기

#SpringBatch1주 전
SSG

“장보기 지원금이 곧 소멸돼요” 알림 뒤에서 일어난 일

#SpringBatch1개월 전
올리브영

오프라인 매장에 코드를 배포하다 Part 2: 올리브영 전자라벨(ESL) 최적화 여정

#SpringBatch5개월 전

Source

카카오페이
카카오페이
Engineering Blog

Published · March 18, 2026

Topics

Spring BatchPartitioningMongoDBCursorItemReaderBulk OperationsOOM성능 최적화