반응형

코루틴 - 코틀린; 비동기

코루틴(Coroutine)은 비동기 프로그래밍동시성 처리를 위한 경량 실행 단위/함수
일반적으로 코루틴은 실행을 일시 중단하고(중단점 제공), 필요한 시점에 다시 시작할 수 있는 기능을 가지고 있음

  • 핵심 아이디어: 사용자 수준의 스케줄링
    • 코루틴은 명시적인 중단 지점을 통해 비동기 작업을 관리
    • 단일 스레드에서도 여러 코루틴을 실행할 수 있음
  • 동작 방식:
    • 비동기: 코루틴은 주로 비동기 작업을 처리하는 데 사용. 코루틴은 일시 중단과 재개가 가능하여, 비동기 네트워크 호출이나 파일 I/O 작업을 쉽게 처리할 수 있음
    • 런타임이 코루틴의 상태를 관리하고, 필요 시 다시 스케줄링
    • 예: suspend 함수 호출 시 작업을 중단하고 다른 작업을 실행

장점:

  • 명시적인 상태 관리로 복잡한 비동기 로직 처리에 강력.
  • 메모리 및 리소스 효율성이 높음.

단점:

  • 프로그래머가 중단 지점을 명시적으로 관리해야
  • 자바에서는 안됨(Kotlin에서 주로 사용)

코루틴의 특징

  1. 경량 스레드:
    • 코루틴은 스레드와 유사하게 보이지만, 실제 스레드를 생성하지 않고 실행되므로 더 적은 리소스를 사용함
    • 코루틴은 스레드보다 가벼운 구조로, 많은 수의 코루틴을 동시에 실행할 수 있어 메모리 사용량을 줄이고 성능을 향상시킴
  2. 비동기 작업 처리:
    • await 또는 yield 같은 키워드를 통해 작업의 흐름을 중단하고, 나중에 재개할 수 있음
    • 코루틴은 비동기적으로 실행되며, 다른 작업과 동시에 진행될 수 있어 CPU 자원을 효율적으로 사용할 수 있게 해줌
  3. 스케줄링 제어:
    • 코루틴은 프로그래머가 명시적으로 실행 순서를 제어할 수 있음
  4. 언제든 중단/재개 가능:
    • 작업의 중간에서 멈췄다가 나중에 다시 이어서 실행할 수 있어 효율적인 비동기 작업 처리가 가능
    • 코루틴은 실행 상태를 유지할 수 있어, 중단된 지점에서 다시 시작할 수 있음

언제 코루틴을 사용하나?

  1. I/O 작업:
    • 네트워크 요청, 파일 읽기/쓰기 등 시간이 오래 걸리는 작업에서 UI 스레드나 메인 스레드를 차단하지 않고 비동기적으로 처리.
  2. 동시성 프로그래밍:
    • 여러 작업을 병렬로 처리할 때 스레드보다 더 효율적으로 관리 가능.
  3. UI 프로그래밍:
    • 애니메이션, 이벤트 처리, 사용자 인터페이스 업데이트 등 비동기 작업을 자연스럽게 구현.
  4. 백그라운드 작업:
    • CPU 집약적인 작업이나 긴 대기 시간이 필요한 작업을 수행하면서 메인 스레드를 차단하지 않음.

 

코루틴 자바 지원 X

자바의 virtual thread랑 비교?

코루틴은 비동기 작업을 간편하게 처리하기 위해 설계된 반면, 버추얼 스레드는 높은 동시성을 요구하는 환경에서 효율적으로 스레드를 관리하기 위한 방법

  • 코루틴: 비동기 작업을 중단하고 재개할 수 있는 경량 구성 요소로, 비동기 작업 처리가 주 용도
  • 버추얼 스레드: 동기적인 프로그래밍 모델을 유지하면서도 높은 동시성을 처리할 수 있는 경량 스레드로, 비동기 코드의 복잡성을 줄임

 

