Widget: 정의, iOS WidgetKit 및 Android 위젯

저자: IT Sectr 게시일: 2026-02-15 읽는 시간: 10 분

Widget은 iOS 또는 Android 홈 화면의 컴팩트한 사용자 인터페이스 요소로, 앱을 열지 않고도 관련 정보를 표시합니다. 위젯은 iOS 14(2020)에서 SwiftUI의 WidgetKit 프레임워크와 함께 등장했으며, Android에서는 버전 1.5부터 Kotlin 또는 Java의 AppWidgetProvider를 통해 존재합니다. 사용자는 홈 화면에서 바로 날씨, 환율, 캘린더, 메모 또는 작업 상태를 확인할 수 있어 시간을 절약하고 상호작용을 간소화합니다. Apple에 따르면 사용자는 하루 평균 4~6회 위젯과 상호작용하며, 홈 화면에 위젯을 배치하면 앱 참여도가 20~30% 증가합니다. Android에서도 이 수치는 비슷합니다. 코드 예제를 통해 두 플랫폼에서 위젯이 어떻게 작동하는지 살펴보겠습니다.

핵심 요점

  • Widget — 기본 앱을 실행하지 않고 빠르게 정보를 확인할 수 있는 홈 화면의 미니 애플리케이션
  • iOS WidgetKit(iOS 14+)은 SwiftUI 기반으로 세 가지 크기와 TimelineProvider를 통한 업데이트 제공
  • Android AppWidgetProvider는 API level 3부터 존재하며 RemoteViews 사용 — 별도 프로세스의 제한된 View 집합
  • 데이터 업데이트 iOS — 날짜 지정 타임라인 방식, Android — updateIntervalMillis 또는 WorkManager 방식
  • Smart Stack(iOS) 및 위젯 스택(Android)은 여러 위젯을 하나의 슬롯에 그룹화 가능

Widget이란

Widget은 모바일 기기의 홈 화면에 배치되는 컴팩트한 사용자 인터페이스 요소로, 앱에서 관련 정보를 표시합니다. 전체 애플리케이션과 달리 위젯은 실행이 필요하지 않습니다 — 사용자는 화면 잠금 해제 후 즉시 데이터를 볼 수 있습니다. 이 개념은 데스크톱 OS(macOS Dashboard, Windows Sidebar)에서 유래했으며, 모바일 환경에서는 Android가 첫 번째 릴리스(Android 1.5 Cupcake, 2009)부터 위젯 지원을 도입한 반면, Apple은 iOS 14에서야 추가했습니다.

기술적 구현은 플랫폼에 따라 다릅니다. iOS 위젯은 Xcode의 별도 target으로, Widget Extension으로 컴파일되어 자체 프로세스에서 실행됩니다. Android 위젯은 AppWidgetProvider를 확장하는 BroadcastReceiver로, RemoteViews를 통해 레이아웃을 렌더링합니다. 두 플랫폼 모두 성능과 메모리에 엄격한 제한을 가합니다: 한도를 초과하면 시스템이 위젯을 제거할 수 있습니다. iOS는 위젯을 30~50MB, 타임라인 생성 시간을 10초로 제한합니다. Android — updatePeriodMillis를 통한 업데이트 간격 최대 30분, onUpdate 중단 시 강제 종료.

Smart Stack(iOS) 및 스택(Android)을 사용하면 사용자가 여러 위젯을 하나의 홈 화면 슬롯에 그룹화할 수 있습니다. 기기는 시간, 위치 또는 사용자 활동에 따라 표시되는 위젯을 자동으로 전환합니다. 예를 들어, 아침에는 캘린더, 낮에는 날씨, 저녁에는 메모가 표시됩니다. 개발자에게 이는 위젯이 스택의 일부로 올바르게 작동해야 하며 지속적인 표시에 의존해서는 안 된다는 것을 의미합니다.

iOS WidgetKit: SwiftUI 및 TimelineProvider

WidgetKit은 iOS 14+, iPadOS 14+ 및 macOS 11+에서 위젯을 만들기 위한 Apple의 프레임워크입니다. 위젯은 SwiftUI와 콘텐츠 업데이트를 위한 TimelineProvider 메커니즘을 사용하여 Swift로 작성됩니다. WidgetKit 아키텍처는 세 가지 구성 요소로 구성됩니다: TimelineProvider — 항목이 있는 타임라인을 형성하는 데이터 소스; Widget Entry View — 항목을 기반으로 콘텐츠를 표시하는 SwiftUI View; Widget Configuration — 위젯 유형, 크기 및 패밀리에 대한 설명.

