주희하세요!

DarkMode 적용하기

2019-12-02
Juhee Kim
iOS

안녕하세요, caution입니다. 오늘은 앱에 Dark Mode를 적용하는 방법에 대해 알아보려고 합니다 :)

Dark Mode

Dark ModeiOS 13.0이상부터 앱에서 설정 가능한 화면 모드입니다. 이전 버전에서는 모두 Light Mode였다고 생각하시면 되요! 화면 모드는 설정 > 디스플레이 및 밝기에서 변경할 수 있습니다.

images

사진에서 보이는 것처럼 간단하게 라이트 모드는 밝은 배경에 어두운 글씨, 다크 모드는 어두운 배경에 밝은 글씨로 설정되어 있다고 생각하시면 쉬워요.

HIG

본격적으로 개발에 다크모드를 적용하기 전 HIG를 읽어보고 오시는 걸 추천합니다 :). 헤헿

프로젝트에 다크모드 적용하기

Dark Mode를 적용하는 가장 쉬운 방법은 xibAsset을 사용하는 거라고 생각합니다.

images

Xcode 11 버전부터는 storyboard를 열었을 때 하단에 Interface Style으로 라이트모드와 다크모드를 바꿔가면서 확인할 수 있기 때문에 ColorImage 모두 Asset을 잘 구성해두면 바로바로 확인할 수 있거든요.

하지만 코드로 화면을 구성하시는 분들도 많을 것 같아요. 그래서 먼저 Apple의 의도에 맞게 Asset Catalog를 사용해서 다크 모드에 대응하는 방법을 살펴보고 TraitCollection을 사용해서 코드로 적용하는 방법을 살펴볼게요~!

Color

시스템 컬러

Apple에서는 기본적으로 Symantic ColorSystem Color를 제공하고 있어요. 이 컬러들을 사용하면 크게 신경쓰지 않아도 라이트 모드, 다크 모드에 맞는 직역하자면 의미론적 색상인데요, 스토리보드에서 Color를 지정할 때 System Background Color나, Table Background Color 등을 보신적이 있나요? 이렇게 미리 의도를 가지고 그 의미를 품은 이름을 가진 색상을 Symantic Color라고 합니다.

Xcode 11에서 컬러를 지정해보셨다면 Symantic Color들이 더 다양해진 걸 볼 수 있을 거에요.

images

System Background Color, System Fill Color, Placeholder Text Color 등등 다양한 Symantic Color들을 살펴보고 싶으시다면 HIG의 Color-dynamic system colors를 살펴보면 좋을 것 같아요. 기회가 되면 다음에 정리해서 올릴게요! 오늘은 시간문제로 패스패스~!!

그래서 이 Symantic Color들과 System Color만을 사용해서 화면을 하나 구성해 볼게요.

images

온전하게 System에서 제공하는 컬러들만 사용된 화면이에요. Apple에서 제공되는 컬러들은 두 가지 모드에 모두 동일한 느낌을 줄 수 있는 컬러들이에요. 비슷해 보이지만 System Color들은 두 모드에서 색상이 서로 다릅니다. 그리고 Symantic Color들은 총 4가지 단계(primary, secondary, tertiary, quaternary)로 분류해서 컬러를 제공해주기 때문에 적절한 단계의 컬러들을 사용하면 앱의 가독성을 높일 수 있습니다.

사용자 컬러

하지만 이 시스템 컬러 외에도 디자이너 분들이 혹은 개발자분들이 원하는 컬러가 있을 수 있겠죠! 그 경우 Color Asset에 Color를 저장해서 Named Color로 스토리보드에서 바로 사용할 수 있습니다.

Named Color? Xcode 9 이상부터 Asset에 컬러를 지정하고 이름을 지정하면 시스템 컬러처럼 스토리보드에서 가져다 쓸 수 있습니다. 이를 Named Color라고 합니다. iOS 11.0+ 을 지원합니다.

Asset을 열고 + 버튼을 눌러 New Color Set을 선택합시다. 그리고 나서 attributes inspector를 열고 Appearance 항목에서 Any, Light, Dark를 선택하면 다음 화면처럼 세 가지 컬러를 선택할 수 있습니다.

image

이미지는 Apple 아티클인 Supporting Dark Mode in your Interface에서 퍼왔습니다.

각각 라이트 모드와 다크 모드에 대한 컬러를 선택하면 이 컬러가 지정됐을 때 그 모드에 따라 컬러값이 변경됩니다.

그렇다면 Any는 무엇일까요? 다크모드의 개념이 사용되기 이전 버전에 대한 컬러를 별도로 지정할 경우 Any를 사용하면 됩니다. 만약 라이트 모드와 이전버전의 컬러를 똑같이 사용할 거라면 Any, Dark만 선택해도 됩니다.

세 가지 컬러를 선택해 볼게요. Any에는 빨간색, Light에서는 초록색, Dark에서는 파란색으로 선택해볼게요. ~매우 극단적인 개발자의 컬러감각~

