WWDC2021: Meet async/await in Swift
๊ด์ฌ ์๋ ์ธ์
์ ํ๋์ฉ ๋ณด๊ณ ์๋๋ฐ, ๊ทธ์ค ์ฒซ ๋ฒ์งธ๋ก ์์ฒญํ ๊ฒ์ด "Meet async/await in Swift"๋ค. ์ค๋ฐ๋ถ๊น์ง์ ๋ด์ฉ์ ์ ๋ฆฌํ๋ค. completionHandler
๋ฅผ ์ฌ์ฉํ์ ๋์ async/await
์ ์ฌ์ฉํ์ ๋๋ฅผ ๋น๊ตํ๋ ๋ด์ฉ์ธ๋ฐ ์ด๊ฒ๋ง ๋ด๋ ์ด๋ ์ ๋ ๊ฐ์ด ์กํ๋ค.
๊ธฐ์กด์๋ completionHandler
๋ฅผ ์ด์ฉํด ๋น๋๊ธฐ ์์
์ ์ฒ๋ฆฌํ๋ค. ๋น๋๊ธฐ ์์
์ ํ๋ฉด, ์ค๋ ๋๊ฐ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
์ ์๋ฃํ ๋๊น์ง ๋ค๋ฅธ ์์
์ ์ํํ ์ ์๋ ์ฅ์ ์ด ์๋ค.
๋ง์ ์ฌ๋๋ค์๊ฒ ์น์ํ ์ ์๋ ์๋ฅผ ์ดํด๋ณด๋ฉด, ํ ์ด๋ธ ๋ทฐ๊ฐ ์๊ณ , ์ฌ๊ธฐ์๋ ์๋ฒ์ ์ ์ฅ๋ ์ธ๋ค์ผ ์ด๋ฏธ์ง๊ฐ ํ์๋๋ค. ์ธ๋ค์ผ ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ค๋ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
ViewModel์์ fetchThumbnail
๋ฉ์๋๋ฅผ ํธ์ถํ๋ค. ๋ค์๊ณผ ๊ฐ์ ์์
๋ค์ด ์งํ๋๋ค.
thumbnailURLRequest
๋ฉ์๋๋ฅผ ํธ์ถํ๋ค. ์ด ๋ฉ์๋๋ ๋ฌธ์์ด์์URLRequest
๋ฅผ ์์ฑํ๋ค.- 1์์ ์์ฑํ
URLRequest
๋ฅผ ์ด์ฉํดURLSession.dataTask(with:completion:)
์ ํธ์ถํ๋ค. ์ด ๋ฉ์๋๋ ์์ฒญ์ ๋ํData
๋ฅผ ๊ฐ์ ธ์จ๋ค. UIImage(data:)
๋ฅผ ์ด์ฉํดData
๋ฅผUIImage
๋ก ๋ณ๊ฒฝํ๋ค.- ๋ง์ง๋ง์ผ๋ก
UIImage.prepareThumbnail
์ ํตํด ์๋ณธ ์ด๋ฏธ์ง์์ ์ถ์ํด ๋ ๋๋งํ๋ค.
์ด๋ฌํ ์์
์์ 1๊ณผ 3์ ์์
์ ์์ฃผ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌ๊ฐ ๋๋ค. ๊ทธ๋ฌ๋ 2, 4์ ์์
์ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค. ๊ทธ๋์ 2, 4 ์์
์ ์ํด (์ง๊ธ๊น์ง๋) completionHandler
๋ฅผ ์ฌ์ฉํ์๋ค. ์ฝ๋๋ก ์ดํด๋ณด์.
func fetchThumbnail(for id: String, completion: @escaping (UIImage?, Error?) -> Void) {
let request = thumbnailURLRequest(for: id)
let task = URLSession.shared.dataTask(withL request) { data, response, error in
if let error = error {
completion(nil, error)
} else if (response as? HTTPURLResponse)?.statusCode != 200 {
completion(nil, FetchError.badID)
} else {
guard let image = UIImage(data: data!) else {
return
}
image.prepareThumbnail(of: CGSize(width: 40, height: 40)) { thumbnail in
guard let thumbnail = thumbnail else {
return
}
completion(thumbnail, nil)
}
}
}
task.resume()
}
์ด ์ฝ๋์ ๋ฌธ์ ์ ์ผ๋ก, ๋ฐ์ดํฐ์์ UIImage
๋ฅผ ๋ง๋ค๊ฑฐ๋ ์ธ๋ค์ผ ์ค๋น๊ฐ ์คํจํ๋ฉด fetchThumbnail
์ ํธ์ถ์์๊ฒ ์๋ฆผ์ด ์ ์ก๋์ง ์๋๋ค. ๊ฒ๋ค๊ฐ ๊ฐ์ธ์ ์ธ ์๊ฒฌ์ผ๋ก ์ฝ๋์ depth๊ฐ ๊น์ด์ ธ์ ๋ณต์กํ๋ค.
๊ทธ๋์ ๋ค์๊ณผ ๊ฐ์ด ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฆผ์ ๋ณด๋ด๊ฒ ์์ฑํด์ผ ํ๋ค.
func fetchThumbnail(for id: String, completion: @escaping (UIImage?, Error?) -> Void) {
let request = thumbnailURLRequest(for: id)
let task = URLSession.shared.dataTask(withL request) { data, response, error in
if let error = error {
completion(nil, error)
} else if (response as? HTTPURLResponse)?.statusCode != 200 {
completion(nil, FetchError.badID)
} else {
guard let image = UIImage(data: data!) else {
completion(nil, FetchError.badImage)
return
}
image.prepareThumbnail(of: CGSize(width: 40, height: 40)) { thumbnail in
guard let thumbnail = thumbnail else {
completion(nil, FetchError.badImage)
return
}
completion(thumbnail, nil)
}
}
}
task.resume()
}
๊ทธ๋ฐ๋ฐ, ๋ฌธ์ ๋ Swift
์์๋ ์ด ๊ณผ์ ์ ๊ฐ์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋ค๋ ๊ฒ์ด๋ค. ๊ฒ๋ค๊ฐ ์ํ๋ ๋์์ ๋ค ๊ฐ์ง ์์
์ ์์๋๋ก ์ํํ๋ ๊ฒ๋ฟ์ด์๋๋ฐ, ์ฝ๋๋ ๋ฐ๋ผ๊ฐ๊ธฐ ๋ณต์กํ๊ณ ์ด๋ ค์์ก๋ค๋ ๊ฑฐ๋ค. ์๋๊ฐ ๋ชจํธํด์ก๋ค.
Result
ํ์
์ ์ฌ์ฉํ์ฌ ์ด๊ฒ์ ์ข ๋ ์์ ํ๊ฒ ๋ง๋ค ์ ์๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ ์ฝ๋๋ฅผ ๋ ์ถํ๊ณ ์ฝ๊ฐ ๋ ๊ธธ๊ฒ ๋ง๋ ๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๊ณผ์ ์ async/await
๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ์ข๊ฒ ๋ง๋ค ์ ์๋ค.
func fetchThumbnail(for id: String) async throws -> UIImage {
let request = thumbnailURLRequest(for: id)
let (data, response) = try await URLSession.shared.data(for: request)
guard (response as? HTTPURLResponse)?.statusCode == 200 else {
throw FetchError.badID
}
let maybeImage = UIImage(data: data)
guard let thumbnail = await maybeImage?.thumbnail else {
throw FetchError.badImage
}
return thumbnail
}
async
๋ฅผ ํ์ํ ๋๋ throws
์ง์ ๋๋ ํจ์๊ฐ throw ๋์ง ์๋๋ค๋ฉด ํ์ดํ ์์ ๊ฐ์ผ ํ๋ค. ์ด๋ ๊ฒ async
๋ฅผ ์ฌ์ฉํ๋ฉด ์๊ทธ๋์ฒ๊ฐ ๋ ๊ฐ๋จํด์ง๋ค. ์ด๋ฏธ์ง๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ถ์๋๋ฉด ์ธ๋ค์ผ ์ด๋ฏธ์ง๊ฐ ๋ฐํ๋๊ณ , ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ๊ทธ๋ฅ ์ค๋ฅ๋ฅผ ๋์ง๋ค.
๋ ์์ธํ ๋ด์ฉ๊ณผ ๋ท๋ถ๋ถ์ด ๊ถ๊ธํ๋ค๋ฉด ํ๋จ ๋งํฌ๋ฅผ ํตํด ์ง์ ์์ฒญํ๋ฉด ์ข์ ๊ฑฐ ๊ฐ๋ค.
์ฐธ๊ณ ์๋ฃ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote