...
본문 바로가기

WWDC

WWDC 20 - Meet WidgetKit


  • 세션보면서 정리한 내용입니다. 해석이 잘못된 경우가 있을수있으니 발견하시면 댓글로 남겨주시면 감사하겠습니다🙏🏻

https://developer.apple.com/wwdc20/10028

 

Meet WidgetKit - WWDC20 - Videos - Apple Developer

Meet WidgetKit: the best way to bring your app's most useful information directly to the home screen. We'll show you what makes a great...

developer.apple.com

 

 

 


요약

  • 위젯은 미니앱이아니다. 위젯은 한눈에 쉽게파악할수있어야하고, Stateless한 UI이다. 
    • 스크롤, 컨트롤기능을 할수없다.
    • 터치를통하여 앱으로들어갈수있고, 또한 위젯내에서도 관련있는 정보로 앱으로들어갈수있다. 
      • widget URL, Link 
    • 위젯뷰들은 크게 3가지 family size를 가질수있다 ( small, medium , large )  
      • default로 모두 가질수있고, 모든 사이즈들을 무조건 지원해야하는건 아니다. 
    • 위젯은 아무데이터가없는 default로 보여줄수있는 placeholder를 필요로한다. 
  • 위젯은 SwiftUI로 구현된다. 
  • 위젯은 크게 configuration, provider, view, timelineEntry 로 구성되어있다.
  • 위젯은 기본적으로 크게 두가지로나뉜다. Static configuration  vs IntentConfigruation 
    • Static은 사용자가 따로 편집할수없는것이며, 
    • Intent는 사용자가 위젯을 편집할수있다. 
      • intent는 IntentFramework로 구현되며, siri, shorcut과도 통합되어있다. 
  • 위젯의 작동원리는 provider에의해 timeline들이 만들어지는데,  이 timeline을통해서 특정시간에 특정뷰( + timelineEntry ) 를 보여주는 메커니즘을가진다. 
    • provider는 특정configuration을 채택하는 Provider로 나뉘고,  timeline, placeholder, snapshot등을 만들어낸다.  
    • 또한 각 timeline 이후에 특정 정책에맞게, 다른 timeline들을 reload할수있다.  ( atEnd, after, never ) 
      • reload는 background notification이나, 앱을통해서 WidgentCenter API를 이용하여  강제적으로 reload할수있다. 
    • 간혹 뷰에 보여줄 데이터가 네트워킹이 필요한경우라면, background URLSession을 이용하고, Widget extension에서는 onBackgroundURLSessionEvents를 통해서 받아오도록한다.
    •  ⬇️timeline 시각화
  • 위젯은 Stack으로써 다른 위젯들을 포함할수있는데, 이때 Shortcut이나, 특정값을정하여 시스템이 더 지능적으로 특정 위젯이  나타나게할수도있다. 

 

 

 

 

 


 

 

무엇이 위젯경험을 더 좋게 만들까? 

한눈에보기쉽고, 의미있고, 개인화가능한 ! 

 

 

glanceable한 것은 무엇을의미할까? 

우선, 더많은 사이즈가있지만, 가장 작은사이즈는 홈스크린아이콘 4개 정도크기다. 

그러므로 공간을아주잘활용해야한다.

위젯이배치되는공간은 홈스크린이므로 굉장히 사용자들이 짧게 만나는 곳이다.

그러므로, 위젯에 버튼을 누를필요도, 복잡한UI를 이해하려고 하지않아도되야 할것이다. 

즉 핵심적인 content에만 집중해야한다. 

 

 

매우중요한데, 위젯은 미니앱이아니다! 

아래세션을 참고하면좋다. 

 

 

 

Relevant는 무슨뜻일까 ? 

Smart Stack은 위젯들의 집합으로써, 여러개의위젯을보여준다.

자동적으로 적절한 위젯을 top에 배치시켜준다. ?? 

  • on-device intelligence 를 이용하여 

또한 개발자는 Siri Shortcut를 이용할수도있다. 

또는 특정 WidgetKitAPI를 이용하여 시스템이 더 파악하기쉽게,  좀더 위젯이 relevant하게할수있다. 

자세한건 아래세션참고!

 

 

small, medium , large 사이즈를 가질수있다. 

무조건 모든사이즈들을 지원해야하는건 아니지만, 가능한 다양한사이즈를 지원하도록해랑 

 

 

위젯도 편집할수있다.

편집하는 옵션들은 intent들을 이용한다. 

  • 이 intent들은 Shortcut과도 매우 친숙하다.

예를들어, 도시를 선택할수있다. 

아주아주 대단한점은, 이 옵션들을 설정하는 UI는 완전히 자동적이다!! 

( 즉 추가적인 UI를 구성하는 작업을 할필요가없다!! ) 

 

 

 


그럼 위젯을 디자인해보자.

 

우선, 위젯은 모든 플랫폼에 적용된다 ( iOS, iPadOS, macOS ) 

그리고 위젯인터페이스는 완전히 SwiftUI로 만들어진다.

  • SwiftUI는 Dynamic Type, DarMode를 완전 쉽게 지원할수있다. 

 

