본문 바로가기

프로그래밍(TA, AA)/JVM 언어

[Spring] 스프링배치 완벽가이드(1) - 배치와 스프링

배치 처리를 이용하면 좋은 몇가지 이유가 있다.

 - 필요한 모든 정보를 원하는 즉시 받아 볼 수는 없다. 배치 처리를 이용하면 실제 처리가 시작되기 전에 필요한 정보를 미리 수집할 수 있다. 월별 은행 거래명세서를 예로 들어보자. 거래가 이뤄질 때마다 바로 월별 거래명세서를 인쇄해내는 것이 합리적일까? 월말까지 기다려서 한번에 거래 내역을 조사하는 것이 더 합리적이다.

 - 자원을 더 효율적으로 활용할 수 있다. 데이터 과학 분야의 사례가 좋은 예다. 일반적으로 데이터 모델 처리는 두 단계로 나뉜다. 첫번째 단계는 모델의 생성이다. 모델을 생성하려면 대량 데이터를 수학적으로 집중 처리해야 하므로 시간이 많이 걸릴 수 있다. 두번째 단계는 생성된 모델을 놓고 새로운 데이터를 평가하거나 점수를 매기는 것이다. 두번째 단계는 매우 빠르다. 따라서 첫번째 단계에서는 스트리밍 시스템이 사용할 데이터 모델을 외부에서 배치 처리를 수행해 생성하고, 두번째 단계에서는 스트리밍 시스템이 해당 결과를 실시간으로 사용하게 하는 것이 합리적이다.

 

여기에서는 스프링 배치(Spring Batch) 프레임워크를 활용하는 배치 처리를 다룬다. 배치 처리의 역사를 알아보고, 배치 잡(Job) 개발의 어려움을 살펴본다. 또한 자바와 스프링 배치를 사용해 배치를 개발해야 하는 필요성을 알아본 후, 마지막으로 스프링 배치 프레임워크의 개요 및 기능을 개략적으로 살펴본다.

배치 처리의 역사

역사를 상세히 살펴보기 전에, 배치 처리가 무엇인지 정확히 정의해야 한다. 여러분이 개발하는 대부분의 애플리케이션은 사용자와 상호작용하다. 예를 들면 웹 페이지의 링크를 클릭하거나 thick 클라이언트가 제공하는 양식에 맞춰 정보를 입력하거나 미들웨어로 메시지를 받거나 휴대전화나 태블릿 앱을 손가락으로 터치하도록 개발한다. 반면 배치 처리는 이런 유형의 애플리케이션과 완전히 다르다. 배치 처리는 상호작용이나 중단 없이 유한한 양의 데이터를 처리하는 것으로 정의한다. 배치 처리가 일단 시작되면 아무런 개입 없이 어떤 형태로든 완료된다.

 

큰 변화인 고급 언어(high-level language)의 등장까지 컴퓨터와 데이터 처리의 발전에 4년이 걸렸다. 코볼이 배치 처리를 평정한 이후 새로운 도구나 기술의 변화가 거의 없었다. 유닉스 서버상에서 사용자가 개발한 처리나 마이크로스트사의 윈도우 서버상에서 예약된 태스크를 크론 잡(cron job)을 사용해 실행시킬 수 있긴 했지만, 업계에서 인정하는 새로운 배치 처리용 도구는 없었다.

 

2007년 액센츄어사는 자사의 풍부한 메인프레임 및 배치 처리 경험을 바탕으로, 오픈소스 프레임워크를 만들고자 Interface21과 파트너십을 맺었다. 협업 결과 수년 동안 액센츄어 아키텍처의 골격이 되던 개념에 영감을 받아, JVM에서 동작하는 배치 처리의 사실상 표준이 될 수 있었다. 액센츄어는 오픈소스 세계에 공식적으로 진출하기 위해, 자사의 배치 처리 전문 지식에 스프링의 인기와 기능을 결합해 견고하고 사용하기 쉬운 프레임워크를 만들기로 결심했다. 2008년 3월 말에 스프링 배치(Spring Batch) 1.0.0이 출시됐다. 이 프레임워크는 자바 세계에서 배치 처리에 대한 최초의 표준 기반 접근 방식을 제공했다.

 

