-
SwiftUI - TipKitSwiftUI 2026. 10. 3. 09:56
안녕하세요. 그린입니다 🍏
이번 포스팅에서는 SwiftUI의 TipKit 프레임워크에 대해 애플 공식 문서를 기준으로 정리해보겠습니다 🙋🏻
Intro
주제: TipKit
프레임워크: TipKit
지원 버전: iOS/iPadOS 17 · macOS 14 · tvOS 16 · watchOS 10 · visionOS 1 이상
TipKit이란
공식 문서는 TipKit을 이렇게 소개해요.
Use TipKit to show contextual tips that highlight new, interesting, or unused features people haven't discovered on their own yet.
즉, 사람들이 아직 스스로 발견하지 못한 기능을 가볍게 알려주는 용도예요.
Tip프로토콜로 팁의 내용과, 그 팁이 언제 나타나야 하는지의 조건을 정의하고,TipView로 그 기능에 시선을 끌게 만들어요.공식 문서는 사용 가이드도 명확히 제시해요.
- 사람들을 부담주지 않도록 팁은 아껴서 써야 함
- 스스로 발견하기 어려운, 눈에 잘 안 띄는 기능에만 써야 함
- 앱을 쓸 때마다 매번 팁을 띄우지 말 것 — 불필요하게 나타나면 방해가 됨
- 팁으로 앱 사용법을 처음부터 끝까지 안내하거나, 광고/프로모션 목적으로 쓰면 안 됨
디자인 가이드는 Human Interface Guidelines의 Offering Help 문서를 참고하라고 안내하고 있어요.
Tip 프로토콜 — 팁의 내용 정의하기
공식 문서의 첫 예제 코드예요.
import SwiftUI import TipKit // Define your tip's content. struct FavoriteLandmarkTip: Tip { var title: Text { Text("Save as a Favorite") } var message: Text? { Text("Your favorite landmarks always appear at the top of the list.") } var image: Image? { Image(systemName: "star") } }Tip은Identifiable,Sendable을 채택하는 프로토콜이에요.팁이 유효하려면
title은 반드시 설정해야 하고,message와image는 선택이에요.rules와options프로퍼티에Rule과Option인스턴스를 전달해서 팁이 언제 나타날지 제어할 수 있어요.앱 시작 시 팁 로드하기 — Tips.configure(_:)
팁을 화면에 띄우기 전에, 먼저 앱에 로드해야 해요.
공식 문서는 앱 세션마다 한 번, 예를 들어
App의init()에서configure(_:)를 호출하는 걸 베스트 프랙티스로 안내해요.@main struct TipKitExamples: App { var body: some Scene { WindowGroup { ContentView() } } init() { do { // Configure and load all tips in the app. try Tips.configure() } catch { print("Error initializing tips: \(error)") } } }configure(_:)에는ConfigurationOption배열을 전달해서 세부 설정도 가능해요.displayFrequency(_:): 팁이 뜬 뒤 다음 팁이 뜨기까지의 최소 간격을 설정..immediate(기본값),.hourly,.daily,.weekly,.monthly중 선택datastoreLocation(_:): 팁 상태를 저장할 위치를 커스터마이즈cloudKitContainer(_:): 팁 동기화에 쓸 CloudKit 컨테이너를 설정
.monthly를 예로 들면, 공식 문서는 이렇게 설명해요.When you set this, the system shows no more than one tip per month.
팁 띄우기 — Inline과 Popover
팁을 보여주는 방법은 두 가지예요.
공식 문서는 가능하면 인라인(Inline) 방식을 먼저 쓰라고 권장해요.
사람들이 상호작용하고 싶어할 UI 요소를 가리지 않기 때문이에요.
인라인 팁 — TipView
struct InlineView: View { // Create an instance of your tip content. let inlineTip = InlineTip() var body: some View { VStack(spacing: 20) { Text("A TipView embeds itself directly in the view.") // Place your tip near the feature you want to highlight. TipView(inlineTip, arrowEdge: .bottom) Button { // Invalidate the tip when someone uses the feature. inlineTip.invalidate(reason: .actionPerformed) } label: { Label("Favorite", systemImage: "star") } Spacer() } .padding() } }인라인 팁은 그 뷰 안에 직접 끼어들어 자리를 차지해요.
그래서 팁이 나타나거나 사라질 때 주변 레이아웃이 그에 맞춰 바뀝니다.
팝오버 팁 — popoverTip(_:arrowEdge:action:)
struct PopoverView: View { let highlightTip = HighlightTip() var body: some View { Image(systemName: "wand.and.stars") .imageScale(.large) // Place the tip on the feature to highlight. .popoverTip(highlightTip) .onTapGesture { tip.invalidate(reason: .actionPerformed) } } }팝오버 방식은 화면 위에 팁을 띄워서 아래 UI를 가려요.
레이아웃을 바꾸고 싶지 않거나, 팁이 가리는 컨트롤과 상호작용할 필요가 없을 때 적합해요.
팝오버는 이미 기능을 가리키고 있으니, 이미지는 생략하는 걸 고려해보라고도 안내합니다.
팁 무효화하기 — invalidate(reason:)
사람이 그 기능을 실제로 쓰고 나면, 팁을 프로그래밍적으로 무효화할 수 있어요.
InvalidationReason에는 다음 네 가지 케이스가 있습니다.actionPerformed: 팁이 설명하는 행동을 사용자가 실제로 수행함displayCountExceeded: 팁이 최대 표시 횟수를 초과함displayDurationExceeded: 팁이 최대 표시 기간을 초과함tipClosed: 사용자가 팁이 떠 있는 동안 명시적으로 닫기 버튼을 눌러 닫음
버튼 추가하기 — actions
팁에 추가 정보나 옵션으로 안내하는 버튼을 넣을 수도 있어요.
Tip의actions프로퍼티에Action인스턴스들을 정의하면 됩니다.struct PasswordResetTip: Tip { var title: Text { Text("Need Help?") } var message: Text? { Text("Do you need help logging in to your account?") } var image: Image? { Image(systemName: "lock.shield") } var actions: [Action] { Action(id: "reset-password", title: "Reset Password") Action(id: "faq", title: "View our FAQ") } }TipView에 전달한 클로저에서action.id를 확인해서 각 버튼을 눌렀을 때의 동작을 분기할 수 있어요.TipView(passwordResetTip, arrowEdge: .bottom) { action in if action.id == "reset-password", let url = URL(string: "https://iforgot.apple.com") { openURL(url) { accepted in print(accepted ? "Success Reset" : "Failure") } } if action.id == "faq", let url = URL(string: "https://appleid.apple.com/faq") { openURL(url) { accepted in print(accepted ? "Success FAQ" : "Failure") } } }언제 보여줄지 제어하기 — Rule, Parameter, Event
팁 구조체에 아무 rules도 정의하지 않으면, 그 팁은 닫히거나 display frequency 한계를 넘기 전까지 계속 나타나요.
앱 상태 기반 — Parameter
추적하고 싶은 앱 상태를 변수로 정의하고,
Parameter프로퍼티 래퍼로 감싼 뒤,rules프로퍼티에서#Rule매크로로 조건을 정의해요.struct ParameterRuleTip: Tip { // Define the app state you want to track. @Parameter static var isLoggedIn: Bool = false var rules: [Rule] { // Define a rule based on the app state. #Rule(Self.$isLoggedIn) { // Set the conditions for when the tip displays. $0 == true } } }이렇게 정의해두면, 앱 상태가 바뀔 때(예: 버튼 탭으로 isLoggedIn을 토글) 팁이 그에 맞춰 나타나거나 사라져요.
Button("Tap") { ParameterRuleTip.isLoggedIn.toggle() }사용자 행동 기반 — Event
사용자 행동을 추적하고 싶다면,
id를 가진Event상수를 정의하고 그 이벤트를 참조하는#Rule을 정의해요.아래 예제는 이벤트가 3번 이상 발생하면 팁이 나타납니다.
struct EventRuleTip: Tip { // Define the user interaction you want to track. static let didTriggerControlEvent = Event(id: "didTriggerControlEvent") var rules: [Rule] { #Rule(Self.didTriggerControlEvent) { $0.donations.count >= 3 } } }TipKit은 이벤트가 발생한 횟수를 자동으로 디스크에 저장하고, 이 상태는 앱을 재시작해도 유지돼요.
여러 조건 조합하기
Parameter와 Event 기반 규칙을 여러 개 정의하면,
rules프로퍼티 안에서 이 규칙들은 AND로 결합돼요.아래
ComboTip은 로그인 상태(parameter)와 화면 진입 3회(event)를 모두 만족해야 나타납니다.struct ComboTip: Tip { @Parameter static var isLoggedIn: Bool = false static let enteredView = Event(id: "enteredView") var rules: [Rule] { // Note: These rules AND together. #Rule(Self.$isLoggedIn) { $0 == true } #Rule(Self.enteredView) { $0.donations.count >= 3 } } }표시 빈도 제어하기 — Option
Tip의options프로퍼티에Option을 설정해서 표시 빈도를 제어할 수 있어요.MaxDisplayCount: 시스템이 자동으로 팁을 무효화하기 전까지 보여줄 최대 횟수를 지정MaxDisplayDuration: 팁이 무효화되기 전까지 표시되는 최대 시간을 지정IgnoresDisplayFrequency: 사전에 설정된 display frequency 간격을 이 팁이 따를지 여부를 제어
struct OptionTip: Tip { var options: [Option] { // Show this tip once. MaxDisplayCount(1) } }여러 팁을 순서대로 — TipGroup
TipGroup은 여러 팁을 특정 순서로 보여주거나, 표시 가능한 첫 번째 팁만 보여줄 수 있는 클래스예요.Priority에는 두 가지 케이스가 있어요.
firstAvailable(기본값): 표시 가능한 첫 번째 팁을 보여줌ordered: 이전 팁들이 모두invalidated상태가 됐을 때, 표시 가능한 팁을 보여줌
init(_ priority: TipGroup.Priority = .firstAvailable, @Tips.GroupBuilder _ builder: () -> [any Tip])currentTip프로퍼티로 현재 표시 가능한 팁을 가져올 수 있어요.팁 모양 커스터마이징 — TipViewStyle
기본적으로
TipView는MiniTipViewStyle(TipViewStyle.miniTip)로 그려져요.뷰 계층 전체에 커스텀 스타일을 적용하려면
TipViewStyle프로토콜을 채택한 타입을 만들고,.tipViewStyle(_:)모디파이어로 적용하면 됩니다.TipViewStyle의 유일한 요구사항은makeBody(configuration:)예요.여기서 받는
TipViewStyleConfiguration에는image,title,message,actions프로퍼티가 있어서, 이를 조합해 원하는 모습으로 그릴 수 있어요.struct HeadlineTipViewStyle: TipViewStyle { func makeBody(configuration: TipViewStyleConfiguration) -> some View { VStack(alignment: .leading) { configuration.image? configuration.title?.font(.headline) configuration.message?.font(.subheadline) ForEach(configuration.actions) { action in Button(action.title) { action.handler() } } } } }.tipViewStyle(HeadlineTipViewStyle())테스트하기 위한 API
팁이 더 이상 표시 자격이 없어지면 앱에서 사라지는데, 이건 개발 중 팁의 배치와 모양을 테스트하기 어렵게 만들어요.
TipKit은 이를 위한 테스트 전용 API를 제공합니다.
// Show all defined tips in the app. Tips.showAllTipsForTesting() // Show some tips, but not all. Tips.showTipsForTesting([tip1, tip2, tip3]) // Hide all tips defined in the app. Tips.hideAllTipsForTesting() // Purge all TipKit-related data. try Tips.resetDatastore()Conclusion
TipKit은
Tip프로토콜로 내용을 정의하고,TipView/popoverTip으로 보여주는 단순한 구조 위에, Parameter·Event 기반Rule과Option으로 "언제, 얼마나 자주" 보여줄지를 세밀하게 제어할 수 있는 프레임워크예요.직접 상태를 들고 조건문으로 온보딩 UI를 관리하던 걸, 선언적인 규칙으로 옮길 수 있게 됐다는 점이 핵심인 것 같습니다 🙌
References
TipKit | Apple Developer Documentation
Display tips that help people discover features in your app.
developer.apple.com
Highlighting app features with TipKit | Apple Developer Documentation
Bring attention to new features in your app by using tips.
developer.apple.com
Make features discoverable with TipKit - WWDC23 - Videos - Apple Developer
Teach people how to use your app with TipKit! Learn how you can create effective educational moments through tips. We'll share how you...
developer.apple.com
Customize feature discovery with TipKit - WWDC24 - Videos - Apple Developer
Focused on feature discovery, the TipKit framework makes it easy to display tips in your app. Now you can group tips so features are...
developer.apple.com
'SwiftUI' 카테고리의 다른 글
SwiftUI - Canvas (4) 2026.09.12 What's new in SwiftUI (feat. WWDC 2026) (1) 2026.06.29 SwiftUI View hierarchy Debugging (1) 2025.12.13 SwiftUI Preview - Thunk (1) 2025.11.29 SwiftUI's diffing (5) 2025.09.27