본문 바로가기
오늘은 뭘 배울까?/Android

코루틴은 왜 빠른 걸까요?

by Kim Juhwan 2022. 8. 27.

 

1. 요약
2. Thread
   2-1. 스레드를 사용하는 이유
   2-2. 스레드의 문제점

3. Coroutine
   3-1. 코루틴의 동작 방식
   3-2. 코루틴과 스레드의 비교

 

 

 


 

 

1. 요약

🧑‍💻: 코루틴이 빠르다, 가볍다라고들 하는데 그 이유가 무엇일까요?

 

👨🏻‍🦱: 코루틴은 동시성 프로그래밍이며
작업마다 스레드를 생성해서 사용하는 것이 아니라
스레드 안에서 루틴을 만들고 교환하여 자원 낭비가 덜 하기 때문입니다.

 

2. Thread

2-1. 스레드를 사용하는 이유

코루틴이 빠른 이유를 알아보기 전에

우선 코루틴을 사용하지 않고 스레드를 사용하는 상황을 알아보자.

 

안드로이드에는 메인 스레드라는 놈이 있다.

(만약 스레드가 무엇인지 잘 모른다면 일꾼 정도로 생각하면 된다. 어떠한 작업을 하는 일꾼)

메인 스레드는 UI와 관련된 작업을 맡아서 하기 때문에 UI 스레드라고도 불린다.

 

이 메인 스레드는 사용자에게 보여줄 버튼이나 텍스트 등 화면을 그리기도 하고

사용자의 터치 입력을 받아 처리하기도 한다.

 

근데 화면 그리기와 터치하기 사이에 네트워크 작업이 들어갔다고 치자.

음.. 어디 서버에서 대용량의 파일을 받는 작업이라고 하자.

아주 시간이 오래 걸리는 작업이 될 것이다. 🤔

 

 

그렇게 되면 문제가 무엇이냐!

네트워크 작업이 끝날 때까지 사용자가 터치 입력을 하든 뭘 하든

스마트폰은 아무런 응답 없이 네트워크 작업만 주구장창 하게 된다.

 

 

끄헝... 내 핸드폰 망가졌나봐 ㅠㅠ

 

아무런 응답이 없는 스마트폰을 보고 사용자는

"아 내 핸드폰이 망가졌구나!"라고 생각할지도 모른다.

TMI로 이 현상을 ANR(Application Not Responding)이라고 한다. 

 

그래서 사용하는 방법이 바로 별도의 스레드를 만들어 사용하는 것이다.

시간이 오래 걸리는 작업을 다른 스레드에게 맡겨버리면 문제는 해결된다.

 

2-2. 스레드의 문제점

 

하지만 여전히 문제는 존재한다.

작업 1을 실행하는 도중에 작업 2의 결과가 필요하다고 해보자.

위 그림의 순서대로 실행이 될 것이다.

 

 

그러면 문제가 무엇이냐!

작업2의 결과가 리턴될 때까지 Thread1이 아무것도 안 하고 빈둥빈둥 놀게 된다.

이런 낭비가 있나!!!

(참고로 이런 걸 blocking이라고 부른다)

 

회사 동료한테 시간 오래 걸리는 작업 부탁해놓고

지는 아무것도 안 하고 빈둥거리고 있으면 양아ㅊ.. 아니겠는가.

애초에 일 처리도 늦어지고 말이다.

그래서 나온 방법이 코루틴이다.

 

3. Coroutine

3-1. 코루틴의 동작 방식

코루틴은 스레드 안에서 더 잘게 나눠지는 작업 단위이다.

그림을 보면 작업 2의 실행 결과를 기다리는 동안 작업 1은 잠시 중단되지만

작업 3이 그동안 실행되는 것을 볼 수 있다.

 

 

[목차 2-2]와 달리 Thread1이 결과를 기다리는 동안 마냥 노는 것이 아니라 작업 3을 실행하고 있다.

그러면 이런 궁금증이 들 수도 있다.

만약 작업 1이 재개되기 전까지 작업 3이 안 끝나면 어떡하지??

 

 

여기서 코루틴의 특성이 나온다.

코루틴은 특정 스레드에 종속적이지 않다.

즉, 그때그때마다 상황에 맞는 적절한 스레드에서 실행이 된다는 것이다.

위 그림에서는 Thread 2가 작업 2를 끝내고 쉬고 있으니 Thread 2에서 작업 3이 마저 실행될 수도 있다는 것이다.

 

출처: https://gist.github.com/chaxiu/d87870528bbfe3e9d7e481e1f6acace1

 

움짤로 보자면 위와 같다.

코루틴이 Thread 1과 Thread 2를 왔다 갔다 하며 실행되는 것을 볼 수 있다.

 

즉, 이렇게 코루틴은 스레드가 blocking 되어 낭비되는 일이 없도록

루틴을 교환해가며 실행하기 때문에 빠르다, 가볍다, 경량 스레드이다라고 부르는 것이다.

 

3-2. 코루틴과 스레드의 비교

fun main() = runBlocking {
    repeat(100_000) { // launch a lot of coroutines
        launch {
            delay(5000L)
            print(".")
        }
 
        /*thread {
            Thread.sleep(1000L)
            print(".")
        }*/
    }
}

코루틴이 빠르다는 게 와닿지 않는 다면 위 예제를 돌려보자.

점(.)을 10만 개를 코루틴과 스레드로 찍었을 때 각각의 차이를 보는 예제이다.

실행해보면 코루틴은 10만 개의 점이 거의 한 번에 찍히듯이 딱! 찍히는데

스레드는 파도치듯이 점이 찍히는 것을 볼 수 있다.

 


💡 느낀 점

  • 코루틴이 빠른 이유를 글로만 읽어서 와닿지 않았는데 이번에 정리하면서 확실히 납득이 되었다.
  • Dispatcher가 스레드 풀 내에서 적절한 스레드를 골라준다는 말도 약간 어정쩡하게 이해한 느낌이었는데 이제 알 것 같다. 다음에는 Dispatcher를 정리해봐야겠다.
  • 프로세스 안에 스레드, 스레드 안에 코루틴... 요즘 운영체제 CS 공부 중인데 뭔가 내용이 이어지는 것 같아서 재밌다.

📘 참고한 자료


 

 

반응형

댓글