[극적인 음악과 함께 화면이 어두워지며 시작]
"네가 5초 안에 내 말에 대답하지 않으면, 넌 이 집안에서 쫓겨날 거야!"
메인 회장(안드로이드 메인 스레드)의 분노에 찬 목소리가 대저택에 울려 퍼졌다. 그는 막강한 권력을 가진 UI그룹의 회장이었지만, 그에게는 치명적인 약점이 있었다. 바로 5초 이상 기다리는 것을 참지 못하는 성격이었다.
"이런 재수 없는 날이 다 있나... ANR 집안의 저주라는 게 진짜였어..."
비서 코루틴은 중얼거렸다. 그는 메인 회장의 일을 도와주기 위해 특별히 고용된 인재였다. 그의 임무는 회장님이 중요한 일(UI 작업)에만 집중할 수 있도록 다른 귀찮은 잡무(백그라운드 작업)를 처리하는 것이었다.
그날 오후, UI그룹의 중요한 사업 파트너(사용자)가 갑자기 방문했다.
"회장님, 네트워크 데이터를 빨리 불러와주세요!" 파트너가 요청했다.
메인 회장은 다급하게 코루틴에게 업무를 지시했다.
"코루틴, 네트워크 데이터를 가져와! 빨리!"
그러나 코루틴은 치명적인 실수를 저질렀다. 그는 IO 디스패처 비서에게 업무를 넘기는 대신, 자신이 메인 회장과 같은 공간(Dispatchers.Main)에 머물며 직접 작업을 처리하기로 한 것이다.
// 코루틴의 치명적 실수
launch(Dispatchers.Main) { // 메인 스레드에서 작업
val hugeData = api.fetchHugeAmountOfData() // 오래 걸리는 작업
processData(hugeData)
}
"이렇게 하면 더 빨리 처리할 수 있을 거야!" 코루틴의 자신만만한 목소리.
시간이 흘렀다. 1초... 2초... 3초...
메인 회장의 얼굴이 점점 붉어졌다. 파트너는 초조하게 시계를 바라봤다.
"왜 이렇게 오래 걸리지? 나 지금 다른 작업도 해야 하는데!" 메인 회장이 분노했다.
4초... 마침내 5초가 지났다.
"ANR!!!!"
갑자기 저택의 모든 불이 꺼지고, 시스템 전체가 마비되었다. 사업 파트너는 격분하여 자리를 박차고 나갔다(앱 강제 종료).
다음 날, 회사 비상 이사회가 소집되었다.
"어제 무슨 일이 있었던 거야?" 메인 회장이 분노에 찬 목소리로 물었다.
IO 디스패처가 앞으로 나섰다.
"회장님, 코루틴이 저에게 작업을 넘기지 않았습니다. 저는 최대 64개의 일꾼을 데리고 네트워크 작업을 처리할 수 있는데도 말이죠. 코루틴이 모든 걸 메인 스레드에서 처리하려고 했습니다!"
디폴트 디스패처도 덧붙였다. "게다가 복잡한 계산은 제가 담당했어야 했는데, 코루틴이 모든 권한을 독차지했습니다!"
코루틴은 자신의 잘못을 깨달았다.
"정말 죄송합니다, 회장님. 제가 withContext를 사용해서 적절한 디스패처에게 작업을 위임했어야 했습니다."
// 올바른 방식
launch {
// UI 작업은 메인 스레드에서
showLoading()
// 네트워크 작업은 IO 디스패처로 위임
val data = withContext(Dispatchers.IO) {
api.fetchHugeAmountOfData()
}
// 복잡한 처리는 Default 디스패처로 위임
val processedData = withContext(Dispatchers.Default) {
processData(data)
}
// 결과 표시는 다시 메인 스레드에서
hideLoading()
showResult(processedData)
}
메인 회장은 한숨을 쉬었다.
"이제 알겠지? 너는 나와 같은 공간에서 무거운 일을 하면 안 돼. 나는 사용자 응답에 즉시 반응해야 하는 중요한 임무가 있어. 5초 이상 기다리게 하면 우리 모두 ANR의 저주에 걸리는 거야."
그 후로 코루틴은 withContext를 적절히 사용하여 작업을 올바른 디스패처에게 위임했고, UI그룹은 다시 한번 번영을 되찾았다.
"이제 우리는 ANR의 저주에서 벗어났어. 메인 스레드는 UI 작업만 처리하고, 나머지는 각자 적합한 디스패처에게 맡기는 거야."
하지만 아무도 모르는 사이, 멀리서 또 다른 위험이 다가오고 있었다... 그것은 바로 '메모리 누수'의 그림자였다...
[극적인 음악과 함께 화면 페이드 아웃]
다음 시즌에 계속...