본문 바로가기
Language/Java & Kotlin

[kotlin] 코루틴(Coroutine) 개념과 MVC

by lucas_owner 2025. 7. 12.

 

kotlin 코루틴(Coroutine) 개념과 MVC

코틀린이 자바를 대체가능하게 되면서 점점 많은 플랫폼들에서 자바에서 코틀린으로 마이그레이션을 완료했거나 진행하고 있는것 같다.

아니면 `코루틴` 이라는 효율적인 라이브러리를 사용하기위해 넘어오는 경우도 존재하는것 같다. 

그럼 코루틴이 뭔지, 기존의 MVC 프로젝트 에서 효율적으로 사용할 수 있는것인지 설명해보도록 하겠다.

 

 

 

코루틴(Coroutine)이란?

우선 코루틴이란 코틀린이라는 언어에 종속적이지 않다. C#, Python, JavaScript 와 같은 언어에서도 지원하고 있다.

코루틴은 Co(함께) + routine(작업의 순서, 규칙적인 일의 순서) 2개의 단어가 합쳐진 단어이다.

 

실행의 지연과 재개가 가능하며, 비선점적 멀티태스킹을 위한 서브루틴을 일반화한 프로그래밍.

이게 무슨 말인지 살펴보자면 다음과 같다. 

 

비선점적: 프로세스가 CPU를 할당 받으면, 종료전까지 다른 프로세스가 CPU 를 강제로 차지할 수 없다. (OS가 통제할 수 없다)

 

실행의 지연과 재개: 일반적으로 병렬작업시 작업시간이 오래걸린다거나 중단되는 상황이 발생하면, 해당 Thread 는 다른 작업을 수행하지 못하고 대기(pending) 상태로 대기하게 된다. 대기상태 동안 다른 작업을 수행할 수 없어 효율적이지 않다.

코루틴은, 코드의 특정 지점(suspend) 에서 중단되면 해당 코루틴은 다른작업을 수행하고, 중단된 지점부터 작업을 이어서 진행한다.

 

즉, 매우 효율적으로 Thread 를 사용하여 프로그램의 효율을 높인다고 할 수 있다.

이런 특징과 더불어 자원의 사용또한 매우 가볍다. 

일반적으로 병렬처리에 사용되는 Thread 와 비교해보도록 하겠다.

 

  • Thread
    • OS 레벨 관리
    • 수 MB ~ 수백 MB 메모리를 사용(무거움)
    • 블로킹시 Thread 점유(다른작업 불가능)
  • Coroutine(코루틴)
    • JVM 레벨 관리
    • 수 kb 메모리 사용(매우 가벼움)
    • 수천 ~ 수만개 이상의 코루틴 생성 & 실행 가능
      • 10,000개 코루틴은 대략 Thread 4~8개 정도만 사용함.
    • 블로킹시 다른 작업 가능

Thread 는 생성에만 MB 단위로 비용이 매우 비싼 작업이지만, 코루틴은 개당 kb 단위의 매우 경량화 되어있다.

Thread 의 생성비용에 대한 오버헤드를 줄였다고 볼 수 있다.

 

또한 Context Switch 에 대한 오버헤드가 적은데 User 레벨에서 동작하기 때문이기 때문이다.

JVM 내부에서 직접 컨텍스트 전환이 발생하고 GC 의 대상이 되는 객체일뿐이기 때문에 부담이 적은것이다. 

Thread 처럼 동작하지만 내부는 전혀 다르게 구현된 전혀 다른 개념인것이다.

 

 

 

코루틴의 동작원리

이런 설명만 보면, 코루틴은 일반적인 Thread 를 사용하는것처럼 생각될 수 있다. (여러개의 객체가 동시에 작업)

왜냐면 여러 작업을 동시에 수행하는것 처럼 보이기 때문이다. 

 

하지만 내부를 본다면 조금 다른 개념이다. 

실제로는, 스레드 내에서 작업들을 번갈아가며 실행되고 있기 때문이다. 

이제 여기서 병행성(Concurrency)과 병렬성(Parallelism)에 대해서 개념을 알아야한다.

 

  • 병행성(Concurrency)
    • 여러 작업이 동시에 진행되는것 처럼 보이지만, 실제로는 하나의 스레드에서 순차적으로 진행됨
    • 예: 싱글 스레드에서 여러 작업이 번갈아 가며 실행되는 경우.
  • 병렬성(Parallelism)
    • 여러 작업을 `동시에` 수행하는것.
    • 예: 멀티코어 CPU에서 여러 스레드가 동시에 실행되는 경우.

즉 병렬성은 작업이 동시에 실행되는것이고, 병행성은 작업을 빠르게 번갈아가며 수행하며 동시에 수행되는것 처럼 보이는것이다.

 

하지만 코루틴은 병행성과 병렬성 동작을 모두 지원한다. 

(코루틴의 Scope 내부에서 (async, launch) 키워드로 사용가능하다.)

 

병행성, 병렬성

 

 

그럼 코루틴은 무조건 1개의 Thread 에서만 수행되는것인가? 

 

이런 의문이 생길 수 있다. 결론부터 말하자면 아니다.

기본적으로 병행성을 이용하여 동작하지만, 병렬적인 작업 처리 또한 가능하다. 

 

하나의 함수에서 여러개의 코루틴이 동작한다고 예를 들어보겠다. 

테스트 코드

 

