launch — 본질, fire-and-forget 코루틴 실행 및 작동 방식

저자: IT Sectr 게시일: 2026-06-22 읽는 시간: 7 분

launch — Kotlin의 Coroutine Builder로, 결과를 반환하지 않고 코루틴을 시작하며 실행 제어를 위한 Job 객체를 반환합니다. 이 빌더는 fire-and-forget 패턴을 구현합니다. 코루틴은 백그라운드 스레드에서 작업을 시작하고 자동으로 완료됩니다. JetBrains 문서, 2024에 따르면, launch는 Kotlin Coroutines에서 병렬 작업을 실행하는 기본 방법입니다.

핵심 사항

  • launch — 결과를 반환하지 않고 코루틴을 시작하는 빌더 (fire-and-forget)
  • Job — cancel(), join(), isActive 메서드를 가진 코루틴 제어 객체
  • launch는 CoroutineScope와 통합되어 하위 코루틴의 자동 취소 지원
  • CoroutineStart.LAZY는 명시적인 start() 또는 join() 호출까지 실행을 지연시킴
  • launch는 Android에서 데이터베이스 저장, 네트워크 호출, UI 업데이트에 사용

Kotlin Coroutines에서 launch란?

launch는 kotlinx.coroutines 임포트를 통해 사용할 수 있는 Kotlin 확장 함수로, 지정된 CoroutineScope 내에 새 코루틴을 생성합니다. 일반 함수와 달리 launch 내부의 코드는 동시에 실행됩니다. 코루틴은 스레드를 차단하지 않고 일시 중단(suspend)되었다가 나중에 재개될 수 있습니다.

launch 빌더는 Kotlin 코루틴 모델의 기본 구성 요소입니다. 계산된 값을 반환하지 않지만 코루틴 실행을 제어할 수 있는 Job 객체를 반환합니다. 다른 코루틴 내에서 launch를 통해 시작된 모든 하위 코루틴은 상위 코루틴에 바인딩됩니다.

launch의 구문 및 매개변수

launch 빌더는 CoroutineScope, CoroutineContext, CoroutineStart 및 suspend 블록의 여러 매개변수를 가진 인라인 함수로 정의됩니다. 매개변수에는 기본값이 있어 launch를 일반적인 시나리오에서 편리하게 사용할 수 있습니다.

kotlin
public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job

context 매개변수는 디스패처, 예외 처리기 및 명명된 요소를 결합한 CoroutineContext를 허용합니다. 오류 격리를 위해 Dispatchers.IO, Dispatchers.Main 또는 SupervisorJob이 가장 자주 전달됩니다.

Job 및 생명주기 관리

Job — 코루틴의 생명주기를 나타내는 반환된 객체입니다. Job은 New, Active, Completing, Completed, Cancelling, Cancelled 상태를 가질 수 있습니다. 각 상태는 실행 상태를 반영하며 변경 사항에 대응할 수 있습니다.

kotlin
val job = CoroutineScope(Dispatchers.IO).launch {
    repeat(10) { i ->
        delay(1000L)
        println("진행: $i")
    }
}

println("작업이 활성 상태입니다: ${job.isActive}")
delay(2500L)
job.cancel()
println("작업이 취소되었습니다: ${job.isCancelled}")

Job은 계층 구조를 지원합니다. 상위 코루틴이 취소되면 모든 하위 코루틴이 자동으로 취소됩니다. SupervisorJob은 이 동작을 변경합니다. 하나의 하위 코루틴이 실패해도 다른 하위 코루틴은 취소되지 않습니다.

launch의 구조적 동시성

구조적 동시성은 각 코루틴이 특정 CoroutineScope 내에서 시작되며, 모든 하위 코루틴이 작업을 완료할 때까지 Scope가 완료되지 않음을 의미합니다. launch는 이 원칙을 완전히 지원합니다. 다른 코루틴 내에서 시작된 코루틴은 그 하위 코루틴이 됩니다.

중첩된 launch 호출

중첩된 launch 호출을 사용하면 코루틴 트리가 형성됩니다. 상위 코루틴은 모든 하위 코루틴이 완료될 때까지 대기하여 예측 가능한 실행 순서를 보장하고 리소스 관리를 단순화합니다.

kotlin
fun main() = runBlocking {
    launch {
        launch {
            delay(1000L)
            println("하위 1 완료")
        }
        launch {
            delay(500L)
            println("하위 2 완료")
        }
        println("모든 하위가 이 줄 앞에서 완료됩니다")
    }
}

