콜백 함수는 주로 비동기 작업을 처리할 때 사용됩니다. 비동기 작업은 실행되는데 시간이 걸리거나, 언제 완료될지 알 수 없는 작업들을 의미해요. 예를 들어, 네트워크 요청, 파일 읽기/쓰기, 타이머, 애니메이션 등이 이에 해당합니다. 이러한 작업들이 완료된 후 특정 작업을 수행해야 할 때, 콜백 함수를 사용해 그 작업이 완료된 후의 행동을 정의할 수 있어요.
콜백 함수가 주로 쓰이는 상황
네트워크 요청
- 서버에서 데이터를 가져오거나, 데이터를 서버에 보낼 때, 네트워크 요청은 시간이 걸리기 때문에 요청이 완료된 후에 데이터를 처리하는 콜백 함수를 사용합니다.
func fetchDataFromServer(completion: @escaping (Data?) -> Void) {
// 비동기 네트워크 요청
DispatchQueue.global().async {
let data = ... // 서버에서 데이터 가져오기
DispatchQueue.main.async {
completion(data) // 요청 완료 후 콜백 호출
}
}
}
fetchDataFromServer { data in
if let data = data {
print("서버에서 데이터를 받았습니다: \(data)")
} else {
print("데이터를 가져오는 데 실패했습니다.")
}
}
파일 입출력
- 파일을 읽거나 쓰는 작업도 시간이 걸릴 수 있기 때문에, 작업이 완료된 후에 콜백을 사용해 결과를 처리합니다.
func readFileAsync(completion: @escaping (String?) -> Void) {
DispatchQueue.global().async {
let content = ... // 파일 읽기
DispatchQueue.main.async {
completion(content) // 파일 읽기 완료 후 콜백 호출
}
}
}
readFileAsync { content in
if let content = content {
print("파일 내용을 읽었습니다: \(content)")
} else {
print("파일을 읽는 데 실패했습니다.")
}
}
타이머
- 일정 시간이 지난 후에 특정 작업을 실행해야 할 때, 타이머와 콜백 함수를 사용할 수 있습니다.
func startTimer(duration: TimeInterval, completion: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
completion() // 타이머 완료 후 콜백 호출
}
}
startTimer(duration: 3.0) {
print("3초가 지났습니다!")
}
애니메이션
- 애니메이션이 끝난 후에 후속 작업을 처리하기 위해 콜백 함수를 사용합니다.
UIView.animate(withDuration: 1.0, animations: {
// 애니메이션 작업
}, completion: { finished in
if finished {
print("애니메이션이 완료되었습니다.")
}
})
콜백 함수의 장점
- 비동기 작업의 결과를 처리: 콜백 함수를 사용하면 작업이 완료된 후에 특정 작업을 쉽게 처리할 수 있어요.
- 코드의 가독성 향상: 콜백 함수를 사용하면 복잡한 비동기 작업의 흐름을 더 직관적으로 표현할 수 있습니다.
- 유연성: 콜백 함수는 함수의 인자로 전달되기 때문에, 다양한 상황에 맞춰 동작을 쉽게 변경할 수 있어요.
정리
- 콜백 함수는 주로 비동기 작업(네트워크 요청, 파일 입출력, 타이머, 애니메이션 등)에서 작업이 완료된 후의 행동을 정의하는 데 사용됩니다.
- 이를 통해 비동기 작업이 완료된 후에 적절한 후속 작업을 수행할 수 있으며, 코드의 가독성과 유연성을 높일 수 있습니다.
비동기 작업과 콜백 함수의 역할
fetchData 함수가 비동기 작업을 한다고 가정했을 때, print("데이터 가져오는 중...")이 출력된 후 실제 데이터를 가져오는 작업이 완료되면 콜백 함수가 호출됩니다. 이때 콜백 함수 내부의 코드(print("데이터를 가져왔어!"))가 실행되는 거죠.
비동기 작업의 특징은, 작업이 끝나는 시간이 언제인지 정확히 예측할 수 없다는 점입니다. 네트워크 요청처럼 시간이 오래 걸리거나 언제 끝날지 모르는 작업이 있는 경우, 이 작업이 완료되기 전에 다음 코드를 실행하지 않도록 콜백 함수를 사용하는 거예요.
왜 fetchData 메서드 안에 다 넣지 않을까?
fetchData 메서드 안에 모든 코드를 넣을 수도 있지만, 콜백 함수를 사용하는 이유는 코드의 유연성을 높이기 위해서입니다. 콜백 함수를 사용하면 fetchData 함수가 완료된 후에 어떤 작업을 수행할지를 호출하는 쪽에서 자유롭게 정의할 수 있기 때문이죠.
예를 들어, fetchData를 호출하는 여러 곳에서 서로 다른 후속 작업을 수행해야 한다고 해볼게요. 콜백 함수 없이 모든 후속 작업을 fetchData 함수 내부에 넣으면, 그 작업들을 고정된 방식으로만 수행해야 합니다.
예시: 콜백 함수가 없는 경우
만약 fetchData 함수 안에 모든 후속 작업을 넣는다면, 다음과 같이 고정된 행동을 해야 합니다.
func fetchData() {
print("데이터 가져오는 중...")
// 데이터 가져오는 비동기 작업 (가정)
print("데이터를 가져왔엉!")
}
// 호출
fetchData()
이 방식의 단점은 fetchData 함수가 항상 "데이터를 가져왔엉!"이라는 메시지를 출력해야 한다는 점이에요.
만약 다른 작업을 하고 싶다면 이 함수 자체를 수정해야 하죠.
예시: 콜백 함수가 있는 경우
콜백 함수를 사용하면 호출하는 쪽에서 어떤 작업을 할지 정할 수 있습니다.
func fetchData(completion: () -> Void) {
print("데이터 가져오는 중...")
// 데이터 가져오는 비동기 작업 (가정)
completion()
}
// 호출 1: 데이터를 가져온 후 메시지 출력
fetchData {
print("데이터를 가져왔엉!")
}
// 호출 2: 데이터를 가져온 후 다른 작업 수행
fetchData {
print("데이터를 저장했엉!")
}
이 방식의 장점은 fetchData 함수가 호출되는 곳마다 그 후속 작업을 다르게 정의할 수 있다는 점이에요.
코드의 유연성과 재사용성이 높아집니다.
결론
- 콜백 함수를 사용하면 비동기 작업이 끝난 후 어떤 작업을 수행할지를 호출하는 곳에서 정의할 수 있어, 코드가 더 유연하고 재사용이 가능해집니다.
- 만약 fetchData 함수 안에 모든 작업을 넣으면, 모든 후속 작업이 고정되어 버려 다른 동작을 하려면 함수 자체를 수정해야 합니다.
- 콜백 함수는 비동기 작업에서 후속 작업을 처리하기 위한 중요한 도구입니다.
'iOS > Swift' 카테고리의 다른 글
enum을 통해 api 함수 관리해보기 (0) | 2024.08.31 |
---|---|
헷갈리기 쉬운 델리게이트 패턴으로 컬렉션 셀의 데이터 전달하기 (0) | 2024.08.28 |
Swift에서 Any와 AnyObject의 차이점은 무엇인가요? (0) | 2024.08.23 |
Storyboard와 XIB의 차이점은 무엇인가요? (0) | 2024.08.21 |
왜 DispatchQueue.main을 tableView(_ : cellForRowAt: )에 안 넣었나? (0) | 2024.08.20 |