본문 바로가기

Kotlin

[Kotlin] Coroutine (1) - 코루틴이란?

 

안녕하세요.

오늘은 코루틴에 대해 알아보도록 하겠습니다.


개념

비동기 프로그래밍을 위한 일종의 서브루틴 또는 경량 스레드 입니다.

코드의 일부를 일시 중단하고 나중에 이어서 실행할 수 있는 프로그래밍 요소 입니다.

 

비동기 프로그래밍은 작업이 완료될 때 까지 기다리지 않고, 다른 작업을 실행하는 프로그래밍 기법입니다.

 

하지만 서브 루틴과 경량 스레드는 익숙치 않은 개념입니다.

 

루틴

  1. 메인 루틴
    • 프로그램의 시작 지점이자 주 실행 흐름을 담당하는 부분입니다.
    • 메인 루틴은 다른 서브 루틴이나 함수를 호출하고, 프로그램의 주요 로직을 수행합니다.
  2. 서브 루틴
    • 메인 루틴에서 호출되어 특정 기능을 수행하는 코드 블록입니다.
    • 함수, 메소드, 프로시저 등으로 불리기도 합니다.
    • 서브 루틴이 실행을 완료하면 호출한 곳으로 돌아가 메인 루틴이나 다른 서브 루틴이 이어서 실행됩니다.
  3. 코루틴
    • 실행을 일시 중단하고 다시 시작할 수 있는 루틴입니다.
    • 루틴을 진행하는 중간에 멈추어서 특정 위치로 돌아갔다가 다시 원래 위치로 돌아와 나머지 루틴을 수행할 수 있습니다.

 

경량 스레드

코루틴은 일반 스레드보다 더 가볍고 효율적으로 생성, 관리됩니다.

  • 사용자 수준에서 구현되므로 운영체제의 지원 없이도 스레드를 생성하고 관리할 수 있습니다.
  • 더 적은 자원을 소비하므로 오버헤드가 낮습니다.

 

스레드와 코루틴은 둘 다 동시성을 지원합니다.

  • 동시성은 다수의 task들을 시분할을 통해 조금씩 나누어서 실행하는 것입니다.

https://velog.io/@haero_kim/Thread-vs-Coroutine-%EB%B9%84%EA%B5%90%ED%95%B4%EB%B3%B4%EA%B8%B0

 

task가 change 되는 과정에서 context switch가 일어납니다.

  • 스레드에서의 context switch
  • 사용하는 자원이 많다보니 register에 저장하고 복구하는 비용 역시 적지 않습니다.

https://help.hcltechsw.com/onedb/1.0.1/admin/ids_admin_0273.html

  • 코루틴에서의 context switch
  • 하나의 스레드 내에서 특정 작업을 suspend 시켜 다른 작업을 수행할 수 있습니다.
    • 스레드보다 사용하는 자원이 적다보니 context swtich 비용이 줄어듭니다.

https://abhinaygupta1998.medium.com/how-coroutines-does-context-switching-d0742af54c46

 

요약

위의 내용을 요약하면 다음과 같습니다.

  • 비동기 작업을 쉽게 처리하기 위한 루틴입니다. (Co + Routine)
  • 기존의 스레드보다 더 가볍고 효율적으로 처리할 수 있습니다.

 

+) 코틀린과 이름이 비슷해서 코틀린 자체 기능일 줄 알았는데, 여러 언어에서 지원하고 있는 개념입니다.


장점

낮은 비용

단일 스레드에서 많은 코루틴을 실행할 수 있습니다.

스레드보다 훨씬 적은 비용이 듭니다.

 

메모리 누수 감소

Structed Concurrency를 사용하여 범위 내에서 작업을 실행할 수 있습니다.

 

Jetpack 통합

Jetpack Library에 코루틴을 지원합니다. (Flow, Retrofit 등에 같이 사용됨)

특정 라이프 사이클에 맞춘 코루틴 범위도 제공합니다. (viewModelScope 등)


코드 비교 (with Java)

아래 코드는 자바로 작성한 비동기 프로그래밍 예제입니다.

스레드풀을 생성해서 2개의 스레드를 사용하는 모습입니다.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

class AsyncExample {

