리스트나 그리드 형태의 UI에서 많은 양의 이미지를 불러와야 할 때 메인 스레드에서 모든 과정을 처리하면 화면이 버벅거리거나 멈추는 현상이 발생할 수 있어요. 특히 이미지 데이터를 네트워크로 가져오고 이를 디코딩하여 메모리에 올리는 과정은 상당한 CPU 자원을 소모하기 때문에 반드시 백그라운드 환경에서 수행해야 하거든요. 이때 실무에서 가장 기본적으로 활용하는 도구가 바로 Grand Central Dispatch(GCD)예요. GCD를 사용하면 복잡한 멀티스레딩 로직을 직접 구현하지 않고도 시스템이 제공하는 큐에 작업을 할당하여 효율적으로 처리할 수 있어요.
func fetchImage(from url: URL, completion: @escaping (UIImage?) -> Void) {
// 백그라운드 큐에서 데이터 로딩 및 이미지 변환 수행
DispatchQueue.global(qos: .userInitiated).async {
if let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
// UI 업데이트는 반드시 메인 스레드에서 수행
DispatchQueue.main.async {
completion(image)
}
} else {
DispatchQueue.main.async {
completion(nil)
}
}
}
}
위 코드에서 `DispatchQueue.global`을 사용하는 이유는 메인 스레드와 별개로 작업을 분리하기 위해서예요. 네트워크 통신이나 데이터 변환 같은 무거운 작업이 백그라운드에서 실행되는 동안 사용자는 UI를 멈춤 없이 조작할 수 있게 되거든요. 하지만 가장 중요한 포인트는 마지막에 이미지를 `UIImageView`나 다른 UI 컴포넌트에 할당하는 과정이에요. iOS 환경에서는 모든 UI 업데이트가 메인 스레드에서만 이루어져야 하기 때문에, 백그라운드에서 작업을 마친 후 반드시 `DispatchQueue.main.async`를 통해 다시 메인 스레드로 돌아와야 해요. 이 흐름을 놓치면 화면이 갱신되지 않거나 앱이 비정상적으로 종료될 수 있거든요.
단순히 비동기 처리를 적용하는 것 외에도 실무에서는 메모리 관리 측면을 함께 고려해야 해요. 동일한 URL에서 반복적으로 이미지를 불러올 때 매번 네트워크 요청을 보내지 않도록 `NSCache`를 활용하여 한 번 로드한 이미지를 캐싱해두는 방식이 일반적이에요. 최근에는 Swift Concurrency가 도입되면서 `async/await` 구문을 사용할 수도 있지만, 기존 코드와의 호환성이나 세밀한 큐 제어가 필요한 상황에서는 여전히 GCD가 강력한 도구로 쓰이고 있어요. 적절한 큐 선택과 메인 스레드 복귀 시점을 정확히 파악하는 것이 매끄러운 사용자 경험을 만드는 핵심이에요.
'develop > iOS' 카테고리의 다른 글
| iOS URLSession 비동기 네트워크 요청 구현 (0) | 2026.07.30 |
|---|---|
| UIStackView 동적 뷰 추가 및 제약 조건 처리 (0) | 2026.07.22 |
| 키체인 인증 정보 저장 구현 (0) | 2026.07.16 |
| Swift 옵셔널 언래핑 방법 (if let, guard let, nil 병합 연산자) (0) | 2026.07.11 |
| ios 탈옥폰 체크(swift) (0) | 2020.04.23 |






