TIL_024 | Trailling Lambda와 Scope functions

묘한묘랑·2024년 1월 4일
0

TIL

목록 보기
24/31

새벽에 runBlocking과 async가 내가 생각한 형태가 맞는지 궁금해져 코드를 보던 도중 한 가지 떠올라 실험을 해보았다.

runBlocking

expect fun <T> runBlocking(
    context: CoroutineContext = EmptyCoroutineContext, 
    block: suspend CoroutineScope.() -> T
): T

공식 문서에는 구현부가 없기에 그냥 내가 생각하던 방식이 맞겠거니 하고 넘기기로 하였다.

그런데... 어라..?

CoroutineScope.() -> T

이 부분이 눈에 띄었다.

async

사실 이 async가 어떻게 코루틴 스코프에서만 작동하는지 계속 궁금하긴 했었다. 그럼에도 불구하고 굳이 찾아보지 않았던 이유는 어떻게 해야 구현이 가능할까 계속 생각을 해보기 위함과 내가 이걸 자주 사용할까? 라는 귀찮음이 합쳐진 결과였다.

일단 결론만 말하자면 async에 구현에 관한 아이디어는 전혀 떠오르지 않은 상태였다!
단지 runBlocking과 suspend가 어떤 구조로써 작동할지에 대해서 감이 잡혔기 때문에 보기로 결정하였다.

public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T> {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyDeferredCoroutine(newContext, block) else
        DeferredCoroutine<T>(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

그리고 async코드를 보고서 떠올랐다.

아, 함수를 매개변수를 받을 때 Class.() -> T로 하게 된다면 클래스 내부의 값을 그대로 사용할 수 있는건가?

그리고 마침 OAuth_Practice 프로젝트에 대한 피드백을 받을 때 Trailling Lambda로 구현하는 방법을 제시 받았으니 그대로 적용시켜 보기로 하였다.

fun <T> getClient(provider: OAuth2Provider, func: OAuthClient.() -> T): T {
	clientList[provider]?.let { return func.invoke(it) }
		?: TODO("FrontEnd 요청 확인 또는 Configuration 확인")
}
oAuthClientContainer.getClient(provider){
	getUserInfoByAuthorizationCode(authorizationCode)
}

된다!

그런데 어......라.....?

어디서 본것 같은 형태이다.

자, 여기서 이제 전혀 관련이 없을 것 같던 Scope functions에 대해 이야기 해보려 한다.

fun getClient(provider: OAuth2Provider) =
	clientList[provider] ?: TODO("FrontEnd 요청 확인 또는 Configuration 확인")

// ---------------

oAuthClientContainer.getClient(provider).getUserInfoByAuthorizationCode(authorizationCode)

사실 위 코드의 형태는 이런 코드였다.

그리고 이제 원래 코드를 보면 생각나는 것이 하나 있었다.

run

oAuthClientContainer.getClient(provider).run{
	getUserInfoByAuthorizationCode(authorizationCode)
}
inline fun <T, R> T.run(block: T.() -> R): R

사실 Scope functions에 대해서 뭔가 다들 비슷비슷해서 감이 확 안왔는데 이번에 감이 온것 같았다.

결론 - 연쇄적으로 알아가는 학습법은 사람 잠도 못잘 정도로 재밌다.

profile
상황에 맞는 기술을 떠올리고 사용할 수 있는 개발자가 되고 싶은 개발자

0개의 댓글