Weekoding

[Swift] 에셋 카탈로그(Assets.xcassets / 1x, 2x, 3x) 본문

카테고리 없음

[Swift] 에셋 카탈로그(Assets.xcassets / 1x, 2x, 3x)

Weekoding 2023. 1. 15. 20:37

앱을 만듦에 있어서, 기본 아이콘이나 View만으로 디자인이 된다면 밋밋한 앱이 될 것이다.

개성있고 좋은 UI가 담긴 앱이 되기 위해서는 일반 이미지 외에도, 아이콘 이미지, ColorSet, 음악등이 추가로 사용될 수 있을 것이다.

이런 파일들을 Xcode에서는 모두 Asset Type이라고 칭한다.

 

그런데, 여기서 Device마다 필요한 크기나 비율이 다르다.

이럴 때 발생하는 소요를 최소화 하기 위해 xcassets라는 이름을 가진 에셋 카탈로그가 프로젝트 생성 시 자동으로 생성된다.

모든 Assets가 이 곳에서 관리되는 것이다.

한 파일에 대해 여러 가지의 화면 크기에 대응해야 하는 문제를 어떤 방법으로 해결하는지 오늘은 이 녀석에 대해 알아보도록 하자.

오늘의 주인공. 이 폴더가 바로 에셋 카탈로그이다.

 

 

 

📂  Assets.xcassets의 구성

다양한 이미지 파일들의 총 집합체인 Asset Type들을 관리하는 프로젝트 내의 Assets폴더는 다음과 같은 구성을 이루고 있다.

  • 에셋 카탈로그 폴더(appiconset, colorset, imageset 등)
  • json 파일
  • 콘텐츠 파일 (사용자가 넣은 실제 리소스 파일)

위 구성을 직접 확인해보자. 프로젝트 내의 Asset폴더를 Finder로 보면 다음과 같다

정말 json이 있네..? 감이 잘 잡히지 않는다.

직관적인 확인을 위해 이미지 파일을 Assets 폴더에 한번 넣어 보도록 하자. 

 

사진에서 Finder를 먼저 보도록 하자. 난 분명 jpeg만 넣었는데, redApple.imageset폴더와 json 파일이 자동으로 생성되었다.

그 안에 내가 넣은 .jpeg파일이 보인다. 그럼 json파일을 열어보자.

{
  "images" : [
    {
      "filename" : "redApple.jpeg",
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}

첫 번째 element, 즉 scale값이 1x인 element에만 "filename" key가 있다.

Xcode에 1x에만 사과 이미지가 있는데, 이와 관련되어 있다.

사과 그림을 2x로 옮기게 되면 json의 값은 변화한다.

그래도 이 json을 우리가 수정할 일은 없으니 너무 걱정하지 않아도 되겠다.

이런 식으로 Assets가 구성되어 있구나~ 정도로만 참고하고 다음으로 넘어가자.

 

 

 

📂  1x, 2x, 3x? - Scale Factor

에셋 카탈로그가 무엇인지, 어떤 형식으로 이루어져 있는지 알아보았다.

근데 1x, 2x, 3x는 당최 무엇인가?

그러나 이것이 에셋 카탈로그를 사용하는 핵심 이유라고 볼 수 있다.

 

 

🖥  Display의 발전과 point의 등장

현재까지 출시된 iPhone Device의 디스플레이 중 3가지 종류를 보자.

  • Normal Display(iPhone 4 이전)
  • Retina Display(iPhone 4, 5)
  • Retina HD Display(iPhone 6, 7, 8)

+) 이후에 등장한 Display는 아래 두 가지가 있다.

- Super Retina Display(iPhone X 시리즈)

- Super Retina XDR(iPhone 11 Pro ~)

 

디스플레이 기술이 발전한다는 것은, 같은 면적에 더 많은 pixel(디스플레이 구성의 최소 단위, px)이 들어간다는 것을 의미했다.

그래서 iPhone 4세대를 출시하며, 애플은 px이 아닌 pt(point)개념을 함께 도입하였다.

Retina Display 이전에는 pt개념이 필요가 없었다. 1pt = 1px 이었기 때문이다.

그러나 4세대 이후부터의 디스플레이에는 1pt = 4px(1 포인트당 4개 픽셀이 들어감)로, 

기술이 더 발전함에 따라 6세대 이후의 디스플레이는 1pt = 9px(1 포인트에 9개 픽셀이 들어감)이 들어가게 된다.

 

이런 변화에 대응하고자, Asset에 이미지를 적용할 때 1x, 2x, 3x라는 배율의 개념이 도입된 것이다.

같은 면적의 화면인데 각각 픽셀의 양이 다르다.(https://developer.apple.com/design/human-interface-guidelines/foundations/images#scale-factors/)

픽셀 단위로 20X40의 뷰를 그리게 되면,

4세대와 6세대 기종을 비교할 경우 뷰의 크기에 차이가 나게 되어 일관된 화면을 제공하기가 어려워지는 것이다.

 

디스플레이에 맞게(1x, 2x, 3x에 맞게), 이미지를 넣어주면 기기는 자동으로 자신에게 맞는 배율의 이미지를 사용한다.

그래서 pt 단위를 이용하면, pixel per inch(ppi), 즉 면적당 픽셀 수에 관계 없이 같은 크기의 화면을 제공할 수가 있는 것이다.

이런 이유로 Xcode에서는 View나 Font크기 등을 다룰 때 pt를 단위로 사용한다.

 

개발자는 유저가 어떤 Device로 앱을 실행할지 알 수 없으므로, 1x 2x 3x에 대한 이미지를 모두 준비해야 한다.

기본적으로는 파일 이름 뒤에 "@1x", "@2x", "@3x" 를 붙여 식별한다.

기기별로 render at ~ 참고(https://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions)

위 사진을 보면 알 수 있듯 pt개념이 도입된 지(Retina Display가 등장한지) 꽤나 많은 시간이 흘렀기 떄문에,

글을 쓰는 시점 기준으로 iOS12의 최소 지원기기가 iPhone 5S이다.

따라서 iOS 13 이상이 최소 지원 버전이라면, 사실상 1x 배율은 고려하지 않아도 되는 셈.

 

 

🏞 간단하게 이미지를 준비하는 방법

 다음과 같은 사이트들을 이용하여 이미지를 준비하면 훨씬 편리하다. Icon Image와 일반 Image모두 생성이 가능하다.

https://www.appicon.co/#image-sets

 

App Icon Generator

 

www.appicon.co

 

👀 직접 눈으로 확인해 보기

생성된 파일들의 사이즈 차이를 다음과 같이 확인해볼 수 있었다.

 

 

 

📂  App Thining

Assets 관련 자료를 찾아보다 App Thining이라는 키워드를 발견해서 좀 찾아보았다.

간단하게 알아보도록 하자.

 

App Thining: 애플리케이션이 설치될 때, Device에 특성에 맞게 설치되도록 하는 설치 최적화 기술.

최소한의 디스크 사용빠른 다운로드를 제공하기 위한 기술이다. 구성은 다음과 같다.

  • Slicing
  • Bitcode
  • On-demand resource

 

🔧 Slicing

: 각각의 Device나 OS Version을 지원하는 다양한 App bundle을 만들고, 전달하는 과정.

Slicing is the process of creating and delivering variants of the app bundle for different target devices and operating system versions.

App Store Connect에 Full version App을 업로드하게 되면,

App Store가 자동으로 App이 지원하는 Device / OS Version 별로 variants들을 생성하여 제공한다.

그래서 User가 App Store를 통해 App을 설치하게 되면 User의 Device와 OS Version에 맞는 variants로 다운된다.

 

⌘) variants, 즉 다양한 App bundle은 오직 실행가능한 architecture나 resources만 포함된다.

⌘) Xcode로 개발 시에도 slicing을 통해 build하기 때문에 다양한 Device / OS version 에서의 테스트가 가능한 것.

 

 

🔧 Bitcode

: 컴파일된 프로그램의 중간표현

Bitcode is an intermediate representation of a compiled program.

Bitcode를 포함하게 되면, 향후 App Store에 새로운 버전을 제출할 필요 없이 Apple이 app binary를 다시 최적화 할 수 있게 한다.

 

⌘) intermediate representation: 소스 코드를 표현하기 위해 컴파일러나 가상 머신에 의해 내부적으로 사용되는 데이터 구조 또는 코드

