코틀린 공식문서를 번역 및 정리한 것입니다
fun postItem(item: Item) {
val token = preparePost()
val post = submitPost(token, item)
processPost(post)
}
fun preparePost(): Token {
// makes a request and consequently blocks the main thread
return token
}
preparePost
가 오래걸리는 작업이여서 ui를 block하는 상황일때, 우리는 이것들을 다른 스레드에서 실행시키므로써 해결할 수 있다. 이것은 매우 보통의 테크닉이지만 몇가지 결점이 있다.
callbacks는 어떤 함수의 파라미터로 또 다른 함수를 가지고 특정 프로세스가 완료되었다면 발동된다.
fun postItem(item: Item) {
preparePostAsync { token ->
submitPostAsync(token, item) { post ->
processPost(post)
}
}
}
fun preparePostAsync(callback: (Token) -> Unit) {
// make request and return immediately
// arrange callback to be invoked later
}
쓰레딩보다 훨씬 더 그럴듯해보이지만 여전히 몇가지 이슈들이 있다.
nested callbacks의 어려움. (a.k.a 콜백 지옥)
실행결과를 외부로 리턴할 수 없다
중첩된 콜백으로 가독성이 매우매우 떨어진다. 코드 모양이 크리스마스 트리같아서 크리스마스 트리라 부르기도 한다
에러 핸들링이 불편하다.
이러한 이유로 Callbacks는 JS에서 이벤트 루프를 사용할때 꽤 자주 사용되는데 심지어 거기서도 사람들은 promise나 reactive extensions로 많이 갈아탔다.
futures or promises(언어에 따라 용어 다름 )는 콜백을 할때 언젠가 promise라는 객체와 함께 반환될꺼라는 약속
promis는 값으로 다룰 수 있다. promise는 실행결과값을 담은 promise를 리턴해서 다음 then으로 전달가능하다.
fun postItem(item: Item) {
preparePostAsync()
.thenCompose { token ->
submitPostAsync(token, item)
}
.thenAccept { post ->
processPost(post)
}
}
fun preparePostAsync(): Promise<Token> {
// makes request and returns a promise that is completed later
return promise
}
이런 접근은 우리가 프로그래밍하는 방법에서 일련의 변화들을 요구한다. 특히
thenCompose
or thenAccept
, which can also vary across platforms.Promise
를 반환한다."everything is a stream, and it's observable"
Rx의 기본 아이디어는 이제 데이터를 스트림(흐름들)로 생각하고 이런 스트림을 관찰하자는 것이다.
실직적으로 Rx는 단순하게 데이터를 작업할 수 있는 Observer 패턴의 확장버전이다.
다양한 언어에서 사용할 수 있고 나이스한 데이터 접근과 에러 핸들링을 제공한다.
비동기 코드 작업에 대한 코틀린의 접근 방식은 코루틴을 사용하는 것이다.
코루틴은 suspendable computation을 기본 개념으로 한다. 즉, 함수가 특정 시점에서 실행하던걸 일시중단하고 나중에 다시 시작할 수 있다는 개념이다.
하지만 개발자에게 무엇보다 매력적인 코루틴의 장점은 blocking 코드와 non-blocking 코드를 작성하든 프로그래밍 모델은 크게 달라지지 않는다는 것이다.
fun postItem(item: Item) {
launch {
val token = preparePost()
val post = submitPost(token, item)
processPost(post)
}
}
suspend fun preparePost(): Token {
// makes a request and suspends the coroutine
return suspendCoroutine { /* ... */ }
}
이 코드는 메인 스레드를 blocking 하지않고 장기 실행 작업을 시작한다.
preparePost
는 suspendable function 라고 하고 함수 앖에 suspend가 붙는다. 이것은 함수가 특정 시점에 실행되다가 일시중지되고 다시 시작된다는 것을 의미한다.
suspend
가 추가로 붙는 것이다. 하지만 리턴 타입은 우리가 원하는 것과 동일하게 반환된다. launch
함수를 사용하는것 외에는 동기식 코드와 동일하게 다른 스페셜한 syntax 없이 top-down 방식으로 작성한다. 코루틴은 코틀린에서 자체적으로 개발한 새로운 개념이 아니다. 이것은 Go같은 다른 PL에서 존재해왔고 잘 사용되어 왔다.
하지만 주목해야 할 중요한 점은 코틀린에서는 suspend 키워드만 사용하면 대부분의 기능이 라이브러리에서 처리되기 때문에 추가적인 코드를 작성할 필요가 없다는 것이다. C#에서는 async 과 await 도 구문의 일부로 있지만 코틀린은 다르다.