
미술관 전시 후기를 남길 수 있는 앱을 만드는 과정 중, 유저가 올린 사진을 업로드 한 순서에 맞게 후기 상세 페이지에 바인딩 하는 과정을 정리 해봤다. 유저의 업로드 할 때의 순서와 후기 페이지에서 그 사진을 보여줄 때의 순서가 동일 하게 하는 것을 목적으로 하고 그 과정을 정리한 글이다.
생각 보다 이 기능을 구현 하는데 꽤 오래 걸렸었다. 우선 이 앱은 FireBase 서버를 사용 했는데, 나의 처음 의도는 서버에 업로드 할때 어떤 배열을 하나 만들고 그 배열에 사진을 저장 하는 로직을 사용 했었다. 사진이 업로드 될 때 파일 이름을 순서에 맞게 생성 했는데, 업로드 할 땐 잘 되는데 그걸 바인딩 할 땐 이상하게 그 순서로 적용이 안되고 섞이는 문제가 발생 했다.
예를 들어 1 - 2 - 3 의 순서로 파일 이름을 만들고 그 이름의 순서로 바인딩 하는데 2 - 3 - 1 이렇게 섞이는 것이 아니겠는가. 섞이는 것이 나름의 순서를 가지고 있으면 어디서 잘 못 됐는지 찾을 수 있겠는데 그게 아니고 무작위 였다.
지금 생각난 나름의 원인은 네트워크에서 비동기로 사진을 가져올 때, 각각 사진의 용량이 다르기 때문에 용량이 작은 사진 먼저 로딩이 완료 되면 그걸 바로 바인딩을 하는 것 같다. 즉, "바인딩이 완료 되고 파일 이름에 따라 정렬을 해라."가 빠져 있었던 것 이다.
그렇기 때문에 사진 로딩이 완료 되고 정렬 하는 로직을 추가 하는 방법을 생각 했다.
func sortImageUrls(_ urls: [String]) -> [String] {
return urls.sorted { url1, url2 in
// 순서 번호 추출 로직
let order1 = extractOrderFromUrl(url1)
let order2 = extractOrderFromUrl(url2)
return order1 < order2
}
}
func extractOrderFromUrl(_ url: String) -> Int {
// URL에서 파일 이름을 추출
let fileName = url.components(separatedBy: "/").last ?? ""
// 파일 이름에서 순서 번호 추출
let numberString = fileName.components(separatedBy: "_").last?.components(separatedBy: ".").first ?? "0"
return Int(numberString) ?? 0
}
우선 이런 식으로 업로드 할 때의 넣은 파일 이름에 있는 순서를 추출하는 함수를 만들고, URL 주소를 정렬 한다.
func loadImages(from urls: [String]) {
// ...
for urlString in sortedUrls {
group.enter()
// SDWebImageManager를 사용한 이미지 로딩
group.leave()
}
group.notify(queue: .main) {
// 컬렉션 뷰 리로드
}
}
그 후에 정렬된 URL을 기반으로 SDWebImageManager를 사용하여 이미지를 비동기적으로 로드한다. 이 때, 각 이미지의 로드 완료 시점을 추적하기 위해 DispatchGroup을 사용하였다.
순서대로 URL 주소가 정렬 되면, 이미지를 그 순서에 맞게 바인딩 하면 유저가 업로드 할 때, 올린 순서로 보여지게 되는 것이다.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let imageData = imageDatas[indexPath.row]
cell.imageView.image = imageData.image
// ...
}
사용자 중심의 개발, 작은 디테일의 큰 영향
이 프로젝트를 통해 배운 가장 중요한 교훈은, 사용자가 업로드한 이미지의 순서를 정확하게 유지하는 것이 얼마나 중요한지였다. 초기에는 간단해 보이는 기능이었지만, 실제로 구현하면서 많은 도전과 어려움이 있었다. 특히, 비동기 로딩과 파일 이름을 기반으로 한 정렬 방식에서의 문제는 새로운 해결책을 찾도록 했다.
정렬된 URL을 기반으로 한 SDWebImageManager를 통한 이미지 로딩과 DispatchGroup을 사용한 동기화 방법은 큰 도움이 되었다. 또한 문제가 발생 했을 때 차근 차근 하나씩 디버깅을 하면서 되짚어 보는 방법이 크게 도움이 됐다.
뭔가가 예상 대로 되지 않는다면 분명 내 생각 대로 로직을 작성 했지만 어디선가 빠진 부분이 있다는 의미 같다. 간혹 컴퓨터의 작동 방법을 사람 처럼 생각 하고 코드를 작성 할 때가 있다. 하지만 컴퓨터는 디테일 하게 코드를 작성 하지 않으면 컴퓨터는 빠진 부분을 어림 잡지 못한다는 사실을 느꼈다.
마지막으로, 이 프로젝트는 사용자 중심의 개발 방식과 작은 디테일의 중요성을 다시 한번 일깨워 준 일화였다. 사용자의 관점에서 생각하고, 항상 세심한 주의를 기울이며 개발하는 것이 중요하다는 것을 잊지 않아야 겠다.