[Rust] 비동기 러스트: async & await

이건 며칠전에 릴리즈된 1.39에 추가된 기능이다.
업뎃을 하지 않았다면 먼저 하자.

async는 함수 선언 앞에 붙으면 그 함수를 비동기용 함수로 만들어버린다.
아래는 간단한 async 함수를 선언 후 호출하는 것이다.

?? 근데 출력결과가 아무것도 없다.
함수가 실행되지 않았다는 것인데...

사실 async 함수는 호출 시에 로직을 수행하지 않고, Future라는 타입의 객체만 반환한다.
진짜 실행시키고 그 흐름을 관리하려면 이 Future라는 객체를 어떻게 핸들링해야 하는 것이다.

여기서 좀 간단하게 쓸만한 것은 block_on이라는 함수다.
futures라는 외부 모듈에 있다.

추가해주고

이렇게 돌리면

이제 잘 돈다.
실행하고 블럭도 해주는 것이다.

근데 이런 형태의 코드는 그리 바람직하지 않아보인다.
그냥 블럭시켜서 실행시키는데 일반 함수의 호출과 다를게 뭔가?

async 문법은 async 함수 안에서 다른 async 함수를 호출할 때 빛을 보인다.
이런 식이다.

이런 식으로, async 함수가 반환한 Future 객체에 await을 하면,
해당 async 함수가 값을 반환할때까지 현재 흐름을 블럭한다.

위에선 함수 반환값을 바로 await했지만, 이렇게 할 수도 있다.

뭐, 결과는 같다만.

유의할 점으론, 이것 자체만으로는 진짜 동시성을 달성하지 못한다는 것이다.
위의 출력문에서 foo와 bar가 동시에 출력되지 않은 것만 봐도 그렇다.

async과 await는 저러한 문법적 표현만을 제공한다.
진짜 동시성을 보이려면 아마 외부모뮬 tokio에 있는 기능들을 사용해야할 것이다.

실제로, Rust의 비동기 기능들은 tokio 등의 외부 모듈에 의존하도록 설계된 듯하다.
이런걸 보면....


여튼, 이외에도 문법적 표현이 더 있다.
하나는 async 블럭이다. 이건 비동기 함수를 함수 대신 스코프의 형태로 명시하는 것이다.
별개 구역에 정의되는 게 아니라 범위 내에 인라인되므로, 어떤 상황에선 가독성이 향상될 듯 하다.

실행결과는 이전의 코드와 같다.

클로저와 마찬가지로 move 키워드를 붙여서 소유권을 이동해올 수도 있고.

저거말고도 async 클로저도 있는데, 아직 unstable한 기능이라 적지 않는다.
그냥 클로저 앞에 async만 붙이는 것이다.



참조
https://rust-lang.github.io/async-book/03_async_await/01_chapter.html
https://rust-lang.github.io/async-book/01_getting_started/04_async_await_primer.html
https://dev.to/gruberb/explained-how-does-async-work-in-rust-46f8