비동기 처리
- 프로그램이 여러 작업을 동시에 실행거나 작업이 완료될 때까지 기다리지 않고 다른 작업을 수행할 수 있는 방식
- 일반적으로 동기 처리는 한 작업이 끝나기를 기다리는 동안 다른 작업은 수행하지 못하고 실행이 차단 됨
- 비동기 처리는 한 작업이 완료되기 전에도 다른 작업을 수행할 수 있어 프로그램의 응답성과 성능 향상
- 주로 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' 카테고리의 다른 글
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 |