Swift

Swift - 비동기처리(async / await)

iosos 2023. 7. 14. 17:50

비동기 처리

- 프로그램이 여러 작업을 동시에 실행거나 작업이 완료될 때까지 기다리지 않고 다른 작업을 수행할 수 있는 방식 

- 일반적으로 동기 처리는 한 작업이 끝나기를 기다리는 동안 다른 작업은 수행하지 못하고 실행이 차단 됨

- 비동기 처리는 한 작업이 완료되기 전에도 다른 작업을 수행할 수 있어 프로그램의 응답성과 성능 향상 

- 주로 I/O 작업(서버 통신), 긴 시간이 소요되는 작업을 처리할 때 사용 

- 비동기 처리를 통해 멀티 태스킹 수행하고 반응적이고 효율적인 살행 가능 

- 사용 방법 : 콜백(callback) 기반 방식, 프로미스(Promise), 비동기/대기(async/await) 패턴 등 

 

 

 

async/await 

- 'async' 키워드를 사용하여 비동기 함수 정의

- 'await' 키워드를 사용하여 비동기 작업의 완료를 기다림 

 

- 메서드 시그니처에 async를 붙여 비동기 작업임을 알리는 키워드 추가

- 메서드 내부 구현에서 비동기가 예상되는 곳에 await 키워드 추가

- 해당 메서드를 호출하는 쪽에서는 Task block에서 호출하고 await 키워드를 붙여서 호출 (async 함수를 호출하기 위해선 await 필요)

 

 

 

 

원리 (스레드 관리)

sync에서의 스레드 관리 - 동기 

- 호출 : A 함수에서 B 함수를 호출하면 A 함수가 실행되던 스레드의 제어권을 B에게 전달

- 진행 : B 함수가 끝날 때까지 해당 스레드는 점유되어 다른 일을 수행하지 않음

- 종료 : B 함수가 종료되면 A 함수에게 다시 스레드 제어권 반납 

 

 

 

 

async에서의 스레드 관리 - 비동기

- 호출 : A 함수에서 B 함수를 호출하면 A 함수가 실행되던 스레드의 제어권을 B에게 전달

- 진행 : B 함수는 async이기 때문에 스레드의 제어권을 포기하는 suspend가 가능

- suspend : 스레드에 대한 제어권은 system으로 가고 시스템은 스레드를 사용해 다른 작업 수행

- resume : 일시 중단된 B 함수를 다시 실행

- 종료 : B 함수가 종료되면 A 함수에게 스레드 제어권 반납

 

 

 


비동기적으로 데이터를 가져오는 함수 예시

 

 

동기 방식

func fetchData() throws -> Data {
    let url = URL(string: "https://example.com/data")!
    let (data, _) = try URLSession.shared.data(from: url)
    return data
}

 

 

비동기 방식

func fetchData() async throws -> Data {
    let url = URL(string: "https://example.com/data")!
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

- async : fetchData() 함수가 비동기 함수임을 나타냄

- throws : 해당 함수가 에러를 던질 수 있다는 것을 나타내는 키워드

- '-> Data' : 함수가 반환하는 값 타입. Data 타입의 결과 반환

- '_' : error를 나타내지만, 해당 함수에서는 사용하지 않으므로 _ (언더바)로 사용 

- 'try await' : await 키워드를 사용하여 비동기 작업이 완료될 때까지 기다림. try 키워드를 사용하여 에러가 발생한 경우 에러 처리 

 

 

 

데이터 처리 메서드

    func process() async {
        do {
            let data = try await fetchData()
            // 데이터를 가지고 추가 작업을 수행
        } catch {
            // 에러 처리
        }
    }

- fetchData() 함수를 호출하여 데이터를 가져오는 비동기 작업의 완료를 기다리고, 작업이 완료되면 데이터를 받아옴

- 받아온 데이터로 추가적인 작업을 수행 

- 'try await fetchData()' 부분에서 발생하는 에러를 'catch' 블럭에서 처리

 

 

 

    override func viewDidLoad() {
        super.viewDidLoad()

        Task{
            await self.process()
        }

    }

- Task : 비동기 작업을 실행하기 위한 구조체 

- 비동기 함수를 수행하기 위핸 Task 구조체의 인스턴스를 생성하고 비동기 함수를 await 키워드와 함꼐 호출해야 함 

- 메서드를 호출하는 쪽에서 Task block을 호출하고 await 키워드를 붙여서 호출해야 함 

 

 

 

 

 

 

전체 코드

import UIKit

class AsyncViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        Task{
            await self.process()
        }

    }
    

    
    func fetchData() async throws -> Data {
        let url = URL(string: "https://example.com/data")!
        let (data, _) = try await URLSession.shared.data(from: url)
     
        return data
    }
    
    
    
    func process() async {
        do {
            let data = try await fetchData()
            // 데이터를 가지고 추가 작업을 수행
        } catch {
            // 에러 처리
        }
    }

}

 

 

 

 

 

참고)

https://asong-study-record.tistory.com/178 

 

[Swift] Concurrency 사용하기

Swift Concurrency - Async, Await 기존에 비동기 처리 방식은 DispatchQueue나 completionHandler를 사용하여 처리했지만 Swift 5.5에서 구현된 Async Await은 더욱 편하게 비동기 처리할 수 있는 문법이다. // DispatchQueue

asong-study-record.tistory.com

 

'Swift' 카테고리의 다른 글

Swift - PickerView  (0) 2023.07.19
Swift - 비동기 처리 (Completion Handler)  (0) 2023.07.15
Swift - sort, sorted 함수 비교  (0) 2023.07.13
Swift - 고차함수 (compactMap, flatMap)  (0) 2023.07.12
Swift - 고차함수 (map, filter, reduce)  (0) 2023.07.11