이전 글
경로 이미지 생성하기 - 기술 선택
경로 이미지 생성하기 - 구현
개요
현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.
주기능의 응답속도 개선
여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
하지만 현재 여행 종료와 감상 생성의 응답 속도가 경로 이미지 생성 시간에 영향을 받고 있다.
경로 이미지 생성은 비동기 처리하여도 애플리케이션 사용에 문제가 되지 않는다.
소요 시간이 1초 이상 걸리는 경우가 존재하기에 이미지 생성을 비동기 처리하고 여행 종료와 감상 생성 기능의 응답 시간을 개선하는 것이 더 중요하다.
확장성 대비
현재 10분 간격으로 위치 정보를 서버에 저장하고 있다.
조금 더 짧은 간격으로 위치 정보를 그리는 경우 하나의 여행에 많은 위치 정보가 저장될 수밖에 없고 따라서 경로 이미지 생성에 걸리는 시간이 더 길어질 수 있다.
따라서 추후에 더 짧은 간격으로 위치 정보를 저장하는 경우를 대비하여 이미지 생성은 비동기로 처리하는 것이 합당하다.
비동기 처리
@Async를 사용하면 간단하게 메서드를 비동기로 동작하도록 만들 수 있다.
비동기 설 정
사용하기 전에 설정 파일을 하나 만들어서 EnableAsync 설정을 해야한다.
해당 설정을 적용하면 비동기적으로 실행하려는 메서드에 @Async 애너테이션을 붙여주기만 하면 비동기로 동작한다.
@EnableAsync
@Configuration
public class AsyncConfig {
}
스프링 부트를 사용하지 않는 경우 기본적으로 비동기 처리를 할 때 매번 새로운 스레드를 생성하기 때문에 스레드 풀 설정을 따로 해줘야 한다. 하지만 스프링 부트를 사용하는 경우 ThreadPoolTaskExecutor를 따로 설정하지 않아도 기본적으로 스프링 부트가 생성을 도와준다.
In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing. 7.7. Task Execution and Scheduling, Spring Boot Docs
@Async 적용
이미지 생성기에 Async 애너테이션을 붙여 비동기로 동작하도록 한다.
@Async
public void generate(
List<Double> latitudes,
List<Double> longitudes,
List<Double> pointedLatitudes,
List<Double> pointedLongitudes,
Long tripId
) {
// 이미지 생성
RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);
Coordinates coordinates = Coordinates.of(latitudes, longitudes);
Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);
drawImage(coordinates, routeImageDrawer, pointedCoordinates);
// 이미지 저장
String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());
// 자원 할당 해제
routeImageDrawer.dispose();
// 데이터베이스 값 변경
Trip trip = tripRepository.findById(tripId)
.orElseThrow();
trip.changeRouteImageUrl(imageUrl);
tripRepository.save(trip);
}