iOS 앱을 개발하다 보면 서버에 저장된 이미지를 URL로 불러와 화면에 표시해야 하는 경우가 자주 있습니다. Swift에서는 URLSession의 dataTask를 활용해 간단하게 구현할 수 있습니다.
이미지는 용량이 클 수 있기 때문에 반드시 백그라운드에서 다운로드해야 합니다. 메인 스레드에서 직접 처리하면 UI가 멈추거나 버벅이는 현상이 발생할 수 있기 때문입니다.
1. 프로젝트 기본 설정
먼저 빈 프로젝트를 생성하고 스토리보드에 UIImageView를 하나 추가합니다. 그다음 해당 이미지 뷰의 아울렛(Outlet)을 ViewController에 연결합니다.
이제 URL로부터 이미지를 가져오는 코드를 작성해 보겠습니다.
2. URLSession으로 이미지 데이터 받아오기
가장 기본적인 방식은 dataTask를 사용해 데이터를 비동기로 받아온 뒤, 메인 스레드에서 UIImage 객체로 변환하는 것입니다.
func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
func downloadImage(from url: URL) {
getData(from: url) { data, response, error in
guard let data = data, error == nil else {
return
}
DispatchQueue.main.async() {
self.image = UIImage(data: data)
}
}
}이 코드를 실행하면 지정한 URL에서 이미지를 다운로드한 후, UIImage 객체를 생성해 imgView에 할당합니다. 네트워크 작업은 백그라운드에서 수행되고, 결과 이미지 적용만 메인 스레드에서 처리되므로 UI가 끊기지 않습니다.
3. UIImageView 확장(Extension)으로 재사용성 높이기
위 코드를 매번 ViewController마다 작성하는 것은 비효율적입니다. UIImageView의 확장(Extension)으로 만들어 두면 어떤 이미지 뷰에서든 손쉽게 재사용할 수 있습니다.
extension UIImageView {
func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
func downloadImage(from url: URL) {
getData(from: url) { data, response, error in
guard let data = data, error == nil else {
return
}
DispatchQueue.main.async() {
self.image = UIImage(data: data)
}
}
}
}4. viewDidLoad에서 호출하기
이제 viewDidLoad() 메서드(또는 원하는 다른 위치)에서 다음과 같이 호출하면 됩니다.
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://static.independent.co.uk/s3fs-public/thumbnails/image/2017/09/12/11/naturo-monkey-selfie.jpg?w968h681")
self.imgView.downloadImage(from: url!)
}5. 실행 결과
앱을 기기나 시뮬레이터에서 실행하면 지정한 URL의 이미지가 정상적으로 화면에 표시됩니다.
추가 팁
실무에서는 강제 언래핑(url!) 대신 옵셔널 바인딩을 사용하는 것이 안전하며, 동일한 이미지를 반복해서 다운로드하지 않도록 캐싱(NSCache)을 적용하는 것이 좋습니다. 또한 Kingfisher, SDWebImage 같은 검증된 오픈소스 라이브러리를 활용하면 캐싱, 플레이스홀더, 오류 처리까지 한 번에 해결할 수 있어 개발 효율이 크게 향상됩니다.