Spring Batch ‐ ItemReader - dnwls16071/Backend_Summary GitHub Wiki

📚 FlatFileItemReader

  • 2차원 데이터로 표현된 유형의 파일을 처리하는 ItemRead(Ex. Excel이나 CSV 등 행/렬로 표현된 데이터)
  • 일반적으로 고정된 위치로 정의된 데이터 필드나 특수 문자에 의해 구별된 데이터의 행을 읽는다.
  • Resource와 LineMapper 두 가지 요소가 필요하다.

[Resource]

  • FileSystemResource : new FileSystemResource("resource/path/config.xml")
  • ClassPathResource : new ClassPathResource("resource/path/config.xml")

[LineMapper]

  • 파일의 라인 한 줄을 Object로 변환해서 FileItemReader로 전달한다.
  • 단순히 문자열을 받기 때문에 문자열을 토큰화해서 객체로 매핑화하는 과정이 필요하다.
  • LineTokenizer와 FieldSetMapper를 사용해서 처리한다.

[FieldSet]

  • 라인을 필드로 구분해서 만든 배열 토큰을 전달하면 토큰 필드를 참조할 수 있도록 한다.
  • JDBC의 ResultSet과 유사하다.

[LineTokenizer]

  • 입력받은 라인을 FieldSet으로 변환해서 리턴한다.
  • 파일마다 형식이 다르기 때문에 문자열을 FieldSet으로 변환하는 작업을 추상화시켜야 한다.

[FieldSetMapper]

  • FieldSet 객체를 받아서 원하는 객체로 매핑해서 리턴한다.
  • JdbcTemplate의 RowMapper와 동일한 패턴을 사용한다.

📚 FlatFileItemReader - delimetedlinetokenizer(구분자 방식)

  • delimetedlinetokenizer : 1개 라인의 String을 구분자 기준으로 나누어 토큰화 하는 방식
    • 이 때, 구분자의 기본값은 콤마(,)이다.
    • String line을 토큰화해서 FieldSet에게 넘겨주고 반환된다.

📚 FlatFileItemReader - fixedlengthtokenenizer(고정길이 방식)

  • fixedlengthtokenenizer : 1개 라인의 String을 사용자가 설정한 고정 길이 기준으로 나누어 토큰화 하는 방식
    • 범위는 문자열 형식으로 설정 가능하다.

📚 FlatFileItemReader - Exception Handling

  • 라인을 읽거나 토큰화할 때 발생할 수 있는 파싱 예외를 처리할 수 있는 예외 계층을 제공한다.
  • 토큰화 검증을 엄격하게 적용하지 않도록 설정하면 파싱 예외가 발생하지 않도록 할 수 있다.
tokenizer.setColumns(new Range[] { new Range(1, 5), new Range(6, 10) })
tokenizer.setStrict(false);  // 토큰화 검증을 적용하지 않겠다.
FieldSet tokens = tokenizer.tokenize("12345");
  • Tokenizer가 라인 길이나 컬럼명을 검증하지 않을 경우 예외가 발생하지 않는다.
  • FieldSet 은 성공적으로 리턴이 되며 두번째 범위 값은 빈 토큰을 가지게 된다.

📚 JsonItemReader

  • Json 데이터의 파싱과 바인딩을 JsonObjectReader 인터페이스 구현체에 위임하여 처리하는 ItemReader
    • JacksonJsonObjectReader
    • GsonJsonObjectReader

📚 DB - cursor & paging 이해

  • 배치 애플리케이션은 실시간적 처리가 어려운 대용량 데이터를 다루며 이 때, DB I/O 성능문제와 메모리 자원 효율성 문제를 해결할 수 있어야 한다.
  • 스프링 배치에서는 대용량 데이터 처리를 위해 두 가지 해결방안을 제시하고 있다.
  • Cursor Based
    • Jdbc ResultSet의 기본 메커니즘을 사용
    • 현재 행에 커서를 유지하며 다음 데이터를 호출하면 커서를 이동하며 데이터 반환이 이루어지는 Streaming I/O이다.
    • ResultSet이 open 될 때마다 next() 메서드가 호출되어 데이터베이스의 데이터가 반환되고 객체와 매핑이 이루어진다.
    • DB 커넥션이 연결되면 배치 처리가 완료될 때까지 데이터를 읽어오기 때문에 DB와 SocketTimeout을 충분히 큰 값으로 설정할 필요
    • 모든 결과를 메모리에 할당하기 때문에 메모리 사용량이 많아진다.
    • Connection 연결 유지 시간과 메모리 공간이 충분하다면 대량의 데이터에 적합할 수 있다. -> fetchSize 조절
  • Paging Based
    • 페이징 단위로 데이터를 조회하는 방식으로 page size만큼 한 번에 메모리로 먼저 가져와 한 개씩 읽는다.
    • 한 페이지를 읽을 때마다 Connection을 맺고 끊기 때문에 대량의 데이터를 처리하더라도 SocketTimeout이 거의 일어나지 않는다.
    • 시작 행 번호를 지정하고 페이지에 반환시키고자 하는 행 수를 지정한 후에 사용한다.
    • 페이징 단위 결과만 메모리에 할당하기 때문에 메모리 사용량이 적어지는 장점이 있다.
    • Connection 연결 시간이 길지 않고 메모리 공간을 효율적으로 사용해야 하는 데이터 처리에 적합할 수 있다.

📚 DB - JdbcCursorItemReader

  • Cursor 기반의 Jdbc 구현체로서 ResultSet과 함께 사용되며 DataSource에서 Connection을 얻어와서 SQL을 실행한다.
  • Thread 안정성을 보장하지 않기 때문에 멀티 쓰레드 환경에서 사용할 경우 동시성 이슈가 발생하지 않도록 동기화 처리가 필요하다.

📚 DB - JpaCursorItemReader

  • Spring Batch 4.3부터 새롭게 등장
  • Cursor 기반의 JPA 구현체로서 EntityManagerFactory 객체가 필요하며 쿼리로 JPQL을 사용한다.

📚 DB - JdbcPagingItemReader

  • Paging 기반의 Jdbc 구현체로서 쿼리에 시작 행 번호와 페이지에서 반환할 행 수를 지정해서 SQL을 실행한다.
  • 스프링 배치에서 offset과 limit을 pageSize에 맞게 자동으로 생성해주며 페이징 단위로 데이터를 조회할 때마다 새로운 쿼리가 실행된다.
  • 페이지마다 새로운 쿼리를 실행하기 때문에 페이징 결과 시 데이터 순서가 보장될 수 있도록 order by 구문이 적용된다.
  • 멀티 쓰레드 환경에서 Thread 안정성을 보장하기 때문에 별도의 동기화를 할 필요가 없다.

[PagingQueryProvider]

  • 쿼리 실행에 필요한 쿼리문을 ItemReader에게 제공하는 클래스
  • 데이터베이스마다 페이징 전략이 다르기 때문에 각 데이터 베이스 유형마다 다른 PagingQueryProvider를 사용한다.
  • Select, from, sortKey는 필수이며 where, group by절은 필수가 아니다.
  • doRead() : 락을 획득해야 메서드 내부로 진입할 수 있다. 즉, 멀티 쓰레드 환경에서 안전하다는 말이 된다.

📚 DB - JpaPagingItemReader

  • Paging 기반의 JPA 구현체로서 EntityManagerFactory 객체가 필요하며 쿼리는 JPQL을 사용한다.

❗추가 학습 : ItemReaderAdapter