관리 메뉴

나만을 위한 블로그

[Kotlin] deferred란? 본문

개인 공부/Kotlin

[Kotlin] deferred란?

참깨빵위에참깨빵_ 2022. 10. 10. 01:48
728x90
반응형

deferred의 사전적 정의는 아래와 같다.

 

연기된

 

코틀린 공식문서에서 말하는 deferred의 원형과 설명은 아래와 같다.

 

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/actor.html

 

actor

Launches new coroutine that is receiving messages from its mailbox channel and returns a reference to its mailbox channel as a SendChannel. The resulting object can be used to send messages to this coroutine. The scope of the coroutine contains ActorScope

kotlinlang.org

interface Deferred<out T> : Job

지연된 값은 취소할 수 없는 미래다. 결과가 있는 작업이다. 비동기 코루틴 빌더 또는 CompletableDeferred 클래스의 생성자를 통해 생성된다. 값이 계산되는 동안 활성 상태다. Deferred에는 수행된 계산의 성공 또는 실패 결과를 검색하기 위한 추가 편의방법이 있는 작업과 동일한 상태 시스템이 있다. deferred의 결과는 완료될 때 사용할 수 있으며 deferred가 실패한 경우 예외를 던지는 await()로 검색할 수 있다
취소된 지연도 완료된 것으로 간주된다. 해당 예외는 deferred의 완료된 인스턴스에서 getCompletionExceptionOrNull을 통해 검색할 수 있다. 일반적으로 지연된 값은 활성 상태에서 생성된다. 그러나 비동기 코루틴 빌더에는 이 매개변수가 CoroutineStart.LAZY로 설정될 때 새 상테에서 지연된 값을 생성하는 선택적 시작 매개변수가 있다. 이런 지연은 시작, 조인, 대기를 호출해 활성화할 수 있다. 지연된 값은 작업이다. 비동기 빌더의 coroutineContext에 있는 작업은 코루틴 자체를 나타낸다. 이 인터페이스와 이 인터페이스에서 파생된 모든 인터페이스의 모든 기능은 쓰레드로부터 안전하며 외부 동기화 없이 동시 코루틴에서 안전하게 호출할 수 있다. 지연된 인터페이스 및 모든 파생 인터페이스는 향후 이 인터페이스에 새 메서드가 추가될 수 있으므로 타사 라이브러리의 상속에 대해 안정적이지 않지만 사용하기에 안정적이다

 

위 문서의 밑에 함수 3개가 나와 있다. 위에서 말하는 getCompletionExceptionOrNull 또한 함수며 각 설명은 아래와 같다.

 

await : 쓰레드를 차단하지 않고 이 값이 완료될 때까지 기다렸다가 지연된 계산이 완료되면 재시작해서 결과값을 반환하거나 지연된 항목이 취소된 경우 해당 예외를 던진다

getCompleted : 이 지연된 값이 아직 완료되지 않은 경우 완료된 결과를 반환하거나 IllegalStateException을 던진다. 이 지연이 취소된 경우 해당 예외를 던진다

getCompletionExceptionOrNull : 이 지연이 취소되어 완료된 경우 예외 결과를 반환하고 정상 완료된 경우 null을 리턴하고 지연된 값이 아직 완료되지 않은 경우 IllegalStateException을 던진다

 

공식문서를 보면 deferred란 취소할 수 없으면서 결과 또는 예외를 리턴하는 인터페이스라고 생각된다.

다른 곳에서 설명하는 deferred는 아래와 같다.

 

https://origogi.github.io/coroutine/%EB%94%94%ED%8D%BC%EB%93%9C/

 

[Coroutine] 디퍼드(Deferred)

 

origogi.github.io

deferred는 결과를 갖는 비동기 작업을 수행하기 위해 job을 확정한다. 다른 언어에서 future 또는 promise라고 하는 것의 코틀린 구현체가 deferred다. 기본 컨셉은 연산이 객체를 반환할 것이며 객체는 비동기 작업이 완료될 때까지 비어 있다는 것이다. deferred를 만들려면 async를 써야 한다. 또는 CompletableDeferred<>()의 생성자를 쓸 수 있다.

 

https://kotlinworld.com/149

 

[Coroutine] 10. Deferred를 이용한 결과값 수신

Deferred란 Deferred는 직역하면 연기라는 뜻을 가진다. "결과값 수신을 연기한다"라는 뜻인데, 이는 미래의 어느 시점에 결과값이 올 것을 뜻한다. Deferred의 의미와 같이 "Deferred는 결과값을 수신하는

kotlinworld.com

deferred는 결과가 있는 비동기 작업을 수행하기 위해 결과값이 없는 job을 확장하는 인터페이스다. 즉 deferred는 job이며 이로 인해 deferred는 job의 모든 특성을 갖는다. job의 상태변수(isActive, isCancelled, isCompleted)와 job의 Exception handling 등을 모두 deferred에서 적용할 수 있다. deferred는 코루틴 async 블록을 써서 생성될 수 있다. deferred의 결과값을 직접 조작하는 CompletableDeferred도 있다. async 블록의 마지막 줄의 값이 deferred로 wrapping되며 이 값이 deferred의 결과값이 된다

deferred에서 결과값을 수신하려면 Deferred 인터페이스의 await()를 쓴다. 코드 상에서 await()을 호출하면 main 함수가 수행되는 코루틴은 IO thread로부터 deferred 결과가 수신될 때까지 일시중단된다

 

아래는 deferred 관련 예제다.

 

suspend fun main() {
    coroutineScope {
        val deferred: Deferred<String> = async {
            println("async {} 내부 진입")
            "Deferred result"
        }

        println("await() 호출 전")
        val deferredResult = deferred.await()
        println("await() 호출")
        println("deferredResult : $deferredResult")
    }
}

 

위에 써있듯 Deferred는 코루틴 빌더 안에서 생성하기 때문에 메인 함수에서 사용하려면 메인 함수에 suspend 키워드를 붙여야 한다. 안 쓰더라도 노랗게 체크되니 확인 후 수정하면 된다.

이것의 결과는 어떻게 나올까? 한번 생각해보고 아래 결과를 확인해보자.

 

 

메인 함수를 실행하면 곧바로 deferred의 async {}이 실행되지 않아서 await() 호출 전까지 출력된다. deferred가 값을 내보내면 그 때 async {}가 실행되서 문자열을 리턴한다.

그리고 await()를 호출하고 async {} 안의 마지막 줄에 적힌 문자열을 가져온 다음 println()으로 출력한다.

위에서 await()을 호출하면 메인 함수의 코루틴은 deferred 결과를 받을 때까지 일시중단된다고 했는데 이 말대로 작동하는 걸 볼 수 있다.

반응형
Comments