약 1년 후인 2009년 4월 스프링 배치의 버전이 2.0.0이 되면서, 지원하는 JDK가 1.4에서 1.5로 교체됐으며, 프레임워크에서 청크 기반(chunk-based) 처리, 개선된 구성 옵션, 다양한 확장성 옵션 등의 기능이 추가됐다. 2014년 봄에 출시된 3.0.0 버전은 새롱누 자바 배치 표준인 JSR-352를 구현했다. 마지막으로 버전 4.0.0은 스프링 부트(Spring Boot) 세계에서 자바 기반 구성(java-based configuration)을 받아들였다.

배치가 직면한 과제

일반적으로 우리에게 식 클라이언트 또는 웹 앱 같은 GUI 기반 프로그래밍과 관련된 문제는 익숙하다. 보안 문제, 데이터 유효성 검증, 사용자 친화적은 오류 처리, 예측할 수 없는 사용 패턴으로 인한 리소스 사용률 급상승 등, 이 모든 것들은 어떠한 사용자가 여러분의 소프트웨어를 사용한다면 고려해야 하는 문제다.

 

그러나 배치는 다르다. 앞서 배치 처리는 사용자가 추가로 개입하지 않아도 특정 완료 지점까지 실행될 수 있다고 언급했다. 그래서 GUI 애플리케이션이 가지는 대부분의 문제가 배치에게는 더 이상 유효하지 않다. 물론 보안도 고려해야 하고 데이터 유효성 검증도 필요하지만, 사용량 급증 문제와 사용자 중심의 에러 처리 문제는 배치 처리 시에 예측 가능하거나 적용하지 않아도 된다. 처리 부하를 예측하고 그에 맞게 설계할 수 있기 때문이다. 확실한 로그와 피드백용 알림만을 사용해 신속하고 정확하게 에러를 발생하면 된다. 알림을 받은 기술지원 담당자가 어떤 오류든 해결할 것이기 때문이다.

 

이처럼 배치 세계에서는 모든 것이 쉽게 처리될 수 있으므로 더 이상의 다른 문제는 없지 않을까? 배치 처리에 관련된 문제에는 일반적인 소프트웨어 개발에 고려해야 하는 문제에 배치 특유의 특성이 섞여있다. 소프트웨어 아키텍처는 공통적으로 사용성(usability), 유지 보수성(maintainability), 확장성(scalability) 등 여러 속성을 가지고 있다. 배치 처리에서는 이러한 속성들이 기존과는 다른 측면으로 관련돼 있다.

 

배치 처리에서 사용성(usability)은 코드에 관한 것이다. 즉, 오류 처리 및 유지 보수성과 관련 있다. 이런 것들이 배치 처리에 영향을 미치는 사용성 측면의 모든 요소이다.

 1. 공통 컴포넌트를 쉽게 확장해 새로운 기능을 추가할 수 있는가?

 2. 기존 컴포넌트를 변경할 때 시스템 전체에 미치는 영향을 알 수 있도록 단위 테스트가 잘 마련돼 있는가?

 3. 잡이 실패할 때 디버깅에 오랜 시간을 소비하지 않고 언제, 어디서, 왜 실패했는지 알 수 있는가? 

 

다음은 확장성(scalability)이다. 기업에서 개발한 대부분의 사이트에 그렇게 많은 사용자가 방문하지는 않는다. 그러나 기업이 밤새 100만 건 이상의 트랜잭션을 처리하는 배치를 가지고 있는 것은 그리 드문 일은 아니다. 배치가 처리할 수 있어야 하는 규모는 과거에 개발했던 웹 애플리케이션보다 몇자리 수 이상 큰 경우가 많다.

 

셋째는 가용성(availability)이다. 배치에서의 가용성은 웹 애플리케이션의 가용성과 다르다. 배치 처리는 일반적으로 항상 실행되는 것이 아니다. 사실 배치 처리 시에는 보통 약속이 정해져 있다. 대부분의 기업은 필요한 리소스(하드웨어, 데이터 등)를 언제 사용할 수 있는지 알고 있는 상태에서 주어진 시간에 잡이 실행되도록 예약한다.

 1. 필요할 때 바로 배치 처리를 수행할 수 있는가?

 2. 허용된 시간 내에 잡을 수행함으로써 다른 시스템에 영향을 미치지 않게 할 수 있는가?

이러한 질문을 비롯한 여러 다른 질문은 배치 시스템의 가용성에 영향을 준다.

 

