Rental Application (React & Spring boot Microservice) - 38: 대여서비스(3)

#1 스케쥴러

관리자 입장에서 매번 모든 데이터를 대상으로 대여가 끝난 대상을 찾아 만료시키는 일은 번거로운 일입니다. 따라서 서비스 자체에서 자동적으로 이러한 작업을 진행해주는 일 또한 중요하죠. 그런 관점에서 스프링에서는 cron을 이용하여 스케줄을 지정해줄 수 있습니다. 이를 이용하여 end_date와 현재 날짜를 비교하여 대여를 자동적으로 만료해주는 시스템을 구축해보도록 하겠습니다.

#2 @Scheduled

스프링부트에서는 @Scheduled라는 어노테이션으로 cron 스케쥴을 생성할 수 있습니다. 기본적으로 cron은 다음과 같은 형식을 가집니다.

* 초(0-59) * 분(0-59) * 시간(0-23) * 일(1-31) * 월(1-12) * 요일(0-7)

Rental Application에서 cron은 대여 만료 시에 자동적으로 실행이 됩니다. 따라서 대여 데이터 중 end_date의 칼럼에 맞추어 그 다음날에 대여 만료라는 상태로 변경시키면 되겠죠.

우선 RentalServiceApplication에 @EnableScheduling 어노테이션을 붙이도록 하겠습니다.

  • ./RentalServiceApplication
package com.microservices.rentalservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableEurekaClient
@EnableScheduling
public class RentalServiceApplication {

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

}

우선 DateUtil을 다음과 같이 수정하도록 하겠습니다.

  • ./util/DateUtil
package com.microservices.rentalservice.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class DateUtil {
    public static String dateNow() {
        return new SimpleDateFormat("yyyy-MM-dd").format(new GregorianCalendar().getTime());
    }

    public static boolean matchingDate(String endDate) {
        Calendar calendar = new GregorianCalendar();

        calendar.add(Calendar.DATE, -1);

        return endDate == new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    }
}

1) dateNow: 현재 시간을 2021-01-01과 같은 타입으로 반환해주는 메서드입니다.

2) matchingDate: 어제 날짜를 가지고있는 Calendar 객체와 endDate를 비교한 boolean값을 반환합니다. 지금 시간을 기준으로 하기 때문에 예를 들어 endDate가 어제의 날짜를 가지고 있다면 calendar객체 또한 어제의 날짜를 가지고 있기 때문에 둘을 비교하면 true의 값을 반환할 것입니다.

그리고 scheduler 패키지를 만들고 Scheduler 클래스를 작성하도록 하겠습니다.

./scheduler/Scheduler

package com.microservices.rentalservice.scheduler;

import com.microservices.rentalservice.dto.RentalDto;
import com.microservices.rentalservice.entity.RentalEntity;
import com.microservices.rentalservice.repository.RentalRepository;
import com.microservices.rentalservice.service.RentalService;
import com.microservices.rentalservice.util.DateUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class Scheduler {
    private RentalService rentalService;
    private RentalRepository rentalRepository;

    public Scheduler(
        RentalService rentalService,
        RentalRepository rentalRepository
    ) {
        this.rentalService = rentalService;
        this.rentalRepository = rentalRepository;
    }

    @Scheduled(cron = "0 0 7 * * *")
    public void cronJob() {
        List<RentalEntity> rentalList = rentalRepository.findAll();

        for(RentalEntity rental: rentalList) {
            if(DateUtil.matchingDate(rental.getEndDate())) {
                rentalService.expiredRental(rental.rentalId());
            }
        }

    }
}

시간은 매일 오전 7시 정각에 스케쥴러를 실행하도록 하였고, 모든 대여 데이터를 불러와 matchingDate 메서드를 실행하도록 하였습니다.

이어서 RentalServiceImpl에서 exipredRental 메서드를 구현하도록 하겠습니다.

  • ./service/RentalServiceImpl
...

@Service
@Slf4j
public class RentalServiceImpl implements RentalService {
    ...

    @Transactional
    @Override
    public void expiredRental(String rentalId) 
        log.info("Rental Service's Service Layer :: Call expiredRental write Method!");

        RentalEntity entity = rentalRepository.findByRentalId(rentalId);

        entity.setStatus(RentalStatus.EXPIRED_RENTAL.name());

        rentalRepository.save(entity);
    }
}

rentalId를 전달받아 대여 데이터를 찾아 상태값을 EXPIRED_RENTAL로 변경하는 메서드입니다.

실제 서비스라면 모든 마이크로서비스들은 상시 작동을 하기 때문에 rental-service에서 Scheduler 클래스는 매일 오전 7시마다 만료 데이터를 변경하는 작업을 진행하겠죠.

이상으로 마이크로서비스에서 실질적으로 작동하는 서비스 코드들을 전부 작성했습니다. 다음 포스트에서는 도커와 젠킨스를 이용한 CI/CD 라든지, AWS로 전환이라던지, 미처 구현하지 못했던 부분들을 구현해보도록 하겠습니다.

좋은 웹페이지 즐겨찾기