images

화면의 배경색으로 이 컬러를 선택해주고 앱을 실행하면?

images

우리가 원하던 대로 라이트 모드와 다크 모드, 그리고 13 이전 버전에서는 Any Appearance에 선택된 빨간색으로 나오는 걸 볼 수 있어요.

자, 개발자라면 이쯤되서 궁금한 점이 하나 나타나야 합니다. 화면 중앙에 나타난 레이블에 텍스트를 어떻게 셋팅해준 걸까요?

컬러의 경우에는 Named Color로 미리 설정해주었지만, 레이블에 들어가는 텍스트는 어떻게 지정된 걸까요?

이건 이미지까지 한 번 다시 살펴보고 코드로 DarkMode에 적용하는 법을 살펴보면서 알려드릴게요~!

이미지

이미지는 컬러와 마찬가지로 Asset Catalog를 사용하면 매우 간편합니다. 마찬가지로 Appearance에 맞는 이미지들만 셋팅해주면 스토리보드에서도 런타임에서도 화면 모드에 맞는 이미지를 가져다 쓰게 됩니다.

위의 컬러 셋팅과 동일한 이야기여서 별도 예를 들지는 않을게요!

SF Symbols

하지만 라이트모드 / 다크모드 모두 이미지를 만드는 게 부담되는 디자이너/개발자 분들을 위해서 Apple에서 SF Symbols를 제공해주고 있어요.

SF-Symbols 앱을 설치하면 Xcode에서 SF-Symbols에 포함된 이미지들을 가져다 쓸 수 있습니다. 단, iOS 13버전 이상에서만 사용할 수 있습니다.

주의하세요!

모든 SF 기호는 Xcode 및 Apple SDK 라이센스 계약에 정의된 시스템 제공 이미지로 간주되며 여기에 명시된 조건에 따릅니다. 앱 아이콘, 로고 또는 상표 관련 사용에는 SF 기호를 사용할 수 없습니다.

스토리보드에서 SF-Symbol 사용하기

iOS 13 이전버전에서는 이미지가 nil로 셋팅되니까 조심하세요! images

코드로 SF-Symbol 사용하기

if #available(iOS 13.0, *) {
  let upImageView = UIImageView()
  upImageView.image = UIImage(systemName: "square.and.arrow.up")
}

코드로 다크모드 대응하기

이제부터는 코드로 다크모드에 대응하는 방법을 알아볼 거에요. 코드로 화면을 구성하고 계셨다면 방식은 이전에 코드를 작성하는 방식 그대로 사용하시면 됩니다. 하지만 이미지나 색상들을 선택할 때 필요한 몇 가지 요소를 알려드릴게요.

UITraitCollection

이 클래스를 아시나요? iOS 8.0에 처음 나타난 개념이고, Apple 문서에서는 UITraitCollection을 다음과 같이 정의합니다.

수평 및 수직 크기 클래스, 디스플레이 척도사용자 인터페이스 관용어와 같은 특성으로 정의된 앱용 iOS 인터페이스 환경

간단히 말하자면 이 앱이 설치된 환경의 수평크기, 수직크기는 얼마이고, 아이패드인지 아이폰인지, 라이트모드인지 다크모드인지 등등 환경적 특성들을 가지고 있는 클래스입니다.

그리고 이 UITraitCollection은 이미 UIViewControllerUIView 내부에 traitCollection이라는 property로 포함되어 있습니다.

// UIViewController의 traitCollection
self.traitCollection
// UIViewController의 view의 traitCollection
self.view.traitCollection

그리고 디스플레이모드에 대한 정보는 traitCollectionuserInterfaceStyle property에서 가져올 수 있습니다. 이 userInterfaceStylelight, dark, unspecific 세 가지 케이스를 가지는 enum class UIUserInterfaceStyle의 인스턴스입니다. 그래서 traitCollection으로 다크모드인지 라이트모드인지 판별해서 알맞은 Asset을 설정해주면 됩니다.

traitCollectionDidChange

앱을 사용하는 도중에도 사용자는 시스템 디스플레이 타입을 변경할 수 있습니다. 이때 traitCollectionDidChange(:)가 호출됩니다.

마찬가지로 UIViewUIViewController 모두 이 메서드를 가지고 있으며, previousTraitCollection을 매개변수로 넘겨받기 때문에 다음과 같이 사용해볼 수 있습니다.

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {

    }

Asset으로 리소스를 관리하고 있는 경우

간단합니다! 앞서 보셨던 방식 그대로 사용하시면 됩니다. Named Color#imageliteral(:)을 사용하고 계셨다면 Asset에서 다크모드용 리소스만 셋팅해주시고 사용하는 방식은 동일합니다.

let image = UIImage(named: "hello")
self.imageView.image = image

함께보기


Similar Posts

다음

Comments