들어가기 전
프로젝트를 하면서 suspend 함수를 활용해 서버통신을 하는 코드를 작성한 경험이 있다.
이것이 코루틴이고 비동기 실행을 간단하게 해준다는 것 까지만 알고있었다. 원리 및 장점을 제대로 알고있는 채로 코루틴을 사용하고 싶다는 생각에 코루틴을 공부하면서 배운 내용들을 시리즈로 포스팅하고자 한다.
Coroutine = Co + Routine
코루틴을 co(with의 의미) + routine = 루틴의 일종으로 협동루틴이라 할 수 있다.
코루틴은 [그림 1]과 같이 이전에 자신의 실행이 마지막으로 중단되었던 지점 다음의 장소에서 실행을 재개한다.
루틴과 코루틴을 비교하면 [그림 2]와 같다.
루틴이 입구와 출구가 하나라면, 코루틴은 중단과 재개가 계속될 수 있는 즉 입구와 출구가 여러개라고 할 수 있다.
비동기 처리와 코루틴
구글에서는 코루틴을 비동기 처리에 이용하는 것을 추천하고 있다.
즉 코루틴이 비동기 실행을 간편하게 해주고, main thread에 blcok을 관리 할 수 있다고 한다.
비동기(async) 처리에서하는 callback 처리를 순차적 코드로 짤 수 있게 해준다.
2019 I/O 세션의 예시를 바탕으로 코루틴의 장점을 더욱 알아보자.
코루틴의 활용
https://www.youtube.com/watch?v=BOHK_w09pVA
Dream Code
val user = fetchUserData()
textView.text = user.name
위 코드를 Dream Code로, 우리가 작성하고 싶은 코드의 모습이다.
하지만 이렇게 코드를 작성하면 안된다.
이유는 fetchUserData()에서 network를 call 하면서 main thread에서 network를 하기때문에 main thread가 bolock된다.
즉 NetworkMainThreadException 이 발생한다.
하지만 드림코드를 구현하기 위한 다른 방법으로 아래와 같은 코드를 시도해볼 수 있다.
thread {
val user = fetchUserData()
textView.text = user.name
}
dream code에서 발생했던 networkMainThreadException을 방지하기 위해서 별도의 thread로 처리를 하는 것이다.
하지만 textView.text = user.name과 같이 UI를 UI thread가 아닌 별도의 thread에서 변경하기 때문에 CalledWrongThreadException이 발생한다.
DreamCode는 아니더라도.. 이렇게는 작성할 수 있다.
fetchUserData { user - >
textView.text = user.name
}
callback을 활용하기 때문에 메모리 관리를 잘 해주어야한다. 잘못된 메모리 관리시 OutOfMemoryException이 발생할 수 있다.
그러면 Dream Code처럼 작성은 어려운걸까? => 이를 해결하는 것이 바로 코틀린의 코루틴이다!
코루틴은 앞서 말했듯이 비동기 (async)를 간단하게 해주고, callback을 순차적인 코드로 바꿀 수 있게 해준다.
따라서 우리는 Dream Code를 코루틴의 suspend 키워드를 통해서 구현할 수 있다.
비교를 위해 suspend 키워드를 붙이지 않는 경우 어떻게 되는지 먼저 알아보도록 하겠다.
예시는 suspend 를 이용하지 않은 코드로 서버에서 user 데이터를 가져오고, 해당 데이터를 ui에 그리는 코드이다.
하지만 이 코드는 실행되지 않는다. 왜냐하면 [그림 3]과 같이 main thread에서 fetchUser() 즉 user의 데이터를 가져오는 행위를 하게되면 UI가 blocking 되어서 ui를 그릴 수 없기때문이다.
이렇게 개선하면 실행할 수 있다.
이렇게 작성하면 우리가 원하는 동작을 할 수 있으나, 처음 봤던 dreamCode와 형태가 비슷하지는 않다.
정말 우리는 DreamCode처럼 코드를 쓸 수 없을까? 코루틴의 suspend 키워드가 있으면 가능하다! 바로 이렇게 말이다.
suspend fun loadUser() {
val user = api.fetchUser()
show(user)
}
코드를 작성하는 입장에서는 비동기를 순차적으로 코드를 작성하면된다. 하지만 내부에서는 fetchUser와 ui thread의 처리가 비동기적으로 처리되고 있다.
[그림 5]와 같이 순차적인 코드를 작성하지만, 별도의 call back이나 thread 없이 비동기 처리가 내부에서 진행되도록 한다.
여기까지 코루틴이 비동기 처리를 어떻게 간편하게 해주는지, 왜 코루틴을 써야하는지를 해당 예시를 통해서 알 수 있었다.
다음 포스팅부터는 코루틴을 실제로 사용하는 코드와 예시를 바탕으로 어떻게 사용하는건지 알아보도록 하겠다.
참고 레퍼런스
'Android > 공부' 카테고리의 다른 글
[Android] Flow란? LiveData와 Flow 비교 (0) | 2023.11.13 |
---|---|
[Android/코루틴] 2.코루틴의 기본요소들을 알아보자 (0) | 2023.09.21 |
[Android] 첫 안드로이드 앱 릴리즈 과정에서 겪은 트러블슈팅들 (0) | 2023.09.11 |
[Android] LifecycleOwner란? viewLifecycleOwner와의 비교 (0) | 2023.08.24 |
[Android] UI State란 무엇일까? (0) | 2023.08.16 |