그리고 가장 원하지않는것은 홈스크린이 loading spinner로 가득한것이다. 

 

watchOS complication을 디자인할때도 loading spinning을 지양했는데,   Widget도 마찬가지고, 비슷한 구현을 적용했다.

WidgetKit extension은 background extension이고,  timeline에 있는 일련의 view hierarchies들을 반환한다. 

  • 즉, SwiftUI를 이용하여, View들을 timline에 패키징하고, timeline에따른, 정확한시간에 맞춰서 해당 View를 보여주는 메커니즘이다. 
  • 덕분에 즉각적으로 반영이된다. 

  • 이러한timeline은 main app에서도 refresh할수있고, 
  • extension으로부터 update할수도있다. 

 

 

아래와같이 예정인 상황에서,

1:05분에 Coffee마시는걸 취소하고 바꾸고싶다면? 

캘린더엡에서 가서 바꾸고 업데이트할것이다. 

 

 

이렇게 앱에서 변경하고, 

캘린더앱은 API를 이용하여 timeline을 업데이트한다. 

그럼 이제, extension은 다시 깨어나고, 새로운 타임라인을 반환할것이다. 

 


자그럼,  여기까지 Widget이어떻게 작동한느지알았으니,

WidgetKit을 어떻게만드는지알아보자. 

 

요런것들을 알아볼것이다. 

 

 

 

 

어떻게 Widget을 정의하나?! 

 

우선 몇개의 컨셉을 얘기하고싶다.

  • kind
  • configuraiton
  • suppoertedFamilies
  • placeholder

 

우선, 하나의 Widet extension으로 다양한 widget들을 지원할수있따. 

 

 

 

 

예를들어, 주식앱은 

가장작은사이즈에도 두개의 다른위젯을제공하고있다. 

 

 

 

 

kind는 지원할 어떤 configuration 타입을 표현한다. 

크게 두가지로나뉜다. static, intent 

 

간단하다. 아래와같이 딱히 configuration이 필요없는 위젯이있다. ( 즉 설정할게없는, 필요없는 ) 

이것을 staticconfiguration이라한다.

 

이렇게, 특정리스트를통해 개인화될수있는건 IntentConfiguration이다. 

 

 

 

특정 kind는 하나또는 여러개의 supportedFamilies를 할수있다.

default로 위젯은 모든 family type을 지원한다.

 

 

즉, 날씨앱은 모든 family들을 지원하고있다. 

 

마지막으로 placeholder는,  각 위젯들은 placeHolder를지원해야하고, 그것은 위젯의 default content이다.

  • 절대 유저데이터를 이용하지말아야한다.
  • 또다른 중요한점으로는, UI는 아주드물게 가져와지기때문에, 그것이 언제발생할거라고 보장하지않는다.
    • 디바이스환경이변할때 새로운 placeholder를 요청할것이다. 예를들면 dynamic type을 변경했을떄. 
  • 아주좋은 placeholder는 어떤위젯인지 보여주는것이다.

 

 


 

 

코드로는 아래와같이 시작한다.

  • Widget 프로토콜을 채택하는 위젯이있고,
  • kind를 명시했고, 
  • WidgetConfiguration을 return하고있다. 
    • 그안에서 Provider, PlaceholderView를 제공하고있다. 
      • provider는 나중에 설명할건데, 어떻게 위젯의엔진을 세팅하는지이다. 

 

 


 

자그럼 어떻게 glanceable하게만드는지 얘기해보자.

 

다음과같은 위젯들이 정말좋은 glanceable한 앱이다. 

  • 누구에게나 유용한정보를 주고있고, 더많은정보를보기위해 터치하고싶은욕구 ( 앱으로들어가서 보려고 ) 가든다 ㅎ 

 

우선 glanceable한 핵심은, StatlessUI이다.

  • SwiftUI가 그것과정말잘맞는다.
  • 위젯에서는 스크롤할수없고, 
  • 스위치, 다른 컨트롤기능들을사용할수없고,
  • 비디오, animated image불가능하다. 
  • 그냥단지, 앱으로들어가기위한 터치만가능할뿐이다. 
    • 단순한 터치기능이 아니라  더 deep하게 앱을연결해준다. 
    • 각 위젯들은 single tap target을 가지고있따.  
    • 예를들어, 뮤직위젯이, 가장최근들은앨범을보여주고, 이를터치하면 앱에서도 가장최근앨범을보여준다. 
    • 심지어, medium은 여러종류의 앨범을보여주고, 각 앨범들은 link로 이루어져있다.  즉 앱에서도 바로 특정앨범으로볼수있다.
    •  
    • 각위젯들은 widget URL API를 이용하여 URL과 관련지어질수있따.
    • 위의medium예시처럼, sub-link를 사용하고싶다면, SwiftUI에서 새로운 link API를 이용할수있따.

 

 

 

 

 


 

 

오케이! 이제 view, timeline, reload들을 살펴보자.

 

 

위젯의 UI경험에는 세가지타입이있다. 

 

placeHolder는 아까얘기했고, 

 