마지막으로 보안을 고려해야 한다. 일반적으로 배치 세계에서 보안은 시스템을 해킹하고 침입하는 사람에 초점을 맞추고 있지 않다. 배치 처리에서 보안의 역할은 데이터를 안전하게 저장하는 것이다.

 1. 민감한 데이터베이스 필드는 암호화돼 있는가?

 2. 실수로 개인 정보를 로그로 남기지는 않는가?

 3. 외부 시스템으로의 접근은 어떠한가?

 4. 자격증명이 필요하며 적절한 방식으로 보안을 유지하고 있는가?

데이터 유효성 검증도 보안의 일부다. 일반적으로 처리 중인 데이터는 이미 검사된 데이터이기는 하지만 여전히 규칙을 준수하는지 확인해야 한다.

 

배치 처리를 개발하는 데는 기술적으로 해결해야 하는 많은 과제가 있다. 시스템의 규모가 대부분 매우 크다는 것부터 보안 문제에 이르기까지 배치는 모든 것을 가지고 있다. 이런 점이 배치 처리를 개발하는 재미 중 하나이기도 하다. 메인프레임에 구성된 기존 인프라를 사용하는 것과 새로운 플랫폼을 채택하는데 따르는 모든 위험을 고려했을때 왜 자바로 배치를 수행할까?

왜 자바로 배치를 처리하는가?

배치 처리 개발 시, 자바와 스프링 배치 같은 오픈소스 도구를 선택하는 이유는 무엇인가? 배치 처리 개발에 자바 및 오픈소스를 사용해야 하는 6가지 이유로, 유지 보수성, 유연성, 확장성, 개발 리소스, 지원, 비용을 생각할 수 있다.

 

배치 처리를 생각할 때는 유지 보수를 고려해야 한다. 배치 처리 코드는 일반적으로 다른 애플리케이션 코드보다 수명이 훨씬 길다. 그 어떤 사용자도 배치 코드를 볼 수 없기 때문이다. 현재 유행이나 스타일을 유지해야 하는 웹 또는 클라이언트 애플리케이션과 달리, 배치 처리는 숫자를 처리하고 정적 출력을 만들어낸다. 배치 처리가 제 역할을 수행하는 동안에 대부분의 사람들은 그 일의 결과를 이용하기만 한다. 그러므로 큰 위험없이 쉽게 수정할 수 있도록 코드를 작성해야 한다.

 

스프링은 테스트 용이성이나 추상화와 같은 몇가지 이점을 얻을 수 있도록 설계됐다. 스프링 프레임워크의 의존성 주입을 통해 객체간 결합을 제거할 수 있고, 스프링 포트폴리오가 제공하는 추가 테스트도구를 사용하면 유지 보수 시 발생할 수 있는 위험을 최소화하는 강력한 테스트 스위트를 구축할 수 있다. 스프링과 스프링 배치의 동작 방식을 깊게 파고들지 않더라도, 스프링은 파일 및 데이터베이스 I/O와 같은 작업을 선언적으로 수행할 수 있는 기능을 제공한다. 그러므로 JDBC 코드를 직접 작성하거나 자바의 파일 I/O API를 다루는 악몽을 감수할 필요가 없다. 또한 스프링 배치는 트랜잭션 및 커밋 횟수와 같은 것들을 애플리케이션에 제공하므로, 처리가 어디까지 진행됐는가라든가 실패시 무슨 일을 해야 하는지 관리할 필요가 없다. 이런 기능은 스프링 배치와 자바가 제공하는 유지 보수성 측면에서의 이점 가운데 일부다.

 

유연성은 자바와 스프링 프레임워크를 사용해야 하는 또 다른 이유다. 배치 처리가 가능한 또 다른 일반적인 플랫폼은 유닉스(UNIX)에서 동작하는 C++이다. 업계에서 통용되는 배치 처리 프레임워크가 없기 때문에, 이는 결국 환경에 맞춰 일일이 개발한 해결책에 불과하다. 메인프레임이나 C++/UNIX 방식은 배포를 위한 JVM의 유연성과 스프링 배치의 기능들을 제공하지 않는다. 유닉스 계열 또는 윈도우 운영체제가 탑재된 서버, 데스크탑 또는 메인프레임에서 배치 처리를 실행하고 싶은가? 아무 문제 없다. 애플리케이션 서버, 도커 컨테이너, 클라우드에 배포하고 싶은가? 필요에 맞는 것을 선택하면 된다. thin war, fat jar, 또는 새로운 무언가가 나온다면? 어떤 것이든 스프링 배치를 사용하면 된다.

 

