SVG 진짜 정답인가? 그럼 PNG는?
생산성과 효율성을 지향합니다. 근데 이제 퍼포먼스와 안정성을 곁들인
작성자 : Leedi— iOS Engineer @ DelightRoom
앱 개발자는 필연적으로 한번씩 겪는 늪이 있죠.
그것은 바로 리소스 관리의 늪…
특히 이미지 리소스 관리의 늪에 필연적으로 빠져버리는 우리의 운명..
그거슨 데스티니..
하지만 이왕 운명을 맞이할 거 조금 더 효율적이었으면 좋겠고, 이왕이면 퍼포먼스적으로도 우수했으면 좋겠고, (왜 우수한지도 알면 더 좋겠고), 안정성은 필수겠죠?! 그래서 준비해 본 이야기를 시작하도록 하겠습니다. (사실 모든 이야기를 다 풀기는 어렵고, 가장 많이 사용하는 PNG와 SVG에 대한 이야기 입니다.)
1. 늪의 탄생
모든 문제에는 원인이 있습니다. 그리고 리소스 늪도 마찬가지죠. 그럼 이 리소스의 늪이 탄생하게 된 원인은 무엇일까요?
아이러니하게도 모든 문제의 원인은 기술의 발전입니다.
히스토리를 간단히 설명하고 가자면, 2007년 애플은 iPhone을 출시했습니다. 그리고 이 때의 아이폰은 240x320의 해상도를 가진 3.5인치 디스플레이를 갖고 있었죠. 하지만 2010년 Retina Display를 가진 iPhone 4를 출시하게 되며, 같은 화면에서 2배 높은 해상도를 갖게 됩니다. 그리고 아이폰 6 Plus가 나오며 해상도는 3배나 증가 해 버립니다.
그리고 너무나 당연하게도 애플은 이미지들이 제대로 들어있지 않을 경우, 앱을 리젝 해 버리기도 합니다.
Retina HD Display를 탑제한 디바이스에 저해상도의 이미지가 있을 경우, 업스케일링을 통해 이미지는 노출 될 수 있지만, 깨진 상태로 보일 것입니다. 반대로 높은 해상도의 이미지만 있을 경우 저 해상도 디바이스에서는 stroke등의 라인들이 사라질 수도 있습니다.. 결국 유저들에게 완벽한 이미지를 제공하기 위해서 우리는 3가지 타입의 디스플레이를 가진 디바이스를 지원해야 합니다.
- Retina Display를 탑제하지 않은 디바이스
(iPhone 4이전 모델들) - Retina Display를 탑제한 디바이스
(iPhone 4 ~ iPhone 5) - Retina HD Display를 탑제한 디바이스
(iPhone 6 ~ 현재)
그리고 이 display들을 지원하기 위해 1x 2x 3x 의 이미지들을 관리 해야 했고, 이렇게 현재의 이미지 리소스의 늪이 탄생하게 되었습니다.
하지만 이렇게 된다고 내 앱의 용량을 걱정할 필요는 없습니다. 왜냐면 똑똑한 애플 앱스토어는 유저가 앱을 다운로드 받을 때 thinning 을 통해 필요한 imageAsset만을 받기 때문이죠 🙂
예를들어 iPhone 4 유저에게는 3x의 이미지 Asset은 굳이 필요 없기 때문에 이를 받지도 않는 것이죠.
하지만 문제는 하나 더 있습니다. 우리는 하나의 scale의 이미지만을 지원하고 있지 않기 때문입니다. 16x16, 24x24, 48x48 등등 아이콘 set이 늘어날 수록 우리가 관리해야할 사이즈는 * n 개가 되는 놀라운 매직..🫢 더불어 이러한 방식은 유저의 앱 사이즈에도 영향을 미치게 됩니다..
그럼 하나의 이미지로 돌려쓰면 안되나요? 라고 질문 하실 수도 있지만..
애플이 하지말래여… 😞
Create images so that they do not need resizing. If you plan to use an image at a particular size, be sure to create the corresponding image resource at that size. Do not create a larger image and scale it down to fit, because scaling requires additional CPU cycles and requires interpolation. If you need to present an image at variable sizes, include multiple versions of the image at different sizes and scale down from an image that is relatively close to the target size.
이렇게 리소스 늪에서 벗어날 수는 없는가? 물론 모든 사이즈에 대응할 수 있는 SVG라는 포멧이 있지만 XCode에서는 지원하지 않고 있었죠.. 그렇게 슬퍼하던 중, 킹플께서는 Xcode 12 부터 svg파일 형식을 하겠다고 발표했습니다. 🎉 (왜 이제서야 지원해준거지 싶을 정도로 늦어서 갓플 아니고 킹플..)
2. SVG(Single Vector Image) 두둥등장-!
그럼 SVG를 썼을 때의 장점은 뭐가 있을까요? 왜 그토록 사람들은 Xcode에서 svg를 지원해주길 기다렸을까요?
두둥-! 탁! 🥁
가장 큰 장점은 관리해야할 이미지 Asset 갯수와 용량이 확연하게 줄어들기 때문입니다.
single scale로 관리를 하기 때문에, 여러 Display에 대응하기 위해 관리해야했던 1x 2x 3x 를 관리할 필요가 없어집니다. (이게 은근히 손이 많이 가더라구요. 특히 이미지 변경할 때는 더..) 더불어 16x16 24x24 48x48 의 사이징도 필요가 없죠. 즉 하나의 svg file만 있으면 모든 사이즈에 대응할 수 있습니다.
어떻게 이런게 가능한걸까요 ?
답은 바로 여러분들도 아시다시피, Vector Image 이기 때문입니다.
(그닥 놀랍지 않은 사실 😋)
svg는 슬쩍 보기에는 image파일 같지만, 막상 파일을 살펴보면 데이터 관리를 위한 XML(Extensible Markup Language)로 짜여져 있음을 확인할 수 있습니다.
그렇기 때문에 어떤 사이즈로 변환을 하던 그에 맞춰 그려주기 때문에 깨지지 않을 수 있는 것이죠!
그리고 xml로 구성되어 있다는 것은 뭐다? svg 파일을 개발자가 직접 수정할 수도 있다는 것이죠.
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.2" d="M64 32C64 49.6731 49.6731 64 32 64C14.3269 64 0 49.6731 0 32C0 14.3269 14.3269 0 32 0C49.6731 0 64 14.3269 64 32Z" fill="#FCD823"/>
<path opacity="0.2" d="M58 32C58 46.3594 46.3594 58 32 58C17.6406 58 6 46.3594 6 32C6 17.6406 17.6406 6 32 6C46.3594 6 58 17.6406 58 32Z" fill="#EDBB07"/>
<path d="M52 32C52 43.0457 43.0457 52 32 52C20.9543 52 12 43.0457 12 32C12 20.9543 20.9543 12 32 12C43.0457 12 52 20.9543 52 32Z" fill="url(#paint0_linear_1796_2820)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.8318 26.2567C23.1697 25.7397 23.8628 25.5945 24.3799 25.9325L28.3469 28.5257C28.4501 28.5931 28.5387 28.675 28.6117 28.767C28.7348 28.8646 28.839 28.9897 28.9142 29.1384C29.193 29.6897 28.9721 30.3625 28.4209 30.6412L23.7594 32.9983C23.2082 33.2771 22.5354 33.0562 22.2567 32.505C21.9779 31.9537 22.1988 31.2809 22.75 31.0022L25.7368 29.4919L23.156 27.8048C22.6389 27.4669 22.4938 26.7738 22.8318 26.2567ZM39.6201 25.9325C40.1371 25.5945 40.8302 25.7397 41.1682 26.2567C41.5061 26.7738 41.361 27.4669 40.8439 27.8048L38.2631 29.4919L41.2499 31.0022C41.8011 31.2809 42.022 31.9537 41.7432 32.505C41.4645 33.0562 40.7917 33.2771 40.2405 32.9983L35.5791 30.6412C35.0278 30.3625 34.8069 29.6897 35.0857 29.1384C35.1609 28.9897 35.2651 28.8646 35.3882 28.767C35.4612 28.675 35.5498 28.5931 35.653 28.5257L39.6201 25.9325ZM42.7746 35.4727C43.0585 35.05 43.6405 34.9314 44.0747 35.2078C44.5088 35.4842 44.6306 36.0509 44.3468 36.4736C43.3304 37.9871 39.5586 42.1848 32.34 42.1848C25.1378 42.1848 20.9308 38.0038 19.712 36.5519C19.3838 36.1608 19.4432 35.5847 19.8449 35.2651C20.2465 34.9455 20.8382 35.0034 21.1664 35.3945C22.2144 36.6429 25.9412 40.3558 32.34 40.3558C38.7223 40.3558 41.9776 36.6595 42.7746 35.4727Z" fill="#171D2E"/>
<defs>
<linearGradient id="paint0_linear_1796_2820" x1="16.7727" y1="45.1818" x2="43.8182" y2="16.7727" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF8A00"/>
<stop offset="1" stop-color="#FFE34E"/>
</linearGradient>
</defs>
</svg>
아래의 이미지는 하나의 Asset을 하나는 SVG로 하나는 PNG 3x 로 추출 한 건데요. 상세 정보를 보면 요렇게다 다름을 눈으로도 바로 확인할 수 있습니다. 그리고 심지어 SVG는 PNG에 비해 용량도 적게 차지함을 확인할 수 있습니다. (svg= 2KB / png = 16KB)
그럼 이렇게 좋은 svg로 전부다 바꿔버리면 되겠네요? 그쵸?
3. 주의사항
하지만 이렇게나 좋은 SVG를 사용함에 있어 몇 가지 주의사항이 있습니다.
1. 너무나 당연하게도 Xcode버젼입니다.
- svg는 xcode12부터 지원을 하기 때문에, 우리가 사용하는 Xcode의 버젼이 몇인지부터 확인을 해보는 것이 필요합니다. 물론 대부분의 독자님들은 이 조건을 충족시킬 것이라 믿어 의심치 않습니다. 🙏
2. App Target이 iOS 13, iPadOS 13, macOS 10.15 이상 인가?
- svg를 사용하기 위해서 우리 앱의 최소버젼도 확인이 필수입니다. 만약 이 이하를 지원해야한다면, PDF형식으로 처리하는 방법 역시 있다고 합니다. (저도 요건 써보지 않아서 잘은 모르겠습니다.)
3. 너무 복잡한 이미지는 아닌가?
- 다소 추상적일 수 있으나 svg는 결국 수학적 계산이 필요합니다. 단순한 이미지는 신경 쓰지 않아도 되지만, 복잡한 이미지일 수록 크기가 커질 수 있어 오히려 png로 처리하는 것이 더 유리할 수 있습니다.
4. Limited Color Depth
- SVG이미지는 color depth가 제한적입니다. 그렇기 때문에 이를 적당한 값으로 재구성하여 보여주기도 합니다. 저희 디자이너분도 ‘종종 예상했던 색과 다르다.’ 라는 피드백을 주시기도 합니다. 그러므로 정확한 이미지 색을 표현하기 위해서는 PNG를 통해 노출시키는 편이 더 효과적이기도 합니다.
5. Gradation이 들어가 있지 않은 가?
- 왜인지는 잘 모르겠지만, Xcode에서 svg를 사용함에 있어 파일에 Gradation이 들어가 있는 경우 아예 비어있는 화면으로 나오는 이상한 버그가 있더라구요 🤔 때문에 Gradation이 있을 경우 안정성을 위해 png로 관리하시길 권장 드립니다. xcode상에서는 정상적으로 나오더라도 유저의 디바이스에서 비어보이는 상황도 몇번 경험을 해본 후로는 안정적으로 gradation은 png로 관리하고 있습니다.
6. Resizing 이 필요한 경우 Preserve Vector Data Check 필요!
- 요거는 사용전의 체크리스트는 아니지만, 모바일 특성상 imageAsset의 sizing을 변경할 일이 많지 않아서 인지, svg 사용하는 곳들을 확인해도 이를 알려주는 곳이 없어서 적어봤습니다.
svg의 특성 상 하나의 asset만 넣어두고 여러 사이즈로 변환하여 쓰게 되는데, 이를 체크해두지 않을 경우 높은 사이즈로 변환시 이미지가 깨지는 것을 확인 할 수 있습니다. svg의 장점을 확실하게 사용하기 위하여 체크를 확인하시면 좋습니다.
4. 결론
결론을 말씀드리자면 당연하게도 저희는 둘 다 씁니다.
이미지가 단순하고, gradation등의 추가적인 요소들이 적을 때에는 SVG를(사실 거의 대부분이 이에 해당합니다.) gradation 등의 요소가 있어 안정성에 문제가 될 수 있다 판단되면 PNG를 씁니다.
생산성도 중요하지만 그보다 중요한 것은 언제나 언제나 유저에게 안정적인 앱을 제공하는 것이라고 생각하기 때문입니다. 하지만 막연한 거부도 막연한 수용도 아닌 이해도가 높은 상태로의 관리를 지향합니다. 그리고 이 글을 읽어주신 독자님들도 저와 마찬가지일 것이라 믿어 의심치 않습니다.
마지막으로 ChatGPT에 물어본 png대신 svg를 썼을 때 생길 수 있는 문제점으로 글을 마치겠습니다.
끝까지 읽어주셔서 감사합니다 🙂
ref:
https://help.apple.com/xcode/mac/current/#/devbbdc5ce4f
https://www.mfractor.com/blogs/news/understanding-ios-image-assets
https://developer.apple.com/library/archive/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/LoadingImages/LoadingImages.html
⏰ 딜라이트룸에서 알라미와 함께 아침을 바꿀 분들을 모십니다 🙌
딜라이트룸의 다양한 채널들을 팔로우하고 빠르게 소식을 받아보세요!
- 지금 바로 미디엄 팔로우하고 다음 아티클도 빠르게 만나보세요!
- 딜라이트룸 소식을 가장 빠르게! 딜라이트룸 링크드인 🔗
- 높은 평점으로 난리난 딜라이트룸 잡플래닛 ✅
- 딜라이트룸 일상을 엿볼 수 있는 인스타그램 📸