1. 빈칸 채우기 문제
1. 코루틴은 Kotlin에서 제공하는 경량 ________ 모델이다.
2. 코루틴의 핵심 3요소는 suspend fun, CoroutineScope, 그리고 ________ 이다.
3. suspend는 함수가 “항상 비동기”라는 뜻이 아니라, ________/재개 가능하다는 뜻이다.
4. 결과가 없는 비동기 작업을 시작할 때 주로 사용하는 빌더는 ________ 이다.
5. 결과가 있는 비동기 작업을 시작하고 await()로 받는 빌더는 ________ 이다.
6. 블로킹 I/O 작업은 보통 withContext(________)로 분리한다.
7. 자식 코루틴이 모두 끝날 때까지 기다리는 안전한 범위를 만드는 함수는 ________ 이다.
8. 자식 하나가 실패해도 다른 자식을 계속 수행하게 하는 범위는 ________ 이다.
9. 지정 시간 안에 끝나지 않으면 취소시키는 API는 with________ 이다.
10. 구조화된 동시성에서 부모가 취소되면 ________ 코루틴도 함께 취소된다.
11. 구조화되지 않은 비동기 작업이 요청 종료 후 떠도는 문제를 ________ task라고 부른다.
12. Kotlin은 예외 전파 중심, Go는 ________ 반환값 체크 중심의 에러 처리 스타일을 가진다.
13. Go의 context.WithTimeout에 대응되는 Kotlin 측 대표 패턴은 ________(ms) 이다.
14. 결제 시스템에서 재시도만 넣고 ________ 키를 빼면 중복 승인 위험이 커진다.
15. 코루틴 사용 시 가장 중요한 원칙 중 하나는 “모든 코루틴은 ________이 있어야 한다”이다.
정답
- 동시성
- Dispatcher
- 중단
- launch
- async
- Dispatchers.IO
- coroutineScope
- supervisorScope
- Timeout (withTimeout)
- 자식
- orphan
- error
- withTimeout
- 멱등성(idempotency)
- 소속(scope)
2. 핵심 개념( suspend, launch/async, withContext, coroutineScope, withTimeout)에 익숙해지도록 짧은 코드 채우기 문제 5개 + 정답 샘플
문제 1) suspend + 순차 실행
아래 코드를 완성해서 A 시작 -> A 끝 -> B 시작 -> B 끝 순서로 출력되게 하세요.
import kotlinx.coroutines.*
suspend fun stepA() {
println("A 시작")
________(100)
println("A 끝")
}
suspend fun stepB() {
println("B 시작")
________(100)
println("B 끝")
}
fun main() = runBlocking {
________()
________()
}
[정답 샘플]
import kotlinx.coroutines.*
suspend fun stepA() {
println("A 시작")
delay(100) // 코루틴을 중단하고 나중에 재개
println("A 끝")
}
suspend fun stepB() {
println("B 시작")
delay(100)
println("B 끝")
}
fun main() = runBlocking {
stepA() // 순차 호출
stepB() // 순차 호출
}
문제 2) async/await 병렬 실행
두 작업을 병렬로 실행해 총 소요시간을 줄이세요.
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
suspend fun callRisk(): String {
delay(200)
return "RISK_OK"
}
suspend fun callPg(): String {
delay(200)
return "PG_OK"
}
fun main() = runBlocking {
val elapsed = measureTimeMillis {
val r1 = ________ { callRisk() }
val r2 = ________ { callPg() }
println("${r1.______()} + ${r2.______()}")
}
println("elapsed=${elapsed}ms")
}
[정답 샘플]
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
suspend fun callRisk(): String {
delay(200)
return "RISK_OK"
}
suspend fun callPg(): String {
delay(200)
return "PG_OK"
}
fun main() = runBlocking {
val elapsed = measureTimeMillis {
val r1 = async { callRisk() } // 결과가 필요한 비동기 작업
val r2 = async { callPg() }
println("${r1.await()} + ${r2.await()}") // 결과 수집
}
println("elapsed=${elapsed}ms") // 보통 200ms대
}
문제 3) withContext(Dispatchers.IO) 분리
블로킹 I/O 성격의 함수를 IO 디스패처에서 실행하세요.
import kotlinx.coroutines.*
fun blockingDbRead(): String {
Thread.sleep(100) // 블로킹 호출 가정
return "order-123"
}
suspend fun findOrder(): String {
return ________(________) {
blockingDbRead()
}
}
fun main() = runBlocking {
println(findOrder())
}
[정답 샘플]
import kotlinx.coroutines.*
fun blockingDbRead(): String {
Thread.sleep(100) // 블로킹 I/O 흉내
return "order-123"
}
suspend fun findOrder(): String {
return withContext(Dispatchers.IO) {
// 블로킹 작업은 IO 풀에서 처리
blockingDbRead()
}
}
fun main() = runBlocking {
println(findOrder())
}
문제 4) coroutineScope 구조화된 동시성
두 API를 병렬 호출하고 둘 다 성공해야 결과를 반환하게 하세요.
import kotlinx.coroutines.*
suspend fun riskCheck(): Boolean { delay(100); return true }
suspend fun limitCheck(): Boolean { delay(100); return true }
suspend fun validatePayment(): Boolean = ________ {
val risk = ________ { riskCheck() }
val limit = ________ { limitCheck() }
risk.________() && limit.________()
}
fun main() = runBlocking {
println(validatePayment())
}
[정답 샘플]
import kotlinx.coroutines.*
suspend fun riskCheck(): Boolean { delay(100); return true }
suspend fun limitCheck(): Boolean { delay(100); return true }
suspend fun validatePayment(): Boolean = coroutineScope {
// 부모 scope 안에서 자식 코루틴을 구조적으로 관리
val risk = async { riskCheck() }
val limit = async { limitCheck() }
risk.await() && limit.await()
}
fun main() = runBlocking {
println(validatePayment())
}
문제 5) withTimeout 타임아웃 처리
외부 호출이 늦으면 타임아웃으로 실패하게 코드를 완성하세요.
import kotlinx.coroutines.*
suspend fun callSlowPg(): String {
delay(1500)
return "APPROVED"
}
fun main() = runBlocking {
try {
val result = ________(1000) {
callSlowPg()
}
println(result)
} catch (e: ________) {
println("타임아웃 발생")
}
}
[정답 샘플]
import kotlinx.coroutines.*
suspend fun callSlowPg(): String {
delay(1500)
return "APPROVED"
}
fun main() = runBlocking {
try {
val result = withTimeout(1000) {
// 1초 안에 끝나지 않으면 취소
callSlowPg()
}
println(result)
} catch (e: TimeoutCancellationException) {
println("타임아웃 발생")
}
}
3. 결제 도메인 미니 프로젝트형(주문검증→리스크→승인)으로 합쳐서 한 파일에서 연습하기
// 파일명 예시: PaymentMiniPractice.kt
import kotlinx.coroutines.*
import kotlin.random.Random
data class Order(
val orderId: String,
val userId: String,
val amount: Long
)
data class RiskResult(
val isSafe: Boolean,
val score: Int
)
enum class PaymentStatus {
APPROVED, REJECTED
}
/** =========================
* 1) 연습용 (TODO 채우기)
* ========================= */
suspend fun validateOrder(order: Order): Boolean {
// TODO 1: amount가 0보다 크고, orderId/userId가 비어있지 않은지 검사
return TODO("주문 검증 로직")
}
suspend fun runRiskCheck(order: Order): RiskResult = withContext(Dispatchers.IO) {
delay(120) // 외부 리스크 API 가정
val score = Random.nextInt(0, 100)
RiskResult(isSafe = score < 70, score = score)
}
suspend fun callPgApprove(order: Order): Boolean = withContext(Dispatchers.IO) {
delay(180) // PG 승인 API 가정
true
}
suspend fun approvePayment(order: Order): PaymentStatus = withTimeout(1000) {
// TODO 2: coroutineScope로 감싸기
// TODO 3: async로 runRiskCheck / callPgApprove 병렬 실행
// TODO 4: await 결과를 이용해 최종 승인/거절 결정
TODO("승인 로직")
}
fun main() = runBlocking {
val order = Order(orderId = "ORD-1001", userId = "USER-7", amount = 15000)
try {
val status = approvePayment(order)
println("결제 결과: $status")
} catch (e: TimeoutCancellationException) {
println("결제 결과: TIMEOUT")
}
}
정답
/** =========================
* 2) 정답
* ========================= */
// 아래 정답은 연습 후 확인하세요.
/*
suspend fun validateOrder(order: Order): Boolean {
// 주문 기본 유효성 검증
return order.amount > 0 &&
order.orderId.isNotBlank() &&
order.userId.isNotBlank()
}
suspend fun approvePayment(order: Order): PaymentStatus = withTimeout(1000) {
if (!validateOrder(order)) return@withTimeout PaymentStatus.REJECTED
coroutineScope {
// 리스크 검사와 PG 호출을 병렬로 수행
val riskDeferred = async { runRiskCheck(order) }
val pgDeferred = async { callPgApprove(order) }
val risk = riskDeferred.await()
val pgOk = pgDeferred.await()
if (risk.isSafe && pgOk) PaymentStatus.APPROVED
else PaymentStatus.REJECTED
}
}
*/'Language > Kotlin' 카테고리의 다른 글
| [Kotlin] Sealed Class와 Result 패턴 복습과제 (0) | 2026.06.01 |
|---|---|
| [복습] 1~3강까지 미션 (0) | 2026.05.27 |
| [Kotlin] Coroutine 기초 (0) | 2026.05.20 |
| [Kotlin] Collection API & 함수형 프로그래밍 (0) | 2026.05.20 |
| [Kotlin] Scope Function 완전 정리 (0) | 2026.05.20 |