비동기 작업이란, 특정 작업이 완료될 때까지 기다리지 않고, 동시에 다른 작업을 수행할 수 있도록 만드는 프로그래밍 기법이다.
Swift에서는 네트워크 요청, 파일 읽기/쓰기, 애니메이션 등 시간이 걸리는 작업에 비동기 처리를 활용한다.
let url = URL(string: "https://dev-test-api.com/users")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
print("Success")
}
task.resume()
print("Done?")
Done?
Success
task.resume() 호출 → 네트워크 요청 시작.print("Done?") -> 메인 스레드는 요청 대기 없이 다음 코드 실행.print("Success")).컴플리션 핸들러는 비동기 작업이 끝난 후 호출되는 클로저(closure)이다.
비동기 작업의 결과를 외부에서 처리하거나 후속 작업을 수행할 수 있게 만든다.
func fetchData() {
let url = URL(string: "https://dev-test-api.com/users")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
print("Success")
}
task.resume()
}
func fetchUserData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
let task = URLSession.shared.dataTask(with: url) { data, response, error in
completion(data, response, error) // 작업 완료 후 결과 전달
}
task.resume() // 작업 시작
}
let url = URL(string: "https://dev-test-api.com/users")!
fetchUserData(from: url) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
if let data = data {
print("Data received: \(data)")
// JSON 파싱 처리
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print("Parsed JSON: \(json)")
} catch {
print("JSON Parsing Error: \(error.localizedDescription)")
}
}
}
컴플리션 핸들러는 함수가 실행된 후 호출될 수 있으므로, @escaping 키워드를 사용해 클로저가 함수의 생명 주기를 벗어날 수 있음을 명시합니다.
@escaping을 사용해야 하는 이유func fetchData(completion: @escaping (String) -> Void) {
DispatchQueue.global().async {
completion("작업 완료") // 함수 종료 후 호출 가능
}
}
func fetchUsers(completion: @escaping ([String]?, Error?) -> Void) {
let url = URL(string: "https://example.com/api/users")!
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
completion(nil, error) // 에러 전달
return
}
if let data = data {
do {
let users = try JSONDecoder().decode([String].self, from: data)
completion(users, nil) // 성공 시 데이터 전달
} catch {
completion(nil, error) // JSON 파싱 에러 전달
}
}
}.resume()
}
// 사용
fetchUsers { users, error in
if let error = error {
print("Error: \(error.localizedDescription)")
} else if let users = users {
print("Users: \(users)")
}
}
func fadeOut(view: UIView, completion: @escaping () -> Void) {
UIView.animate(withDuration: 0.5, animations: {
view.alpha = 0
}, completion: { _ in
completion() // 애니메이션 완료 후 호출
})
}
// 사용
fadeOut(view: someView) {
print("Fade-out animation completed!")
}
비동기 작업은 현대 앱에서 필수적인 기능이며, 컴플리션 핸들러는 이를 효율적으로 처리하기 위한 강력한 도구입니다.
이를 통해 작업 완료 후의 동작을 유연하게 정의할 수 있으며, 코드를 더 읽기 쉽고 재사용 가능하게 만듭니다.