1. 이번 주 항해 취업 리부트코스에서 내가 구현한 기능
원래대로라면 6주차에 구현해야했었던 기능이었지만 새로 배우는 과정이다보니 시간이 오래걸렸다.
- spring batch 기반 조회수 누적(일일, 주간, 월간)
- spring batch 기반 정산 금액 누적(일일, 주간, 월간)
- 정산된 금액 API 형태로 전달.
2. 이번 주 겪은 트러블슈팅
문제와 원인
로직 상에는 큰 문제가 없다고 생각했는데 ItemReader에서 제대로 읽어오지 못하고 NullPointerException 발생.
@Bean
@JobScope
public Step monthlyVideoViewStatsStep(
ItemReader<VideoViewStats> videoViewStatsJpaPagingItemReader,
ItemProcessor<VideoViewStats, VideoViewStats> monthlyVideoViewStatsItemProcessor
) {
log.info("Starting monthly video view stats step");
return new StepBuilder("monthlyVideoViewStatsStep", jobRepository)
.<VideoViewStats, VideoViewStats>chunk(10, transactionManager)
.reader(videoViewStatsJpaPagingItemReader)
.processor(monthlyVideoViewStatsItemProcessor)
.writer(videoViewStatsItemDBWriter)
.build();
}
// JPA PagingItemReader 정의
@Bean
@StepScope
public ItemReader<VideoViewStats> videoViewStatsJpaPagingItemReader(
@Value("#{jobParameters['dateTime']}") LocalDateTime dateTime,
@Value("#{jobParameters['statisticsType']}") String dateType
) {
log.info("Starting video view stats jpa paging item reader");
LocalDate date = dateTime.toLocalDate();
LocalDate startDate = date.minusDays(7).with(DayOfWeek.MONDAY);;
LocalDate endDate = startDate.plusDays(6);
if(dateType.equals("month")){
startDate = date.minusMonths(1).withDayOfMonth(1); // 직전 월의 첫째 날
endDate = startDate.plusMonths(1).minusDays(1); // 해당 월의 마지막 일
}
Map<String, Object> parameters = new HashMap<>();
parameters.put("category", VideoViewStats.Category.DAY);
parameters.put("startDate", startDate);
parameters.put("endDate", endDate);
return new JpaPagingItemReaderBuilder<VideoViewStats>()
.name("videoViewStatsJpaPagingItemReader")
.entityManagerFactory(entityManagerFactory)
.pageSize(10)
.queryString("SELECT v FROM VideoViewStats v WHERE v.category = :category " +
"AND v.startDate BETWEEN :startDate AND :endDate " +
"ORDER BY v.startDate ASC")
.parameterValues(parameters)
.build();
}
문제 해결 시도
- 별도의 커스텀 Reader로 클래스를 생성해서 시도해봤으나 동일한 문제 발생.
해결
참고 : https://jojoldu.tistory.com/132
- @Bean이랑 @StepScope를 동시에 사용해서 JopParameter 사용 시 리턴 타입과 생성한 값이 완전히 동일하지 않으면 도중에 proxy 객체에 걸려서 오류가 발생함.
- 참고 사이트에서 확인해보니, reader()에서 ItemReader 객체로 반환하게 될 때, @StepScope가 없으면 정상적으로 동작하지만 만약 @Bean과 @StepScope를 동시에 사용할 경우 @StepScope의 proxyMode = ScopedProxyMode.TARGET_CLASS로 인해 ItemReader 인터페이스의 프록시 객체를 생성하여 리턴하게 된다.
- 다만 프록시 객체에는 stream을 open/close 하는 메소드가 없음.
- 즉 stream을 관리하는 메소드가 없으므로 EntityManager가 생성이 되지 않음.
따라서 반환타입 자체를 구현체의 타입을 직접 쓰게 되면 정상적으로 동작함. 위 코드를 예시로 든다면 ItemReader 대신 JpaPagingItemReader를 반환하면 정상적으로 동작한다.
3. 이번 주 진행된 개인 프로젝트에서 얻은 인사이트
- 배치 작업을 비즈니스 로직에서 처리해야되는 부분만 고려했었는데, 그게 아니더라도 더 많은 활용이 가능하다는 걸 깨달았다. 개발 과정에서 테스트에 필요한 더미 데이터를 생성하고 DB에 저장하는 역할도 가능하고, 이외에도 다양하게 테스트 해볼 수 있는 영역이 많다보니 좀 더 알아보면 좋겠다라는 생각을 했다.
- 배치의 성능을 향상시키기 위해서는 디테일한 부분들에 대해서 이해해야 할 필요성을 느꼈다. 배치 작업의 성능을 향상시키는 대표적인 방법은 4가지가 있는데, 그 중에서도 가장 많이 쓰는 방식은 multi thread, parallel processing, partitioning step 정도가 대표적이다.(이외에도 remote chunking이 있지만 입문 단계에서 사용하기에는 어려움이 있다.) 위 과정 중에서 multi thread의 경우 간단한 방식이라면 쉽게 구현이 가능하지만, 좀 더 성능을 개선시키기 위해 별도의 TaskExecutor를 상속받아 구현한다고 하면 thread Pool 이나 등등 고민해야될 부분들이 많다. 이처럼 큰 영역은 아니지만 세세한 부분에서 조정해야 될 부분이 많다고 느꼈다.
항해99 취업 리부트 코스를 수강하고 작성한 콘텐츠입니다.
IT 커리어 성장 코스 항해99, 개발자 취업부터 현직자 코스까지
항해99는 실무에 집중합니다. 최단기간에 개발자로 취업하고, 현직자 코스로 폭발 성장을 이어가세요. 실전 프로젝트, 포트폴리오 멘토링, 모의 면접까지.
hanghae99.spartacodingclub.kr
'항해99 > 5-8주차' 카테고리의 다른 글
[항해 취업 리부트 코스] 6주차 프로젝트 WIL (0) | 2024.04.30 |
---|---|
[항해 취업 리부트 코스] 5주차 프로젝트 WIL (0) | 2024.04.22 |
1. 이번 주 항해 취업 리부트코스에서 내가 구현한 기능
원래대로라면 6주차에 구현해야했었던 기능이었지만 새로 배우는 과정이다보니 시간이 오래걸렸다.
- spring batch 기반 조회수 누적(일일, 주간, 월간)
- spring batch 기반 정산 금액 누적(일일, 주간, 월간)
- 정산된 금액 API 형태로 전달.
2. 이번 주 겪은 트러블슈팅
문제와 원인
로직 상에는 큰 문제가 없다고 생각했는데 ItemReader에서 제대로 읽어오지 못하고 NullPointerException 발생.
@Bean
@JobScope
public Step monthlyVideoViewStatsStep(
ItemReader<VideoViewStats> videoViewStatsJpaPagingItemReader,
ItemProcessor<VideoViewStats, VideoViewStats> monthlyVideoViewStatsItemProcessor
) {
log.info("Starting monthly video view stats step");
return new StepBuilder("monthlyVideoViewStatsStep", jobRepository)
.<VideoViewStats, VideoViewStats>chunk(10, transactionManager)
.reader(videoViewStatsJpaPagingItemReader)
.processor(monthlyVideoViewStatsItemProcessor)
.writer(videoViewStatsItemDBWriter)
.build();
}
// JPA PagingItemReader 정의
@Bean
@StepScope
public ItemReader<VideoViewStats> videoViewStatsJpaPagingItemReader(
@Value("#{jobParameters['dateTime']}") LocalDateTime dateTime,
@Value("#{jobParameters['statisticsType']}") String dateType
) {
log.info("Starting video view stats jpa paging item reader");
LocalDate date = dateTime.toLocalDate();
LocalDate startDate = date.minusDays(7).with(DayOfWeek.MONDAY);;
LocalDate endDate = startDate.plusDays(6);
if(dateType.equals("month")){
startDate = date.minusMonths(1).withDayOfMonth(1); // 직전 월의 첫째 날
endDate = startDate.plusMonths(1).minusDays(1); // 해당 월의 마지막 일
}
Map<String, Object> parameters = new HashMap<>();
parameters.put("category", VideoViewStats.Category.DAY);
parameters.put("startDate", startDate);
parameters.put("endDate", endDate);
return new JpaPagingItemReaderBuilder<VideoViewStats>()
.name("videoViewStatsJpaPagingItemReader")
.entityManagerFactory(entityManagerFactory)
.pageSize(10)
.queryString("SELECT v FROM VideoViewStats v WHERE v.category = :category " +
"AND v.startDate BETWEEN :startDate AND :endDate " +
"ORDER BY v.startDate ASC")
.parameterValues(parameters)
.build();
}
문제 해결 시도
- 별도의 커스텀 Reader로 클래스를 생성해서 시도해봤으나 동일한 문제 발생.
해결
참고 : https://jojoldu.tistory.com/132
- @Bean이랑 @StepScope를 동시에 사용해서 JopParameter 사용 시 리턴 타입과 생성한 값이 완전히 동일하지 않으면 도중에 proxy 객체에 걸려서 오류가 발생함.
- 참고 사이트에서 확인해보니, reader()에서 ItemReader 객체로 반환하게 될 때, @StepScope가 없으면 정상적으로 동작하지만 만약 @Bean과 @StepScope를 동시에 사용할 경우 @StepScope의 proxyMode = ScopedProxyMode.TARGET_CLASS로 인해 ItemReader 인터페이스의 프록시 객체를 생성하여 리턴하게 된다.
- 다만 프록시 객체에는 stream을 open/close 하는 메소드가 없음.
- 즉 stream을 관리하는 메소드가 없으므로 EntityManager가 생성이 되지 않음.
따라서 반환타입 자체를 구현체의 타입을 직접 쓰게 되면 정상적으로 동작함. 위 코드를 예시로 든다면 ItemReader 대신 JpaPagingItemReader를 반환하면 정상적으로 동작한다.
3. 이번 주 진행된 개인 프로젝트에서 얻은 인사이트
- 배치 작업을 비즈니스 로직에서 처리해야되는 부분만 고려했었는데, 그게 아니더라도 더 많은 활용이 가능하다는 걸 깨달았다. 개발 과정에서 테스트에 필요한 더미 데이터를 생성하고 DB에 저장하는 역할도 가능하고, 이외에도 다양하게 테스트 해볼 수 있는 영역이 많다보니 좀 더 알아보면 좋겠다라는 생각을 했다.
- 배치의 성능을 향상시키기 위해서는 디테일한 부분들에 대해서 이해해야 할 필요성을 느꼈다. 배치 작업의 성능을 향상시키는 대표적인 방법은 4가지가 있는데, 그 중에서도 가장 많이 쓰는 방식은 multi thread, parallel processing, partitioning step 정도가 대표적이다.(이외에도 remote chunking이 있지만 입문 단계에서 사용하기에는 어려움이 있다.) 위 과정 중에서 multi thread의 경우 간단한 방식이라면 쉽게 구현이 가능하지만, 좀 더 성능을 개선시키기 위해 별도의 TaskExecutor를 상속받아 구현한다고 하면 thread Pool 이나 등등 고민해야될 부분들이 많다. 이처럼 큰 영역은 아니지만 세세한 부분에서 조정해야 될 부분이 많다고 느꼈다.
항해99 취업 리부트 코스를 수강하고 작성한 콘텐츠입니다.
IT 커리어 성장 코스 항해99, 개발자 취업부터 현직자 코스까지
항해99는 실무에 집중합니다. 최단기간에 개발자로 취업하고, 현직자 코스로 폭발 성장을 이어가세요. 실전 프로젝트, 포트폴리오 멘토링, 모의 면접까지.
hanghae99.spartacodingclub.kr
'항해99 > 5-8주차' 카테고리의 다른 글
[항해 취업 리부트 코스] 6주차 프로젝트 WIL (0) | 2024.04.30 |
---|---|
[항해 취업 리부트 코스] 5주차 프로젝트 WIL (0) | 2024.04.22 |