[Swift] 앱 인텐트 알아보기

2025. 9. 3. 17:25·Apple/Swift
728x90
반응형

안녕하세요! 피피아노입니다 🎵

 

이번 포스팅에서는 App Intents 프레임워크에 대해서 정리를 해보려고 합니다.

 

관심 있으신 분들은 아래 영상을 참고하시면 좋을 것 같습니다.

https://developer.apple.com/kr/videos/play/wwdc2025/244

 

앱 인텐트 알아보기 - WWDC25 - 비디오 - Apple Developer

앱 인텐트 프레임워크에 대해 알아보고 Apple의 개발자 플랫폼 내에서 점점 더 중요해지는 이 프레임워크의 역할에 대해 살펴보세요. 인텐트, 엔티티, 쿼리 등 핵심 개념을 차근차근 설명합니다.

developer.apple.com

 

그럼 바로 시작하겠습니다!

App Intents란 무엇인가?

App Intents는 시스템 전체 및 모든 Apple 플랫폼에서 앱의 발견 가능성, 가시성, 기능을 확장해 주는 프레임워크입니다. 단순히 기능을 빌드하기 위해 앱으로 가져오는 프레임워크가 아니라, 앱의 기능을 시스템 전체로 확장해 주는 생태계라고 할 수 있습니다.

제공하는 경험

  • Spotlight 검색에서 맞춤형 결과
  • Siri를 통한 음성 명령 실행
  • 동작 버튼 및 Apple Pencil Pro 연동
  • 위젯과 제어 센터에서 바로 실행

올해부터는 Mac의 Spotlight에서도 앱 동작을 직접 실행할 수 있습니다.

핵심 구조

1. Intent - 앱의 "동사"

앱이 실행할 수 있는 동작을 정의합니다. "메모 열기", "운동 시작", "쇼핑 목록 추가" 같은 액션들이죠.

2. AppEnum vs AppEntity - 앱의 "명사"

  • AppEnum: 고정된 값들 (예: 앱 섹션 - 지도, 랜드마크, 컬렉션)
  • AppEntity: 동적인 데이터 (예: 개별 랜드마크들)

3. App Shortcut - 시스템 노출

Intent를 시스템 전체에 자동으로 노출시키는 방법입니다.

실제 예시: 여행 앱

랜드마크를 탐색하는 여행 앱을 예로 들어보겠습니다.

기본 Intent 만들기

struct NavigateToLandmarksIntent: AppIntent {
    static var title: LocalizedStringResource = "랜드마크 보기"
    static var supportedModes: [AppIntentMode] = [.foreground]

    @MainActor
    func perform() async throws -> some IntentResult {
        SharedNavigator.shared.navigate(to: .landmarks)
        return .result()
    }
}

매개변수 추가하기

앱 섹션을 선택할 수 있도록 AppEnum을 만들고,

enum NavigationOption: String, AppEnum {
    case landmarks, map, collections
    
    static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "탐색 옵션")
    // DisplayRepresentation으로 각 옵션에 아이콘 추가 가능
}

 

Intent에 매개변수로 추가해줍니다.

@Parameter(title: "섹션")
var section: NavigationOption

App Shortcut으로 노출

struct AppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: NavigateIntent(),
            phrases: ["\(.applicationName)에서 \(.section) 열기"],
            shortTitle: "탐색"
        )
    }
}

동적 데이터: AppEntity 활용

랜드마크 같은 동적 데이터는 AppEntity로 처리합니다.

Entity 정의

struct LandmarkEntity: AppEntity {
    var id: UUID

    @Property(title: "이름")
    var name: String

    @Property(title: "위치")  
    var state: String

    static var defaultQuery = LandmarkQuery()
}

Query 구현

시스템이 엔티티를 이해할 수 있도록 Query를 제공해줍니다.

struct LandmarkQuery: EntityQuery {
    func entities(for identifiers: [UUID]) async throws -> [LandmarkEntity] {
        // ID로 엔티티 조회 로직
    }
    
    func suggestedEntities() async throws -> [LandmarkEntity] {
        // 추천 랜드마크 반환
    }
}

 

고급 기능들

Transferable로 데이터 공유

엔티티의 이미지나 다른 데이터를 앱 간에 공유하거나 단축어에서 활용할 수 있도록 설정하기

