Spring Scheduler 와 배치

박우영·2023년 4월 12일
0

자바/코틀린/스프링

목록 보기
20/37

solved ac api 를 주기적으로 확인하는 메서드를 작성해야하는데 사용자들이 직접 확인한다면 아무런 서비스도 제공하지 않는것이라고 생각합니다. 우리는 자동화 서비스를 제공 하고싶기때문에 스케줄링 기능이 필요하다고 생각했습니다.

계속해서 데이터를 받아오는 방법은 여러가지가 있겠지만

이번 프로젝트에서 현재는 스케줄러만 이용할 예정이지만 Spring Batch 기능 의 필요성이 느껴진다면 추가 할 예정입니다.

먼저 배치란?


배치프로그램은 사용자의 요청에 따라 실행하는 프로그램이아니라

  • 정기 (정해진 시간)
  • 이벤트 (특정 이벤트가 발생했을때)
  • 온디멘드 (사용자 요청)

위와 같이 설정하여 일괄 작업하는 프로그램이다.

이러한 점이 우리 프로젝트에 spring batch 를 사용하고자 생각 한 이유 이다.
날짜 별 데이터를 비교하여 쉽게 처리 할 것이라 판단.

스케줄러 (Scheduler) 란?


일정한 시간 간격 또는 일정한 시각에 특정 로직을 돌리기 위해 사용하는 것으로
spring batch는 스케줄러 기능은 제공하지 않기에 스케줄러도 필요 할 것이라 생각하였다.
쿼츠 와 스케줄러가 있는데 둘 다 사용해 본적은 없어서 먼저 스케줄러로 사용해볼 예정이다.


스케줄러 적용

먼저 gradle 추가입니다.

	testImplementation 'org.awaitility:awaitility:4.2.0'

Test 환경에서 사용할 라이브러리 (await)을 추가 해줬습니다.

@RestController
@RequestMapping("/users")
@Slf4j
public class UserController {
    @Autowired
    private UserService userService;

    private TeamRuleService teamRuleService;

    @Scheduled(fixedRate = 1000)
    public void create(@Valid UserRequest userRequest, @Valid ProblemRequest problemRequest, User user) {
        if (this.userService.getUser(user.getId()) == null) {
            this.userService.save(user);
        } else {

        }
    }

//    @Scheduled(cron = "0 0 18 * * *")
    @Scheduled(fixedRate = 1000)
    public void abc() throws IOException, ParseException, UnsupportedEncodingException {
        log.info("문제 난이도 별 풀이 실행");
        Long temp = userService.getTier("Gold");
        System.out.println(temp);
    }

주석 처리한부분은 배포환경에서 적용 할 예정입니다. 하루에 한번 실행해야하기때문에 cron 표현식 사용 했습니다.
물론 테스트환경과 배포/개발환경에서 yml 파일을 설정 하는 방법이 있지만 간단하게 스케줄러 기능만 테스트해보려고 작성했기 때문에 이렇게 설정 해놨습니다.

먼저 로그 확인을 위해 @Slf4j 어노테이션을 사용했고

@Scheduled(fixedRate = 1000)를 사용해 1초마다 실행되게 작성했습니다.
스케줄 안에 괄호 설정으로 cron 형태로도 할 수있습니다.

스케줄러를 사용하기 위해선
application main 이있는 클래스 위에

@SpringBootApplication
@EnableJpaAuditing
@EnableScheduling
@EnableBatchProcessing
public class BaekJoonSupporterApplication {

	public static void main(String[] args) {
		SpringApplication.run(BaekJoonSupporterApplication.class, args);
	}

}

위처럼 @EnableScheduling 을 명시해줘야하고 @EnableBatchProcessing 을작성한 이유는 배치 프로그램을 사용할때 작성해주면 됩니다.


위 Controller 테스트 입니다.

@SpringBootTest
@Transactional
@TestPropertySource(properties = { "spring.config.location=classpath:application.yml" })
public class UserControllerTests {
    @SpyBean
    private UserController userController;

    @Test
    @DisplayName("스케줄러 테스트")
    void abcTest() throws IOException, ParseException {
        await().atMost(4, TimeUnit.SECONDS).untilAsserted(() -> {
            verify(userController, atLeast(2)).abc();
        });
    }
}

await 라이브러리를 사용했고 비동기 방식으로 작동하다보니 2초에 2번 실행이 안됐습니다 따라서 4초로 작성했고 PropertySource로 테스트 환경과 개발/배포 환경을 분리했습니다.

2023.05.14 수정


Spring Batch 를 도입하지않고 간단하게 스케줄링 기능만 사용하려 했으나 MSA로 전환하면서 Batch를 도입하는게 처리량 향상과 서비스 개선이 될 것이라 생각이 들었고 Spring Batch또한 도입하고자 합니다. 공부를 하다보니 정리해야 할 것도 많고 구 버전과 현재 버전 비교와 사용방법을 정리하다보니 내용이 많아져서 가독성을 위해 분리했습니다.

Spring Batch 이곳에 옮기고 정리 하겠습니다.

회고


Spring Batch을 사용하고싶어 검색을 해보면 jobbuilderfactory 가 deprecated 된다고 나온다. 즉 조만간 없어지는 기능인데 물론 구 버전을 지속적으로 사용한다면 문제가 없겠지만 버전이 다르다면 얘기가 다르다 따라서 구버전, 신버전 방식을 전부 배워보고 싶어 기존 방식과 바뀌는 방식을 비교하며 학습했고 왜 저렇게 바뀌게 됐는지 생각해보고자 한다.

한글로된 자료가 많이 부족했고 공식문서를 참고해서 공부하고자 하다보니 영어가 많이 부족하다고 느꼈다.. 영어공부를 해서 정확한 의미를 파악하는게 좋지만 gpt를 활용해서 시간이 걸리지만 하나하나 번역하며 공부했다.

참고


https://docs.spring.io/spring-batch/docs/current/reference/html/whatsnew.html#whatsNew

https://kitty-geno.tistory.com/161

0개의 댓글