하지만 위 특성만이 스프링 배치가 제공하는 유연성의 전부는 아니다. 유연성의 또 다른 측면은 시스템 간 코드를 공유할 수 있는 능력이다. 웹 애플리케이션에서 이미 테스트 및 디버깅된 서비스를 배치 처리에서 동일하게 바로 사용할 수 있다. 실제로, 다른 플랫폼에 종속돼 동작하던 업무 로직을 재사용할 수 있다는 것은 플랫폼 전환 시에 누릴 수 있는 가장 큰 장점 중 하나이다. POJO로 업무 로직을 구현하면, 해당 로직을 웹 애플리케이션이나 배치 처리에서 사용할 수 있다.

 

또한, 스프링 배치의 유연성은 자바로 작성된 배치 처리를 확장할 수 있는 능력에도 영향을 미친다. 배치 처리를 확장하는 방안을 살펴보자.

 

메인프레임

메인프레임에서는 확장성을 위한 용량 증설이 제한된다. 병렬로 작업을 수행하는 유일한 방법은 단일 하드웨어 내에서 전체 프로그램을 병렬로 실행하는 것이다. 이 방식은 병렬 처리용 관리 코드를 작성하고 유지 보수해야 하며, 이로 인해 오류처리나 플랫폼 간 상태 관리 등에 어려움이 발생한다. 게다가 단일 머신 자원에 의한 제약이 생긴다.

 

커스텀 처리

자바를 사용하더라도 아무것도 없이 처음부터 기능을 만들어 가기는 어렵다. 먼저, 대량 데이터 처리에 적합한 확장성과 안정성을 얻기는 매우 어렵다. 메인프레임에서와 마찬가지로 부하 분산을 위한 코딩이 필요하다는 동일한 문제도 안고 있다. 또한 여러 물리 장비나 가상 컴퓨터로 배치 처리를 분산하려고 할 때 인프라스트럭처가 복잡해진다. 분산 환경에서 어떻게 통신할지도 고민해야 한다. 데이터 안정성도 문제다.커스텀하게 작성된 워커 중 하나가 중단되면 어떻게 될까? 배치 처리에 필요한 기능을 새로 만들기보다는 기존에 잘 만들어진 기능을 사용하고, 그대신 업무 로직을 작성하는데 시간을 들이는 것이 더 나을 것이다.

 

자바와 스프링 배치

자바는 앞서 언급했던 대부분의 문제를 처리할 수 있는 기능을 갖고 있지만, 이 기능을 유지 보수가 가능하도록 구성하기는 매우 어렵다. 하지만 스프링 배치가 이 문제를 해결한다. 단일 서버 내의 단일 JVM에서 배치 처리를 수행하기를 원하는가? 문제없다. 사업이 성장함에 따라 이제는 청구 계산 작업을 5개의 서로 다른 노드로 나눠 밤새 완료해야 하는가? 이 또한 가능하다. 데이터 신뢰성은 어떠한가? 몇가지 주요 원칙을 염두에 두고 몇가지 구성을 하기만 하면 완전히 처리된 트랜잭션 커밋 건수와 롤백 건수를 얻을 수 있다.

 

스프링 배치 프레임워크 및 관련 에코 시스템을 자세히 살펴보면, 이들이 잘 설계되고 검증된 해결책을 제시함으로써 앞서 살펴본 배치 처리를 괴롭히는 문제를 완화시킬 수 있음을 알 수 있다. 지금까지 자바 및 오픈소스를 이용해 배치 처리를 해야하는 기술적 이유를 설명했다. 그러나 기술적인 이유로만 자바의 오픈소스를 선택해야 하는 것은 아니다. 시스템을 코딩하고 유지 보수할 수 있는 적합한 개발 인력을 찾는 것도 중요하다. 배치 처리 코드는 일반적인 웹 애플리케이션보다 수명이 훨씬 더 긴 경향이 있다. 그래서 관련 기술을 이해하는 사람을 찾는 것이 기술 자체만큼 중요하다. 스프링 배치는 매우 인기 있는 스프링 프레임워크를 기반으로 한다. 스프링의 규칙을 따르며, 스프링의 도구와 다른 스프링 기반 애플리케이션을 사용한다. 또한 스프링 부트의 일부다. 따라서 스프링을 다뤄본 경험이 있는 모든 개발자는 최소한의 학습 노력으로 스프링 배치를 선택할 수 있다.

 

