Spring 기초/Spring 기초 지식

[Spring] 스프링과 자바의 동시성과 병렬 처리

Stark97 2023. 10. 31. 18:29
반응형
 
 

Java의 동시성과 병렬 처리에 대해 알아보자.

📌 서론

백엔드 개발을 하다보면 동시성 문제에 직면하게 되는 경우가 있다.

그러나 동시성이 무엇인지 모르면 문제가 발생하는 원인조차 모를수 있기 때문에 간단하게라도 지식을 얻어두면 좋다고 생각한다.

이 글을 통해 정말 간단하게 자바의 동시성이 무엇이고 병렬 처리 기능은 어떤것이 있는지 알아보자!

 

1. 간단하게 알아보는 동시성 문제

동시성이 뭔데?

  • 동시성이란 것은 여러 스레드가 동시에 같은 api를 호출한다고 생각하면 이해하기 쉽다.

  • 예를 들면 스프링은 멀티 스레드로 동작하는 프레임워크이기 때문에 100개의 같은 요청이 1개의 api에 동일한 시간에 발생할 수도 있다. 이 상황에는 스레드의 경쟁이 발생할 것이고 "동시성 제어"가 되지 않는다면 서버에 문제가 발생할 것이다.

  • 선착순 쿠폰발급 시스템 같은 것을 생각해 보자 "동시성 제어"가 되지 않아서 쿠폰발급이 이상하게 된다면 시스템에 대한 신뢰도부터 하락하고 그 서비스를 사용하려 하지 않을 것이다.

자바의 동시성 제어

  • 자바에서는 이미 동시성 제어가 가능한 List, HashMap 클래스를 만들어 두었다.
  • 스프링에서는 필드에 상태값을 가지는 클래스를 선언하지 않는 것이 권장된다.
  • 그러나 만약 사용해야 하는 상황이 있다면 아래의 글을 참고해 보도록 하자 (동시성을 이해하기 위해 보는 것도 좋다.)
 

[Java] 동시성 제어가 가능한 CopyOnWriteArrayList와 일반 ArrayList의 차이점

동시성 제어가 가능한 List인 CopyOnWriteArrayList를 알아보자📌 서론동시성 제어가 가능한 HashMap인 ConcurrentHashMap에 대해 공부하고 사용하다 보니 List에도 동시성 제어가 가능한 클래스가 존재할 것

curiousjinan.tistory.com

 

 

[Java] ConcurrentHashMap의 동작원리 (CAS 기법)

Java의 ConcurrentHashMap을 이해해 보자📌 서론Java에서 일반적인 HashMap을 사용하면 동시성 문제가 발생할 수 있다. HashMap은 멀티스레드 환경에서 안전하지 않기 때문에, 여러 스레드가 동시에 HashMap

curiousjinan.tistory.com

 

2. 스프링에서의 병렬성(Parallelism)

병렬성은 스프링 애플리케이션에서 데이터 처리와 계산 작업의 성능을 향상하는 데 중요한 역할을 한다.

병렬 데이터 처리

  • 스프링의 ForkJoinPool을 활용하여 복잡한 데이터 처리 작업을 병렬로 수행할 수 있다.
  • 이는 CPU 바운드 작업의 성능을 극대화하는 데 도움이 된다.

 

배치 처리

  • 스프링 배치(Spring Batch)는 대량의 데이터를 효율적으로 처리하기 위한 병렬 처리 기능을 제공한다.
  • 이를 통해, 대규모 데이터셋을 더 빠르게 처리할 수 있다.

3. @Async 어노테이션을 사용한 비동기 처리

웹 애플리케이션에서의 비동기 요청 처리

  • 웹 애플리케이션에서는 동시에 많은 사용자의 요청을 처리해야 한다.
  • @Async 어노테이션을 사용하여 요청 처리를 비동기적으로 실행함으로써, 메인 스레드가 막히는 것을 방지하고 사용자 요청에 더 빠르게 응답할 수 있다.
@Service
public class AsyncRequestService {

    @Async
    public CompletableFuture<String> processRequest(String requestData) {
        // 비동기적으로 요청 처리 로직을 구현
        return CompletableFuture.completedFuture("Processed " + requestData);
    }
}

 

2. 데이터 처리 작업의 스케줄링

  • 대량의 데이터 처리 작업이 필요한 경우, @Scheduled 어노테이션을 사용하여 주기적으로 작업을 실행할 수 있다.
  • 이를 통해 시스템 리소스를 효율적으로 관리하고, 작업의 부하를 분산시킬 수 있다.
@Service
public class DataProcessingService {

    @Scheduled(fixedRate = 60000)
    public void periodicDataProcessing() {
        // 데이터 처리 로직을 구현
    }
}

 

3. REST API 호출의 병렬 처리

  • 외부 서비스와의 REST API 호출은 때때로 시간이 많이 소요될 수 있다.
  • 이러한 경우, CompletableFuture를 사용하여 병렬적으로 여러 API 호출을 처리할 수 있다. 이렇게 하면 전체 응답 시간이 단축된다.
@Service
public class ParallelApiService {

    private RestTemplate restTemplate = new RestTemplate();

    public void callExternalApisInParallel() {
    
        CompletableFuture<String> apiResponse1 = CompletableFuture.supplyAsync(
                            () -> restTemplate.getForObject("http://api1.com/data", String.class)
                );
        CompletableFuture<String> apiResponse2 = CompletableFuture.supplyAsync(
                            () -> restTemplate.getForObject("http://api2.com/data", String.class)
                );

        // 두 API 응답을 병렬적으로 처리
        CompletableFuture.allOf(apiResponse1, apiResponse2).join();
    }
}

 

반응형