Notice
Recent Posts
Recent Comments
Link
반응형
관리 메뉴

쿵야지식떨이

[Spring] 비동기 처리 @Async 적용 (4) - 어떤 걸 적용해야 할까? 본문

Spring

[Spring] 비동기 처리 @Async 적용 (4) - 어떤 걸 적용해야 할까?

김쿵야 2024. 3. 5. 17:22
반응형

이전 글에서 정리한 것처럼 비동기 처리를 할 수 있는 방법은 다양하다. 이번 글에서는 내가 진행하고 있는 프로젝트에 어떤 비동기 처리 기법을 적용할 것인지, 이유는 무엇인지 정리해보려 한다. 

 

고민했던 두 가지는 @AsyncWebFlux의 Mono였고  최종적으로 선택한 것은 @Async이다.

 

둘의 공통점과 차이점, 현재 진행하고 있는 프로젝트에 더 적합한 것을 선택하여 정리해보려 한다. 


@Async와 WebFlux Mono의 공통점과 차이점

  @Async Mono
공통점 - 비동기 처리
- 블로킹하지 않고 비동기 작업의 결과를 반환할 수있다. 
차이점 - 별도의 스레드에서 메서드 실행
- 일반적인 비동기 처리에 사용
- Future를 통해 비동기 작업의 결과를 가져온다.
- 리액티브 스트림을 통해 데이터를 비동기 적으로 전달
- 리액티브 프로그래밍 패러다임을 따른다.
리액티브 연산자를 통해 비동기 작업의 결과를 처리한다. 

 

@Async와 WebFlux Mono를 각각 언제 사용하는 게 좋고, 주의할 점은?

@Async

  • 주로 I/O 작업이나 오래 걸리는 작업을 비동기 적으로 수행할 때 사용.
  • JPA와 같은 Blocking I/O를 사용하는 데이터 접근 기술을 사용할 때 @Async를 사용하면 Blocking 작업을 별도의 스레드에서 처리하여 메인 스레드의 효율을 높일 수 있다. 
  • @Async를 사용할 때 비동기 작업의 동시성 제어와 오류 처리, 스레드 풀의 설정과 관리를 주의해야 한다.
    • 별도의 스레드에서 실행되므로 동시에 여러 스레드에서 @Async 메서드를 호출할 경우 데이터 일관성을 유지하기 위해 동기화 처리가 필요할 수 있다. 
    • 해당 메서드에서 발생하는 예외는 호출자 스레드가 아닌 실행 스레드에서 처리해야 한다.

WebFlux Mono

  • I/O 작업뿐만이 아니라 CPU 바운드 작업도 비동기적으로 처리할 때 사용.
  • 웹 요청의 처리, 외부 API 호출, 데이터베이스 쿼리, 복잡한 계산, 암호화 등의 작업을 수행할 수 있다.
  • R2DBC와 같은 Non-Blocking I/O를 사용하는 데이터 접근 기술을 사용할 때 Mono를 함께 사용하면 시스템의 처리량과 효율을 높일 수 있다. 
  • Mono는 데이터의 생성과 소비가 동시에 일어나지 않을 수 있기 때문에 이를 처리하기 위한 리액티브 연산자를 사용해야 한다.
  • Mono에서 발생하는 예외는 호출자가 아닌 구독자가 처리해야 하므로 적절한 예외 처리가 필요하다.

 

🧐현재 프로젝트에 어떤 것을 사용해야 할까?

  • 맨 처음 언급했던 것처럼 최종적으로 비동기 처리를 위해 선택한 방법은 @Async이다.
  • @Async를 선택하게 된 가장 큰 이유는 현재 프로젝트에서 JPARepository를 사용하고 있는 것이었다. 
  • Mono를 사용하려면 R2DBC라는 관계형 데이터베이스를 사용해야 했다. 
    • 더보기
      - 관계형 데이터베이스에서 Reactive Programming API를 가능하게 해 준다
         - 관계형 데이터베이스에 Non-Blocking 접근이 가능하게 해 준다.
      - Blocking Programming 일 때보다 높은 동시성이 요구되는 상황에서 좋은 성능을 낼 수 있다. 
      - 하지만 기술 측면에서 숙련도가 높지 않으며  아직 제공되지 않는 데이터베이스 벤더가 있다.
    • 더보기
      - 사용해도 되지만 사용하지 않는 것이 좋다.
      - JPA는 기본적으로 비동기를 제공하지 않는다.
      - WebFlux는 Non-Blocking I/O를 사용하고 JPA는 Blocking I/O를 사용한다.
      - JPA를 사용하면 데이터베이스 작업을 수행하는 동안 스레드가 Blocking되어야 한다. 
         → 요청을 처리하는 동안 스레드가 대기 상태에 있어야 함을 의미!
         → WebFlux의 Non-Blocking과 맞지 않다.
      - WebFlux와 JPA를 함께 사용하면 Non-Blocking 모델의 이점을 누리기 어렵다. 
  • 현재 프로젝트에서 JPA를 모두 R2DBC로 바꾸기에는 부담감이 컸고 R2DBC는 JPA에서 쉽게 사용했던 여러 기능들을 제공하지 않는다는 점도 컸다.
  • @Async는 스레드 풀에서 별도의 스레드를 할당받아 비동기 작업을 수행하기 때문에 JPA를 사용해도 별도의 스레드에서 실행시키기 때문에 기다리지 않고 다른 작업을 할 수 있다고 한다. 

 

 

  위 상황들을 고려해 @Async로 비동기 처리를 해보려 한다!

  이제 다음 글 부터는 실제 코드로 @Async를 사용하여 비동기를 적용해보려 한다 :)

반응형