Snapshot은 시스템이 빠르게 하나의 Entry를 보여주려는 곳이다.

그러므로, timeline의 첫뻔째 entry와 snapshot은 같은 entry를 반환할수도있다. 

  • (음, 현재시간에바로보여지는것이 Snapshot인건가.. )

 

snapshot이 단하나의 entry라면,  특정시간에 보여져야할 여러개의뷰의 연속들이 timeline이다. 

  • 뷰와 데이터의 집합이다.  어떤시간에 어떤뷰를 보여줄지 정한다.
  • 또한, 타임라인이 반환하는것은 다크,라이트모드 둘다포함해야한다.

 

 

TimelineProvicer 프로토콜이다.

 

 

구현한 코드이다. 

snapshot은 하나의 엔트리를 반환하고,

timeline은 여러개의 엔트리를 반환한다.

그리고 timeline은 reload policy를 가지고있따.

 

 

각 타임라인들은 reload policy를 가지고있는데, 이것은 언제 다음 타임라인을 요청할지 시스템에게 말하는것이다.

 

이러한 reload는 reloadpolicy에의해 결정되어질수있고, 그로인해 더 많이자주, 덜 reload될수있고,

디바이스환경이변할때 reload되어진다. 

 

시스템은 reload할 가장좋은시간을 결정할것이다.

 

그리고 앱을통해 시스템에게 강제적으로 reload하라고할수도있따.

예를드렁, background notification을받거나, 또는 앱안에서 변화를 만들었거나 

 

 

background notification을 받으면, WidgetCenter를 통해서 WidgetKit API를 이용하여 extension을 깨워, 타임라인을 reload하라고할수있다. 

마찬각지로 포그라운드에있는 앱에서 변경할수도있다. 

포그라운드일때는 신중해라, 오직 의미있는변화가발생할경우에만 reload하라.

 

그래서 WidgetCenter 에는  타임라인을 reload할 여러 API가있다. 

또한 현재 configruations들을 얻을수도있다.

 

 

그리고 정보를위해 서버네트워킹이 필요할수있다.

이런경우에는 background URLSession을 이용하라. 

onBackgroundURLSessionEvents를 통해서 extension은 정보를받게된다. 

 

 

백그라운드에있을때, reload는 시스템에의해 책정되어지므로, 네트워킹작업을 신중하게해라, 

위젯들은 바로실행되는것도아니고, live running이 아니기때문이다. 

 

( 그러니까, 정보들이 실시간이 중요한경우에는, 타임라인하나에 하나의엔트리만 두어야겠네? 그래서 하나타임라인이끝나면 그다음 그시간때 타임라인을 요청하고?  이건 background URLSession을 이용하고, WidgetKit에서 onBackgroundURLSessionEvents를 구현해야하고.. ?

만약 ㅇ할일앱이나, 날씨앱같이 미리 어느정도 몇시간뒤 데이터들을 알수있는경우에는, 타임라인하나에 여러개의 엔트리를 두도록하고? 

 

 

 


 

이제 마지막으로 Personalization과 Stack에서 intelligence을 알아보자.

둘다 중요한 두개컨셉이있는데,

하나는 intent으로, 

  • 유저가 위젯을 환경설정할수있도록 하기위해 사용되어지는것이고,

나머지하나는 relevance로,

  • 개발자가, Stack에서 intelligence에 영향을미치도록하는것이다. 

 

 

 

intents은 intents framework에 의해 작동디고,유저에게 물어볼수있는 파라미터의집합으로 구성된다. 

  • 예를들어, 날씨에서는 위치가될수있다. 
  • 또한 이미, Siri나 Shortcut과도 통합되어있다. 그리고 이제 iOS14에서부터 widget configuration과도 사용된다.
  • 주식앱에서는 주식에있는 다른주식리스트에서 특정주식을 찾도록 할수있다.
  • 또한, 리스트에서 원하는 주식이없다면, 검색을통하여 dynamic하게 추가되어질수있따? 

 

 

 

 

 

또한 intent는 in-app intent handling도 지원하는데, 자세한건 세션을참고. 

 

 

 

아까 위젯을 정의하는 코드로다시가보면,

우리는 StaticConfiguration대신 IntentConfiguraton을 정의하고있따. 

그리고 특정 Intent를 정의하고있다. ( ConfigurationIntent.self ) 

 

그리고, 아까봤던 Provider는 TimeLineProvider에서 IntentTimeLineProvider로 바꼇고, 

그리고 특정 intent를 받으면서, 특정타임라인을 만들어낼수있다.

 

 

 

 

 

위젯의 또다른 특징중 하나는, Stack이다.

시스템은 지능적으로 가장관련있느 위젯으로 변경시킨다. 

그리고 앱과 위젯은 이러한 지능에 도움을줄수있다. 

  • shortcut을이용...하거나 
  • 위젯extension은 타임라인 엔트리에 TileineEntryRelevance API를통해 relevance value를 정할수있다. 
  • 자세한건세션참고 

 

Score, duration을 정하여, Stack안에서 위젯이 더 나오게...할수있다.