ItemProcessor

ItemPorcessor는 데이터를 가공하거나 필터링하는 역할을 하며, 필수가 아니다. 이 역할은 ItemWriter에서도 구현이 가능하지만, 분리함으로써 비즈니스 코드가 섞이는 것을 방지할 수 있다.

public interface ItemProcessor<I, O> {
    @Nullable
    O process(@NonNull I var1) throws Exception;
}

I는 ItemReader에서 받을 데이터 타입이며, O는 ItemWriter에 보낼 데이터 타입이다. 즉, Reader에서 읽은 데이터가 ItemProcessor의 process()를 통과한 후 Writer에 전달된다. 구현해야할 메소드는 process하나이며, Java 8부터는 인터페이스의 추상 메서드가 1개인 경우 람다식을 사용할 수 있다.

@Bean(BEAN_PREFIX + "processor")
@StepScope
public ItemProcessor<ReadType, WriteType> processor() {
    return item -> {
        item.convert();
        return item;
    };
}
  • 불필요한 코드가 없어 구현 코드 양이 적다. (빠르게 구현 가능)

  • 고정된 형태가 없어 원하는 형태의 어떤 처리도 가능하다.

  • Batch Config 클래스 안에 포함되어 있어야만 하며, Batch Config 코드 양이 많아질 수 있다.

    • 코드 양이 많아지만 별도 클래스로 Processor를 분리해서 사용하기도 한다.

크게 ItemProcessor는 다음 역할을 한다.

  • 변환 : Reader에서 읽은 데이터를 원하는 타입으로 변환하여, Writer에 넘겨줄 수 있다.

  • 필터 : Reader에서 넘겨준 데이터를 Writer로 넘겨줄 것인지 결정할 수 있으며, null을 반환하면 Writer에 전달되지 않는다.

ItemProcessor가 null을 반환하면 해당 Item의 모든 이후 처리가 중지된다. 이때 null을 반환하더라도 다른 Item 처리가 계속 이루어진다.

구현체

Spring Batch 에서는 자주 사용하는 용도의 Processor를 미리 클래스로 만들어서 제공해주고 있다.

  • ItemProcessorAdapter

  • ValidatingItemProcessor

  • CompositeItemProcessor

하지만 최근에는 대부분 processor를 직접 구현하는 경우가 많고, 람다식으로 빠르게 구현할때도 많다. 그래서 ItemProcessorAdapterValidatingItemProcessor는 거의 사용하지 않는다.

입력 데이터 유효성 검증에 사용하는 ItemProcessor 구현체이다. 입력 아이템의 유효성 검증을 수행하는 스프링배치 Validator를 사용할 수 있으며, 유효성 검증이 실패하면, ValidationException이 발생한다.

  • org.springframework.batch.item.validator.ValidatingItemProcessor

BeanValidatingItemProcessor

JSR 303은 빈 유효성 검증을 위한 것으로, 스프링 배치는 미리 정의된 유효성 검증 기능을 어노테이션으로 제공해준다. 해당 어노테이션을 사용하려면, 다음 의존성을 추가해줘야한다.

어노테이션
속성
설명

@NotNull @Null

값이 null인지 아닌지 검사

@Size

int min : 최소 크기(default : 0) int max : 최대크기

길이나 크기가 지정한 값 범위에 있는지 검사 null은 유효하다고 판단

@Pattern

String regexp = 정규표현식

값이 정규 표현식에 일치하는지 검사 null은 유효하다고 판단

@AssertTrue @AssertFalse

값이 true인지 false인지 검사 null은 유효하다 판단

@DecmialMax @DecimalMin

String value: 최대값 또는 최솟값 boolean inclusive : 지정값 포함 여부(default : true)

지정한 값보다 작거나 같은지 혹은 크거나 같은지 검사 null은 유효하다 판단

@Max @Min

long value

지정한 값보다 작거나 같은지 혹은 크거나 같은지 검사 null은 유효하다 판단

@Digits

int integer : 허용가능한 정수 자릿수 int fraction : 허용 가능한 소수점 이하 자릿수

자릿수가 지정한 크기를 넘지 않는지 검사 null은 유효하다 판단

@NotEmpty

문자열, 배열 : null이 아니고, 길이가 0이 아닌지 검사 Collection : null이 아니고, 크기가 0이 아닌지 검사