이 동작은 하위 스레드가 상위 스레드에 바인딩되지 않는 스레드 기반 동시성과 다릅니다. 코루틴에서는 모든 하위 코루틴이 작업을 완료할 때까지 상위 코루틴이 완료되지 않습니다.

launch의 예외 처리

launch의 예외 처리는 Job 유형에 따라 다릅니다. 일반 Job의 경우 예외가 상위 코루틴으로 전파되어 취소됩니다. SupervisorJob 또는 SupervisorScope의 경우 예외가 격리됩니다. 하나의 하위 코루틴 오류가 다른 코루틴에 영향을 미치지 않습니다.

kotlin
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
    try {
        riskyOperation()
    } catch (e: Exception) {
        println("포착됨: ${e.message}")
    }
}
scope.launch {
    println("SupervisorJob 덕분에 계속 실행됩니다")
}

잡히지 않은 예외의 전역 처리를 위해 CoroutineExceptionHandler가 사용됩니다. 코루틴 내에서 처리되지 않은 예외를 포착하여 애플리케이션을 중단시키지 않고 오류를 기록할 수 있습니다.

Android에서 launch 사용 예제

Android에서 launch는 ViewModel부터 WorkManager까지 모든 곳에서 사용됩니다. 주요 패턴은 구성 요소 생명주기가 종료될 때 코루틴을 자동 취소하기 위해 Fragment에서 lifecycleScope를, ViewModel에서 viewModelScope를 사용하는 것입니다.

kotlin
class ProfileViewModel : ViewModel() {
    private val repository = UserRepository()

    fun loadProfile(userId: String) {
        viewModelScope.launch(Dispatchers.IO) {
            val profile = repository.fetchProfile(userId)
            withContext(Dispatchers.Main) {
                _profileState.update { it.copy(profile = profile) }
            }
        }
    }
}

viewModelScope는 ViewModel이 소멸될 때 코루틴을 자동으로 취소합니다. 이는 메모리 누수를 방지하고 컨텍스트 손실 후에도 백그라운드 작업이 계속되지 않도록 보장합니다. 추가로 withContext를 사용하여 디스패처 간 전환할 수 있습니다.

자주 묻는 질문

Kotlin Coroutines에서 launch와 async의 차이점은?

launch는 Job을 반환하고 결과를 반환하지 않는 반면, async는 결과를 얻기 위해 Deferred<T>를 반환합니다. launch는 fire-and-forget 작업에 사용되고, async는 반환된 값을 기다렸다가 사용해야 할 때 사용됩니다.

launch로 시작된 코루틴을 취소하려면?

저장된 Job 객체에서 job.cancel()을 호출하세요. 그룹 취소의 경우 scope.cancel()을 통해 전체 CoroutineScope를 취소하세요. 코루틴은 협력적이어야 합니다. isActive를 확인하거나 취소 가능한 suspend 함수를 사용하세요.

launch가 예외를 던지면 어떻게 하나요?

launch 블록 내에서 try-catch를 사용하거나 CoroutineContext에 CoroutineExceptionHandler를 전달하세요. 오류 격리를 위해 SupervisorJob을 사용하면 하나의 하위 코루틴 예외가 다른 코루틴을 취소하지 않습니다.

CoroutineScope 없이 launch를 사용할 수 있나요?

아니요, launch는 CoroutineScope의 확장 함수입니다. Scope가 없으면 코루틴이 구조적 동시성 원칙을 따를 수 없습니다. GlobalScope.launch는 주의해서 사용하세요. 생명주기에 바인딩되지 않은 코루틴을 생성합니다.

동시에 몇 개의 launch 코루틴을 실행할 수 있나요?

숫자는 디스패처의 스레드 풀에 의해 제한됩니다. Dispatchers.Default는 CPU 코어 수만큼의 스레드를 사용합니다. Dispatchers.IO는 최대 64개의 스레드를 지원합니다. 더 많은 코루틴이 시작되면 대기열에 추가됩니다.

요약

  • launch — fire-and-forget 코루틴의 주요 빌더, Job 객체 반환
  • Job은 제어 메서드 제공: cancel(), join(), isActive, isCancelled, isCompleted
  • 구조적 동시성은 상위 코루틴 취소 시 하위 코루틴 취소 보장
  • 예외 처리는 Job 유형에 따라 다름: 일반은 오류 전파, SupervisorJob은 격리
  • lifecycleScopeviewModelScope — Android에서 코루틴 시작을 위한 즉시 사용 솔루션
  • CoroutineStart.LAZY는 명시적인 start() 또는 join() 호출까지 실행 지연
  • launch는 Android에서 네트워크 요청, 데이터베이스 쓰기, 분석, 캐싱에 사용

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기