extension LandmarkEntity: Transferable {
    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(contentType: .jpeg) { landmark in
            try await landmark.imageData()
        }
    }
}

이렇게 해주면 단축어에서 "Show Content" 액션으로 랜드마크 이미지를 직접 표시하거나, 다른 앱으로 이미지를 전달할 수 있습니다.

Spotlight 통합

extension LandmarkEntity: IndexedEntity {
    @Property(title: "이름") 
    @SpotlightIndexingKey(\.title)
    var name: String
}

@SpotlightIndexingKey를 사용하면 해당 속성이 Spotlight에서 검색 가능해지고, 사용자가 관련 키워드로 검색했을 때 결과에 나타나게 해줄 수 있습니다.

딥링킹

Spotlight에서 엔티티를 탭했을 때 앱 내 특정 화면으로 바로 이동하도록 설정

struct OpenLandmarkIntent: OpenIntent {
    @Parameter(title: "랜드마크")
    var target: LandmarkEntity
    
    // OpenIntent는 자동으로 앱을 열고 실행
}

OpenIntent 프로토콜을 채택하면 자동으로 앱을 포그라운드로 가져온 후 실행되므로, supportedModes 설정이 불필요합니다.

아키텍처 고려사항

빌드 타임 처리

  • App Intents는 컴파일 시점에 메타데이터 생성
  • Intent의 title 등은 반드시 상수여야 함
  • 시스템이 앱 실행 없이도 기능을 이해할 수 있음

다중 타겟 지원

여러 타겟에서 App Intent 타입을 공유하려면 AppIntentsPackage 등록이 필요합니다.

struct SharedIntentsPackage: AppIntentsPackage {}

struct MyAppPackage: AppIntentsPackage {
    static var includedPackages: [any AppIntentsPackage.Type] = [
        SharedIntentsPackage.self
    ]
}

 


감사합니다.

 

잘못된 내용이 있거나 더 좋은 내용 피드백은 언제나 환영합니다!

궁금하신 부분은 댓글로 질문 부탁드립니다!

728x90
반응형

'Apple > Swift' 카테고리의 다른 글

[Swift] Multipeer Connectivity 톺아보기  (5) 2025.08.23
[Swift] Swift Testing 톺아보기  (6) 2025.07.02
[Swift] suffix()로 인한 시간 초과 문제 해결하기  (8) 2025.06.27
[Swift] Foundation Models Framework  (6) 2025.06.22
[Swift] Core ML과 MFCC를 활용한 감정 추론  (7) 2025.05.14
'Apple/Swift' 카테고리의 다른 글
  • [Swift] Multipeer Connectivity 톺아보기
  • [Swift] Swift Testing 톺아보기
  • [Swift] suffix()로 인한 시간 초과 문제 해결하기
  • [Swift] Foundation Models Framework
P_Piano
P_Piano
Apple 생태계 개발자가 되기 위한 학습과 경험의 기록
    반응형
    250x250
  • P_Piano
    피피아노의 개발 일지
    P_Piano
  • 전체
    오늘
    어제
    • 분류 전체보기 (212)
      • Apple (130)
        • iOS (22)
        • visionOS (4)
        • Swift (70)
        • UIKit (2)
        • SwiftUI (24)
        • RxSwift (2)
        • Xcode (5)
      • C언어 (5)
      • C++ (8)
      • Dart (1)
      • Python (3)
      • JavaScript (17)
      • Git (1)
      • CS (39)
        • 디자인 패턴 (6)
        • 네트워크 (20)
        • 운영체제 (8)
        • Database (5)
        • 자료구조 (0)
      • IT 지식 (2)
      • IT 뉴스 (4)
      • 출처 표기 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    비동기
    combine
    제어문
    변수
    함수
    Xcode
    Apple
    옵셔널
    자바스크립트
    코딩테스트
    연산자
    네트워크
    오블완
    프로퍼티 래퍼
    Initializers
    프로그래머스
    스위프트
    swiftUI
    티스토리챌린지
    디자인패턴
    visionOS
    클래스
    SWIFT
    ios
    프로세스
    운영체제
    이니셜라이저
    배열
    Vision Pro
    UIKit
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
P_Piano
[Swift] 앱 인텐트 알아보기
상단으로

티스토리툴바