    public static void main(String[] args) {
        // 스레드 풀 생성
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        // 첫 번째 작업을 비동기적으로 실행
        Future<Integer> future1 = executorService.submit(() -> {
            System.out.println("Task 1 is running on thread: " + Thread.currentThread().getName());
            Thread.sleep(2000); // 가상의 작업 수행
            return 1;
        });

        // 두 번째 작업을 비동기적으로 실행
        Future<Integer> future2 = executorService.submit(() -> {
            System.out.println("Task 2 is running on thread: " + Thread.currentThread().getName());
            Thread.sleep(1000); // 가상의 작업 수행
            return 2;
        });

        // 메인 스레드는 계속 다른 작업을 수행할 수 있음

        try {
            // 각 작업의 결과를 얻음 (blocking)
            int result1 = future1.get();
            int result2 = future2.get();

            // 결과 출력
            System.out.println("Result of Task 1: " + result1);
            System.out.println("Result of Task 2: " + result2);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 스레드 풀 종료
            executorService.shutdown();
        }
    }
}

 

그리고 아래는 코틀린으로 작성한 비동기 프로그래밍 예제입니다.

코루틴을 사용했습니다.

import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

suspend fun task1(): Int {
    println("Task 1 is running on thread: ${Thread.currentThread().name}")
    delay(2000) // 가상의 작업 수행
    return 1
}

suspend fun task2(): Int {
    println("Task 2 is running on thread: ${Thread.currentThread().name}")
    delay(1000) // 가상의 작업 수행
    return 2
}

fun main() = runBlocking {
    // 비동기로 각 작업 실행
    val deferred1 = async { task1() }
    val deferred2 = async { task2() }

    // 메인 스레드는 계속 다른 작업을 수행할 수 있음

    // 각 작업의 결과를 얻음 (비동기로 대기)
    val result1 = deferred1.await()
    val result2 = deferred2.await()

    // 결과 출력
    println("Result of Task 1: $result1")
    println("Result of Task 2: $result2")
}

 

thread를 별도로 만들 필요없이, suspend 키워드를 함수 앞에 붙여서 사용해주면 끝입니다.

훨씬 간단해지고 읽기도 편해졌습니다.

 

코틀린에서 코루틴을 사용하는 문법에 대해서는 다음 포스팅에서 다루도록 하겠습니다.

감사합니다.


Reference

코틀린 코루틴(coroutine) 개념 익히기 · 쾌락코딩

 

코틀린 코루틴(coroutine) 개념 익히기 · 쾌락코딩

코틀린 코루틴(coroutine) 개념 익히기 25 Aug 2019 | coroutine study 앞서 코루틴을 이해하기 위한 두 번의 발악이 있었지만, 이번에는 더 원론적인 코루틴에 대해서 알아보려 한다. 코루틴의 개념이 정확

wooooooak.github.io

코루틴(Coroutine)에 대하여

 

코루틴(Coroutine)에 대하여

안녕하세요. Checkout Engineering 팀 안세희입니다. 코루틴에 대해 많이 들어 봤지만 원론적인 의미에서 코루틴을 이해하기는 어렵다고 생각합니다. 언어 수준에서 다양한 라이브러리가 코루틴을 사

dev.gmarket.com

코틀린 코루틴(Coroutine) 기초

 

코틀린 코루틴(Coroutine) 기초

코루틴이란?

medium.com

코루틴(coroutine)에 대하여. 1편. 코루틴을 왜 쓸까?

 

코루틴(coroutine)에 대하여. 1편. 코루틴을 왜 쓸까?

코루틴(Coroutine)? 실행의 지연과 재개를 허용함으로써, 비선점적 멀티태스킹을 위한 서브 루틴을 일반화한 컴퓨터 프로그램 구성요소. 이제 진하게 칠한 단어를 하나씩 공부해보자! 1. 루틴과 서

eocoding.tistory.com

 

'Kotlin' 카테고리의 다른 글

[Kotlin] Sealed Class  (3) 2024.09.22
[Kotlin] Extension Function (확장 함수)  (0) 2024.09.10
[Kotlin] Null Safety  (0) 2024.07.29
[Kotlin] Coroutine (3) - 예외 처리  (1) 2023.12.01
[Kotlin] Coroutine (2) - Use in Kotlin  (0) 2023.11.30