코루틴 Scope 에서 3개의 코루틴을 생성하여, 시작과 종료시 출력하는 간단한 코드이다. 이 코드에서 Thread 의 결과가 어떨것 같은지 생각해보자...

 

 

테스트 출력

위에서 보이는것처럼 각 코루틴은 다른 스레드(worker)에서 실행되며, 종료는 동일한 Thread 에서 출력된것을 볼 수 있다. 

 

즉 코루틴은 실행시점에 다른 Thread 에서 실행될수 있고,  수행완료 시점에 다른 Thread 에서 종료될 수 있다.

위의 결과로 1개의 Thread 에서만 수행되지 않는다는것을 알 수 있다. 

 

 

Dispatcher(디스패처) ?

다른 코루틴의 예제들을 보면 보이는 단어, Dispathcer 에 대해서 알게 된다면 어떻게 이런 결과가 나오는지 알 수 있다.

 

디스패처는 코루틴이 실행되는 Thread, Thread Pool 를 결정, 지정하는 역할을 한다.

코루틴의 실행작업(파일 I/O, 네트워크, 연산 작업) 에 따라 효율적으로 분배하게 되어 작업에 성격에 따라 효율적으로 자원을 사용하도록 한다.

 

크게 4가지의 기본 디스패처가 존재하고, 작업의 성격에따라 지정할 수 있다.

  • `Dispatchers.Default`: CPU 코어 수에 따라 자동으로 Thread 수 조정 (일반적으로 Core * 2)
  • `Dispatchers.IO`: I/O 작업에 최적화된 Thread Pool (네트워크, 파일 I/O 등)
  • `Dispatchers.Unconfined`: 현재 스레드에서 실행, suspend 되면 다른 스레드에서 재개
  • `Dispatchers.Main`: UI 스레드에서 실행(안드로이드, JavaFX 등)

기본적으로 아무것도 지정하지 않는다면, Default 로 실행이 되고, 외부 API 호출이나 I/O 병렬 작업처리가 필요할때는 I/O(async) 를 사용하는등 작업의 성격에 맞게 사용할 수 있다. 

 

 

 

MVC 에서 코루틴?

지금까지 봤던 코루틴의 기본 개념들을 생각하며, MVC 에 적용하는게 좋을지 생각해보자. 

검색을 해보면 수많은 칼럼들과 의견들이 존재하는데, 필자또한 대부분의 칼럼과 비슷한 생각을 갖고있다. 

대부분, 코루틴의 최대효율을 뽑아내지 못하고 제약이 많다 라는 의견이 많다.

 

 

우선 MVC 의 특성에 대해서 생각해보자 MVC 는 thread-per-request 구조로 동작한다.

즉 1개의 요청은 1개의 Thread 에서 처리되며, 응답시까지 Block 되는 특징을 가지고 있다. 

 

 

Tomcat 을 예로든다면 201번째 요청부터는 pending(대기) 상태가 되는것은 똑같다.

즉 요청이 들어오는 Controller 에 suspend 키워드를 사용한다고 해서, 서블릿 컨테이너 스레드는 결국 블로킹 상대로 대기하게 되는것이다.

 

일반적인 Layer 구조일때 service 로직 내부가 병렬 또는 병행으로 처리된다고 해도 전체적인 구조는 non-blocking 이 아닌것이다.

가장많이 사용할 수 있는 경우인 DB Call 을 생각해보면

`DB Driver` + `Connection Pool` 이 비동기를 지원해야지만 의미가 있다. (다만. Dispatcher.IO 를 사용하여 멀티쓰레드로 돌릴수 있음)

 

외부 API 호출을 WebClient 로 non-blocking 호출을 하게된다면, 의미가 좀 있을수도 있을것 같다, 다만? 외부 API 호출이 엄청 무겁지 않은 작업일 경우에 Reactor 의존성을 추가해서 억지로 굳이 사용을 해야하나,,, 라는 생각도 든다(개인적인 생각)

 

이러한 단점들과 코루틴의 장점을 극대화 할 수 없는 환경이기에 MVC 에서 비동기,병행 작업을 해야하는 경우라면 

기존처럼 CompletableFuture 혹은 JDK21 에서 사용 가능한 Virtual Thread 사용을 고려해보는게 더 좋을것 같다고 고려된다.

 

즉 코루틴의 최대의 장점을 활용해야 하는 모듈이라면, 애초에 MVC 가 아닌 WebFlux(Reactor) 로 도입하여 non-blocking 방식의 최대 효율을 뽑아먹는것이 좋아보인다. 

 

그래도 MVC 에서 사용을 해봐야겠다 라는 생각이 든다면, Service 내부의 로직, 로깅, 연산 과 같은

내부 병렬처리의 보조 수단으로만 사용해보는것을 추천한다. 

https://www.inflearn.com/community/questions/1289556/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C%EC%9D%98-%EC%BD%94%EB%A3%A8%ED%8B%B4?srsltid=AfmBOorfxejEbwrHjNp1eOtpxDkrSzhp6CTYPdzzuxBWRL1VVMskQvJE

 

스프링 MVC 환경에서의 코루틴 - 인프런 | 커뮤니티 질문&답변

누구나 함께하는 인프런 커뮤니티. 모르면 묻고, 해답을 찾아보세요.

www.inflearn.com

 

해당 글 뿐아니라 다른 글에서도 MVC 에서 코루틴을 도입하는것에 대한 많은 의견들이 존재한다, 궁금하다면 읽어보는것도 좋을것 같다.

반응형

댓글