스프링 배치를 사용해야 하는 근거는 확실하다. 스프링 배치를 사용하는 것은 기술적으로 가장 괜찮은 길이며 가장 비용 효율적인 방법이기도 하다.

스프링 배치의 기타 사용 사례

스프링 배치의 가장 일반적인 사용 사례는 아마도 ETL(추출 extract, 변환 transform, 적재 load) 처리일 것이다. 한 형식에서 다른 형식으로 데이터를 전환하는 작업은 엔터프라이즈 데이터 처리에서 많은 부분을 차지한다. 스프링 배치의 청크 기반 처리 및 압도적인 확장 기능은 ETL 워크로드에 자연스럽게 들어맞는다.

 

또 다른 사용 사례는 데이터 마이그레이션이다. 시스템을 재구축할 때에도 일반적으로 기존 형식의 데이터를 새 형식에 맞게 마이그레이션 한다. 이러한 사례에서 위험한 점은, 마이그레이션 작업이 제대로 테스트가 안될 수도 있으며, 일반적인 개발 절차를 따르면 당연히 포함됐을 무결성 제어 기능이 빠진 일회성 솔루션을 만들게 될 수 있다는 것이다. 반면 스프링 배치의 기능을 검토해보면 스프링 배치가 이러한 사례에 적합하다는 것을 알 수 있다. 스프링 배치는 간단한 배치 잡을 기동하고 수행하는 데 많은 코딩이 필요 없으며, 데이터 마이그레이션을 수행할 때 당연히 포함해야 할 기능임에도 대부분 제대로 구현하지 않는 커밋 횟수 측정이나 롤백 기능 등을 제공한다.

 

스프링 배치의 세번째 일반적인 사용 사례는 병렬 처리가 필요할 때다. 무어의 법칙의 한계에 맞닥뜨리게 되면서, 개발자가 앱 성능을 지속적으로 향상시키는 유일한 방법은 단일 작업을 더 빨리 처리하는 것이 아니라 더 많은 작업을 병렬로 처리하는 것임을 깨닫게 된다. 그 결과 병렬 처리를 지원하는 많은 프레임워크가 최근 출시됐다. Apache Spark, YARN, GridGain, Gazlecast 등과 같은 대부분의 빅데이터 플랫폼은 최근 멀티 코어 프로세서와 클라우드로 사용 가능한 한 수많은 서버를 활용하려 했다. 그러나 아파치 스파크와 같은 프레임워크를 사용하려면 알고리즘 또는 데이터 구조에 맞게 코드와 데이터를 변경해야 한다. 스프링 배치는 멀티 코어 또는 멀티 서버에서 처리를 분산하는 기능을 제공하며, 웹 애플리케이션에서 사용하는 것과 동일한 객체 및 데이터 소스에 접근하는 기능도 제공한다.

워크로드를 조정하는 데에도 스프링 배치를 자주 사용한다. 일반적으로 기업의 배치 처리에 단 하나의 스텝만 존재하지는 않으며, 분리된 많은 스텝을 조정해야 한다. 어떤 파일을 로드한 다음에 해당 데이터를 이용해 두 가지 독립적인 처리를 수행하고, 뒤이어 결과를 하나로 내보낼 수도 있다. 스프링 배치는 이러한 태스크를 아주 잘 조정한다. 예를 들어 스프링 클라우드 데이터 플로우(Spring Cloud Data Flow)와 스프링 배치를 사용한 "컴포즈 태스크(composed task)" 처리는 좋은 예다. 여기서 스프링 배치는 다른 기능을 실행하기 위해 스프링 클라우드 데이터 플로우를 호출하며, 무엇을 수행했고 무엇을 수행해야 하는지 추적한다. 다음은 스프링 클라우드 데이터 플로우가 제공하는 드래그 앤 드롭 사용자 인터페이스로 "컴포즈 태스크"를 구성하는 모습이다.

