Meet WidgetKit

링크

What makes a greate Widget?

Glanceable

위젯은 미니앱이 아니다. 단순히 앱의 컨텐츠를 보여주는 것이므로, 컨텐츠에 집중해야하며 한 눈에 볼 수 있는(Glanceable) 컨텐츠를 제공해야 한다.

Relevant

스마트 스택을 이용해 특정 시점에 적절한 위젯을 보여주어야 한다. 즉 연관성이 있어야 한다.

연관성을 뒷받침 하는 요소들은 다음과 같다.

  • Stacks use on-device intelligence
  • Siri Shortcuts donation
  • WidgetKit API

관련 WWDC 세션 - Add Configuration and intelligence to Your Widgets

Personalized

위젯에는 세 가지 크기가 존재한다. 모든 크기를 지원할 필요는 없지만 최대한 많은 사이즈를 지원해 위젯의 개인화를 더욱 향상 시킬 수 있다.

또한 Shortcut에서 사용했던 Intent를 이용해 구성 옵션(Configuration Option)과 구성 화면(Configuration UI)를 쉽게 구현할 수 있다.

How WidgetKit works

위젯은 멀티플랫폼을 지원해야 하기 때문에 SwiftUI로 만들어졌다.

위젯은 위에서 언급했듯이 한 눈에 볼 수 있어야(Glanceable) 한다. 이를 위해 WidgetKit은 타임라인에 따른 연속된 뷰 계층을 반환해야 한다. 그렇기 때문에 이는 백그라운드 익스텐션에 속한다.

타임라인에 따른 연속된 뷰 계층을 패키징하여 홈 스크린에 전달하면 홈 스크린은 주어진 타임라인에 따라 정해진 뷰를 그리게 된다. 우리는 이런 메커니즘을 통해 런치 프로세스, 뷰 로딩 등을 피할 수 있다. 이를 통해 위젯은 항상 적절한 컨텐츠를 즉시 볼 수 있게끔 준비되어 있다.

이렇게 미리 뷰가 준비되어 있다는 것은 다른 곳에서 이를 재사용할 수 있다는 것을 의미한다. 아래는 이렇게 준비된 뷰가 위젯 갤러리에서 사용되는 모습이다.

이런 타임라인 메커니즘으로 우리는 위젯을 통해 항상 적절한 컨텐츠를 바로 볼 수 있다.

그리고 이런 타임라인은 메인 앱에서 사용자가 컨텐츠에 영향을 주는 데이터를 변경했을 때 갱신될 수 있다. 혹은 익스텐션에서 이러한 갱신을 스케쥴링해줄 수도 있다.

예를 들어 캘린더 위젯은 하루동안의 이벤트가 언제 일어날지에 대해 알고 있다. 익스텐션은 이 정보를 바탕으로 적절한 시간에 해당하는 뷰를 랜더링한다.

How to make a great Widget?

훌륭한 위젯을 만드는 방법을 아래 주제들을 통해 알아보자

  • Defining a widget
  • Creating a glanceable experience
  • Views, timelines and reloads
  • Personaliztion and intelligence

Defining a widget

위젯을 정의하기 위해선 몇 가지 컨셉에 대해서 짚고 넢어가야한다.

  • kind
  • configuration
  • supportFamilies
  • placeholder

처음 위젯을 설계할 때 하나의 익스텐션으로 다양한 유형의 위젯을 지원할 수 있는 메커니즘을 구상했다.

주식 앱 익스텐션을 예로 들자면, 이는 몇 가지 종목에 대한 개요를 볼 수 있는 위젯을 제공한다. 하지만 추가로 한 가지 종목에 대한 상세 정보를 확인할 수 있는 위젯을 제공하거나 혹은 macOS의 알람 센터에서 확인할 수 있는 위젯을 제공한다.

위젯의 종류(kind)는 자신들이 어떤 유형의 Configuration을 지원하는지를 나타내기도 한다. 이런 Configuration에는 두 가지가 존재한다.

  • StaticConfiguration
  • IntentConfiguration

StaticConfiguration

피트니스앱의 위젯은 단순히 현재 피트니스 상태를 알려주고, 딱히 사용자가 이를 구성할 수 있도록 지원할 필요는 없다. 이는 StaticConfiguration 타입이다.

IntentConfiguration

다시 알림앱은 목록을 사용자가 수정하고 개인화할 수 있다. 이는 IntentConfiguration 타입에 해당한다.

위젯은 하나 혹은 다수의 supportedFamilies를 지원할 수 있다. 기본적으로 위젯은 모든 supportedFamilies 타입을 지원한다.

placeholder는 위젯의 기본 컨텐츠(Default Content)가 된다. placeholder를 통해 위젯이 어떤 유형의 컨텐츠를 제공하는지만을 나타내야지 사용자 데이터가 포함되어 있어서는 안된다.

또한 placeholder는 자주 볼 수 있는 UI가 아니고 언제 보일지는 보장할 수 없다. 일반적으로 기기 환경 설정이 변경되었을 때 새 placeholder를 요청하곤 한다.

사용자에게 위젯이 어떤 유형의 컨텐츠를 제공하는지를 잘 나타내는 placeholder가 훌륭한 placeholder다.

아래의 코드는 위에서 살펴본 네 가지 키워드가 모두 담겨져있다.

