
코루틴을 사용하다보면 코루틴을 중간에 일시 중단하고 재개를 해야되는 일이 발생할 수 있습니다.
또는 코루틴 내부에서 콜백을 처리해야 하는 경우가 있는데, 예를들어 Retrofit을 활용하여 네트워크 성공/실패에 대한 각각의 작업을 처리해야 할 때가 있습니다.
이와 같은 상황을 해결하기 위해 코루틴에서 SuspendCancellableCoroutine이라는 API를 지원하고 있습니다.
- 코루틴을 중단시키고 재개할 수 있다.
- 외부 콜백을 코루틴 일시 중단과 재개 메커니즘에 연결하는 데 사용할 수 있다.
- 코루틴이 취소될 때 필요한 작업을 수행할 수 있다.
SuspendCancellableCoroutine API 뿐만 아니라 SuspendCoroutine라는 API도 코루틴 라이브러리에서 지원해주고 있습니다.
1번과 2번은 동일하게 사용이 가능하지만, 두 API의 가장 큰 차이점은 코루틴 취소에 대한 처리 지원 여부로 SuspendCancellableCoroutine만 취소에 대한 처리를 지원합니다..
이번 포스팅에서는 SuspendCancellableCoroutine에 대한 내용을 다뤄보고 SuspendCoroutine에 대한 내용은 다음번 포스팅에서 다뤄보도록 하겠습니다.
SuspendCancellableCoroutine을 사용하면 람다 매개변수로 CancellableContinuation을 사용할 수 있습니다.
이는 코루틴의 Continuation 인터페이스의 확장 인터페이스로 코루틴을 중단하거나 재개하기 위해 다양한 메서드를 지원하고 있습니다.
우선 CancellableContinuation을 알기전에 Continuation 객체에 대해 먼저 살펴봅시다.

'코루틴의 실행 환경을 캡처하고 재개가 되었을 때 사용됩니다.'
사진을 보면 Continuation 인터페이스는 CoroutineContext와 resumeWith() 함수를 각각 가지고 있습니다.
CoroutineContext는 코루틴의 실행 환경을 저장하고 있어 코루틴을 재개하였을 때 동일한 실행 환경에서 코루틴을 실행할 수있도록 보장해줍니다.
resumeWith() 함수는 가지고 있는 중단된 코루틴을 다시 재개하기 위하여 사용되는 함수로, 특이하게도 Result 클래스를 매개변수로 받고 있습니다.
때문에 코루틴에서는 이를 항상 Result로 감싸주는것이 귀찮(?)았던 것인지 확장함수의 형태인 Continuation.resume()을 지원하고 있습니다.
또한, Result 클래스를 사용하게 된다면 Failure가 발생될 수 있기 때문에 Continuation.resumeWithException() 함수를 지원 하여 예외 처리도 가능하게 해줄 수 있습니다.

결국 이 과정들을 수행함으로써, Continuation은 포스팅에 처음 쓴 것처럼 코루틴을 일시중단하고 재개할 수 있게 만들어 줍니다.
그럼 Continuation의 확장 인터페이스 형태인 CancellableContinuation은 무엇을 더 추가로 해줄 수 있을까요?
Continuation의 확장 인터페이스인 CancellableContinuation는 이름에서도 예상 가능하듯이 '취소'에 대한 내용도 함께 사용할 수 있습니다.

사진에 나와있는것처럼 다양한 함수와 프로퍼티를 제공하고 있지만 이번 포스팅에서 우리는 isCancelled와 cancel(), invokeOnCacellation() 추상 메서드들에 대해서 살펴보겠습니다.
각각의 추상 프로퍼티는 코루틴의 현재 상태를 뜻 합니다.
isCancelled는 말 그대로 현재 코루틴이 '취소' 되어 있는 상태이며 해당 값을 통해 코루틴이 취소가 되었는지 확인이 가능합니다.
cancel() 메서드는 코루틴을 취소시키기 위해 사용됩니다.
매개변수로 Throwable?을 받기 때문에 취소에 대한 이유도 개발자가 직접 넣어 사용이 가능합니다.
마지막으로 invokeOnCacellation()은 코루틴이 취소가 되었을 때의 행동을 정의 하는데 사용됩니다.
cancel()이 호출되어 코루틴이 취소가 되면 그에 따라 동작해야될 작업을 람다로 정의하여 CompletionHandler를 통해 코루틴이 취소된 이유까지 받아와 정의할 수 있습니다.
처음 SuspendCancellableCoroutine이란 코루틴에서 처리되는 하나의 작업 즉, Job을 의미하는지 알았습니다.
하지만 사용법을 익히고 하나씩 내부의 코드를 보니 이는 하나의 Job을 의미하는것이 아닌 Job을 도와주는 '유틸리티 함수' 인것을 알게 되었습니다.
또한, Continuation의 역할과 이를 품은 CancellableContinuation과의 차이에 대해서 배우게 되었습니다.
끝으로 이번 포스팅에서는 SuspendCancellableCoroutine이 하는 역할에 대해서 살펴보았습니다.
CancellableContinuation에서 정의된 내용들이 많지만 그에대한 내용은 다른 포스팅에서 따로 정리하여 보도록 하겠습니다.
코루틴의 취소가 이루어지고 그에 따른 필요한 작업이 동반된다면 SuspendCancellableCoroutine을 사용하여 쉽게 처리해보는것은 어떨까요?