마지막으로 무중단 처리 또는 상시 데이터 처리를 살펴본다. 시스템이 완전히 일정하거나 또는 거의 일정하게 데이터를 입력받는 사례는 많다. 데이터 누락을 방지하려면 데이터가 들어오는 속도에 맞게 받아져야 하지만, 해당 데이터 처리 시에는 받아들인 데이터를 한번에 처리할 청크 단위로 모아서 배치 처리를 하는 것이 성능면에서 더 나을 수 있다. 스프링 배치는 신뢰할 수 있고 확장 가능한 방식으로 이런 유형의 처리를 가능하게 하는 도구를 제공한다. 프레임워크의 기능을 사용하면 큐(queue)에서 메시지를 읽은 뒤, 청크 단위로 배치 처리를 수행하는 과정을 끝없이 반복할 수도 있다. 따라서 이러한 솔루션을 처음부터 개발해야 하는 복잡한 상황을 이해할 필요없이 대량 데이터 처리량을 늘릴 수 있다.

위 그림에서 볼 수 있듯이 스프링 배치는 메임프레임의 처리와 유사한 처리 작업을 할 수 있게 설계됐지만, 그 밖의 다양한 개발 문제를 단순화할 때도 사용할 수 있는 프레임워크다. 배치가 무엇이며 왜 스프링 배치를 사용해야 하는지와 관련된 모든것을 발펴봤으니, 마지막으로 프레임워크 자체를 살펴보자.

스프링 배치 프레임워크

스프링 배치 프레임워크는 일반적인 배치 패턴 및 패러다임을 구현하는 표준 기반 방법으로, 액센츄어사와 스프링소스(SpringSource)사 간의 협업으로 개발됐다. 스프링 배치에는 데이터 유효성 검증, 출력 포맷팅, 복잡한 비즈니스 규칙을 재사용 가능한 방식으로 구현하는 기능, 대규모 데이터셋 처리 기능이 구현돼 있다. 프레임워크를 개략적으로 살펴보는 것부터 시작해보자.

스프링 배치는 레이어(layer) 구조로 조립된 세 개의 티어로 이뤄져 있다. 가장 바깥쪽에 애플리케이션 레이어가 있으며, 배치 처리 구축에 사용되는 모든 사용자 코드 및 구성이 이 레이어에 포함된다. 업무 로직, 서비스 등은 물론 잡 구조화와 관련된 구성까지도 애플리케이션 레이어에 포함된다. 애플리케이션 레이어가 최상위에 있는 것이 아니라, 다른 두 레이어인 코어 레이어와 인프라스트럭처 레이어를 감싸고 있음을 주목하기 바란다.

 

그 이유는 개발자가 개발하는 대부분의 코드가 코어 레이어와 함께 동작하는 애플리케이션 레이어지만, 때로는 Custom Reader와 Custom Writer와 같이 인프라스트럭처의 일부를 만들기도 하기 때문이다.

 

애플리케이션 레이어는 다음 레이어인 코어 레이어와 상호작용하는 데 대부분의 시간을 소비한다. 코어 레이어에는 배치 도메인을 정의하는 모든 부분이 포함된다. 코어 컴포넌트의 요소에는 잡(Job), 스텝(Step) 인터페이스와 잡 실행에 사용되는 인터페이스 즉, JobLauncher 및 JobParameters 등이 있다.

 

이 모든 것의 밑에는 인프라스트럭처 레이어가 있다. 어떤 처리를 수행하려면 파일, 데이터베이스 등으로부터 읽고 쓸 수 있어야 한다. 잡 수행에 실패한 이후 재시도될 때 어떤 일을 수행할지를 다룰 수 있어야 한다. 이러한 부분은 공통 인프라스트럭처로 간주되며, 프레임워크의 인프라스트럭처 컴포넌트 내에 들어 있다.

 

일반적으로 스프링 배치가 스케줄러이거나 스케줄러를 가지고 있다고 많이 오해하지만 그렇지 않다. 프레임워크 내에는 주어진 시간에 또는 주어진 이벤트에 따라 잡이 실행되도록 스케줄링하는 기능이 없다. 간단한 크론(cron) 스크립트부터 쿼츠(Quartz) 또는 컨트롤-M(Control-M)과 같은 엔터프라이즈 스케줄러에 이르기까지 잡을 구동시키는 여러 방법이 있지만 프레임워크 내에 존재하지는 않는다.

스프링으로 잡 정의하기

