안녕하세요.
오늘은 Java에서 어노테이션 Async를 이용한 비동기 처리방법에 대하여 알아보겠습니다.
javaSpringFramework에서 컨트롤러의 매핑 값을 호출시 다른 컨트롤러의 매핑 값을 재호출해도 이전 컨트롤러의 메서드가 종료되지않고 백그라운드에서 계속해서 진행되게 하고 싶은 경우가 있습니다.
예를 들어 화면(View)에 "엑셀 생성" 버튼이 있습니다.
"엑셀 생성" 버튼은 100만건이상의 데이터로 엑셀 파일을 생성하여서 3시간이 걸리는 작업입니다.
이런 경우 사용자가 엑셀 생성버튼을 눌러서 엑셀 생성 진행시에 다른 작업을 하지않고 3시간을 기다려야 정상적으로 생성이 완료되며, 생성완료이전에 다른 컨트롤러를 다시 호출했다면 이전 작업이 중단 되고 새로운 컨트롤러 호출 동작을 진행하게됩니다.
이런 문제를 해결하려면, 작업을 비동기 처리하여 사용자가 생성 버튼을 누른 후 진행되는동안 사용자는 다른 작업을 진행할 수 있어야합니다.
그 방법에 대하여 알아보겠습니다.
1. 비동기 작업을 위한 @Async 사용
Spring의 @Async 애노테이션을 사용하면, 특정 메서드를 별도의 쓰레드에서 실행하여 비동기로 처리할 수 있습니다.
이렇게 하면 기존 요청은 빠르게 반환되고, 작업은 백그라운드에서 계속 실행됩니다.
구현 방법
- 비동기 설정 추가: @EnableAsync를 설정합니다.
- 비동기 메서드 정의: 비동기로 실행할 메서드에 @Async 애노테이션을 추가합니다.
// AppConfig.java
@Configuration
@EnableAsync
public class AppConfig {
}
// AsyncService.java
@Service
public class AsyncService {
@Async
public void performAsyncTask() {
try {
// 긴 작업 (예: 파일 처리, 외부 API 호출 등)
for (int i = 0; i < 10; i++) {
Thread.sleep(1000); // 1초 대기
System.out.println("백그라운드 작업 진행 중: " + i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Task interrupted", e);
}
}
}
// MainController.java
@RestController
@RequestMapping("/api")
public class MainController {
private final AsyncService asyncService;
public MainController(AsyncService asyncService) {
this.asyncService = asyncService;
}
@GetMapping("/start-task")
public String startTask() {
asyncService.performAsyncTask(); // 비동기 작업 시작
return "비동기 작업 시작!";
}
@GetMapping("/another-task")
public String anotherTask() {
return "다른 컨트롤러 작업 수행 중!";
}
}
설명
- /api/start-task를 호출하면 performAsyncTask가 백그라운드에서 실행됩니다.
- /api/another-task를 호출하면 이전 비동기 작업에 영향을 주지 않고 다른 요청을 처리할 수 있습니다.
2. 스레드 풀 설정
@Async는 기본적으로 Spring의 기본 스레드 풀을 사용하지만, 필요하면 커스텀 스레드 풀을 설정할 수도 있습니다.
@Configuration
@EnableAsync
public class AppConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 최소 스레드 수
executor.setMaxPoolSize(10); // 최대 스레드 수
executor.setQueueCapacity(25); // 작업 대기 큐 크기
executor.setThreadNamePrefix("AsyncThread-");
executor.initialize();
return executor;
}
}
3. 비동기 작업의 결과 처리
비동기 작업의 결과를 받아야 할 경우 Future 또는 CompletableFuture를 사용할 수 있습니다.
예제: CompletableFuture 사용
@Async
public CompletableFuture<String> performAsyncTaskWithResult() {
try {
Thread.sleep(3000); // 3초 대기
return CompletableFuture.completedFuture("작업 완료!");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return CompletableFuture.failedFuture(e);
}
}
@GetMapping("/async-result")
public CompletableFuture<String> getAsyncResult() {
return asyncService.performAsyncTaskWithResult();
}
4. 주의사항
- @Async를 사용하는 메서드는 다른 클래스에 정의되어야 제대로 동작합니다. 동일 클래스 내에서 호출하면 프록시를 통해 비동기 처리가 되지 않습니다.
- 백그라운드 작업이 많아질 경우, 스레드 풀 설정을 적절히 조정해야 서버 성능에 영향을 주지 않습니다.
위와 방식으로 비동기 작업을 백그라운드에서 실행하면서, 다른 컨트롤러 요청을 처리할 수 있습니다.
감사합니다.
'programming language > Java' 카테고리의 다른 글
Java _ 장시간 걸리는 Excel 생성시 비동기처리 (0) | 2024.12.02 |
---|---|
intelliJ에서 vmOption 및 JavaProject 메모리 설정 (3) | 2024.11.20 |
Java _ 데이터를 엑셀 파일로 만들기 (2) | 2024.11.19 |
Java_ 엑셀 파일 시트별로 병합하기 (2) | 2024.11.18 |
보안) FileUtils를 이용한 업로드 확장자를 제한하는 방법 (0) | 2024.07.23 |