Table of Contents
						
						Spring Boot 비동기 서비스 만들기(@Async)
로그 저장 로직을 비동기로 해 놓으면, 서비스 속도 저하가 없어,
서비스 품질 향상에 도움이 된다.
@Configuration
CorePoolSize : 기본 실행 대기하는 Thread의 수
MaxPoolSize : 동시 동작하는 최대 Thread의 수
QueueCapacity : MaxPoolSize 초과 요청시 최대 수용 가능한 Queue의 수
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("mg-async-");
        executor.initialize();
        return executor;
    }
}
@Async
@Async 애너테이션 추가만으로 비동기 서비스가 된다.
@RequiredArgsConstructor
@Service
public class LoggerService {
    private final LogKakaoRestaurantInfoRepository repository;
    private final LogKakaoRestaurantInfoMapper mapper = Mappers.getMapper(LogKakaoRestaurantInfoMapper.class);
    @Async
    @Transactional
    public void saveKakaoRestaurantInfo(List<Document> documents) {
        for (Document document : documents) {
            try {
                LogKakaoRestaurantInfo info = repository.getById(document.getId());
                mapper.updateFromDto(document, info);
            } catch (EntityNotFoundException ex) {
                repository.save(mapper.toEntity(document));
            }
        }
    }
}
주의사항
- 
private method 사용 불가
 - 
self-invocation(자가 호출) 불가
같은 Class 에 존재하는 method 에 @Async Annotation을 붙여도 동기방식으로 작동한다.
 - 
QueueCapacity 초과 요청에 대한 비동기 method 호출시 방어 코드 작성 필요
 
QueueCapacity 를 모두 소진한 경우, TaskRejectedException 이 발생한다.
@AllArgsConstructor
@Controller
public Class TestController {
    private TestService testService;
    @GetMapping("async")
    public String testAsync() {
        log.info("TEST ASYNC");
        try {
            for(int i=0; i<50; i++) {
                testService.asyncMethod(i);
        } catch (TaskRejectedException e) {
            // 방어코드
        }
        return "";
    }
}