버추얼 스레드 - 자바; 대규모동시성동기

  • 핵심 아이디어: JVM이 직접 관리
    • 전통적인 스레드는 OS 커널에서 관리되지만, 버추얼 스레드는 JVM 내부에서 관리되어 더 적은 자원을 소비
    • 각 작업은 자체적인 스레드처럼 동작하므로 프로그래머가 명시적으로 중단점을 관리할 필요가 없음
    • 버추얼 스레드는 동기적으로 작업을 수행. 전통적인 스레드와 유사한 방식으로 작동하지만, 더 가볍고 효율적
  • 동작 방식:
    • 동기적 코드 작성: 버추얼 스레드는 비동기 작업을 동기적인 코드 스타일로 작성할 수 있게 한다. 이는 비동기 코드의 복잡성을 줄이고, 동기적인 프로그래밍 모델을 유지. (동기 방식도 대규모 동시성 지원 가능! 많은 스레드를 동시에 처리 가능)
    • 차단 호출(예: I/O 작업) 발생 시 자동으로 OS 스레드에서 분리
      • IO 대기 상태에서는 스레드 반환해 대규모 작업 가능
    • 기존 스레드 풀보다 더 많은 수의 동시 작업 가능

장점:

  • 기존 스레드 API와 호환성 높음 (학습 곡선 낮음).
    • synchronized 블록, wait/notify 메서드 등을 그대로 사용 가능
  • 차단 호출도 자동으로 처리하므로 더 간단한 코드 작성 가능.

단점:

  • 자바 19 이상의 JVM에서만 사용 가능.
  • 특정 시나리오에서는 기존 스레드 풀만큼의 효율성 제공 어려움.

전통적인 스레드와의 비교

  • 전통적인 스레드:
    • OS에서 관리되며, 각각의 스레드는 상당한 메모리와 자원을 차지
    • 많은 수의 스레드를 생성하면 성능 문제가 발생할 수
  • 버추얼 스레드:
    • JVM에서 관리되며, 매우 가벼움
    • 대량의 동시 작업을 처리할 때 효율적
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < 10_000; i++) {
        executor.submit(() -> {
            Thread.sleep(1000);
            return "Task completed!";
        });
    }
}

위 코드에서 10,000개의 Virtual Thread를 동기적으로 처리하지만, 비동기를 사용하지 않아도 효율적으로 실행됨

 

정리

 

2024.11.26 - [개발/java] - [병렬처리] Folkjoinpool & executorService

 

대규모 처리를 동시에 하려면 비동기 작업이 필수 아닌가?

 

그럼 비동기는 언제?

IO작업이 많을 때, 대기 시간을 최소화하고 자원을 효율적으로 활용할 수 있을 때

비동기는 주로 대기 시간이 많은 작업에서 활용됩니다. 이 대기 시간은 CPU가 직접 연산하는 시간이 아니라, 외부 시스템에서 응답을 기다리는 시간으로 인해 발생합니다. 비동기를 선택하는 주요 이유는 자원 효율성대규모 처리 능력입니다.

DB, file, API, 네트워크..

대규모 데이터 처리(ETL, 스트리밍)

작업 성격에 따른 선택

 

  • I/O 바운드 작업:
    대기 시간이 많은 작업에서 비동기를 사용하면 자원 활용이 극대화됩니다.
    • :
      • 외부 API 호출
      • 데이터베이스 쿼리
      • 파일 읽기/쓰기
      • 네트워크 요청
    • 추천 방식:
      • 비동기 프로그래밍: CompletableFuture, Kotlin Coroutines, async/await.
      • Reactive Streams: Project Reactor, RxJava.
      • Event-driven frameworks: Node.js.
  • CPU 바운드 작업:
    복잡한 계산, 데이터 변환 등 CPU가 주로 사용되는 작업에서는 동기나 멀티스레드 기반의 병렬 처리가 적합합니다.
    • :
      • 데이터 처리(대규모 연산)
      • 이미지 변환, 암호화
      • 머신 러닝 모델 실행
    • 추천 방식:
      • 동기 처리: 단일 스레드에서 작업.
      • 멀티스레드 기반 병렬 처리: Java ForkJoinPool, Parallel Streams, ExecutorService.

 

 

  • 멀티스레드는 작업을 물리적으로 병렬로 실행하는 방식이고,
  • 비동기는 작업을 논리적으로 대기 시간을 줄이며 논블로킹으로 처리하는 방식입니다.
  • 비동기는 멀티스레드를 사용하지 않을 수도 있지만, 필요하면 내부적으로 멀티스레드를 활용할 수도 있습니다. (예: Java NIO, Kotlin Coroutines).

성능 비교

https://tech.kakaopay.com/post/coroutine_virtual_thread_wayne/

728x90
반응형

+ Recent posts