본문 바로가기
모바일앱/동시성(Concurrency)

Swift Concurrency - Async / Await 로 시작하기

by GeekCode 2025. 3. 10.
반응형

 

 

안녕하세요!

 

오늘은 iOS 개발에서 비동기 프로그래밍을 쉽게 만들어주는

asyncawait에 대해 알아보겠습니다.

 

💡 비동기 프로그래밍이란?

비동기 프로그래밍은 시간이 오래 걸리는 작업을 수행하는 동안, 다른 작업을 멈추지 않고 동시에 실행할 수 있도록 하는 프로그래밍 방식입니다.
iOS 앱에서는 네트워크 요청, 파일 입출력, 데이터베이스 조회 등의 작업이 대표적인 비동기 작업입니다.

예를 들어, 사용자가 앱에서 버튼을 눌러 데이터를 가져올 때, 데이터를 가져오는 동안 앱이 멈추지 않고 다른 기능을 사용할 수 있도록 해야 합니다.
이때 비동기 처리가 필요합니다.

 



🚀 Swift 5.5와 함께 등장한 async/await!

 

Swift 5.5는 2021년 9월에 출시되었으며, Apple은 이를 WWDC 2021에서 처음 발표했어요.

 

 

 

asyncawait를 사용하면 비동기 코드를 동기 코드처럼 간결하게 작성할 수 있습니다.
즉, 마치 함수가 순차적으로 실행되는 것처럼 보이지만, 내부적으로는 비동기적으로 동작합니다.

 

 

💡 왜 async/await가 필요했을까?

 

 

이전에는 비동기 코드를 작성할 때 GCD(Grand Central Dispatch)나 Completion Handler를 사용했는데, 코드가 중첩되거나 길어지면서 가독성이 떨어지고 유지보수가 어려운 문제가 있었습니다. 이를 해결하기 위해 Swift 5.5에서 async/await이 도입되었죠!

 

 

 

📱 iOS 15부터 사용 가능!

 

Swift 5.5의 async/await 기능은 iOS 15, macOS Monterey, watchOS 8, tvOS 15 이상에서 사용할 수 있으며, Apple의 UIKit, Foundation, SwiftUI 등 주요 프레임워크의 많은 API가 비동기 호출을 지원하도록 업데이트되었습니다.

 

 

 

 

🎯 어떤 변화가 있었을까?

이제 복잡한 completion handler 없이, 동기 코드처럼 자연스럽게 비동기 코드를 작성할 수 있습니다! 예를 들어, 기존 코드에서는 다음과 같이 작성해야 했습니다.

 

func fetchImage(url: URL, completion: @escaping (UIImage?) -> Void) {
    URLSession.shared.dataTask(with: url) { data, response, error in
        if let data = data, let image = UIImage(data: data) {
            completion(image)
        } else {
            completion(nil)
        }
    }.resume()
}

// 사용 예시
fetchImage(url: imageUrl) { image in
    DispatchQueue.main.async {
        self.imageView.image = image
    }
}

 

 

하지만 async/await을 사용하면 이렇게 간결해집니다!

 

func fetchImage(url: URL) async -> UIImage? {
    do {
        let (data, _) = try await URLSession.shared.data(from: url)
        return UIImage(data: data)
    } catch {
        return nil
    }
}

// 사용 예시
Task {
    if let image = await fetchImage(url: imageUrl) {
        imageView.image = image
    }
}

 

 

 

 

 

✅ 기본 사용법

  1. async 함수 선언: async 키워드를 사용하여 함수가 비동기적으로 실행될 것임을 명시합니다.
  2. await 키워드 사용: await 키워드는 해당 작업이 완료될 때까지 기다린 후 결과를 반환합니다.

 

💡 기존 코드보다 가독성이 좋아지고, 코드 중첩이 사라진 것을 볼 수 있습니다!

 

 

📌 asyncawait의 동작 원리

  1. async 함수는 항상 비동기적으로 실행된다.
    • async로 선언된 함수는 비동기적으로 실행되므로, 실행되는 동안 다른 코드가 멈추지 않습니다.
    • 따라서 UI가 멈추지 않고 부드럽게 동작할 수 있습니다.
  2. await 키워드는 비동기 작업이 끝날 때까지 기다린다.
    • await을 사용하면, 특정 작업이 완료될 때까지 해당 코드만 일시적으로 중단됩니다.
    • 하지만 앱 전체가 멈추는 것이 아니라, 다른 비동기 작업들은 계속 실행됩니다.

 

 

🎯 async let을 사용한 동시 실행

보통 여러 개의 비동기 작업을 동시에 실행하고 싶을 때, DispatchGroup을 사용하거나 여러 Task를 생성해야 했습니다.
하지만 Swift의 async let을 사용하면 매우 간단하게 동시에 실행되는 비동기 작업을 선언할 수 있습니다.

 

 

 

📌 async let 예제

예를 들어, 두 개의 이미지를 동시에 다운로드하는 경우를 살펴보겠습니다.

async let image1 = fetchImage(url: url1)
async let image2 = fetchImage(url: url2)

let (result1, result2) = await (image1, image2)

 

 

💡 fetchImage 함수는 동시에 실행되며, await을 만나면 두 작업이 모두 완료될 때까지 기다립니다.
이를 통해 네트워크 요청을 병렬로 실행하여 성능을 향상시킬 수 있습니다.



 

 

asyncawait 사용 시 주의할 점

1️⃣ 메인 스레드에서 실행하는 경우 주의해야 한다.

  • 비동기 작업을 UI 업데이트와 함께 사용할 때는 반드시 메인 스레드에서 실행하도록 해야 합니다.
  • await을 사용할 때 메인 스레드가 차단되지 않도록, Task 블록 내에서 실행하는 것이 좋습니다.
Task {
    let image = await fetchImage(url: imageUrl)
    DispatchQueue.main.async {
        imageView.image = image
    }
}

 

 

2️⃣ 오래 걸리는 작업을 Task 내부에서 실행할 것.

  • async 함수는 Task 내부에서 호출해야 안전하게 사용할 수 있습니다.
  • 네트워크 요청, 파일 입출력 등 비동기 작업을 Task 없이 실행하면 예기치 않은 동작이 발생할 수 있습니다.

 

3️⃣ 오래 걸리는 작업을 async let로 실행할 때는 await이 필요하다.

  • async let을 사용할 경우 반드시 await을 사용하여 값을 가져와야 합니다.
  • 그렇지 않으면 코드가 실행되지 않습니다.



🎬 정리

기존의 completion handler 방식과 비교했을 때, asyncawait을 사용하면 코드가 훨씬 간결하고 가독성이 좋아집니다.
async let을 사용하면 여러 개의 비동기 작업을 동시에 실행할 수 있어 성능을 향상시킬 수 있습니다.
UI 업데이트는 반드시 메인 스레드에서 실행해야 하므로, Task 블록을 사용하여 실행하는 것이 좋습니다.



이제 iOS에서 비동기 프로그래밍을 더욱 쉽고 직관적으로 구현할 수 있습니다!

앞으로 asyncawait을 활용하여 더 깔끔한 코드를 작성해보세요. 🚀

반응형

'모바일앱 > 동시성(Concurrency)' 카테고리의 다른 글

동기와 비동기에 대한 개념  (0) 2024.08.12