🌿 Spring

메일 발송 - 스케쥴링 간 문제 해결 with Async

sh_bong 2023. 10. 3. 03:22

160개의 BEFORE_APPROVE 그림 중 100개의 그림을 APPROVED로 고치기
위 과정에서 걸리는 시간과 쓰레드의 log

 

스케쥴링의 결과물인 경매 작품의 상태 변화에 따라

사용자에게 메일을 발송하는 작업을 테스트했을 때 발생하는 문제를

위 사진으로 간략하게 나타내었다.

(위 사진의 결과는 메일 발송 메소드를 Thread.sleep(500)으로 처리한 결과이다.)

 

위 사진에서처럼 160개의 상태 변화가 필요한 작품들에 대해

스케쥴링을 적용하였고, 한 작품당 한 사람에게 메일을 보낸다고 가정했을 때

100개의 작품에 스케쥴링을 적용한 후 메일을 보내면

50초의 시간이 걸리고 그 시간 동안 다른 작업(그림의 상태 변경)은 Block되는 현상을 관찰할 수 있었다.

 

서비스 장애이지 않을 수 없다.

이러한 장애를 비동기를 이용하여 해결해보았다.

 

1) 코드 변경점

1-1) Application

@Slf4j
@EnableScheduling // Schedule사용을 위한 Annotation
@EnableAsync
@SpringBootApplication
@RequiredArgsConstructor
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@EnableAsync 어노테이션을 추가하여

비동기가 가능하게 설정하였다.

 

1-2) SendMailService

@Async
public void adminApproveMail(Picture picture) {
    sendMailUtil.sendMail(
            picture.getUser().getEmail(),
            REJECT.getMailTitle(),
            PICTURE_APPROVE_MAIL,
            new HashMap<>() {{
                put("pictureName", picture.getPictureName());
                put("startBidDate", picture.getBidStartDate().toString());
                put("link", picassoProperties.getDomain() + "pictures/" + picture.getPictureId());
            }}
    );
}

SendMailService의 모든 메소드에

@Async 어노테이션을 붙여 비동기 처리가 되도록 한다.

 

2) 비동기 적용 후 테스트

 

비동기를 적용한 후 2000개 가량의 데이터로 테스트를 해보았다.

만약 메일 발송을 비동기를 적용하지 않고 동기 방식으로 진행했다면

미술품의 상태 변경에는 약 1000초의 시간이 걸렸을 것이다.

 

비동기를 적용한 후의 테스트

테스트 결과...

0.2초도 걸리지 않아 미술품 상태 변화가 완료되었다.

처음으로 혁신적인 성능 개선을 경험해보았다.

한 메소드 안에서 두 개의 작업을 할 때

먼저 완료된 작업에서 나오는 값을 다음 작업에 넘겨주지 않고

다음 메소드로 넘어갈 수 있게 하는 비동기 처리를 실제로 해보니

이해가 되지 않았던 동기/비동기, 블락킹/논블락킹에 대해

더 깊이 이해할 수 있었다.