우당탕탕

[비동기 프로그래밍] 코틀린 Coroutines로 백엔드 비동기 처리 – 입문자도 쉽게 이해하는 가이드 본문

Tech

[비동기 프로그래밍] 코틀린 Coroutines로 백엔드 비동기 처리 – 입문자도 쉽게 이해하는 가이드

모찌모찝 2025. 7. 28. 19:48
코틀린 Coroutines로 실전 백엔드 서비스 비동기 처리 완전정복

안녕하세요!
오늘은 백엔드 개발을 처음 접하는 분들도 쉽게 이해하도록, 코틀린 Coroutines(코루틴)를 활용한 비동기 프로그래밍 방법을 작성해 보겠습니다.
“비동기”, “코루틴” 같은 용어가 어렵게 느껴질 수 있지만, 최대한 쉬운 일상 예시와 실습 예제까지 활용해 한번 작성해 보도록 하겠습니다.

코틀린 코루틴

1. 동기와 비동기란?

예를 들어, 편의점 계산대에 고객이 줄 서서 차례대로 계산한다고 생각해 보겠습니다.
이게 바로 동기 처리 방식입니다. 한 사람의 계산이 끝나야 다음 사람이 계산할 수 있죠.

반면, 계산대가 여러 대 있어서 여러 사람이 동시에 계산할 수 있다면?
이건 바로 비동기 처리라고 할 수 있어요.

서버도 마찬가지입니다. 만약 동기로만 처리하면 요청이 많아질 때 병목 현상이 생기고, 응답이 느려지지만, 비동기를 이용해 여러 작업을 동시에 처리하면 더 빠르고 효율적으로 응답할 수 있습니다.

2. 코틀린 ‘코루틴’이란?

코루틴은 쉽게 말하면, 서버에서 동시에 여러 일을 가볍고 효율적으로 처리할 수 있는 특수한 도구입니다.
기존에는 ‘스레드’라는 방식으로 동시에 일하는 것을 표현했는데, 스레드는 무겁고 관리가 어렵습니다.

코루틴은 “아주 가벼운 스레드”라고 생각하면 됩니다.
수천, 수만 개의 코루틴이 동시에 돌아도 서버에 큰 부담이 없을 정도로 효율적입니다.

3. 예시코드 ( 실습 )

아래 코드는 코루틴으로 동시에 2가지 일을 하고, 그 결과를 한꺼번에 사용자에게 돌려주는 예시 코드입니다.
만약 해당 서비스를 코루틴이 아닌 기본 api호출방식으로 사용했다면 API 응답은 최소 3초이상이 소요되게 됩니다.

@RestController
class SampleAsyncController {
    @GetMapping("/async-wait")
    suspend fun getData(): List<String> = coroutineScope {
        val job1 = async { fetchDataFromServiceA() }
        val job2 = async { fetchDataFromServiceB() }
        listOf(job1.await(), job2.await())
    }

    suspend fun fetchDataFromServiceA(): String {
        delay(1000) // 1초 기다림, 실제로는 외부 API 호출 같은 작업
        return "서비스A 데이터"
    }

    suspend fun fetchDataFromServiceB(): String {
        delay(2000) // 2초 기다림
        return "서비스B 데이터"
    }
}

async { ... }는 새로운 코루틴을 시작해 동시에 작업을 합니다.
await()는 해당 작업이 끝날 때까지 기다려주는 함수로, 두 작업 모두 완료될 때까지 기다리게 됩니다.
이렇게 하면, 두 작업을 순차적으로 할 때보다 훨씬 빠르게 결과를 받을 수 있습니다.

suspend 함수는 ‘잠시 멈출 수 있는 함수’라는 뜻으로, 비동기 작업에 필수적입니다.
delay() 함수는 실제로는 기다리지만, 서버는 그동안 다른 작업도 할 수 있도록 대기합니다.

데이터베이스 접근이나 파일 입출력 같은 무거운 작업은 withContext(Dispatchers.IO) 블록 안에서 실행해야 서버 부하를 줄일 수 있습니다.

suspend fun heavyIoTask() = withContext(Dispatchers.IO) {
    // 파일 읽기, DB 작업 등
}



TIP : 절대로 Thread.sleep()을 코루틴 안에서 사용하면 안 됩니다! Thread.sleep()을 사용하게 되면 이는 서버를 멈추게 만듭니다. 

4. 디버깅

IntelliJ IDEA에는 코루틴 전용 디버깅 기능이 있어 상태 추적이 쉽습니다.
단위 테스트도 runBlocking { ... } 안에 코루틴 코드를 작성하면 동기식처럼 테스트할 수 있어서 진입 장벽이 낮습니다.

코루틴은 현업에서 응답속도를 개선하기 위해 많이 사용하는 방법입니다. 보통 아래와 같은 상황에서 많이 사용하니 사용해 보시는 것을 추천드립니다. 

1. 여러 외부 API를 한눈에 동시에 호출할 때
2. 사용자에게 대량 이메일이나 알림을 빠르게 발송할 때
3. 서버가 많은 요청을 효율적으로 처리해 사용자 경험을 향상할 때
이런 상황에서 코루틴은 큰 힘을 발휘합니다!  

코루틴은 처음 접할 땐 낯설지만, “멀티태스킹을 컴퓨터가 아주 가볍게 하는 방법”이라 생각하고, 위 예제를 직접 따라 해 보면 금세 익숙해질 수 있을 것 같습니다.
추후엔 이 코루틴을 활용해 더 복잡한 비동기 서비스, 예를 들어 대용량 데이터 처리나 무중단 배포에도 적용할 수 있으며, 이와 관련된 주제로 글을 한번 더 작성해 보도록 하겠습니다. 

Reference

스프링 코루틴 가이드 : https://docs.spring.io/spring-framework/reference/
코루틴 공식가이드 : https://kotlinlang.org/docs/coroutines-overview.html

Comments