배치 처리에는 다양한 도메인 특화 개념이 있다.

 Job(잡) - 잡은 중단이나 상호작용 없이 처음부터 끝까지 실행되는 처리이다. 잡은 여러 개의 스텝이 모여 이뤄질 수 있다. 

 Step(스텝) - 각 스텝에는 관련된 입력과 출력이 있을 수 있다. 스텝이 실패했을때 반복 실행할 수도 있고 못할 수도 있다.

 

잡의 플로우는 조건부일 수 있다(예를 들어 수익을 계산하는 스텝이 $1,000,000 이상의 수익을 반환할 때만 보너스 계산 스텝을 실행하는 경우). 스프링 배치는 자바를 이용해 이런 개념을 정의하는 클래스, 인터페이스, XML 스키마, 자바 구성 유틸리티를 제공함으로써, 이러한 문제들을 적절히 나누고 스프링 유경험자에게 익숙한 방식으로 서로 연결한다. 다음은 자바 구성 클래스에 구성한 기본적인 스프링 배치 잡을 보여준다. 이 예제는 스프링에 대한 기본적인 이해가 있다는 전제하에, 아주 빠르게 선택할 수 있는 배치 처리의 뼈대다.

@Bean
public AccountTasklet accountTasklet() {
	return new AccountTasklet();
}

@Bean
public Job accountJob() {
	Step accountStep = 
			this.stepBuilderFactory
				.get("accountStep")
				.tasklet(accountTasklet())

	return this.jobBuilderFactory
			.get("accountJob")
			.strat("accountStep")
			.build();
}

위 구성 내에 두 개의 빈(Bean)이 작성됐다. 첫번째 빈은 AccountTasklet이다. AccountTasklet은 커스텀 컴포넌트로써, 스텝이 동작하는 동안에 비즈니스 로직을 수행한다. 스프링 배치는 AccountTasklet이 완료될때까지 단일 메서드(execute 메서드)를 반복해서 호출하는데, 이때 각각은 새 트랜잭션으로 호출된다.

 

두번째 빈은 실제 스프링 배치 잡이다. 이 빈 정의내에서는 팩토리가 제공하는 빌더를 사용해, 조금 전에 정의했던 AccountTasklet을 감싸는 스텝 하나를 생성한다. 그런 다음에 잡 빌더를 사용해 스텝을 감싸는 잡을 생성한다. 스프링 부트(Spring Boot)는 애플리케이션 기동 시에 이 잡을 찾아내 자동으로 실행시킨다.

잡 관리하기

어떤 데이터가 한번만 처리되고 다시는 처리되지 않도록 자바 프로그램을 작성할 수 있다. 그러나 절대로 실패해서는 안되는 처리 대상이 있다면 좀 더 견고한 접근 방식이 필요하다. 재실행을 위해 잡의 상태를 유지하고, 트랜잭션을 관리해 잡 수행 실패시 데이터 무결성을 유지하며, 추세 분석을 위해 과거 잡 실행의 성능 메트릭을 저장하는 기능은 엔터파이즈 배치 시스템이 갖춰야 할 기능이다. 이러한 기능은 스프링 배치에 포함돼 있으며, 대부분 기본으로 동작하게 돼 있다. 개발자가 배치 처리를 개발할 때는 성능 및 요구 사항에 맞게 최소한의 조정만 하면 된다.

로컬 및 원격 병렬화

배치 잡의 규모를 확장할 수 있어야 한다는 필요성은 모든 엔터프라이즈 배치 솔루션에 필수적이다. 스프링 배치는 다양한 방법으로 이를 해결하는 기능을 제공한다. 각 커밋 간격(commit interval) 내의 처리를 스레드 풀에서 가져온 자체 스레드에서 처리하는 단순한 스레드 기반 방식을 시작으로 병렬 청크/스텝 처리, 원격 청크 처리, 파티셔닝 기능을 포함하며, 모든 스텝을 병렬로 실행하기, 파티셔닝을 통해 원격 마스터로부터 작업 단위를 제공받는 워커의 그리드를 구성하기 등 스프링 배치와 관련 에코 시스템은 다양한 옵션을 제공한다.

I/O 표준화하기

