학습
Swift 동시성 프로그래밍(Concurrency)
Swift 동시성 프로그래밍(Concurrency) — 고급
동시성 프로그래밍(Concurrency)
1. 도입 (왜 배워야 하는가)
동시성 프로그래밍은 현대 애플리케이션에서 매우 중요한 요소입니다. 모바일 혹은 웹 애플리케이션은 사용자 인터페이스(UI)와 백그라운드 작업을 동시에 처리해야 하며, 이 과정에서 효율적인 자원 관리를 통해 성능을 극대화하는 것이 필요합니다. 동시성을 이해하고 활용하지 않으면, 앱은 느려지거나 사용자 경험이 저하될 수 있습니다. 예를 들어, 네트워크 요청을 처리하는 동안 UI가 멈춘다면 사용자는 앱이 응답하지 않는다고 느낄 것입니다. 따라서 동시성 프로그래밍을 통해 이러한 문제를 예방하고, 애플리케이션의 전반적인 성능을 향상시킬 수 있습니다.
2. 핵심 개념 설명
동시성 프로그래밍에서 자주 사용되는 주요 개념은 다음과 같습니다:
| 개념 | 설명 |
|---|---|
| 스레드(Thread) | 작업을 수행하는 기본 단위로, 여러 개의 스레드를 사용하면 동시에 여러 작업을 처리할 수 있다. |
| 비동기(Asynchronous) | 작업이 완료되는 것을 기다리지 않고 다음 작업을 시작하는 방식. 마치 여러 개의 요리를 동시에 하는 것과 같다. |
| 동기(Synchronous) | 작업이 완료될 때까지 기다리는 방식. 한 가지 요리를 끝내고 다음 요리를 시작하는 것과 유사하다. |
| GCD(Grand Central Dispatch) | Apple의 API로, 비동기 작업을 쉽게 관리할 수 있도록 도와준다. |
이러한 개념들은 마치 주방에서 여러 요리를 동시에 하는 것과 비슷합니다. 요리사가 각 요리를 효율적으로 처리하기 위해 스케줄을 조정하고, 필요한 재료를 준비하는 것과 같죠.
3. 기본 코드 예제
기본적인 비동기 작업을 수행하는 예제를 살펴보겠습니다.
import Foundation
print("작업 시작")
DispatchQueue.global().async {
// 1초 대기
sleep(1)
print("비동기 작업 완료")
}
print("작업 진행 중...")
실행 결과:
작업 시작
작업 진행 중...
비동기 작업 완료
print("작업 시작"): 작업이 시작됐음을 출력합니다.DispatchQueue.global().async { ... }: 전역 스레드에서 비동기 작업을 시작합니다.sleep(1): 1초 동안 대기합니다. 이 시간 동안 다른 작업이 진행될 수 있습니다.print("비동기 작업 완료"): 비동기 작업이 완료되었음을 출력합니다.print("작업 진행 중..."): 비동기 작업이 완료되기 전에 이 메시지가 출력됩니다.- 쇼핑몰에서 장바구니에 상품 추가하기:
- 이미지 다운로드:
- 메인 스레드에서 긴 작업 수행하기:
- UI 업데이트를 메인 스레드에서 하지 않기:
- 동시성 프로그래밍은 현대 애플리케이션에서 필수적이다.
- 비동기와 동기 개념을 확실히 이해해야 한다.
- GCD는 비동기 작업을 쉽게 관리할 수 있도록 도와준다.
- UI 업데이트는 항상 메인 스레드에서 수행해야 한다.
- 다음 학습 주제로는
Swift의 Async/Await를 추천합니다. 이는 코드 가독성을 높이고, 비동기 작업을 더욱 간편하게 관리할 수 있도록 도와줍니다.
4. 실전 활용 예제
쇼핑몰 앱에서 사용자가 상품을 장바구니에 추가할 때, 네트워크 요청을 통해 서버와 통신해야 합니다. 이 과정에서 UI가 멈추지 않도록 비동기 처리를 합니다.
func addToCart(productId: String) {
DispatchQueue.global().async {
// 서버에 상품 추가 요청
let success = server.addProductToCart(productId)
DispatchQueue.main.async {
if success {
print("상품이 장바구니에 추가되었습니다.")
} else {
print("상품 추가 실패")
}
}
}
}
앱에서 이미지를 다운로드할 때도 비동기 처리가 필요합니다. 사용자는 이미지를 기다리는 동안 다른 작업을 할 수 있어야 합니다.
func downloadImage(url: String) {
DispatchQueue.global().async {
// 이미지 다운로드
let imageData = downloadData(from: url)
DispatchQueue.main.async {
// UI 업데이트
self.imageView.image = UIImage(data: imageData)
}
}
}
5. 흔한 실수와 주의사항
- 잘못된 코드:
// 메인 스레드에서 긴 작업 수행
for _ in 0..<1000000 {
print("Processing...")
}
- 올바른 코드:
DispatchQueue.global().async {
for _ in 0..<1000000 {
print("Processing...")
}
}
- 잘못된 코드:
DispatchQueue.global().async {
// 비동기 작업
self.label.text = "업데이트" // 메인 스레드가 아님
}
- 올바른 코드:
DispatchQueue.global().async {
// 비동기 작업
DispatchQueue.main.async {
self.label.text = "업데이트" // 메인 스레드에서 UI 업데이트
}
}