WidgetKit은 업데이트를 자동으로 관리합니다 — 개발자는 시스템이 허용하는 것보다 더 자주 위젯을 업데이트할 수 없습니다. Apple은 기기의 모든 위젯에 분배되는 업데이트 예산을 사용합니다. 최소 간격은 15~30분입니다. 중요 데이터(예: 배송 상태)의 경우 push-to-refresh가 사용됩니다 — 관련 미래 날짜의 푸시 알림을 보내고 WidgetKit이 새 타임라인을 요청합니다. iOS 17부터 위젯은 App Intents를 통한 상호작용성을 지원합니다 — 사용자는 앱을 열지 않고 위젯 내부의 버튼을 누를 수 있습니다.

크기iOS (pt)콘텐츠
Small170 × 1701~2 지표: 온도, 환율
Medium360 × 1702~4 지표: 5일 예보, 목록
Large360 × 3805~10 지표: 캘린더, 뉴스 피드

Android AppWidgetProvider: RemoteViews

AppWidgetProvider는 Android에서 위젯을 만들기 위한 기본 클래스로, API level 3부터 Android SDK의 일부입니다. Android 위젯은 BroadcastReceiver로, 시스템으로부터 업데이트, 활성화 및 비활성화 이벤트를 수신합니다. iOS가 자체 엔진에서 SwiftUI로 위젯을 렌더링하는 것과 달리, Android는 RemoteViews를 사용합니다 — 시스템 프로세스(런처)에서 렌더링되는 제한된 View 구성 요소 집합입니다. 사용자 정의 View, 복잡한 애니메이션 또는 UI 라이브러리는 사용할 수 없습니다.

Android 위젯 워크플로는 네 단계로 구성됩니다. 구성 — 화면에 위젯을 추가할 때 시스템이 설정 Activity를 시작하여 사용자가 설정을 선택할 수 있습니다. 업데이트 — 시스템이 지정된 간격(최소 30분) 또는 WorkManager를 통한 앱 신호에 따라 onUpdate()를 호출합니다. 렌더링 — 제공자가 현재 데이터로 RemoteViews를 생성하고 AppWidgetManager를 통해 전달합니다. 터치 처리 — 위젯은 버튼에 대한 PendingIntent를 지원하며, 클릭 시 Activity가 열리거나 작업이 수행됩니다. Android 12부터 위젯은 둥근 모서리, 적응형 Material You 색상 및 동적 크기 변경을 지원합니다.

iOS에서 WidgetKit으로 위젯 만들기

WidgetKit과 SwiftUI를 사용하여 Swift로 날씨 위젯을 만들어 보겠습니다. 프로젝트에는 Widget Extension target이 포함되어야 하며, Xcode에서 File → New → Target → Widget Extension을 통해 추가됩니다.

swift
import WidgetKit
import SwiftUI

// 1. 위젯용 데이터 모델
struct WeatherEntry: TimelineEntry {
    let date: Date
    let temperature: Int
    let condition: String
}

// 2. TimelineProvider — 데이터 제공자
struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> WeatherEntry {
        WeatherEntry(date: Date(), temperature: 22, condition: "맑음")
    }

    func getSnapshot(in context: Context, completion: @escaping (WeatherEntry) -> Void) {
        let entry = WeatherEntry(date: Date(), temperature: 22, condition: "맑음")
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<WeatherEntry>) -> Void) {
        let now = Date()
        let entry = WeatherEntry(date: now, temperature: 20, condition: "흐림")
        let nextUpdate = Calendar.current.date(byAdding: .hour, value: 3, to: now)!
        let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
        completion(timeline)
    }
}

// 3. 표시용 SwiftUI View
struct WeatherWidgetEntryView: View {
    var entry: WeatherEntry

    var body: some View {
        VStack(alignment: .leading) {
            Text("날씨").font(.caption).foregroundColor(.secondary)
            HStack {
                Text("\(entry.temperature)°").font(.largeTitle).fontWeight(.bold)
                Spacer()
                Text(entry.condition).font(.body)
            }
        }.padding()
    }
}