복잡한 형식의 플랫(flat) 파일, XML 파일(XML은 스트림으로 변환되므로 전체 파일이 로드되지 않는다), 데이터베이스, NoSQL 저장소 내에 저장돼 있는 데이터를 읽거나 파일이나 XML에 데이터를 쓰는 일은 간단한 구성만으로 수행할 수 있다. 개발자의 코드 내에 존재하는 파일이나 데이터베이스 입력/출력 기능과 같은 로직을 추상화하는 기능은 스프링 배치로 작성된 잡의 유지 보수를 수월하게 만들어준다.

나머지 스프링 배치 에코 시스템

스프링 포트폴리오 내의 대부분의 프로젝트가 그렇듯이 스프링 배치는 동떨어져 있지 않으며, 다른 프로젝트를 확장하고 보완해 더욱 강력한 솔루션을 제공하는 에코 시스템의 일부다. 스프링 배치와 함께 동작하는 포트폴리오의 다른 프로젝트는 다음과 같다.

 

스프링 부트

2014년 소개된 스프링 부트(Spring Boot)는 스프링 애플리케이션의 개발과 관련된 다양한 의견을 수렴했다. 스프링 애플리케이션 개발 방식의 사실상 표준인 스프링 부트는 배치를 포함한 모든 스프링 워크로드를 쉽게 패키징, 배포, 실행할 수 있는 기능을 제공한다. 또한 스프링 클라우드가 제공하는 클라우드 네이티브 환경에서 중요한 역할을 한다. 따라서 스프링 부트는 여기서 소개하는 배치 애플리케이션을 개발하는 기본 방법이 될 것이다.

 

스프링 클라우드 태스크

스프링 클라우드 태스크(Spring Cloud Task)는 스프링 클라우드의 하위 프로젝트이며, 클라우드 환경에서 한정된 태스크를 실행하는 여러 기능을 제공한다. 스프링 클라우드 태스크는 유한한 워크로드를 대상으로 하는 프레임워크로써 배치 처리와 잘 통합된다. 스프링 클라우드 태스크는 정보성 메시지(잡의 시작/종료, 스텝의 시작/종료 등)를 제공하는 기능과 배치 잡을 동적으로 확장하는 기능(스프링 배치가 직접 제공하는 정적인 방법을 대신하는 기능)을 포함해, 스프링 배치의 다양한 확장 기능을 제공한다.

 

스프링 클라우드 데이터 플로우

자체적인 배치 처리 프레임워크를 만든다는 것은 이미 스프링 배치가 제공하던 성능, 확장성, 안정성을 가진 기능을 처음부터 다시 개발해야 된다는 것만 의미하는 것이 아니다. 잡의 시작, 중지나 이전 잡의 실행 통계를 보는 등의 일을 하려면 관리 및 조정 도구 같은 것도 필요하다. 그러나 스프링 배치를 사용한다면 앞에서 언급한 모든 기능뿐만 아니라 스프링 클라우드 데이터 플로우(Spring Cloud Data Flow) 프로젝트와 같은 새로운 기능을 사용할 수 있다. 스프링 클라우드 데이터 플로우 프로젝트는 클라우드 플랫폼에서 마이크로서비스를 오케스트레이션하는 도구다. 배치 애플리케이션을 마이크로서비스로 개발하면 스프링 클라우드 데이터 플로우를 사용해 동적으로 배포할 수 있다.

그리고 스프링의 모든 기능

스프링 배치가 가진 여러 인상적인 특징 가운데 가장 큰 장점으로 꼽을 수 있는 것은 스프링 기반으로 구축됐다는 점이다. 스프링 기반으로 엔터프라이즈 배치 처리를 구축한다면 스프링은 의존성 주입, AOP, 트랜잭션 관리, 일반적인 작업을 위한 템플릿/헬퍼 등 개발자에게 필요한 모든 기능을 제공한다.

 

이처럼 스프링 배치는 개발자에게 많은 것을 제공한다. 스프링 프레임워크의 검증된 개발 모델, 확장성, 관리 애플리케이션, 안정성을 가진 기능 등은 스프링 배치를 통해 배치 처리를 빠르게 수행할 수 있게 해준다.

 

배치 처리의 역사를 살펴보며, 또한 배치 처리 개발자가 마주치는 몇가지 문제를 살펴보며, 이런 과제를 극복하려면 자바 빛 오픈소스 기술을 사용해야 함을 알아봤다. 마지막으로 고수준의 컴포넌트와 기능을 검토하면서 스프링 배치 프레임워크를 개략적으로 알아봤다. 이후 장에서는 스프링 배치 사용법을 배운다.