@NotBlank

null이 아니고 최소한 한개 이상의 공백이 아닌 문자를 포함하는지 검사

@Positive @PositiveOrZero

양수인지 검사 OrZero는 양수 혹은 0인지 검사 null은 유효하다 판단

@Negative @NegativeOrZero

음수인지 검사 OrZero는 음수 혹은 0인지 검사 null은 유효하다 판단

@Email

이메일 주소가 유효한지 검사 null은 유효하다 판단

@Future @FuterOrPresent

해당 시간이 미래인지 검사 OrPresent는 현재 또는 미래시간인지 검사 null은 유효하다 판단

@Past @PastOrPresent

해당 시간이 과거인지 검사 OrPresent는 현재 또는 과거시간인지 검사 null은 유효하다 판단

위 예제와 같이 고유한 메세지를 지정할 수 있으며, 필드 값의 길이가 잘못됐는지 형식이 잘못됐는지 식별할 수 있다.

다음과 같이 지정한 validation에 맞지 않으면 예외가 발생하는 것을 볼 수 있다.

ValidatingItemProcessor

데이터셋 내에서 한개의 필드의 값이 고유해야하는 경우가 있을 수 있다. 고유한 값의 필드를 ItemStream 인터페이스를 구현하여, 각 커밋과 필드 값을 ExecutionContext에 저장해 상태를 유지할 수 있다.

Validator를 구현한 후 Step을 다음과 같이 구현하면 된다.

ItemProcessorAdapter

  • org.springframework.batch.item.adapter.ItemProcessorAdapter

서비스를 ItemProcessor 역할을 하도록 만들 수 있다.

고객의 이름을 대문자로 바꿔주는 서비스이다. 이 서비스를 ItemProcessorAdapter를 사용하여 Processor로 사용할 수 있다.

ScriptItemProcessor

Ruby, JavaScript, Groovy 등 다양한 스크립트 언어를 실행할 수 있다.

  • org.springframework.batch.item.support.ScriptItemProcessor

수행하고 싶은 스크립트를 다음과 같이 바인딩하여 사용할 수 있다.

CompositeItemProcessor

https://media.springernature.com/original/springer-static/image/chp%3A10.1007%2F978-1-4842-3724-3_8/MediaObjects/215885_2_En_8_Fig1_HTML.png

CompositeItemProcessorItemProcessor간의 체이닝을 지원하는 Processor이다.

다음과 같이 Processor가 여러개 필요한 경우 체이닝 작업을 할 수 있다.

하지만, 여기서 제네릭 타입은 사용하지 못하며, 만약 제네릭타입을 사용하게 되면 delegates에 포함된 ItemProcessor는 모두 같은 제네릭 타입을 가져야한다. 만약 같은 제네릭 타입을 사용할 수 있는 ItemProcessor간 체이닝이라면 제네릭을 선언하는 것이 더 안전한 코드가 될 수 있다.

ClassifierCompositeItemProcessor

  • org.springframework.batch.item.support.ClassifierCompositeItemProcessor

Classifier 구현체로 사용할 ItemProcessor를 선정해 classify 메서드를 수행해 분류 처리를 할 수 있다.

다음은 우편번호를 짝수 홀수로 분류한 Classifier 구현체이다.

구현한 ClassifierClassifierCompositeItemProcessor로 구현하여 수행할 수 있다.

홀수인 경우에는 upperCase출력, 짝수인 경우 lowerCase로 분류해서 출력하도록 구현하였으며, 다음과 같이 정상적으로 출력되는걸 확인할 수 있다.

ItemProcessor 직접 구현하기

커스텀 프로세서를 생성하여 짝수 우편번호는 필터링하고 홀수 우편번호만 남겨두는 ItemProcessor 예제를 살펴볼 것이다.

ItemProcessor는 **null**을 반환하면 해당 아이템은 그 이후 수행되는 ItemProcessorItemWriter로 전달되지 않고, 필터링된다. 이렇게 필터링된 레코드의 수를 JobRepository에 관리하고 있다.

다음과 같이 ItemProcessor를 구현하여, process 메서드에 원하는 로직을 작성해주면 된다.

BATCH_STEP_EXECUTION 내에 성공한 수, 필터링 걸린 아이템 수를 확인할 수 있다.

image-20211203232101096

참고

Last updated

Was this helpful?