// 4. 위젯 구성
@main
struct WeatherWidget: Widget {
    var body: some WidgetConfiguration {
        StaticConfiguration(kind: "WeatherWidget", provider: Provider()) { entry in
            WeatherWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("날씨")
        .description("현재 온도를 표시합니다")
        .supportedFamilies([.systemSmall, .systemMedium])
    }
}

핵심 사항: TimelineProvider는 언제 어떤 데이터를 표시할지 결정하고, getTimeline은 .after(nextUpdate) 업데이트 정책으로 타임라인을 생성하며, StaticConfiguration은 제공자를 View에 연결합니다. 동적 데이터의 경우 사용자 정의 매개변수가 있는 IntentConfiguration이 사용됩니다.

Android에서 AppWidgetProvider로 위젯 만들기

AppWidgetProvider와 RemoteViews를 사용하여 Kotlin으로 유사한 날씨 위젯을 구현해 보겠습니다.

kotlin
// WeatherWidgetProvider.kt
class WeatherWidgetProvider : AppWidgetProvider() {

    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        for (appWidgetId in appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId)
        }
    }

    override fun onAppWidgetOptionsChanged(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetId: Int,
        newOptions: Bundle
    ) {
        updateAppWidget(context, appWidgetManager, appWidgetId)
    }

    companion object {
        fun updateAppWidget(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetId: Int
        ) {
            val temperature = 20
            val condition = "흐림"
            val views = RemoteViews(
                context.packageName, R.layout.widget_weather
            ).apply {
                setTextViewText(R.id.tv_temperature, "$temperature°")
                setTextViewText(R.id.tv_condition, condition)
                setOnClickPendingIntent(
                    R.id.widget_root, PendingIntent.getActivity(
                        context, 0,
                        Intent(context, MainActivity::class.java),
                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                    )
                )
            }
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

// AndroidManifest — 제공자 등록
<receiver android:name=".WeatherWidgetProvider" android:exported="true">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/widget_weather_info" />
</receiver>

widget_weather_info.xml 파일은 최소 크기, 간격 및 레이아웃을 설정합니다: minWidth 160dp, minHeight 80dp, updatePeriodMillis 3600000(1시간). RemoteViews는 지원되는 구성 요소만 사용합니다: LinearLayout, TextView, ImageView. 사용자 정의 View 및 ConstraintLayout은 Android 5.0부터 사용 가능합니다. GlanceLayout — RemoteViews를 위한 실험적인 Compose 기반 접근 방식 — 은 Android 15에서 등장했습니다.

자주 묻는 질문

iOS와 Android의 Widget 차이점은 무엇인가요?

iOS WidgetKit은 세 가지 고정 크기(small, medium, large)와 시스템 예산을 통한 TimelineProvider 업데이트를 제공합니다. Android AppWidgetProvider는 유연한 셀 기반 크기, 렌더링을 위한 RemoteViews, updatePeriodMillis 또는 WorkManager를 통한 업데이트를 사용합니다.

Widget은 얼마나 자주 업데이트되나요?

iOS에서는 시스템이 업데이트를 제어합니다 — 최소 간격은 15~30분이며, 중요 데이터에는 push-to-refresh가 사용됩니다. Android에서는 간격이 updatePeriodMillis(최소 30분) 또는 백그라운드 작업을 위한 WorkManager를 통해 설정됩니다.

Widget은 어떤 크기를 지원하나요?

iOS는 small(170x170pt), medium(360x170pt), large(360x380pt)를 지원합니다. Android는 유연한 셀 그리드를 사용합니다: 2x1에서 5x5까지, 크기는 런처와 OS 버전에 따라 다릅니다.

Widget에 애니메이션을 추가할 수 있나요?

iOS에서는 위젯 내부의 애니메이션을 사용할 수 없습니다 — 정적 요소입니다. Android RemoteViews는 setFloat() 및 ViewPropertyAnimator를 통한 기본 애니메이션을 지원하지만, 복잡한 애니메이션은 사용할 수 없습니다.

Widget이 기기 성능을 저하시키나요?

올바르게 구현하면 — 아닙니다. 시스템은 위젯 리소스를 엄격하게 제한합니다: iOS — 업데이트 및 메모리 예산(30~50MB), Android — 최소 업데이트 간격. 문제가 있는 위젯은 시스템에 의해 강제 종료됩니다.

요약

  • Widget — 앱을 열지 않고 데이터에 빠르게 접근할 수 있는 홈 화면의 컴팩트 요소
  • iOS WidgetKit은 세 가지 고정 크기와 SwiftUI를 통한 TimelineProvider 업데이트 지원
  • Android AppWidgetProvider는 BroadcastReceiver와 RemoteViews로 유연한 셀 크기로 작동
  • 데이터 업데이트는 두 플랫폼 모두 시스템 제한: iOS — 업데이트 예산, Android — 최소 30분
  • 상호작용성은 iOS 17(App Intents)과 Android 12(동적 색상, 버튼)에서 등장
  • Smart Stack(iOS) 및 스택(Android)은 자동 전환으로 여러 위젯 그룹화 가능
  • 성능이 중요 — 한도 초과 시 시스템이 문제 위젯을 강제 종료

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기