async let

치킨치·2023년 8월 8일
0
import Foundation

Task {
    let userName = await getUserName()
    let userImage = await getUserImage()
    
    updateUI(userName: userName, userImage: userImage)
}

위의 코드는 첫 번째 await 결과가 나온 후에야 두 번째 await가 실행된다.
하지만 getUserImage()는 첫 번째 결과를 기다릴 이유가 없으므로 동시에 실행해줘야 더 좋은 코드가 된다.

그렇다면 어떻게 고쳐야 될까?

import Foundation

Task {
    async let userName = getUserName()
    async let userImage = getUserImage()
    
    await updateUI(userName: userName, userImage: userImage)
}

Swift 5.5부터는 위처럼 async let을 사용하면 병렬처리를 쉽게 구현 할 수 있다.
updateUI 함수는 async가 아니라는 것이 흥미롭다.
await 키워드는 라인에 존재하는 모든 let async들을 병렬로 실행한다.

위 코드엔 함정이 하나 존재한다.
async let 변수를 await 없이 사용한다면 그 이유를 알 수 있는데, 다음과 같은 오류를 확인 할 수 있다.

즉, await를 통해서 async let을 실행하더라도 값의 결과가 저장되는 것이 아니라 실행 라인에서만 일시적으로 결과 가져온다는 것이다.
async let을 사용하는 변수는 일반 변수와 다르므로 이름을 다소 특별하게 가져가면 어떨까?

Task {
    async let userNameAsync = getUserName()
    async let userImageAsync = getUserImage()
    
    struct User {
        var name: String
        var image: Data
    }
    let user = await User(userName: userNameAsync, userImage: userImageAsync)
    
    updateUI(userName: user.name, userImage: user.image)
}

async let 변수에 Async 어미를 붙여서 일반 변수들과 차별점을 두었고, 구조체 생성자에서 await를 실행시켜서 데이터를 가져오는 코드로 바꾸어 본 것이다.
구조체를 쓰고 싶지 않으면 아래와 같이 tuple을 이용해 보는 건 어떨까?

Task {
    async let userNameAsync = getUserName()
    async let userImageAsync = getUserImage()
    
    let (userName, userImage) = await (userNameAsync, userImageAsync)
    
    updateUI(userName: userName, userImage: userImage)
}

첨언

Swift 언어 개발자 그룹에서 async let을 병렬성(parallelism)이 아니라 동시성(concurrency)으로 설명하고 있다는 점이 의문이다.
병렬성은 같은 시간에 실행될 수 있음을 의미하고, 동시성은 짧은 시간동안 CPU 타임을 분할해서 여러가지 일을 동시에하는 것처럼 보이는 걸 의미한다.
컴퓨터공학에서 이 두가지의 차이점은 명확히하고 있을텐데 왜 병렬성으로 표기하지 않는 이유는 무엇일까.
혹시 싱글 코어에서도 멀티 쓰레드가 가능하기 때문에 멀티 코어에 큰 의미를 두지 않기 때문일지도 모르겠다.

심화 과정은 SE-0317를 참고하여 공부하자.

profile
풀스텍이었던 iOS개발자

1개의 댓글

comment-user-thumbnail
2023년 8월 8일

개발자로서 배울 점이 많은 글이었습니다. 감사합니다.

답글 달기