Kotlin 문법 - 코루틴 기초 (Coroutine 소개)

느린달팽이·2025년 8월 24일

코틀린 복습

목록 보기
18/25

1️⃣ 코루틴이란 무엇인가? (경량 스레드)

코루틴은 OS 스레드보다 훨씬 가벼운 경량 스레드(Light-weight Thread)입니다.

복잡한 콜백(Callback) 지옥 없이 비동기 코드를 마치 순차적인 코드처럼 작성할 수 있게 해줍니다.


🔹 핵심 키워드: suspend

코루틴의 마법은 suspend 키워드에서 시작됩니다.

suspend 함수는 실행을 잠시 중단(Suspend)했다가, 필요할 때 다시 이어서 실행(Resume)할 수 있는 함수입니다.

이 중단/재개 메커니즘 덕분에, 코루틴은

I/O 작업(네트워크 통신, 파일 읽기 등)처럼 대기 시간이 긴 작업 동안

스레드를 점유하지 않고 효율적으로 자원을 사용할 수 있습니다.


2️⃣ launchJob: 코루틴의 시작과 생명 주기

2.1 launch 함수 — 코루틴을 시작하는 빌더

launch는 새로운 코루틴을 시작하는 가장 기본적인 코루틴 빌더(Coroutine Builder)입니다.

  • 역할: 결과를 반환할 필요가 없는, “실행 후 잊어버리는” 비동기 작업 시작 시 사용
  • 반환값: 실행된 코루틴 자체를 의미하는 Job 객체를 반환
import kotlinx.coroutines.*

fun main() = runBlocking {
    // launch를 사용해 비동기 작업 시작
    val myJob: Job = launch {
        println("작업 시작: 네트워크 통신 중...")
        delay(1000L) // 1초간 suspend
        println("작업 완료: 데이터 수신됨")
    }

    // launch는 Job 객체를 반환하므로, 이를 통해 코루틴 제어 가능
}

2.2 Job 객체 — 코루틴의 생명 주기 제어 핸들

Job은 실행 중인 코루틴의 생명 주기(Lifecycle)를 관리하고 제어하는 역할을 합니다.

메서드역할
cancel()코루틴에게 취소 요청을 보냄
join()해당 Job이 완료될 때까지 현재 코루틴을 일시 중단하고 기다림
isActive코루틴이 현재 활성화(실행 중) 상태인지 확인

또한, 부모-자식 관계가 있어 부모 코루틴이 취소되면 모든 자식 코루틴이 자동으로 취소됩니다.

이를 구조화된 동시성(Structured Concurrency)이라 합니다.

import kotlinx.coroutines.*

fun main() = runBlocking {
    val job = launch {
        try {
            delay(2000L) // 중단 가능한 함수 필요
            println("이 메시지는 출력되지 않을 수 있습니다.")
        } catch (e: CancellationException) {
            println("작업이 취소되었습니다.")
        }
    }

    delay(500L)
    job.cancel() // 0.5초 후 취소 요청
    job.join()   // 취소가 끝날 때까지 대기
    println("메인 루틴 종료")
}

3️⃣ CoroutineScope: 코루틴의 실행 범위와 생명 주기 관리

코루틴은 혼자서 존재할 수 없으며, 반드시 CoroutineScope 내에서 실행되어야 합니다.

Scope는 코루틴이 활동할 수 있는 범위(Scope)를 정의하고, 생명 주기를 관리하는 단위입니다.


3.1 스코프의 역할

  • 책임 범위 정의: 스코프 내에서 시작된 코루틴들은 해당 스코프의 생명 주기를 따름
  • 구조화된 동시성: 스코프가 종료되거나 취소되면 그 안의 모든 자식 코루틴(Job)이 자동으로 취소됨 → 메모리 누수 및 예측 불가능한 동작 방지

3.2 대표적인 스코프

스코프 유형설명주요 사용처
runBlocking현재 스레드를 차단하며 코루틴 실행테스트 코드, main 함수
CoroutineScope()새로운 스코프 생성클래스 내 특정 비동기 작업 관리
coroutineScope자식 스코프 생성, 모든 작업 완료 시까지 suspend병렬 작업 수행 및 완료 대기

3.3 CoroutineScope 사용 예시

launchJob은 항상 Scope 내에서 사용됩니다.

import kotlinx.coroutines.*

// 1. CoroutineScope 생성
val myApplicationScope = CoroutineScope(Dispatchers.Default)

fun startWork() {
    // 2. 스코프 내에서 launch 호출
    val workJob = myApplicationScope.launch {
        println("백그라운드에서 작업 시작")
        delay(3000L)
        println("긴 작업 완료")
    }
}

fun cleanup() {
    // 3. 스코프 취소
    myApplicationScope.cancel()
    println("스코프 취소 완료: 모든 자식 코루틴 종료됨")
}

✅ 결론: 세 가지 핵심 요소 정리

요소역할관계
CoroutineScope코루틴이 실행될 범위와 생명 주기를 정의 (부모)launchJob을 감싸는 컨테이너
launch코루틴을 실행하는 빌더Job 객체를 반환
Job실행된 코루틴의 생명 주기를 제어하는 핸들 (자식)cancel(), join() 등 제공

한 줄 요약

“CoroutineScope는 무대, launch는 배우의 등장, Job은 그 배우의 생명줄이다.”

profile
한걸음이라도 제대로... 쓰임있는 앱을 만들자

0개의 댓글