728x90
반응형
Kotlin의 강력한 기능 중 하나인 코루틴(Coroutines)에 대해 자세히 알아보도록 하겠습니다. 비동기 프로그래밍을 쉽고 효율적으로 구현할 수 있는 코루틴의 기본 개념부터 실전 활용법까지 살펴보겠습니다.
1. 코루틴이 뭔가요? 🤔
코루틴은 비동기 프로그래밍을 위한 코틀린의 솔루션입니다. 기존의 콜백이나 Future/Promise 패턴의 복잡성을 줄이고, 동시성 프로그래밍을 더욱 직관적으로 작성할 수 있게 해줍니다.
실생활 비유로 이해하기
식당에서 일하는 웨이터를 생각해봅시다. 웨이터가 한 테이블의 주문을 받고 주방에 전달한 후, 음식이 나올 때까지 그 자리에서 기다린다면 어떨까요? 매우 비효율적이겠죠! 실제로는 주문을 전달한 후 다른 테이블의 손님도 응대합니다.
코루틴도 이와 같습니다! 시간이 오래 걸리는 작업(예: 네트워크 요청, 파일 다운로드)을 기다리는 동안 다른 작업을 할 수 있게 해주는 똑똑한 도구입니다.
왜 코루틴을 사용하나요?
- 간단해요: 복잡한 비동기 코드를 쉽게 작성할 수 있어요
- 효율적이에요: 수많은 작업을 동시에 처리할 수 있어요
- 안전해요: 오류 처리가 쉽고 안전해요
2. 코루틴 시작하기 🚀
기본 설정
먼저 코루틴을 사용하기 위한 준비를 해봅시다:
1. 기본 코루틴 설정 👣
// build.gradle.kts
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
}
📝 설명
- kotlinx-coroutines-core: 코루틴의 핵심 라이브러리
- 1.7.3: 안정적인 최신 버전
- 이 의존성 추가로 코루틴의 모든 기능 사용 가능
2. 첫 번째 코루틴 예제 🚀
fun main() = runBlocking {
println("시작")
launch {
delay(1000)
println("코루틴 내부")
}
println("메인 코드 실행 중")
}
📝 상세 설명
- runBlocking: 코루틴 스코프를 생성하고 완료될 때까지 현재 스레드를 블록
- launch: 새로운 코루틴을 시작하는 빌더. 별도의 작업을 비동기적으로 실행
- delay(1000): 1초 동안 현재 코루틴을 일시 중단 (다른 코루틴이 실행될 수 있음)
- 실행 순서: "시작" → "메인 코드 실행 중" → (1초 후) → "코루틴 내부"
3. 스코프(Scope) 📦
스코프는 코루틴의 생명주기를 관리하는 범위입니다.
주요 스코프 종류
- GlobalScope
GlobalScope.launch { // 앱 전체 수명주기와 함께 동작 }
- 앱의 시작부터 종료까지 유지
- 메모리 누수 위험이 있어 사용 주의
- CoroutineScope
val scope = CoroutineScope(Dispatchers.Default) scope.launch { // 특정 목적을 위한 스코프 }
- 명시적인 생명주기 관리
- 필요할 때 취소 가능
- viewModelScope (안드로이드)
class MyViewModel : ViewModel() {
init {
viewModelScope.launch {
// ViewModel의 생명주기와 함께 동작
}
}
}
- ViewModel 인스턴스의 생명주기와 연동
4. 컨텍스트(Context) 🎯
코루틴이 실행되는 환경을 정의합니다.
주요 컨텍스트 요소
- Dispatchers (디스패처) 종류:
withContext(Dispatchers.IO) { // I/O 작업 실행 }
- Dispatchers.Main: UI 작업용
- Dispatchers.IO: 파일/네트워크 작업용
- Dispatchers.Default: 복잡한 연산용
- Job
- 코루틴의 생명주기 관리
- 취소 가능한 작업 단위
kotlin
Copy
val job = launch {
// 작업 내용
}
job.cancel()// 작업 취소
5. 코루틴 빌더 🏗️
코루틴을 시작하는 다양한 방법을 제공합니다.
주요 빌더
- launch
val job = launch { // 결과를 반환하지 않는 코루틴 }
- Fire-and-forget 방식
- Job 객체 반환
- async
val deferred = async { // 결과를 반환하는 코루틴 "결과" } val result = deferred.await()// 결과 받기
- 결과를 반환하는 코루틴
- Deferred<T> 객체 반환
- runBlocking
runBlocking { // 현재 스레드를 블록하는 코루틴 }
- 주로 테스트에서 사용
- 메인 함수에서 사용
6. 실제 사용 예시 💡
네트워크 요청 처리
class UserRepository {
suspend fun fetchUser(userId: String) = withContext(Dispatchers.IO) {
// 네트워크 호출
api.getUser(userId)
}
}
class UserViewModel(private val repository: UserRepository) {
init {
viewModelScope.launch {
try {
val user = repository.fetchUser("123")
// UI 업데이트
} catch (e: Exception) {
// 에러 처리
}
}
}
}
병렬 처리
kotlin
Copy
suspend fun loadData() = coroutineScope {
val data1 = async { fetchData1() }
val data2 = async { fetchData2() }
// 두 데이터 모두 로드될 때까지 대기
val combinedData = combineData(data1.await(), data2.await())
}
7. 코루틴 장점 정리 ✨
- 간단한 비동기 처리
- 동기 코드처럼 작성 가능
- 가독성 향상
- 유지보수 용이
- 효율적인 리소스 사용
- 경량 스레드 사용
- 시스템 리소스 절약
- 많은 동시 작업 가능
- 구조화된 동시성
- 생명주기 관리 용이
- 메모리 누수 방지
- 에러 처리 간편
8. 주의사항 ⚠️
- GlobalScope 사용 주의
- 가능하면 제한된 스코프 사용
- 명시적인 생명주기 관리 필요
- 예외 처리 필수
- 컨텍스트 적절한 사용
- UI 작업은 반드시 Main 디스패처
- 무거운 작업은 IO 또는 Default 디스패처
반응형
'업무 기록 > ETC' 카테고리의 다른 글
스레드 개수 설정 및 성능 최적화와 방법들 (1) | 2025.02.20 |
---|---|
개발자와 비개발자와의 효과적인 협업 가이드: 소통의 벽을 허물다 (2) | 2024.11.22 |
L4 로드벨런싱과 암호화 및 VIP (0) | 2024.06.11 |
[Oracle] PL/SQL정의, 기능, 대량 데이터 추가 (1) | 2024.05.22 |
SSL 인증서 확인 및 Nginx 인증서 변경 Openssl (2) | 2024.04.22 |