⌘) app binary: 컴퓨터가 실행할 기계어 코드가 포함된 파일

⌘) iOS는 Bitcode가 default이지만 optional이며, tvOS/watchOS는 required라고 한다.

 

🔧 On-demand resource

: resource(이미지나 사운드 등)들을 키워드로 태그하고, 태그별로 그룹 요청이 가능한 리소스.

On-demand resources are resources—such as images and sounds—that you can tag with keywords and request in groups, by tag.

App Store는 Apple Server에 있는 resources를 호스팅하고 다운로드를 관리한다. 고 적혀있는데..

사례를 보니 이해가 되었다.

 

For example, an app may divide resources into levels and request the next level of resources only when the app anticipates that the user will move to that level. Similarly, the app can request In-App Purchase resources only when the user makes the corresponding in-app purchase.

예를 들자면, app은 level에 따라 resources를 나누고

유저가 다음 레벨로 나아갈 것이 예상될 때만 다음 레벨에 대한 resources를 요구한다.

비슷한 예로, app은 Use의  In-App Purchase에 대응되는 resources만을 요구할 수도 있다.

 

resources를 키워드를 통해 태깅하고, 그 태그별로 그룹요청을 하면 위 두 사례와 같은 작업들이 가능한 것이다.

그랬을 때 얻을 수 있는 효과는 다음과 같다.

- App size가 작아지므로 다운로드와 실행 속도가 향상된다.

- 필요시마다 background로 resources가 다운로드되므로, User는 그동안 앱을 탐색할 수 있다.

- OS가 디스크 공간이 부족할 때, 잘 사용되지 않는 on-demand resource를 정리함으로써 공간을 확보할 수 있다.

 

 

 

 

 

 

📌 마치며

처음 Image를 넣을 때 참참참 게임도 아니고 세 가지 Scale Factor박스를 보고 멘붕이 왔었던 것이 기억난다.

이후 슥슥 훑어가며 아 그냥 다 채워주어야 하는구나~ 하고 넘어갔었는데

이미지를 Asset에 추가할 때 마다 궁금하기도 했고 이미지 추가에 있어 확신도 없었던 것 같다.

묵은 궁금증이 해소되어 속이 다 후련하다 !

 

 

 

오류 및 지적사항은 댓글로 남겨주시면 감사하겠습니다!

참고 : 

https://help.apple.com/xcode/mac/current/#/dev10510b1f7

https://kangraemin.github.io/ios/2021/01/21/iOS-image-set/

https://developer.apple.com/design/human-interface-guidelines/foundations/images#scale-factors/

https://velog.io/@zeke/App-thinning-%EC%9D%B4%EB%9E%80

https://help.apple.com/xcode/mac/current/#/devbbdc5ce4f

Comments