NukeUI
안녕하세요. 그린입니다🟢
이번 포스팅에서는 이미지 캐싱을 처리해주는 NukeUI에 대해 알아보겠습니다🙌
이미지 캐싱을 처리해주도록 도와주는 대표적인 라이브러리로 Kingfisher와 NukeUI가 있죠?
그리고 요즘은 애플에서 제공하는 AsyncImage로도 많이 쓰이는것 같더라구요.
저는 이중에 NukeUI가 편리하다고 생각하고 성능 상 이점도 존재하기에 이를 학습해봤어요.
그럼 NukeUI가 어떤것이고 어떻게 사용할 수 있는지 자세히 알아보시죠!
NukeUI?
아시다시피 Nuke라는 라이브러리에서 파생되었어요.
SwiftUI 환경에 가장 최적화시켜 LazyStack과 같이 지연 이미지 로딩을 제공해줍니다.
즉 AsyncImage와 비슷하다고 할 수 있겠어요!
기존 SwiftUI에서 Image라는 기능을 제공해 이미지를 보여주는데 여기서 조금 더 보완해 LazyImage라는 타입을 만들어
사용할 수 있게 도와줍니다.
즉 기조는 Nuke를 사용해 이미지를 로드하기에 사용자 지정 캐시, 미리 가져오기, 병합, 백그라운드 작업, 우선순위 등 기본적으로 다양하게 쓰는 성능을 활용할 수 있습니다.
물론 LazyImageView를 이용하여 UIKit 환경에서도 아주 잘 사용될 수 있습니다.
또한 아래 Gifu에서 지원하는 GIF도 지원하기에 애니메이션 이미지도 효율적으로 재생할 수 있습니다..!
https://github.com/kaishin/Gifu
NukeUI를 채택하면 요 Gifu도 설치될거에요🙌
NukeUI의 최소 요구사항
Swift 5.3, Xcode 12 그리고 iOS 11 이상에서 사용 가능합니다!
다만 SwiftUI에서 LazyImage를 사용하기 위해서는 iOS 14 이상이 되어야합니다.
그럼 저희는 우선 SwiftUI 환경에서 사용해보도록 하죠!
NukeUI 기본 사용법
우선 아주 간단하게 LazyImage를 이용해 이미지를 띄워줄 수 있습니다.
아래와 같이 source에 이미지가 저장된 URL, String, ImageRequest로 전달해 설정해줄 수 있습니다.
struct ContainerView: View {
var body: some View {
LazyImage(source: "https://example.com/image.jpeg")
}
}
아주 간단하죠?
NukeUI를 통해 이미지 옵션 설정
받아온 이미지의 리사이징 모드 및 프레임 사이즈 등을 아래와 같이 지정해서 사용할 수 있습니다.
LazyImage(
source: "https://example.com/image.jpeg",
resizingMode: .center
)
.frame(height: 300)
다만 LazyImage이기에 aspectRatio를 직접 사용할 수 없습니다.
NukeUI를 통해 이미지 로드 전 대체 이미지 보여주기
이미지를 로드하기까지 아주 짧은 시간이지만 간혹 서버의 이슈 등으로 길게 걸릴때도 있고 그 짧은 시간이라도 대체 이미지를 보여주고 싶을때가 있습니다.
즉 해당 이미지 영역을 아무것도 노출하지 않는것보다 이미지 준비중과 같은 이미지 혹은 gif등이 들어오면 더 좋겠죠?
이를 위해 NukeUI는 아주 손쉽게 사용하도록 도와줍니다.
LazyImage(source: $0) { state in
if let image = state.image {
image // Displays the loaded image
} else if state.error != nil {
Color.red // Indicates an error
} else {
Color.blue // Acts as a placeholder
}
}
이렇게 image가 에러 혹은 없다면 원하는 대체 이미지 및 뷰를 넣어주면 됩니다!
NukeUI 애니메이션 끄기
이미지가 로드 되면 기본적으로 애니메이션과 함께 표시됩니다.
만약 애니메이션 없이 빠르게 팟!하고 뜨고 싶다면 아래 메서드를 이용하면 됩니다.
LazyImage(source: "https://example.com/image.jpeg")
.animation(nil)
NukeUI의 ImageRequest
위에서 봤던 source 전달자로 ImageRequest도 받을 수 있다 했습니다.
쉽게 말해 URLRequest 타입으로 생각하면 됩니다.
이걸 소스로도 전달할 수 있지만 직접 편의 수정자를 통해 구성해줄수도 있습니다.
LazyImage(source: "https://example.com/image.jpeg")
.processors([ImageProcessors.Resize(width: 44)])
.priority(.high)
.pipeline(customPipeline)
NukeUI의 이미지 다운로드 상태 모니터링
이미지 다운로드 시 해당 상태들을 직접 모니터링 해줄 수 있도록 메서드를 아래와 같이 크게 5가지로 사용할 수 있습니다.
LazyImage(source: "https://example.com/image.jpeg")
.onStart { ... }
.onProgress { ... }
.onSuccess { ... }
.onFailure { ... }
.onCompletion { ... }
시작, 다운로드중, 성공, 실패, 완료 이렇게 말이죠!
NukeUI의 LazyImageView
위에서 보던것은 거진 SwiftUI에서의 사용 방법으로 볼 수 있고,
LazyImgeView라는것은 UIKit, AppKit에서의 대응되어 사용하는 방법입니다.
즉 LazyImage와 같다고 보시면 됩니다🙌
let imageView = LazyImageView()
imageView.placeholderView = UIActivityIndicatorView()
imageView.priority = .high
imageView.pipeline = customPipeline
imageView.onCompletion = { print("Request completed") }
imageView.source = "https://example.com/image.jpeg"
이런식으로 LazyImageView 인스턴스를 만들고 설정 조건을 부여하고 source를 통해 원하는 이미지의 경로를 넣어줍니다.
NukeUI vs Kingfisher vs AsyncImage 비교
실제로 Nuke가 두개보다 성능이 훨 빠르다는 레퍼런스가 공식 문서에 나와있더라구요.
보면 메인 스레드의 성능 비교더라구요.
즉 Nuke가 아주 성능 최적화가 잘 되어있다고 합니다.
그게 실제로도 유의미하게 사용자가 느낄 수 있는 로드 속도차이가 있나 비교 확인하기 위해 아주 간단히 프로젝트를 파봤어요.
https://github.com/GREENOVER/playground/tree/main/ImageTest
요기 레포에 있습니다!
근데 이미지가 몇개 없어서인지 아니면 메인 스레드의 성능일뿐 로드의 속도 차이는 유의미하게 없는건지 몰라도
제가볼땐 느껴지는 체감 차이는 없었습니다🥲
느낀점
킹피셔가 갓피셔인줄 알았는데 그건 또 아닌것 같더라구요.
확실히 Nuke가 사용하기가 되게 쉬웠던것 같아요.
까다롭지 않은 친구여서 좋았습니다ㅎㅎ
다만 킹피셔나 AsyncImage와는 약간 다른 방식이라 프로젝트에서 이미지를 어떻게 띄우고 프레임을 어떻게 가져갈지에 따라 채택하는 라이브러리가 달라질것 같습니다🙌