개발지식 먹는 하마 님의 블로그

[내일배움캠프 48일차] 배달앱 장바구니 만료 시간 적용 본문

내일배움캠프 (CS25)

[내일배움캠프 48일차] 배달앱 장바구니 만료 시간 적용

devhippo 2025. 4. 24. 21:18

스케줄러로 장바구니 삭제하기

(Redis를 사용하지 않는)  event Schedule 방법에는 스프링에 제공하는 것과 MySQL이 제공하는 것 2가지가 있다고 한다.

나는 스프링에서 제공하는 방식을 사용하였다. 

@Component
@RequiredArgsConstructor
public class CartCleanupScheduler {

    private final CartRepository cartRepository;

    @Scheduled(fixedRate = 1000 * 60 * 30) //30분마다
    @Transactional
    public void deleteExpiredCarts() {
        //만료시간이 현재보다 이전인 경우를 조회해온다.
        List<Cart> expiredCarts = cartRepository.findAllByExpiredAtBefore(LocalDateTime.now());
        cartRepository.deleteAll(expiredCarts);
    }

    @PostConstruct
    public void onStartupCleanup() {
        deleteExpiredCarts(); // 앱 시작 시 정리
    }

    @PreDestroy
    public void onShutdownCleanup() {
        deleteExpiredCarts(); // 앱 종료 시 정리
    }
}

주기는 일단 30분으로 설정하였고, PostConstruct와 PreDestroy 어노테이션으로 앱 시작과 종료 시점에도
만료된 장바구니를 삭제하도록 설정하였다.

 

장바구니 유효성 검증

너무 어렵게 생각했다.
만료된 장바구니인지 아닌지를 앞쪽에서 쳐내야 한다고 생각했기 때문에
해결 방법으로 AOP나 Service 클래스 내에서 이를 처리하는 메서드를 작성해야한다고 생각했다.

그러나 해결 방법은 간단했다.
애초에 Repository에서 만료된 장바구니는 조회가 되지 않도록 설정하면 되는 것이었다.

 

만료된 장바구니가 아직 삭제되지 않았는데요?

위에서 설정한 주기 사이에 만료된 장바구니에 대해서 메뉴를 추가하려고 하는 경우를 고려해야 했다.

만료된 장바구니는 조회되지 않지만 유저 아이디에 해당하는 장바구니가 아직 삭제되지 않은 채, 존재하고 있다.
조회된 객체가 없어서 새로운 장바구니를 만들고자 한다면 만들 수 없다.
장바구니는 유저Id 당 1개만 존재할 수 있기 때문이다.

따라서, 장바구니 메뉴 추가의 경우 만료된 장바구니가 조회되도록 허용해야했다.

        // userId에 해당하는 장바구니 존재 여부를 확인한다.
        Cart cart = cartRepository.findByUserId(userId).orElse(null);

        //존재하는 장바구니가 없다면 새로운 장바구니를 생성한다.
        if (cart == null) {
            cart = cartRepository.save(Cart.createCart(user, store));
        }

        //존재하는 장바구니가 이미 만료되었거나, 장바구니의 가게 id와 메뉴가 속한 가게 id가 다른 경우 초기화한다.
        if(cart.isExpired()|| !cart.isEqualStoreId(store.getId())){
            cartRepository.deleteById(cart.getId());
            cart = cartRepository.save(Cart.createCart(user, store));
        }