2025. 1. 3. 18:42ㆍIT정보/초보자를 위한 IT 팁
비동기 프로그래밍은 웹 애플리케이션의 성능을 최적화하고, 처리량(Throughput)을 높이는 데 중요한 역할을 합니다. Java Spring Boot는 비동기 프로그래밍을 지원하며, 이를 통해 사용자 요청을 보다 효율적으로 처리할 수 있습니다. 이번 글에서는 Spring Boot에서 비동기 처리를 구현하는 방법과 주의사항에 대해 알아보겠습니다.
비동기 처리가 필요한 이유
비동기 처리는 다음과 같은 상황에서 유용합니다.
- 긴 실행 시간 : I/O 작업(파일 읽기/쓰기, 데이터베이스 조회 등)이나 외부 API 호출처럼 시간이 오래 걸리는 작업을 처리할 때, 해당 요청이 완료될 때까지 기다리지 않고 다른 작업을 수행할 수 있습니다.
- 시스템 자원 최적화 : 쓰레드를 효율적으로 활용하여 병렬 작업을 처리함으로써 애플리케이션의 성능을 향상시킬 수 있습니다.
- 응답 시간 단축 : 메인 쓰레드가 장시간 점유되지 않아 사용자가 더 빠르게 응답을 받을 수 있습니다.
Spring Boot에서 비동기 처리 설정하기
Spring Boot에서 비동기 처리를 사용하려면 간단한 설정과 애노테이션을 통해 구현할 수 있습니다.
1. 의존성 추가
Spring Boot Starter에는 기본적으로 비동기 처리를 위한 의존성이 포함되어 있습니다. 별도의 추가 의존성은 필요하지 않지만, 프로젝트의 pom.xml이나 build.gradle에서 Spring Web 모듈이 포함되어 있는지 확인!!
<!-- Maven -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
// Gradle
implementation 'org.springframework.boot:spring-boot-starter-web'
2. 비동기 활성화
Spring Boot에서 비동기 처리를 활성화하려면 @EnableAsync 애노테이션을 사용합니다. 이 애노테이션은 비동기 작업을 위한 환경을 구성합니다.
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfig {
// 추가적인 비동기 설정이 필요한 경우 여기에 작성합니다.
}
3. 비동기 메서드 정의
@Async 애노테이션을 사용하여 비동기 작업을 정의할 수 있습니다. 이 애노테이션은 메서드 수준에서 사용되며, 해당 메서드는 별도의 쓰레드에서 실행됩니다.
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
@Async
public void executeAsyncTask() {
System.out.println("비동기 작업 시작: " + Thread.currentThread().getName());
try {
Thread.sleep(5000); // 5초간 작업 실행
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("비동기 작업 완료");
}
}
4. 비동기 메서드 호출
컨트롤러 또는 다른 서비스 클래스에서 비동기 메서드를 호출할 수 있습니다. 비동기 메서드는 호출 즉시 반환되며, 호출한 쓰레드는 다른 작업을 계속 수행할 수 있습니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AsyncController {
private final AsyncService asyncService;
public AsyncController(AsyncService asyncService) {
this.asyncService = asyncService;
}
@GetMapping("/async")
public String asyncEndpoint() {
asyncService.executeAsyncTask();
return "비동기 작업이 실행되었습니다.";
}
}
CompletableFuture로 비동기 처리 심화 학습
CompletableFuture는 Java의 비동기 프로그래밍을 보다 강력하게 지원하는 도구입니다. @Async보다 더 유연하고, 비동기 작업의 결과를 처리하는 데 적합합니다.
1. CompletableFuture 기본 사용법
CompletableFuture를 사용하여 비동기 작업을 수행하고 결과를 반환하는 예제를 살펴보겠습니다.
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class AsyncService {
@Async
public CompletableFuture<String> executeAsyncTaskWithResult() {
System.out.println("비동기 작업 시작: " + Thread.currentThread().getName());
try {
Thread.sleep(3000); // 3초간 작업 실행
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("비동기 작업 완료");
return CompletableFuture.completedFuture("작업 완료");
}
}
2. 비동기 결과 처리
CompletableFuture의 결과를 컨트롤러에서 처리할 수 있습니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
@RestController
public class AsyncController {
private final AsyncService asyncService;
public AsyncController(AsyncService asyncService) {
this.asyncService = asyncService;
}
@GetMapping("/async-result")
public CompletableFuture<String> asyncEndpointWithResult() {
return asyncService.executeAsyncTaskWithResult()
.thenApply(result -> "비동기 작업 결과: " + result);
}
}
3. 여러 작업 조합하기
CompletableFuture는 여러 비동기 작업을 조합하거나 체인으로 연결할 수 있습니다. 예를 들어, 두 개의 작업을 병렬로 실행하고 결과를 결합하는 방법은 다음과 같습니다:
import java.util.concurrent.CompletableFuture;
public CompletableFuture<String> combineAsyncTasks() {
CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Task 1 완료";
});
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Task 2 완료";
});
return task1.thenCombine(task2, (result1, result2) -> result1 + ", " + result2);
}
비동기 처리 시 주의사항
1. 쓰레드풀 설정
기본 쓰레드풀은 제한된 수의 쓰레드를 사용합니다. 작업이 많아질 경우 사용자 정의 쓰레드풀을 설정이 필요합니다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
public class AsyncConfig {
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("AsyncThread-");
executor.initialize();
return executor;
}
}
2. 예외 처리
비동기 작업 중 발생하는 예외는 별도로 처리해야 합니다. handle 또는 exceptionally를 사용하여 예외를 관리할 수 있습니다.
public CompletableFuture<String> asyncWithExceptionHandling() {
return CompletableFuture.supplyAsync(() -> {
if (true) { // 일부 조건
throw new RuntimeException("에러 발생");
}
return "성공";
}).exceptionally(ex -> "에러 처리: " + ex.getMessage());
}
결론
Spring Boot에서 비동기 처리는 대규모 작업을 효율적으로 처리하고 애플리케이션의 성능을 향상시키는 데 매우 유용합니다. @EnableAsync와 @Async를 활용한 기본적인 비동기 처리부터 CompletableFuture를 활용한 고급 작업까지 다양한 방법을 배울 수 있습니다.
비동기 프로그래밍은 강력한 도구이지만, 적절한 설정과 예외 처리가 중요합니다. 특히, 쓰레드풀 설정과 작업 조합 방식을 이해하면 더욱 안정적이고 효율적인 애플리케이션을 개발할 수 있습니다.
추가적으로 Java 공식 문서와 Spring Async Documentation에서 더 자세한 정보를 확인하세요.
#자바 비동기 프로그래밍자바 비동기 프로그래밍 태그 삭제#spring boot asyncspring boot async 태그 삭제#spring boot 비동기 처리spring boot 비동기 처리 태그 삭제#completablefuture 사용법completablefuture 사용법 태그 삭제#spring boot 비동기 메서드spring boot 비동기 메서드 태그 삭제#completablefuture 병렬 처리completablefuture 병렬 처리 태그 삭제#자바 쓰레드풀 설정자바 쓰레드풀 설정 태그 삭제#spring boot enableasyncspring boot enableasync 태그 삭제#spring 비동기 설정spring 비동기 설정 태그 삭제#completablefuture 에러 처리completablefuture 에러 처리
'IT정보 > 초보자를 위한 IT 팁' 카테고리의 다른 글
Spring Batch를 이용한 대용량 처리 (1) | 2025.01.06 |
---|---|
꾸준히 사용하는 오라클(Oracle) 함수 정리 (1) | 2025.01.06 |
Spring Boot로 구현하는 REST API와 토큰 인증 (2) | 2024.12.31 |
REST API와 Access Token, Refresh Token 쉽게 알아보기 (1) | 2024.12.31 |
오라클 힌트(Hint)에 대한 오해와 진실 (1) | 2024.12.31 |