Creating a glanceable experience

아래는 glanceable한 위젯의 예들이다. 위젯은 유용한 정보를 제공하며 사용자로 하여금 위젯을 탭 하여 더 많은 정보를 볼 수 있게끔 유도하고 있다.

한 눈에 보기 쉬운 위젯을 만들기 위한 요소 중 하나는 Stateless한 UI다. 이는 다음과 같은 특성을 갖는다.

  • No Scrolling
  • No videos or animated images
  • Tap interactions

위젯은 딥 링크를 지원하므로, 탭을 통해 메인 앱의 특정 컨텐츠로 사용자를 유도할 수 있다. 이런 딥 링크는 widgetURL를 이용해 구현할 수 있다.

Views, timelines and reloads

뷰, 타임라인 그리고 갱신은 위젯의 엔진 역할을 한다.

뷰를 위한 세 가지 개념이 존재한다.

  • Placeholder
  • Snapshot
  • Timeline

Snapshot

Snapshot은 시스템이 위젯을 빠르게 제공하기 위해 필요한 단일 진입점이다. 이를 위해 익스텐션은 이 뷰를 최대한 빨리 반환해주어야 한다. 그리고 이렇게 반환된 Snapshot은 위젯 갤러리에서 확인할 수 있다.

보통 Timeline의 첫 번째 진입점과 Snapshot은 동일한 진입점으로 반환될 수 있다. 그렇기 때문에 위젯 갤러리에서 보는 것은 사용자가 위젯을 디바이스에 추가했을 때의 보는 모습과 동일하다.

Snapshot이 단지 하나의 단일 진입점이라면, 제시간에 보여지는 다수의 연속된 뷰는 Timeline이라고 할 수 있다.

Timeline

Timeline은 뷰와 날짜의 조합으로 어떤 뷰가 언제 보여져야 하는지를 나타낸다. Timeline은 다크모드, 라이트모드 모두 반환해야 한다.

익스텐션이 진입점을 제공하면 우리는 이 정보를 받아 디스크에 뷰 계층을 직렬화한다. 이를 통해 적절한 타이밍에 각 항목을 렌더링할 수 있다. 이런 방식으로 시스템은 수많은 Timeline을 통해 동시에 수많은 위젯에 이를 적용할 수 있다.

타임라인은 일반적으로 하루치 컨텐츠를 제공해야 한다. 그러나 주어진 시간에 따른 컨텐츠가 아닌 최신 정보를 보여주어야 할 때가 있다. 우린 이를 갱신(Reload)이라 부른다.

Reload

Reload란, 시스템이 익스텐션을 깨우고 각각의 위젯을 위한 새 Timeline을 요청하는 것을 말한다. Reload를 통해 사용자의 컨텐츠가 항상 최신 상태로 유지되도록 할 수 있다.

아래는 TimelineProvider 프로토콜로 WidgetKit에 언제 위젯을 갱신해주어여 하는지 알릴 때 사용된다.

reloadPolicy

시스템에게 언제 다음 Timeline을 요청해야 하는지를 알려주는 일종의 갱신 정책이다.

시스템은 reloadPolicy를 받아 위젯을 갱신(reload)한다. 자주 보는 위젯은 더 자주 갱신될 것이고, 아닌 위젯은 덜 자주 갱실될 것이다. 또한 기기 환경 설정이 변경되면 시스템은 강제로 위젯을 갱신한다.

이렇게 시스템에 의한 위젯 갱신도 있지만 메인 앱 주도의 갱신도 존재한다.

백그라운드 노티피케이션 혹은 앱 내의 데이터 변경에 의해 위젯이 갱신될 수 있는데 이때 우리는 WidgetCenter를 사용해 위젯을 갱신해줄 수 있다.

서버로부터 받아온 정보를 바탕으로 위젯을 갱신해주기 위해선 백그라운드 세션을 사용해야 한다. 또한 서버 통신으로 만들어진 payload는 onBackgroundURLSesionEvents 변경자를 통해 전달된다. 요청은 일괄처리하고, 서버 통신은 필요한만큼만 사용해야 한다.

위젯은 매초마다 수행되는 작업이 아니다. 실시간 실행 환경도 아니다. 상태에 맞는 갱신 정책을 통해 위젯을 효율적으로 갱신해야 한다.

Personalized and intelligence

위젯의 개인화와 지능은 두 가지 요소로 결정된다.

  • Intents
  • Relevance

Intents

Intent는 사용자가 위젯을 구성하는데 사용되는 메커니즘이다.

Intent를 통해 사용자에게 일종의 질문을 하고 (어떤 위치의 날씨 정보를 원하는지, 어떤 주식 종목을 원하는지) 시스템이나 앱은 이에 대한 응답으로 위젯을 갱신한다. 이를 통해 우린 위젯의 사용자화를 향상시킬 수 있다.

Relevance

스마트 스택의 지능에 영향을 미칠 수 있는 요인 중 하나다.

When users perform actions in your app, your app can donate shortcuts.
If your widget is backed by the same INIntent, then your widget may be rotated to in the stack when the user would have typically perform that action.

또한 TimelineEntryRelevance 구조체의 scoreduration을 이용해 관련성(Relevance)에 영향을 줄 수 있다.

[관련 WWDC 세션 - Add Configuration and intelligence to Your Widgets](

Comments