Date :

앱을 실행하면 하나의 주된 Main Thread가 배정되고 화면을 그리는 일처리를 하게 됩니다. 제가 사용하는 iphone 15 Pro Max는 화면 주사율이 최대 120Hz를 지원합니다. 즉 1초에 120번 화면을 그리는 동작을 Main Thread가 담당하게 됩니다.

앱을 개발하다 보면 네트워크 요청, 이미지 처리, 파일 입출력처럼 시간이 오래 걸리는 작업을 호출하게 됩니다.
이러한 작업을 Main Thread에서 하면 어떻게 될까요?

Main Thread는 이미 1초에 120번 화면을 그리는 동작을 하고 있는데 무거운 작업을 하게 되면 해당 작업이 끝날 때 까지 화면이 멈추거나 사용자 입력에 반응하지 못할 수 있습니다. 이를 해결하기 위해 여러 작업을 효율적으로 나누어 처리해야 하는데 이때 등장한 개념이 동시성 프로그래밍입니다.

동시성(Concurrency)

여러 작업을 동시에 실행하는 것이 아니라 CPU가 작업마다 시간을 분할해 적절하게 Context Switching함으로써 동시에 실행되는 것처럼 보이게 하는 것을 동시성이라고 부릅니다.

병렬성(Parallelism)

독립적으로 동시에 여러 작업을 실행하는 것을 병렬성이라고 부르며, 동시성과는 다르게 여러 작업을 다른 코어, 프로세스에서 동시에 실행하는 것을 병렬성이라고 부릅니다.

GCD

func loadProfile(completion: @escaping (Profile) -> Void) {
    fetchUser { user in
        fetchPosts(for: user) { posts in
            fetchThumbnailURL(for: posts[0]) { thumbnailURL in
                fetchImage(from: thumbnailURL) { image in
                    completion(Profile(user: user, posts: posts, thumbnail: image))
                }
            }
        }
    }
}

Objective-C부터 존재하던 개념으로 동시성 프로그래밍에 대한 높은 추상화를 제공합니다. Serial DispatchQueue는 한 번에 하나의 Task를 순차적으로 실행하고 Concurrent DispatchQueue는 많은 작업을 동시에 실행합니다. 두 경우 모두 작업이 실행되는 순서는 FIFO 입니다. GCD를 이용하면 async로 작업을 수행하고 나서 보통 탈출 클로저를 이용한 completion handler를 통해 해당 작업이 끝났을때의 처리를 해주게 됩니다.

Swift Concurrency

func loadProfile() async throws -> Profile {
    let user = try await fetchUser()
    let posts = try await fetchPosts(for: user)
    let thumbnailURL = try await fetchThumbnailURL(for: posts[0])
    let image = try await fetchImage(from: thumbnailURL)

    return Profile(user: user, posts: posts, thumbnail: image)
}

++WWDC 2021++에서 새로 소개된 동시성 프로그래밍 API입니다. Swift Concurrency는 동시성 프로그래밍을 가독성이 좋은 코드로 작성하고자 도입된 개념입니다. async, await 키워드를 이용해 비동기 코드를 작성할 수 있습니다. await 키워드로 인해 중지되면 이후에 사용해야 하는 데이터를 heap 영역에 저장해 두고, 이후에 다시 heap 영역에서 해당 데이터를 가져와 사용합니다.

GCD의 비동기 vs Swift Concurrency 비동기 개념 차이

GCD 비동기 함수는 다른 Thread로 작업을 시키고 기다리지 않습니다. 해당 작업이 끝나는 시점에 콜백 함수를 통해 값을 리턴받습니다. 기존 비동기 개념은 작업 진행이 되면서 작업이 끝나는 것을 기다리지 않았습니다. (언젠가 실행되겠지…)

Swift Concurrency의 async 함수는 중간에 잠깐 멈추었다가(suspend) 다시 재개(resume)될 수 있는 함수입니다. 해당 작업을 실행시키지만 중간에 멈출 수 있는 suspension point에서 운영체제에게 스레드를 양보하고(작업의 진행상황을 운영체제에 잠시 저장) 나중에 다시 실행할 수 있습니다. 새로운 비동기 개념은 Thread가 해당 작업을 실행시키다가 중간에 멈출 수 있는 suspension point에서 작업의 진행상황을 운영체제에 저장했다가, 나중에 다시 실행시킬 수 있습니다.

 

 

 

 

 

 

Reference