View in English

  • 메뉴 열기 메뉴 닫기
  • Apple Developer
검색
검색 닫기
  • Apple Developer
  • 뉴스
  • 둘러보기
  • 디자인
  • 개발
  • 배포
  • 지원
  • 계정
페이지에서만 검색

빠른 링크

5 빠른 링크

비디오

메뉴 열기 메뉴 닫기
  • 컬렉션
  • 주제
  • 전체 비디오
  • 소개
  • 소개
  • 자막 전문
  • 파운데이션 모델 프레임워크 코딩 실습

    파운데이션 모델 프레임워크를 사용해 Apple의 온디바이스 LLM을 직접 경험해 보세요. 온라인 세션을 통해 Xcode에서 실시간으로 함께 생성형 AI 기능을 샘플 앱에 구현해 볼 수 있습니다. 기본 텍스트 생성과 같은 핵심 기능 구현은 물론, 구조화된 데이터 출력을 위한 가이드 생성, 동적 UI 업데이트를 위한 스트리밍 응답, 데이터를 검색하거나 작업을 수행하기 위한 도구 호출과 같은 고급 주제를 살펴봅니다.

    누구나 참여할 수 있는 세션입니다. 코딩 실습에 적극적으로 참여하려면 macOS Tahoe 26와 Xcode 26의 최신 릴리즈를 실행하는 Apple Intelligence를 지원하는 Apple Silicon 탑재 Mac이 필요합니다.

    챕터

    • 0:00:00 - 소개
    • 0:03:33 - 리소스 및 시스템 요구 사양
    • 0:05:04 - 요건 및 설정
    • 0:06:30 - 스타터 프로젝트 살펴보기
    • 0:10:32 - 1장: Foundation Models 프레임워크 기본 사항
    • 0:11:51 - 1.1장: 첫 번째 생성 요청하기
    • 0:15:50 - 1.2장: 지침으로 모델 안내하기
    • 0:18:46 - 1.3장: 모델 가용성 처리하기
    • 0:20:50 - 1.4장: 뷰에서 가용성 처리하기
    • 0:24:07 - 1.5장: 일정 생성기 만들기
    • 0:27:07 - 1.6장: 텍스트 출력을 표시하도록 뷰 업데이트하기
    • 0:32:43 - 2장: 구조화된 출력 생성하기
    • 0:34:36 - 2.1장: 간단하고 구조화된 출력 생성하기
    • 0:37:52 - 2.2장: 중첩되고 구조화된 출력 생성하기
    • 0:41:58 - 2.3장: 일정 생성기 리팩터링하기
    • 0:44:48 - 2.4장: 구조화된 데이터를 표시하도록 뷰 업데이트하기
    • 0:49:22 - 3장: 프롬프팅 기법
    • 0:50:25 - 3.1장: PromptBuilder로 프롬프트 빌드하기
    • 0:53:23 - 3.2장: 원샷 프롬프팅
    • 0:55:31 - 3.3장: 예제로 일정 생성기 업데이트하기
    • 0:59:11 - 4장: 응답 스트리밍하기
    • 0:59:51 - 4.1장: 스트리밍을 위해 일정 생성기 업데이트하기
    • 1:02:52 - 4.2장: 스트리밍 콘텐츠를 렌더링하도록 뷰 업데이트하기
    • 1:08:16 - 5장: 도구 호출
    • 1:11:12 - 5.1장: FindPointsOfInterestTool 빌드하기
    • 1:16:32 - 5.2장: 모델에 FindPointsOfInterestTool 접근 권한 부여하기
    • 1:23:07 - 5.3장: 도구를 사용하도록 일정 생성기 업데이트하기
    • 1:27:39 - 6장: 성능 및 최적화
    • 1:34:20 - 6.1장: 모델 사전 준비하기
    • 1:36:56 - 6.2장: 프롬프트 최적화하기
    • 1:41:16 - 마무리 및 다음 단계

    리소스

    • Foundation Models Code-Along Project Files
    • Foundation Models Code-Along Instructions
      • HD 비디오
      • SD 비디오
  • 비디오 검색…

    안녕하세요, Foundation Models 프레임워크 코딩 실습입니다 제 이름은 Shashank이고 Apple의 기술 에반젤리스트입니다 오늘은 온디바이스 생성형 AI 기능을 앱에 직접 통합하는 방법을 안내하겠습니다 기본적인 프롬프팅부터 구조화된 출력 생성 응답 스트리밍 등을 모두 다룹니다 Slido에 뛰어난 전문가 팀이 있으니 언제든지 궁금한 점이 있으면 그곳에서 질문해 주세요 간략한 개요부터 살펴보죠 모두 같이 시작할 수 있도록요 WWDC24에서는 운영 체제 핵심에 내장된 대규모 파운데이션 모델로 구동되는 Apple Intelligence를 소개했습니다 이를 통해 시스템 수준 기능이 구현됩니다 글쓰기 도구와 젠모지 등이죠 여러분 중 많은 분이 기본 모델 이용을 요청하셨고 WWDC25에서 Foundation Models 프레임워크를 제공했습니다 이를 사용하면 Apple Intelligence를 구동하는 같은 온디바이스 대규모 언어 모델에 직접 접근할 수 있죠 강력한 Swift API를 통해서요 개발자에게 온디바이스 접근 방식은 큰 이점이 있습니다 모든 것이 로컬에서 실행되므로 사용자 데이터가 보호되죠 앱의 기능이 완전히 오프라인으로 작동하고 계정 설정이나 API 키 관리가 필요 없습니다 이러한 요청에 대해 개발자 또는 앱을 사용하는 다른 사용자에게 발생하는 비용이 없습니다 또한 이 모든 것은 OS의 일부이므로 앱 크기에 영향을 미치지 않습니다

    오늘은 앱 하나를 함께 빌드해 보겠습니다 랜드마크를 나열하는 간단한 정적 앱으로 시작한 후 동적 여행 플래너로 전환해 보죠 맞춤형 UI에 맞게 풍부한 구조의 일정을 생성하고 생성되는 결과를 실시간으로 스트리밍하는 방법을 알아봅니다 또한 모델에 맞춤형 도구 접근 권한을 부여하여 실제 관심 지점을 찾는 방법도 알아봅니다 마지막으로, 성능을 위한 앱 최적화 방법을 알아봅니다

    여러분이 빌드하게 될 최종 앱을 간략히 살펴보죠

    완성된 앱이 제 Mac에서 실행되고 있습니다 오늘 세션이 끝날 때쯤이면 이런 앱이 완성될 겁니다 SwiftUI를 사용해 빌드한 유명 랜드마크의 간단하고 깔끔한 목록으로 시작해 보죠 랜드마크를 하나 선택하겠습니다 세렝게티는 어떠세요?

    세부 뷰를 클릭하면 헤더 이미지와 설명이 표시됩니다 하단에는 일정 생성 버튼이 있습니다 이 버튼을 클릭하면 앱이 온디바이스 모델을 호출하여 3일간의 완전한 여행 계획을 생성합니다 이 작업이 수행되는 동안 화면을 자세히 살펴보세요

    UI가 실시간으로 자체 빌드됩니다 먼저 제목, 그 다음에 설명 그 다음에 일일 계획입니다 이것이 바로 4장에서 통합할 스트리밍 API로 환상적인 동적 사용자 경험을 선사합니다 단순한 코드 블록이 아니라 풍부한 구조화된 응답이며 이에 대해서는 2장에서 알아보겠습니다 날짜별로 제목, 부제목, 지도의 개별 섹션들이 있습니다 여기에 있는 이름에 주목하세요 호텔 1, 식당 1 등입니다 무작위가 아닙니다 앱에서 도구 호출을 사용해 이러한 이름을 가져옵니다 이에 대해서는 5장에서 다루겠습니다 Foundation Models 프레임워크를 사용하면 풍부하고 구조화된 지능형 경험을 선사할 수 있으며 이 경험은 앱에 매끄럽게 통합된 느낌을 줍니다 이것이 바로 오늘 우리가 함께 빌드할 앱입니다 오늘의 코딩 실습을 최대한 활용하기 위해 세 가지 핵심 리소스가 있습니다 첫 번째는 Xcode 스타트업 프로젝트입니다 모든 보일러플레이트 UI와 애셋을 즉시 사용할 수 있습니다 developer.apple.com/kr/이나 Developer 앱에서 시청하고 있다면 페이지 하단의 리소스 아래에서 찾을 수 있습니다 YouTube에서 시청 중이라면 설명에 링크로 연결되어 있습니다 두 번째는 해당 웹페이지의 단계별 가이드입니다 외부 파일 정보나 도구는 필요 없습니다 모든 지침과 코드 스니펫이 포함되어 있습니다 오타를 방지하려면 복사해서 붙여넣기만 하면 됩니다 마지막으로, 라이브 스트리밍을 진행하는 저와 함께하고 있는 전문가 팀이 여러분의 질문에 답변드리겠습니다 여기서 바로 여러분과 함께 이 프로젝트를 빌드하면서 각 변경의 이유를 설명하겠습니다 설정으로 넘어가 프로젝트를 설정하기 전에 오늘의 세션을 위한 시스템 요구 사양을 간략히 살펴보죠 누구나 시청하고 따라 할 수 있습니다 하지만 저와 함께 실시간으로 코딩하실 계획이라면 Apple Silicon 기반 Mac이 필요하며 macOS Tahoe와 Xcode 26를 실행해야 합니다 또한 설정에서 Apple Intelligence가 켜져 있는지 확인해야 합니다 오늘은 제 Mac에서 직접 앱을 빌드하고 실행하겠지만 Xcode 26를 사용해 iOS 26를 실행하는 최신 iPhone을 대상으로 삼을 수도 있습니다

    그럼 이제 코딩 실습 가이드의 요건 섹션으로 넘어가서 스타트업 프로젝트를 다운로드하고 구성해 보죠

    여기 가이드에 요건 섹션이 있습니다 먼저, 링크를 클릭하여 프로젝트 파일을 다운로드하세요

    다운로드를 마치면 zip 파일이 macOS에서 자동으로 압축 해제될 수 있습니다 FoundationModelsCodeAlong 폴더가 그 안에 있습니다 이것이 오늘 우리가 사용할 스타트업 프로젝트입니다 시작에 필요한 모든 뷰, 모델 플레이스홀더 코드가 포함돼 있죠 프로젝트를 열어 두었고 시작할 준비가 되었습니다

    가장 먼저 해야 할 일은 개발자 팀을 구성하는 것입니다 프로젝트 내비게이터에서 프로젝트 파일을 선택합니다

    그런 다음 대상을 선택합니다

    Signing & Capabilities를 클릭합니다 Team에서 드롭다운을 선택하고 팀을 선택합니다

    모든 것이 올바르게 작동하도록 하려면 Xcode 도구 막대에서 My Mac을 실행 대상으로 선택합니다

    그런 다음 실행 버튼을 클릭합니다 이렇게 하면 프로젝트가 빌드되고 실행됩니다 또는 Command + R을 사용할 수 있습니다

    이것이 바로 우리가 빌드하고 생성형 AI 기능을 추가할 앱입니다 이것이 우리의 시작점이며 이 세션 전체에 걸쳐 강력한 기능을 추가할 것입니다 이제 스타트업 프로젝트를 간략히 살펴보겠습니다

    먼저 Playground.swift 파일이 Playgrounds 폴더 아래에 있습니다 여기서 프롬프트를 반복하고 Foundation Models API를 격리하여 테스트합니다 앱 전체를 빌드하고 실행할 필요 없이요 프롬프트가 만족스러우면 이 코드를 앱 내로 옮깁니다

    다음은 ViewModels 폴더입니다 여기서 가장 중요한 파일은 ItineraryGenerator.swift입니다 파운데이션 모델 세션을 생성 및 관리하고 프레임워크 API를 호출하고 결과를 처리하기 위한 모든 핵심 로직이 바로 여기에 있습니다 마지막으로 Views 폴더가 있습니다

    모든 SwiftUI 코드가 있는 곳입니다 이 코딩 실습에서는 UI가 대부분 사전 빌드되어 있어 Foundation Models 프레임워크에 집중할 수 있습니다 여기에 여러 개의 파일이 있고 따라 하기 쉽도록 편집할 주요 파일에 번호가 매겨져 있습니다

    일정 생성기의 출력을 가져와서 이러한 뷰에 연결해 앱에서 볼 수 있는 풍부한 대화형 UI를 생성할 것입니다

    이 파일들을 살펴보면 다음과 같은 형식의 특별한 주석이 있습니다 MARK, CODE ALONG, CHAPTER 그리고 숫자입니다 각 숫자는 코딩 실습 가이드에서 동일한 번호의 장과 섹션에 직접 해당합니다 Xcode 찾기 탐색기를 사용해 장 번호를 검색하면 남아 있는 모든 코드 변경 사항을 확인할 수 있습니다

    여기에 장 번호를 입력하면 모든 코드 변경 사항이 표시됩니다 각 단계를 완료하면서 이러한 주석을 계속 삭제하면 코딩 실습 전체에 걸쳐 진행 상황을 확인할 수 있습니다

    요약하면, 우리는 간단한 세 단계를 따를 것입니다 첫째, 플레이그라운드에서 실험해 봅니다 둘째, 뷰 모델에서 핵심 로직을 구현합니다 마지막으로 뷰에 결과를 표시합니다 이러한 각각의 뷰를 더 자세히 살펴보겠습니다

    첫 번째 화면은 시작점으로 주요 랜드마크 목록입니다 이 기능은 LandmarksView.swift로 구동됩니다 오늘은 이 파일을 건드리지 않을 것입니다 목적지를 탐색하고 선택할 수 있게 모든 것이 설정되어 있습니다 랜드마크를 탭하면 세부 정보 화면으로 이동합니다 이 뷰는 LandmarkDetailView.swift 파일이 제어하죠 주요 작업은 Foundation Models 프레임워크를 기기에서 사용할 수 있는지 확인하고 그에 따라 표시할 UI를 결정하는 것입니다

    다음은 LandmarkTripView입니다 이 뷰의 역할은 일정 생성 버튼을 표시하는 것입니다 또한 여기서는 모델에서 다시 얻는 원시 비정형 텍스트를 먼저 표시합니다

    마지막으로 ItineraryView는 우리의 목적지입니다 이 뷰는 코딩 실습이 끝날 때쯤 완성될 풍부하고 구조화된 일정 데이터를 렌더링합니다

    이제 오늘 다룰 주제를 자세히 살펴보죠 코딩 실습을 여섯 개 장으로 구성했습니다 우선, 기본 사항으로 시작해 모델 프롬프팅으로 텍스트를 생성하는 방법을 알아봅니다 그런 다음 간단한 텍스트를 넘어 모델에서 구조화된 Swift 유형을 다시 얻는 방법을 살펴보겠습니다 이를 통해 모델 출력을 맞춤형 뷰에 쉽게 매핑할 수 있습니다 그런 다음 프롬프팅 기법에 대해 자세히 알아보겠습니다 이를 사용하면 프롬프트에서 직접 고품질 예제를 제공하여 모델 정확성을 높일 수 있습니다 다음으로, 멋진 사용자 경험을 위해 모델의 응답을 스트리밍하여 UI를 실시간으로 업데이트하는 방법을 알아봅니다 그런 다음 도구 호출을 살펴봅니다 도구는 고유한 맞춤형 함수와 데이터에 대한 접근 권한을 모델에 부여하여 모델의 기능을 확장하는 강력한 방법입니다 마지막으로 성능 최적화로 더 빠르고 반응성이 뛰어난 생성형 기능을 구현하는 방법을 알아봅니다 이제 Foundation Models 프레임워크의 기본 사항을 자세히 살펴보죠 Foundation Models 프레임워크를 사용해 온디바이스 대규모 언어 모델 즉 LLM에 프롬프트를 전송할 수 있습니다 LLM이 프롬프트에 대해 추론하고 텍스트를 생성할 수 있습니다 예를 들어 파리에서의 3일 일정을 생성하도록 요청할 수 있습니다 그러면 모델이 자세한 계획으로 응답할 것입니다

    모델 프롬프팅을 시작하려면 세션을 생성해야 합니다 이 프레임워크는 모든 프롬프트와 응답의 기록을 유지하는 스테이트풀 언어 모델 세션이라는 아이디어를 중심으로 구축됩니다 이 장에서는 파운데이션 모델 프롬프트와 세션에 익숙해져 보겠습니다 먼저 플레이그라운드에서 시작해 API를 알아보죠 언어 모델 세션을 생성하고 모델에서 첫 번째 응답을 얻습니다 그런 다음 간결한 지침을 추가하여 톤과 콘텐츠를 형성합니다 다음으로, 다양한 상태를 문제 없이 처리하기 위한 가용성 API를 살펴보겠습니다 편해지면 앱으로 전환하고 뷰 모델에서 일정 생성기를 업데이트한 후 뷰에 원시 텍스트 출력을 표시합니다 이제 코딩 실습 가이드를 살펴보겠습니다

    1장에서의 목표는 온디바이스 언어 모델에 대한 첫 번째 요청을 만드는 것입니다 Xcode 플레이그라운드를 사용해 간단한 텍스트 프롬프트를 보내고 어떻게 되는지 살펴보죠 모델의 기본 동작을 이해하는 데 도움이 됩니다

    이 코드 블록을 복사해 Xcode Playground.swift 파일에 붙여넣고 오른쪽 상단에 있는 편리한 복사 버튼을 사용할 수 있습니다 이러한 코드 줄을 단계별로 추가하고 어떻게 되는지 설명하겠습니다 Xcode를 살펴보죠 Playground.swift 파일을 엽니다 모델을 프롬프팅하려면 간단한 세 단계가 필요합니다 첫 번째 단계는 Foundation Models 프레임워크를 가져오는 것인데 우리는 이미 완료했습니다 다음 단계는 플레이그라운드를 생성하는 것입니다

    플레이그라운드 매크로를 사용해 플레이그라운드를 생성하는 즉시 오른쪽에 캔버스가 표시됩니다 표시되지 않으면 언제든지 편집기 옵션을 클릭하고 캔버스 옆에 체크 표시가 있는지 확인하세요 새로 고침 버튼을 클릭하면 플레이그라운드 블록 내에 포함된 모든 코드가 실행됩니다 지금은 출력이 표시되지 않습니다 아무것도 추가하지 않았으니까요 모델 프롬프팅의 두 번째 단계는 세션을 생성하는 것입니다

    여기에 let 변수 session = LanguageModelSession이 있고 플레이그라운드 캔버스에 해당 session 변수에 포함된 내용이 자동으로 표시됩니다 tools가 있네요 이에 대해서는 나중에 살펴보죠 그리고 transcript가 있는데 여기에는 해당 모델과 나누는 모든 대화가 포함됩니다

    세 번째 단계는 모델을 프롬프팅하는 것입니다

    let response = try await session.respond(to:라고 하고 프롬프트 Generate a 3-day itinerary to Paris를 제공합니다 이것은 비동기 요청이므로 응답을 기다립니다

    이렇게 하는 즉시 캔버스 오른쪽에 몇 가지 속성을 포함하는 response 변수가 표시됩니다 첫 번째는 prompt입니다 prompt에 Generate a 3-day itinerary to Paris라고 표시되고 그 다음에 String 유형인 content 속성이 있습니다 이를 클릭하면 자세한 파리에서의 3일 일정이 표시됩니다 파리를 살펴보기 위한 3일간의 일정입니다 파리의 가장 대표적인 명소와 경험을 강조하고 일일 계획을 첫째 날, 아침 오후 등으로 나누어 보여 줍니다

    이제 가이드로 돌아가서 핵심 주제를 살펴보겠습니다 Session.response를 처음 호출할 때 약간의 지연이 발생하는 것을 알 수 있습니다 그 이유는 요청을 처리하려면 먼저 온디바이스 언어 모델이 메모리에 로드되어야 하기 때문입니다 첫 번째 요청은 시스템에서 모델을 로드하도록 트리거하는데 이로 인해 초기 지연 시간이 발생합니다 이를 해결하는 방법은 이후 장에서 살펴보겠습니다 또한 출력은 비정형 자연어 텍스트이므로 우리가 읽기는 쉽지만 맞춤형 Swift UI에서 사용하기는 어렵다는 것을 확인했습니다 다음 장에서는 원시 텍스트 대신에 Swift 유형을 사용하여 구조화된 출력을 생성하는 방법을 살펴보겠습니다 마지막으로, 데이터가 절대로 기기를 벗어나는 일 없이 일정 전체가 생성되었다는 점이 중요합니다 완전히 비공개로 유지되고 오프라인으로 작동합니다 축하합니다 Foundation Models 프레임워크를 사용해 온디바이스 파운데이션 모델을 성공적으로 프롬프팅했습니다

    아, 마지막 한 가지가 있습니다 플레이그라운드로 돌아가 보죠

    저희는 항상 모델 향상에 관심이 있습니다 피드백을 제공해 주시려면 언제든지 캔버스에 있는 이 버튼들을 사용해서 피드백을 공유하실 수 있습니다 코딩 실습 가이드로 돌아가 보죠 섹션 1.2 지침으로 모델 안내하기입니다

    이제 목표는 일관성을 향상하고 결과의 품질을 높이는 것입니다 모델에 지침을 제공하여 이렇게 할 수 있습니다 지침을 단일 세션 내 대화 전체에 대한 영구적 규칙이나 Persona로 생각해 보세요 이 코드를 플레이그라운드에 복사하고 실행하세요 저는 이 지침을 추가하겠습니다

    다시 Playground.swift 파일에서

    instructions라는 새로운 변수를 추가하고 이렇게 씁니다 Your job is to create an itinerary for the user Each day needs an activity hotel, and restaurant Always include a title, a short description and a day-by-day plan instructions 인수를 사용해 이 지침을 언어 모델 세션에 전달할 수 있습니다

    이를 전달하면 캔버스가 코드 변경 사항을 자동으로 감지하고 결과를 업데이트합니다 이제 response 아래에 content 속성이 있고 여기에 우리가 만든 요청이 포함됩니다 즉 활동, 호텔, 식당을 포함하라는 것이죠 그리고 여기에서 활동, 호텔 식당을 볼 수 있습니다 여러분이 궁금해하실 만한 점이 있는데 바로 이 지침과 프롬프트의 차이점입니다 한번 살펴보죠

    지침은 Persona를 정의하고 규칙을 설정하고 원하는 응답 형식을 지정하는 데 사용할 수 있습니다 지침은 개발자가 제공해야 합니다 반면에 프롬프트는 앱 사용자가 제공할 수 있습니다 이 모델은 프롬프트보다 지침을 우선적으로 따르도록 학습되었으며 이는 사용자가 모델에 프롬프트의 안내를 무시하도록 요청할 수 있는 프롬프트 인젝션 공격을 막는 데 도움이 될 수 있습니다 원칙적으로, 지침은 정적 상태로 유지하고 사용자 입력이 지침에 삽입되지 않도록 하세요

    또한 지침은 세션 기간 내내 유지된다는 점에 유의하세요 모든 상호작용은 세션의 전사문에 기록되며 초기 지침이 항상 첫 번째 항목입니다

    성공적으로 모델을 프롬프팅하고 응답을 얻을 수 있게 되었습니다 하지만 앱이 Apple Intelligence를 사용할 수 없는 기기에서 실행될 수 있으며 작동하지 않는 기능을 표시하면 나쁜 사용자 경험이 될 수 있음을 고려하는 것이 중요합니다 예를 들어 기기가 Apple Intelligence를 지원하지 않거나 기기가 Apple Intelligence를 지원하더라도 사용자가 이를 활성화하지 않았을 수도 있습니다 또는 모델 애셋이 여전히 다운로드 중이고 아직 사용할 준비가 되지 않았을 수도 있습니다 이러한 경우를 처리하는 방법을 자세히 살펴보겠습니다 코딩 실습 가이드로 다시 돌아가죠 이제 코딩 실습 가이드의 섹션 1.3 모델 가용성 처리하기입니다

    이 모델은 가용성에 대한 API를 제공합니다

    Xcode로 가서 이 스위치 블록의 각 케이스를 자세히 살펴보고 앱에 어떤 의미가 있는지 알아보겠습니다

    Playground.swift 파일로 돌아가죠 플레이그라운드의 멋진 기능은 동일한 Swift 파일에 이를 여러 개 추가할 수 있다는 겁니다

    여기에 가용성 코드를 포함하는 새로운 #Playground 블록을 추가했습니다 좋습니다

    이러한 API를 살펴보죠 여러 플레이그라운드의 출력도 확인할 수 있습니다 두 번째 플레이그라운드는 캔버스에서 두 번째 탭입니다 제 Mac이 Apple Intelligence를 지원한다는 걸 보실 수 있습니다 파운데이션 모델을 바로 사용할 수 있다고 되어 있네요 이제 이 케이스들을 자세히 살펴보겠습니다

    첫 번째 케이스는 available입니다 즉, 사용할 수 있다는 뜻입니다 모델이 로드되었고 생성 요청을 할 준비가 되었습니다

    unavailable 및 deviceNotEligible이 표시되면 모델이 Apple Intelligence를 지원하지 않는다는 뜻입니다 생성형 UI를 문제 없이 숨기고 대체 경험을 표시해야 합니다

    unavailable 및 appleIntelligenceNotEnabled는 기기에서 이를 사용할 수 있지만 Apple Intelligence가 설정에서 꺼져 있음을 의미합니다 이 경우 사용자에게 활성화하도록 요청할 수 있습니다

    unavailable 및 modelNotReady는 일시적 상태이며 모델 애셋이 아직 다운로드 중이기 때문일 가능성이 높습니다 가장 좋은 방법은 사용자에게 다시 시도해 보라고 하는 것입니다 이제 앱에 이러한 기능을 추가할 준비가 되었습니다 코딩 실습 가이드를 살펴보죠

    이제 1장의 앱 섹션입니다 이 섹션에서는 랜드마크 DetailView.swift를 업데이트하여 모델 가용성을 확인하고 사용할 수 없는 경우 메시지를 표시합니다 이러한 코드 블록을 복사하세요 Mark 표시된 이 주석을 검색하면 코드 변경 사항을 삽입할 정확한 위치를 알 수 있습니다 여러분과 함께 실시간으로 이 작업을 해 보겠습니다 Xcode 프로젝트로 가서

    LandmarkDetailView.swift를 Views 폴더에서 클릭합니다 다시 말씀드리지만 항상 찾기 탐색기를 사용해 이 장에서 변경해야 할 모든 코드를 찾을 수 있습니다 가장 먼저 할 일은 모델 인스턴스를 추가하는 겁니다

    private let model = SystemLanguageModel.default 플레이그라운드에서 사용한 코드 줄과 정확히 동일하므로 익숙해 보일 것입니다 이 코드를 추가했으니 이 주석을 삭제하겠습니다 찾기 탐색기에서 사라집니다 우리가 해야 할 다음 코드 변경은 이 플레이스홀더 가용성 코드를 삭제하는 것입니다 이것은 순전히 편의를 위한 것이었으니 삭제하겠습니다 그렇게 하자마자 Xcode가 가용성이 아직 정의되지 않았다고 신속히 알려 줍니다 하지만 이제 모델이 있기 때문에 쉽게 수정할 수 있습니다 바로 model.availability입니다

    이 코드 줄도 삭제하겠습니다 괜찮으시죠? 해당 코드 변경으로 이 특정 파일에 대한 모든 변경을 완료했습니다

    이제 이러한 가용성 검사를 추가했습니다 플레이그라운드에서 사용하는 것과 동일하니까 익숙하실 겁니다 하지만 어떻게 테스트할까요? 여러 대의 테스트 기기를 이용할 수 없을 수도 있습니다 다행히도 쉬운 방법이 있습니다 바로 여기 프로젝트의 스키마 설정에 사용 불가능한 경우를 시뮬레이션하는 옵션이 있습니다 한번 살펴보죠 FoundationModelsCodeAlong을 클릭합니다 Edit Scheme을 클릭하고 아래로 스크롤하면 Simulated Foundation Models Availability라는 옵션이 표시됩니다

    이 항목을 클릭하면 몇 가지 옵션이 있습니다 이러한 옵션은 여러분에게 익숙할 것입니다 플레이그라운드에서 다룬 케이스들이기 때문입니다 Apple Intelligence Not Enabled를 클릭하고 닫은 후

    앱을 빌드하고 실행하겠습니다

    여기 우리 앱이 있습니다 사하라 사막을 선택하죠 Trip Planner is unavailable because Apple Intelligence has not been turned on이라는 메시지가 표시되네요

    사용 불가능한 경우의 뷰에서와 동일한 메시지입니다

    좋습니다 이를 다시 전환해서 코딩 실습 전체에 걸쳐 추가 기능을 계속 추가할 수 있도록 해 보죠

    좋습니다 이제 코딩 실습 가이드의 섹션 1.5로 넘어가 보겠습니다

    이제 앱의 일정 생성기를 업데이트하여 언어 모델 세션을 초기화하고 generateItinerary 함수를 정의해 뷰에서 모델을 호출할 준비가 되었습니다 이 코드는 이미 코딩 실습에서 구현했기 때문에 여러분에게 익숙해 보일 것입니다 이제 이를 앱으로 마이그레이션하겠습니다 Xcode로 가서 ItineraryGenerator.swift 파일을 열어 보죠 ViewModels 폴더에 있습니다

    다시 한번 찾기 탐색기를 사용해 필요한 모든 코드 변경 사항을 찾고 진행 상황을 확인하겠습니다 좋습니다 ItineraryGenerator.swift 파일에서 가장 먼저 변경해야 할 내용은 세션 속성을 추가하는 것입니다 이것을 먼저 해 보겠습니다 LanguageModelSession에 대해 session 변수를 정의합니다

    다음으로, Xcode에서 세션을 초기화하지 않았다고 알려 줍니다 바로 여기 init 함수에서 이 세션을 초기화하겠습니다

    우리가 추가한 내용은 다음과 같습니다

    플레이그라운드에서와 동일한 지침을 사용하는 instructions 변수를 추가했습니다 Your job is to create an itinerary for the user Each day needs an activity hotel and restaurant Always include a title, a short description and a day-by-day plan 또한 session의 LanguageModelSession에서 지침을 전달합니다 세 번째이자 마지막으로 변경해야 할 사항은 generateItinerary 함수를 업데이트하는 것입니다 이 함수는 프롬프트를 보내고 응답을 얻기 위해 뷰에서 호출할 함수입니다 이 코드를 변경해 보겠습니다

    추가한 내용은 다음과 같습니다 먼저, let prompt = “Generate a \(dayCount)-day itinerary to

    \(landmark.name)”라고 작성했습니다 여기서 dayCount는 기본적으로 3으로 설정되고 landmark.name은 사용자가 앱을 열 때 클릭하는 랜드마크의 이름입니다 이 이름을 수집해 프롬프트에 전달합니다 따라서 해당 특정 랜드마크에 대한 응답을 생성할 수 있습니다 다음으로, let response = try await session.respond가 있고 프롬프트를 전달합니다 마지막으로, response 변수는 속성 .content를 갖습니다 앞서 살펴본 플레이그라운드 캔버스에서 본 기억이 나실 텐데요 해당 캔버스에는 자연스러운 비정형 텍스트가 포함되었습니다 이 속성은 문자열이며 이를 itineraryContent에 할당합니다

    여기에는 뷰 모델에 대한 모든 코드 변경 사항이 포함되며 이제 뷰에서 뷰 모델을 호출할 준비가 되었습니다 코딩 실습 가이드의 섹션 1.6으로 돌아가 보죠 1장의 마지막 섹션입니다 이제 LandmarkTripView를 업데이트하여 일정 생성기에서 출력을 가져와 앱에 표시하겠습니다 다시 한번 말씀드리지만 이러한 주석을 따라가면서 자유롭게 코드를 변경하세요 Xcode로 가 보죠

    Views를 클릭하고

    LandmarkTripView를 클릭합니다 좋습니다

    변경해야 할 첫 번째 코드는 뷰 모델의 ItineraryGenerator 클래스에 로컬 변수를 추가하는 것입니다

    Itinerary 유형의 ItineraryGenerator를 작성했으니 이 주석을 삭제하겠습니다

    다음으로 작성해야 할 코드 즉 필요한 코드 변경은 뷰가 로드될 때 이것의 인스턴스를 생성하는 것입니다

    task 수정에서 도입할 내용은 다음과 같습니다 let generator = ItineraryGenerator를 작성했는데 이는 ViewModel 클래스이며 landmark를 전달하여 사용자가 어떤 랜드마크를 클릭했는지 정보를 제공하죠 기억나시겠지만 이를 프롬프트에 전달합니다 그런 다음 여기에 ItineraryGenerator를 유지합니다 방금 변경한 코드를 삭제하겠습니다

    다음으로 변경해야 할 사항은 뷰 자체를 업데이트하는 것입니다 해당 뷰를 자세히 살펴보죠 기본적으로 requestedItinerary라는 부울 변수가 있고 false로 설정되어 있습니다 false로 설정되어 있기 때문에 첫 번째 뷰를 맨 위에 로드합니다 이는 랜드마크 이름이 포함된 텍스트 필드입니다 landmark.name에 접근한 다음 landmark.shortDescription을 사용해 짧은 설명에 접근합니다 이것이 바로 사용자가 생성하지 않은 경우 모델에 일정 생성을 요청하지 않은 경우 표시되는 내용입니다 하지만 requestedItinerary가 false로 설정된 경우 모델의 출력으로 채울 수 있는 새로운 뷰를 로드해야 합니다 이것이 바로 우리가 지금 바로 구현할 내용입니다 여기서 else 케이스를 제거하고

    새로운 else 케이스를 도입합니다 이렇게 작성합니다 if let content = ItineraryGenerator?.itineraryContent 기억나시겠지만 itineraryContent는 문자열 변수로 모델의 출력을 포함합니다 그런 다음 해당 콘텐츠를 가져와 Text 뷰에서 업데이트합니다 이렇게 변경했으니 이 주석도 삭제하겠습니다

    거의 다 됐네요 이 뷰에서 수행할 마지막 변경 사항이 하나 있습니다 다시 아래로 스크롤해 보면

    화면 하단에 표시될 버튼을 정의했는데 현재 이 버튼은 숨겨져 있습니다 따라서 두 가지 사소한 코드 변경이 필요합니다 첫째, 버튼을 표시하기 위해 이를 주석 처리하거나 바로 삭제할 수 있습니다 제가 하고 있는 것처럼요 그런 다음 여기에 코드를 삽입해 사용자가 버튼을 탭하면 일정을 생성하도록 합니다 여기에 추가해 보겠습니다

    await itineraryGenerator라고 작성했고 generateItinerary 함수를 호출합니다 기억나시겠지만 이 함수는 프롬프트를 받은 다음 모델에 전달하고 출력을 얻습니다 이것으로 이 장의 모든 코드 변경을 마칩니다 이제 앱을 빌드하고 실행할 준비가 되었습니다 좋습니다 여기에서 실행 버튼을 클릭하면 앱이 빌드되고 실행됩니다

    앱이 표시됩니다

    사하라 사막을 클릭하겠습니다 일정 생성 버튼이 있는 것을 볼 수 있습니다 이 일정 생성 버튼을 클릭하면 프롬프트와 지침이 온디바이스 LLM에 전송됩니다 이 LLM에서 토큰별로 비동기식으로 응답을 생성합니다 온디바이스 방식으로요

    저처럼 이 일정이 보이신다면 축하합니다 Foundation Models 프레임워크를 사용해 완벽하게 작동하는 첫 번째 온디바이스 생성형 AI 기능을 빌드하셨습니다 Swift 단 몇 줄만으로 Apple Intelligence의 강력한 성능을 활용하셨습니다

    훌륭합니다 하지만 여기엔 텍스트가 가득하죠 호텔 이름을 가져와 지도에 표시하고 싶다면 어떻게 할까요? 이건 우리가 원하는 풍부한 경험이 아닙니다 2장에서 가이드 생성을 통해 이 내용을 다루겠습니다 Swift 구조체를 사용해 모델에서 직접 출력을 얻는 방법을 살펴보죠 지금은 1장을 간략히 요약해 보겠습니다

    이 장에서는 세션 생성 방법과 기본 텍스트 응답을 위한 모델 프롬프팅 방법을 알아봤습니다 모델의 출력을 안내하는 지침을 제공하는 방법을 살펴봤고 가용성 API를 사용하여 다양한 가용성 상태를 처리하는 방법을 다루었습니다 마지막으로, 뷰 모델과 뷰를 업데이트하여 이러한 기능을 앱에 통합했습니다

    이것으로 1장을 마칩니다

    이제 원시 텍스트를 생성할 수 있으니 모델에서 구조화된 데이터를 얻어 한층 더 풍부한 UI를 빌드하는 방법을 살펴보겠습니다

    LLM 작업 시의 기본적인 과제로 시작해 보겠습니다 기본적으로 LLM은 비정형 텍스트를 제공합니다 방금 생성했던 일정처럼요 사람이 읽을 수 있지만 앱 개발자에게는 다루기 어려울 수 있습니다 예를 들어 어떻게 하면 첫날 호텔을 안정적으로 추출하여 지도에 표시할 수 있을까요? 모델의 출력이 변경될 경우 작동이 중단될 수 있는 복잡한 문자열 파싱 코드를 작성해야 합니다 그 대신에 우리가 원하는 것은 앱 로직에 직접 매핑되는 구조화된 데이터입니다

    Swift 구조체를 사용해 구현할 수 있는 고급 중첩 구조가 필요합니다 이 일정 객체는 객체 배열을 포함해야 하며 객체 배열은 다시 활동 객체 배열 등을 포함해야 합니다 여기서 가이드 생성이 필요합니다 Foundation Models 프레임워크는 출력의 형태를 정확하게 지정할 수 있는 API를 제공합니다 Swift 구조체가 있는 경우 해당 구조체에 @Generable을 적용하기만 하면 됩니다 그러면 모델이 네이티브 Swift 유형을 사용해 구조화된 데이터를 생성할 수 있습니다

    이 장은 플레이그라운드에서 시작해 generable 매크로가 적용된 간단한 구조체를 정의합니다 그런 다음 이를 기반으로 모델이 생성할 수 있는 더 복잡한 중첩 데이터 구조를 생성합니다 마지막으로, 앱으로 돌아가서 ItineraryGenerator를 리팩터링해 새로운 구조화된 일정 유형을 출력하고 풍부한 UI로 표시하도록 뷰를 업데이트합니다

    코딩 실습 가이드로 돌아가 보겠습니다

    이제 2장에서는 구조화된 출력을 생성합니다 우리의 목표는 간단한 문자열을 넘어서서 모델에서 직접 구조화된 타입 세이프 Swift 데이터를 얻는 것입니다 이를 통해 취약한 문자열 파싱 없이 풍부한 맞춤형 UI를 빌드할 수 있습니다

    자유롭게 이 코드를 다시 플레이그라운드에 복사하고 그 출력을 살펴보세요 SimpleItinerary라는 새로운 구조체를 도입하면 어떻게 되는지 설명해 드리겠습니다 Xcode 플레이그라운드 파일로 가서 코드를 변경해 보겠습니다

    방금 추가한 두 번째 플레이그라운드를 삭제하고 바로 여기에

    SimpleItinerary라는 새로운 구조체를 도입하겠습니다 이 구조체는 어떤 형태이며 이를 어떻게 파운데이션 모델 코드에 통합해 이 출력을 생성할 수 있는지 살펴보죠 첫째, 이 구조체에는 몇 가지 다른 속성이 있습니다 title은 String 유형입니다 description은 String 유형입니다 days는 String 배열입니다

    우리는 모델이 이러한 필드를 생성하기를 원하며 가이드를 제공하여 모델에 추가 정보를 제공할 수 있습니다 가이드에는 description 인수가 있고 An exciting name for the trip이라고 되어 있습니다 이는 모델에 이 변수에 대한 제목을 생성해야 함을 알려 줍니다 마찬가지로 description은 여행에 대한 짧고 매력적인 설명이 필요함을 나타내고 일수의 경우에도 마찬가지입니다 지금 우리가 할 수 있는 일은 이를 모델에 제공하는 것입니다 generating 인수를 사용해 이를 수행할 수 있습니다 이전에는 session.respond와 프롬프트만 있었습니다 generating이라는 새로운 인수를 추가하고

    SimpleItinerary.self를 제공하려고 합니다

    캔버스를 새로 고침할 수 있습니다 그러면 코드가 실행됩니다 출력을 살펴보겠습니다

    좋습니다 우리의 response가 여기에 있네요 content 속성을 자세히 살펴보겠습니다 이전에는 이 콘텐츠가 String이었습니다 주의 깊게 살펴보면 struct SimpleItinerary라고 되어 있죠 이걸 열어 보겠습니다 출력이 우리가 방금 정의한 구조체와 일대일로 일치하는 것을 확인할 수 있습니다 title은 Parisian Bliss입니다 이것이 바로 title 속성입니다 바로 여기에 description이 있습니다 그리고 String 배열이 있습니다 days라는 String 배열인데 일일 활동 계획이 포함되어 있습니다

    멋지네요 코딩 실습 가이드의 섹션 2.2로 돌아가 보죠 일정이 String 또는 String 배열일 필요는 없습니다 중첩된 구조체도 가질 수 있습니다 이제 앱에서 빌드할 전체 일정 구조체를 살펴보죠 작은 코드 변경을 해 보겠습니다 SimpleItinerary를 Itinerary.self로 대체하면 되죠 이 코드 체인을 만들고 이 itinerary 구조체가 어떤 형태인지 설명하겠습니다 Xcode로 돌아갑니다

    이 SimpleItinerary를 삭제하고

    SimpleItinerary를 Itinerary로 대체하겠습니다 일정은 어떤 형태일까요? 이를 command-클릭하여 정의를 열거나 Models 폴더로 가서 Itinerary.swift 파일을 클릭하면 Itinerary라는 새 구조체가 표시되는데 SimpleItinerary에서와 비슷한 필드를 갖지만 더 많습니다 자세히 살펴보죠 String 유형의 title도 있습니다 description이 있고 rationale이 있습니다 days를 자세히 살펴보면 더 이상 String 배열이 아님을 알 수 있습니다 실제로 DayPlan의 배열이며 이는 다시 자체 구조체입니다 자체 title, 자체 subtitle 자체 destination과 activities가 있으며 activities는 activity라는 또 다른 구조체의 배열로 type, title, description을 갖습니다 여기서 유형은 enum이며 또한 generable입니다 enum은 모델이 사전 정의된 특정 케이스를 생성하도록 하는 좋은 방법입니다 예를 들어 여기에서 type은 sightseeing, foodAndDining shopping, hotelAndLodging만 가능합니다 맨 위까지 스크롤하면 모델이 생성할 수 있는 내용을 제한하는 또 다른 방법이 있습니다 enum 또는 destinationName을 사용할 수 있습니다 anyOf를 작성하는 가이드가 있으며 ModelData.landmark를 제공합니다 이것은 앱을 열면 표시되는 랜드마크 중 하나인 목적지 이름을 생성해야 한다는 것을 모델에 알려 줍니다 여기에는 세렝게티 그랜드 캐니언 사하라 사막 등이 포함됩니다 따라서 출력은 이들 중 하나여야 합니다 Itinerary 구조체의 형태는 이와 같습니다 또한 이것이 우리가 앱에서 실제로 사용하는 것입니다 Swift Playground로 돌아가겠습니다 기억하시겠지만 목적지 이름은 목록에 있는 이름 중 하나여야 한다고 했습니다 Paris는 목록에 포함되지 않았습니다 따라서 실제로 목록에 있는 목적지로 변경하려고 합니다 그랜드 캐니언은 어떠세요?

    캔버스에서 이 코드 변경을 감지합니다 출력을 살펴보죠

    response가 표시됩니다 content가 포함되어 있으며 다시 한번 자세히 살펴보면 SimpleItinerary가 아닌 struct Itinerary입니다 업데이트했기 때문이죠 이걸 열어 보겠습니다 title, destinationName description rationale, days가 있으며 days는 DayPlan 구조체의 배열입니다 열어 보면 여러 날짜가 있고 activities는 Activity 구조체의 한 유형이며 등등입니다

    여기서 주목해야 할 중요한 점은 @Generable을 적용하면 완전히 구성 가능하다는 것입니다 프레임워크는 구조적 정확성을 보장하면서 위에서 아래로 이 복잡한 객체 전체를 빌드하는 방법을 이해합니다 이제 이것을 앱에 통합해 보겠습니다 코딩 실습 가이드를 살펴보죠 이제 2장의 앱 섹션입니다 이 섹션에서는 일정 생성기를 업데이트하여 방금 플레이그라운드에서 테스트한 itinerary generable 구조체를 사용하겠습니다

    자유롭게 이 코드를 다시 복사하세요 저는 여러분과 함께 이 코드 변경을 수행하겠습니다 ViewModels 폴더 아래의

    ItineraryGenerator로 가서

    찾기 탐색기를 열고 2장으로 설정하면 이 장에서 수행할 모든 코드 변경 사항을 볼 수 있습니다

    첫 번째로 해야 할 코드 변경은 여기 맨 위에 있는 것입니다 여기서 itineraryContent를 더 이상 String이 아닌 Itinerary 유형으로 업데이트해야 합니다 먼저 이 변수의 이름을 itinerary로 변경하고 String을 Itinerary로 업데이트하겠습니다

    이 코드를 변경했기 때문에 이 주석을 삭제할 수 있습니다

    다음으로 해야 할 코드 변경은 generateItinerary 함수까지 아래로 스크롤하면 Xcode가 itineraryContent가 더 이상 존재하지 않는다고 신속히 알려 주는 것을 볼 수 있습니다 따라서 이것을 itinerary로 업데이트할 수 있습니다 방금 추가했으니까요 또한 현재 session.respond에서 나오는 콘텐츠가 문자열이기 때문에 문제를 알려 주고 있습니다

    지난번에 플레이그라운드에서 했던 것과 비슷하게 generating 인수를 추가하고 Itinerary.self를 제공합니다

    이제 모델이 itinerary 유형의 값을 출력할 수 있습니다 이 코드를 변경했으니 이 주석을 삭제하겠습니다

    마지막으로 변경해야 할 사항은 지침에서 제공하는 추가적인 구조 안내를 제거하는 것입니다 날마다 활동, 호텔 식당이 필요하며 제목, 짧은 설명, 날짜별 계획을 항상 포함하라고 되어 있습니다 하지만 이 모든 정보는 이미 itinerary generable 구조체에 포함되어 있습니다 지침에서 이를 다시 제공할 필요가 없습니다 generable 사용의 또 다른 이점은 프롬프트를 훨씬 더 간단하게 작성할 수 있어 성능 향상에도 도움이 될 수 있다는 것입니다 따라서 이 주석을 삭제하겠습니다

    이것으로 이 섹션의 모든 코드 변경을 마칩니다 generable 구조를 생성할 수 있도록 일정 생성기 뷰 모델을 업데이트했습니다 이제 섹션 2.4로 가서 구조 데이터를 표시하도록 뷰를 업데이트하겠습니다 이 섹션에서는 LandmarkTripView를 업데이트해 이전 섹션에서 본 원시 텍스트 대신에 ItineraryView를 생성합니다 아주 간단한 코드 변경입니다 LandmarkTripView로 이동합니다

    Views 폴더의 두 번째 항목입니다

    변경해야 할 코드는 바로 여기에 있습니다

    이전에 기억나시겠지만 모델 출력이 생성될 때 이 뷰를 로드했습니다 하지만 더 이상 문자열을 생성하지 않죠 따라서 더 이상 Text 뷰를 사용할 수 없습니다 먼저 이것을 업데이트한 다음 텍스트 대신에 다른 뷰로 이를 업데이트해야 합니다 그러면 일정에서 필드를 실제로 추출해 풍부한 UI에 채울 수 있습니다 이것을 업데이트된 뷰로 대체하고 어떤 형태인지 설명하겠습니다

    저는 이렇게 작업했습니다 가이드에서 복사하여 붙여넣을 수도 있습니다 자세히 살펴보죠 이렇게 썼죠, itinerary = itineraryGenerator?.itinerary 그리고 Text 뷰 대신에 ItineraryView가 있는데 여기에는 landmark와 생성된 일정이 포함됩니다 이 ItineraryView는 Views 폴더에 있지만 우리는 아직 살펴보지 않았으니 자세히 살펴보겠습니다 이것은 파일 번호 3입니다 물론 이를 command-클릭하여 열 수도 있습니다 이 장에서는 이 파일의 코드를 변경하지 않겠지만 여기에 주석이 있는 만큼 이후 장에서 틀림없이 변경할 가능성이 높습니다 이 뷰는 모델이 생성한 일정을 가져와 필드를 추출하고 초기 데모에서 본 풍부한 UI를 생성합니다 여기 body를 자세히 살펴보죠 일정 제목과 설명을 추출하고 채워 넣은 다음 아래로 스크롤하면 일일 활동을 추출할 때 이를 표시할 수 있는 DayView라는 전용 뷰가 있습니다 ForEach를 사용해 이를 반복하고 모든 속성을 추출해 배치합니다 문자열을 파싱하고 업데이트하는 것보다 훨씬 더 간단하죠

    슬라이드로 넘어가 보죠 가이드 생성의 핵심 이점은 구조적 정확성을 근본적으로 보장한다는 것입니다 제약 조건 디코딩이라는 기법을 사용해 이를 수행합니다 이 기법은 모델이 생성해야 하는 내용을 제어할 수 있습니다 문자열, 숫자, 배열 여러분이 정의하는 맞춤형 데이터 구조 등입니다

    또한 프롬프트가 훨씬 더 간단해질 수 있으며 특정 출력 형식을 위해 모델을 프롬프팅하는 대신에 원하는 동작에 더 초점을 맞출 수 있습니다 모델 정확성을 향상하는 경향도 있으며 추론 속도를 높이는 최적화가 가능합니다 요약하면, 이 장에서는 모델에서 구조화된 데이터를 얻는 방법을 살펴봤습니다 generable 매크로를 사용해 고유한 Swift 유형을 정의하고 구조를 중첩해 복잡한 데이터 구조를 만드는 방법을 확인했죠

    그런 다음 앱을 업데이트하여 구조화된 데이터를 풍부한 사용자 인터페이스로 생성하고 렌더링합니다

    이 모델을 빌드해 모든 변경 사항을 살펴보죠

    앱이 표시됩니다 사하라 사막을 클릭해 일정을 생성합니다 이전과 마찬가지로 프롬프트와 지침을 가져와 모델에 전송하며, 이제는 텍스트를 한가득 생성하는 대신에 일정 유형을 생성합니다 모든 필드를 추출한 다음 새로운 뷰인 ItineraryView를 사용해 앱에 채웁니다

    이것으로 이 장을 마칩니다

    이제 구조화된 데이터를 모델 출력으로 얻고 있습니다 이제는 방향을 전환해 추가적인 프롬프팅 기법으로 출력의 품질과 일관성 향상에 초점을 맞출 수 있습니다 좋은 프롬프트는 모델에 무엇을 해야 할지 알려 주지만 때로는 그냥 보여 주는 것이 더 효과적입니다 고품질 예제를 generable 유형의 인스턴스로 프롬프트에 직접 포함할 수 있습니다

    이 방법은 모델에 내가 찾고 있는 응답 유형에 대한 더 나은 아이디어를 제공하기 때문에 좋습니다 이 장에서는 생성되는 콘텐츠의 품질을 향상하는 데 초점을 맞추겠습니다 다시 한번 플레이그라운드에서 Prompt Builder API를 사용해 더 동적인 프롬프트를 생성하는 것으로 시작하겠습니다 그런 다음 프롬프트에서 고품질 예를 제공하여 모델의 정확성을 향상하는 원샷 프롬프팅을 살펴보겠습니다 마지막으로, 학습한 내용을 앱 일정 생성기에 통합하겠습니다

    코딩 실습 가이드를 살펴보죠

    이제 3장 프롬프팅 기법입니다 우리의 목표는 모델 출력의 품질과 안정성을 향상하는 것입니다 먼저, Prompt Builder API를 사용해 동적 프롬프트를 도입하는 방법을 살펴보겠습니다

    플레이그라운드로 가서 살펴보죠 다시 한번 말씀드리지만 자유롭게 이 코드 블록을 Playground.swift 파일에 복사하세요

    Xcode에서 Playground.swift 파일로 이동합니다

    좋습니다 여기서 핵심적인 코드 변경은 Prompt Builder API를 사용해 프롬프트를 도입하는 것입니다 기억하시겠지만, 이전에 session.respond에서 두 개의 인수를 제공하여 Generate a 3-day itinerary to Grand Canyon을 문자열 형식으로 작성했습니다 그 대신에, 프롬프트를 문자열로 정의하는 것이 아니라 Prompt Builder API를 사용하고 값을 클로저에 전달할 수 있습니다 핵심 이점은 Swift 조건문 등을 포함할 수 있다는 것입니다 여기 맨 위에 부울 변수 kidFriendly가 있는데 현재 true로 설정되어 있습니다 Prompt Builder API 내에서 이 부울 값을 사용하여 프롬프트를 조건부로 업데이트하죠 kidFriendly 부울 값이 true이면 일정이 어린이 친화적이어야 한다는 추가 정보를 프롬프트에 삽입합니다 session.respond 호출 업데이트로 새로운 prompt를 포함하고

    캔버스를 새로 고침할 수 있습니다

    출력을 살펴보겠습니다

    response 변수 content가 있습니다 여기서 rationale을 열고 살펴보죠 This itinerary provides a safe engaging, and educational experience for children ensuring they enjoy the natural beauty of Grand Canyon while being supported by age-appropriate activities and accommodations입니다 보시다시피 모델이 우리의 요청을 이행하는 것을 확인할 수 있으며 이 내용이 조건문으로 적용되었고 이 경우 이점은 이러한 프롬프트 속도를 동적으로 구현할 수 있다는 것이죠 이는 사용자가 앱에서 선택하는 내용일 수도 있고 개발자가 사용자의 기호에서 학습하여 프롬프트를 업데이트하는 내용일 수도 있습니다

    멋지네요 코딩 실습 가이드의 섹션 3.2로 돌아가 보죠 이제 우리의 목표는 원샷 프롬프팅이라는 고급 프롬프팅 기법을 사용해 고품질 응답은 어떤 것인지를 모델에 보여 주는 것입니다 코딩 실습으로 넘어가 보죠

    Prompt Builder API의 클로저 내부에서 코드를 한 줄 더 추가하려고 합니다 Here is an example of the desired format but don’t copy its content라고 작성합니다 예제 하나를 도입합니다 자세히 살펴보죠 이렇게 되어 있습니다 Itinerary.exampleTripToJapan 이건 무엇일까요? 이를 command-클릭하거나 Models 폴더로 가서 Itinerary를 클릭하고 아래로 스크롤하면 exampleTripToJapan이 정의되어 있는 것을 볼 수 있습니다 가장 먼저 눈에 띄는 점은 이것이 예제를 포함하는 큰 문자열이 아니라는 것입니다 실제로 모든 속성이 채워진 itinerary generable 인스턴스입니다 title, destinationName description, rationale days가 있고 모든 속성이 수동으로 채워져 있습니다 플레이그라운드로 돌아가면 여기에 출력이 있고 이 출력에는 응답의 톤과 품질을 안내하기 위해 원샷 예제로 제공한 추가 정보가 포함됩니다

    가장 중요한 부분은 itinerary.exampleTripToJapan을 프롬프트에 직접 임베드한다는 것입니다 이는 우리의 황금 예제입니다 또한 콘텐츠를 복사하지 말라고 명시적으로 모델에 말합니다 데이터 반복이 아니라, 스타일과 구조를 학습하려는 것입니다 이제 가이드로 돌아가 보죠

    3장의 앱 섹션입니다 이제 이 원샷 프롬프팅 접근 방식을 앱에 통합하겠습니다

    우리가 해야 할 코드 변경은 ViewModels 폴더의 ItineraryGenerator에서 프롬프트를 업데이트하고 예제를 포함하는 것입니다 이 코드를 변경해 보겠습니다 Xcode로 돌아왔습니다 ViewModels와 ItineraryGenerator를 클릭합니다 찾기 탐색기를 열고 섹션 3을 클릭합니다 바로 여기서 우리가 변경해야 할 코드를 볼 수 있습니다

    generateItinerary 함수 내에서 프롬프트를 확실히 정의하고 이 프롬프트를 대체합니다

    그리고 이전 프롬프트를 삭제합니다

    다시 말씀드리지만 플레이그라운드에서 사용한 것처럼 let prompt로 Prompt Builder API를 사용하고 이 클로저를 전달합니다 여기에는 이전에 사용했던 동일한 문자열과 Itinerary.exampleTripToJapan을 도입하는 추가 정보도 포함되며 이 정보는 Itinerary 유형입니다 여기에는 모든 안내뿐만 아니라 이제 이 프롬프트의 일부인 스키마도 포함됩니다

    이렇게 변경했기 때문에 이 주석을 삭제할 수 있습니다 3장에서 모든 변경을 완료했으니 앱을 빌드하고 실행할 준비가 되었습니다 앱 빌드를 살펴보죠

    여기서 세렝게티를 선택하고 일정 생성을 클릭합니다 모델이 프롬프트 지침 및 추가 예제를 받아서 모델에 전달하고 최종 출력을 생성하도록 할 수 있습니다 됐습니다

    앱이 잘 작동하고 있네요 이제 닫고 슬라이드로 넘어가 보죠 이 장에서는 프롬프팅 기법에 초점을 맞추었습니다 Prompt Builder를 사용해 프롬프트를 동적으로 구성하는 방법을 알아봤고 원샷 프롬프팅을 사용해 모델 출력의 품질과 일관성을 향상하는 방법을 살펴봤습니다 그런 다음 앱을 업데이트해 자세한 예제를 프롬프트에 포함하는 방법으로 이를 적용했습니다 @Generable은 구조를 적용하고 원샷 예제는 관계와 구조 내 스타일에 대해 모델에 알려 줍니다 또한 모델은 원하는 어조에 대해 제공된 예제를 사용하여 생성된 텍스트가 앱에 설정하려는 어조와 일치하도록 합니다

    출력의 차이가 항상 극적이지는 않을 수 있지만 이는 생성된 콘텐츠의 품질을 크게 향상하는 중요한 방법입니다 이것으로 프롬프팅 기법에 관한 섹션을 마칩니다

    잠시 쉬어 가기에 적합한 시점이네요 10분간 짧은 휴식을 취하겠습니다 이 시간을 이용해 코드에 대해 놓친 부분을 확인하고 커피도 마시고 스트레칭도 해 보시기 바랍니다 휴식을 마친 후 정말 흥미로운 주제들을 살펴보겠습니다 스트리밍을 통해 UI를 실시간으로 업데이트하고 도구 호출로 모델의 기능을 확장하고 성능 최적화로 마무리하겠습니다 10분 후에 다시 시작하겠습니다 곧 뵙죠

    모두 다시 한번 환영합니다 좋은 휴식 시간 가지셨기를 바랍니다 계속 진행해 보겠습니다 고품질 프롬프트를 도입했으니 이제 실시간으로 응답을 스트리밍하여 사용자 경험을 향상해 보죠 이 장에서는 모델의 응답을 스트리밍하여 사용자 경험을 향상하기 위해 스트리밍 API를 사용하도록 ItineraryGenerator를 리팩터링하는 데 초점을 맞춥니다 모델이 응답을 생성할 때 PartiallyGenerated 콘텐츠를 처리하는 방법을 살펴봅니다 그런 다음 일정이 생성될 때 일정을 렌더링하도록 뷰를 업데이트하여 반응성이 매우 뛰어난 느낌을 제공합니다 그럼 가이드로 이동해 보죠 이제 4장 응답 스트리밍하기입니다 이 장에서 우리의 목표는 응답을 스트리밍하고 일정이 생성될 때 일정을 보여 주는 방법으로 사용자 경험을 크게 향상하는 것입니다 ItineraryGenerator 파일을 업데이트하는 것으로 시작하죠 이 섹션에는 플레이그라운드 구성요소가 포함되지 않습니다 스트리밍 응답을 앱에서 직접 쉽게 살펴볼 수 있기 때문입니다 Xcode로 가서 ItineraryGenerator를 열어 보죠

    찾기 탐색기를 다시 사용하여 4장으로 업데이트하고 변경해야 할 모든 코드를 살펴보겠습니다 itinerary로 시작하죠 우리가 해야 할 첫 번째 변경은 itinerary 변수를 Itinerary.PartiallyGenerated 유형으로 업데이트하는 것이죠

    PartiallyGenerated란 무엇일까요? 이것을 모든 속성이 선택 사항인 구조체의 미러 버전이라고 생각해 보세요 @Generable이 이를 자동으로 정의합니다 시간이 지남에 따라 도착하는 데이터를 나타내는 완벽한 방법입니다 이것이 첫 번째 코드 변경입니다 여기 주석을 제거하겠습니다

    필요한 다음 코드 변경 사항은 여기에 있습니다 기억하시겠지만 generateItinerary 함수에는 session.respond에 대한 이 비동기 호출이 포함되었습니다 우리는 프롬프트를 전달한 다음 generable을 전달했고 출력을 받았습니다 그 대신에 원하는 것은 모델이 응답을 생성하고 우리에게 응답을 스트리밍하는 것입니다 따라서 우리가 할 일은 이 코드를 session.streamResponse라는 새로운 API로 대체하는 것입니다 한번 살펴보죠

    session.response를 session.streamResponse로 대체하고 나머지 인수는 동일하게 유지했습니다 여전히 프롬프트를 전달하고 일정과 함께 generating 인수를 제공합니다 하지만 여기에는 await가 없습니다 그 대신에 우리가 얻는 것은 stream이라는 비동기 시퀀스입니다 따라서 우리는 이를 반복하여 모든 출력을 itinerary에 할당할 수 있습니다 여기에는 이러한 모든 옵션이 포함됩니다 따라서 try await partialResponse in stream이라고 작성하고 partialResponse.content를 사용해 이를 추출할 수 있습니다 여기서 해당 시점에 생성된 모든 내용의 스냅샷을 항상 얻을 수 있습니다 이 코드를 변경했기 때문에 이 주석도 제거하겠습니다

    이제 itineraryGenerator에 필요한 모든 코드 변경 사항이 포함되었습니다 코딩 실습 가이드의 섹션 4.2를 살펴보겠습니다 이제 뷰를 업데이트할 준비가 되었습니다 PartiallyGenerated 필드는 선택 사항이므로 if let 문을 사용해 이러한 옵션을 안전하게 래핑 해제할 수 있습니다 이 섹션에서는 바로 이 내용을 다루겠습니다 ItineraryView를 업데이트합니다 이 뷰는 이전 장에서 미리 보기만 했지만 이제 실제로 이에 대한 코드를 변경하겠습니다 Xcode로 가서

    Views 폴더를 클릭하고

    ItineraryView를 클릭합니다

    맨 위에 itinerary가 있으므로 역시 뷰 모델에서 정의한 PartiallyGenerated 유형으로 이것도 업데이트해야 합니다 여기에 있는 모든 generable 항목에 대해 이 코드를 변경해야 합니다 itinerary뿐 아니라 모든 중첩된 generable 항목도 포함됩니다 아래로 스크롤하면 기억하시겠지만 DayView가 있는데 여기에는 DayPlan이 포함되며 이것도 PartiallyGenerated여야 합니다 이 코드를 변경할 때마다 이러한 주석을 제거하며 더 아래쪽에는 Activity 배열이 있다는 것도 기억하실 겁니다 이에 대해서도 동일한 작업을 합니다

    generable 항목에 대한 주요 코드 변경 사항이었습니다 다시 맨 위로 돌아가면 Xcode가 몇 가지 다른 문제를 알려 주고 있습니다 필요한 또 다른 코드 변경은 기억하시겠지만, 선택 사항이므로 래핑 해제해야 합니다 그렇게 해 보죠

    저는 이렇게 했습니다 if let title = itinerary.title if let은 이러한 선택 사항을 처리하는 좋은 방법입니다 여기에 title이 있기 때문에 itinerary에서 추출할 필요가 없죠 따라서 이를 제거합니다 title을 이렇게 처리합니다 이제 description에 대해 같은 단계를 반복해야 합니다

    if let을 사용하고 description을 포함하게 Text 뷰를 업데이트하죠

    rationale에 대해서도 이를 다시 반복해야 합니다

    다른 필드 days에 대해서도 이를 다시 수행해야 합니다

    핵심을 파악했습니다 우리가 속성에 접근하는 모든 itinerary 필드에 대해 이 작업을 계속 수행해서 안전하게 래핑 해제해야 합니다 이제 저는 지금까지 제가 여러분께 요청해 온 작업을 하려고 합니다 바로 코딩 실습 가이드로 돌아가서 완전히 업데이트된 파일을 복사해 여기에 붙여넣는 것입니다 모든 속성에 대해 이 작업을 해야 하기 때문입니다 여기로 스크롤하면 3단계에 Repeat this for all properties라고 되어 있습니다 title, description rationale을 변경했지만 모든 DayPlan과 Activity 뷰에 대해서도 이렇게 해야 합니다 그 대신에, 제가 지금 바로 이 코딩 실습에서 하려는 작업은 Show the updated Views를 클릭하는 것입니다 여기에는 모든 코드 변경 사항이 포함됩니다 오른쪽 상단에 있는 복사 버튼을 클릭하고 Xcode ItineraryView.swift 파일로 돌아가서 모든 코드를 업데이트된 코드로 대체하는 것입니다 또한 찾기 탐색기에서 볼 수 있듯이 더 이상 주석이 없으므로 모든 코드 변경이 완료된 것입니다 필요한 몇 가지 다른 코드 변경 사항을 보여 드렸는데 모든 속성에 대해 동일한 작업을 해야 합니다 이것으로 4장의 모든 코드 변경을 마칩니다 간략히 요약하면 PartiallyGenerated를 사용하는 뷰 모델에 필요한 변경 사항에 대해 이야기했고 이러한 옵션을 래핑 해제하도록 뷰를 업데이트했습니다 이제 앱을 실행할 준비가 되었습니다 실행을 클릭하면 앱이 빌드되고 실행됩니다 바로 여기에 앱이 있습니다 여기서 사하라 사막을 클릭하고 일정 생성을 클릭하겠습니다

    이전에는 비동기 호출이었던 것과 달리 이제는 응답이 생성될 때 응답을 스트리밍할 수 있습니다 이 경우 뛰어난 사용자 경험을 선사합니다 모든 일정이 로드되기 전에도 앱을 사용하는 누군가가 이 콘텐츠를 소비하기 시작할 수 있기 때문이죠

    멋지네요, 이 장에서는 사용자 경험을 크게 향상했습니다 스트리밍 API를 사용하도록 앱을 리팩터링했고 뷰 모델에서 PartiallyGenerated 콘텐츠로 작업하는 방법을 알아봤습니다 마지막으로, 일정이 실시간으로 생성될 때 일정을 표시하도록 뷰를 업데이트했습니다

    이것으로 응답 스트리밍하기에 관한 4장을 마칩니다 이제 앱이 멋져 보이지만 도구 호출로 모델에 새로운 기능을 부여해 더 스마트하게 만들어 보겠습니다

    먼저 도구 호출의 개념을 소개하겠습니다 프롬프트에 제공하는 내용 외에도 모델은 학습 데이터에서 고유한 핵심 지식을 가져오지만 모델은 OS에 내장되어 있고 그 지식은 특정 시점에 고정되어 있다는 점을 기억하세요 예를 들어, 지금 쿠퍼티노의 날씨에 대해 묻는 경우 그 정보가 무엇인지 알 수 있는 방법이 없습니다 실시간 또는 동적 데이터가 필요한 케이스를 처리하기 위해 프레임워크는 도구 호출을 지원합니다 원리는 다음과 같습니다 세션 전사문이 있습니다 세션에 도구를 제공한 경우 세션에서 도구 정의가 지침과 함께 모델에 제공됩니다 우리 예제에서 프롬프트는 방문할 목적지를 모델에 알려 줍니다

    이제 모델이 도구 호출로 응답이 향상될 수 있다고 판단하면 하나 이상의 도구 호출이 생성됩니다 이 예에서 모델은 식당과 호텔을 쿼리하는 두 개의 도구 호출을 생성합니다 이 단계에서는 Foundation Models 프레임워크가 이러한 도구에 대해 작성한 코드를 자동으로 호출합니다 그런 다음 프레임워크는 도구 출력을 세션 전사문에 다시 자동으로 삽입합니다

    마지막으로, 모델은 도구 출력과 전사문의 나머지 모든 내용을 최종 응답에 통합합니다

    지금까지 살펴봤듯이 모델은 매우 창의적일 수 있으며 요청할 때마다 약간씩 다른 일정을 제공하는 경우가 많습니다 이 무작위성은 창의성을 발휘하는 데 유용하지만 예측 가능한 동작이 필요한 경우 문제가 될 수 있습니다 도구 호출 등 고급 기능의 경우 특히 테스트 및 디버깅 시 모델이 일관되게 동작하는지 확인해야 합니다 예상대로 도구가 호출되도록 보장하고자 합니다 이를 위해, 생성 옵션 API를 사용해 요청을 또 살짝 변경하여 탐욕적 샘플링을 사용하도록 하겠습니다 탐욕적 샘플링은 모델에 창의성을 발휘하지 말고 항상 가장 명백한 다음 토큰을 선택하도록 지시합니다 이렇게 하면 확정적인 모델 출력이 제공됩니다 우리 앱의 경우 이를 통해 모델이 항상 안정적으로 도구를 호출합니다

    이 장에서는 관심 지점을 찾을 수 있는 도구를 살펴봅니다 그런 다음 이 도구를 언어 모델 세션에 제공하고 도구 사용 방법을 모델에 지시합니다 앱으로 돌아가서, 이 도구를 일정 생성기에 통합해 실제 데이터를 일정에 적용하겠습니다 코딩 실습 가이드를 살펴보죠 이제 5장, 도구 호출입니다

    일정에는 모델에서 생성된 호텔 및 식당 이름이 포함되며 이는 최신이 아닐 수 있습니다 우리의 목표는 Swift 코드를 호출하고 우리가 제공한 호텔 및 식당 이름을 가져오기 위해 사용할 수 있는 도구를 모델에 제공하는 것입니다

    코드를 변경해서 먼저 도구를 빌드하고 나중에 앱에서 이 도구를 사용해 보죠 Xcode로 가서 ViewModels 폴더를 클릭하면 FindPointsOfInterestTool이라는 새 파일이 보일 겁니다

    해당 파일을 클릭합니다 도구 프로토콜을 따르는 FindPointsOfInterestTool이라는 클래스가 있습니다 즉, 단계별로 살펴볼 몇 가지 속성을 정의해야 합니다 코드 변경을 시작해 보죠 어떻게 되는지 설명하겠습니다 필요한 첫 번째 변경 사항은 도구 이름과 설명 추가입니다 여기서 해 보겠습니다

    도구에 findPointsOfInterest라는 이름과 Find points of interest for a landmark라는 설명을 제공합니다 이는 모델이 도구를 언제 호출해야 하는지 이해하는 데 중요합니다 즉, 이름과 설명을 사용해 이 도구를 언제 호출해야 하는지를 결정합니다 다음으로 변경해야 할 부분은 여기에 있습니다 여기서 찾기 탐색기를 열어서 변경해야 할 모든 코드를 확인할 수 있습니다

    우리가 해야 할 다음 코드 변경은 도구가 관심 지점을 검색할 수 있는 카테고리를 정의하는 것입니다

    이를 위해 이 Generable enum을 도입합니다

    여기서 카테고리는 호텔과 식당을 포함하는 열거형입니다 물론 여기엔 박물관이나 캠핑장 등 다른 케이스도 포함될 수 있습니다 인수를 업데이트하는 다음 코드 체인에서 이를 사용할 것입니다

    여기에 Arguments 구조체가 있습니다 이를 업데이트하고 그 기능을 설명하겠습니다

    Arguments 구조체에는 속성이 하나 있는데 let pointOfInterest로 Category 유형입니다 이것은 우리가 조금 전에 정의한 것입니다 이 pointOfInterest는 호텔 또는 식당일 수 있으며 가이드도 제공합니다 가이드에는 다음과 같은 description이 있습니다 This is the type of destination to look up for 이 인수는 도구와 모델 사이의 계약입니다 모델이 도구를 호출하려는 경우 이 인수를 도구에 전달하여 도구의 응답을 원하는 것이 호텔이든 식당이든 도구로부터 응답을 얻으려는 카테고리에 도구가 접근할 수 있도록 합니다

    우리는 이 인수를 업데이트했습니다 이제 바로 여기서 call 함수를 업데이트하겠습니다

    이 함수는 도구의 핵심입니다 인수를 받고, 작업을 수행하고 출력을 반환하며 이는 세션의 전사문에 다시 추가돼 모델이 보고 사용할 수 있도록 합니다 이렇게 변경해 보겠습니다

    좋습니다 어떻게 진행되고 있는지 단계별로 살펴보겠습니다

    첫째, let results = await getSuggestions라고 작성합니다 우리는 이를 정의하지 않았습니다 곧 이것을 정의하겠습니다 기본적으로, 이를 특정 관심 지점을 얻기 위해 call 메서드가 호출할 수 있는 함수로 생각하세요 results는 출력의 일부이며 return 문에서 볼 수 있듯이 이 결과를 문자열 출력으로 다시 삽입하여 모델에 다시 제공할 수 있습니다 그런 다음 모델은 해당 정보를 프롬프트 및 지침과 함께 사용해 최종 응답을 생성합니다 필요한 마지막 코드 변경은 물론 이 함수를 정의하는 것입니다 여기에 getSuggestions라는 플레이스홀더 함수가 있습니다 이것을 업데이트해 보겠습니다

    좋습니다 getSuggestions 내에는 카테고리를 입력받는 switch 블록이 있습니다 식당인 경우 이 블록은 Restaurant 1, Restaurant 2 또는 Restaurant 3을 반환할 수 있죠 호텔이면 Hotel 1, Hotel 2 또는 Hotel 3을 반환할 수 있습니다 이 데모에서는 하드 코딩된 데이터를 사용합니다 실제 앱에서는 MapKit 등의 API나 서버 측 API를 호출하여 실제 실시간 데이터를 가져옵니다

    도구에 대한 모든 코드 변경을 완료했습니다 즉, 도구를 완전히 정의했다는 의미입니다 코딩 실습 가이드로 돌아가 섹션 5.2로 넘어가겠습니다

    이제 이 도구를 테스트해 보죠 플레이그라운드로 가서 이 도구를 모델에 제공하고 결과를 살펴보겠습니다 다시 한번 이전과 마찬가지로 이것을 복사해 붙여넣으세요 각 코드 줄을 단계별로 살펴보고 정확히 어떻게 진행되고 있는지 설명하겠습니다 Xcode로 다시 돌아가서 Playground.swift 파일로 전환하겠습니다 이 섹션에서는 이전 코드를 지우고 처음부터 새로 시작하겠습니다

    여기에 빈 플레이그라운드가 있습니다

    먼저 지침을 추가하겠습니다

    플레이그라운드의 한 가지 멋진 기능은 Xcode 프로젝트의 모든 데이터 구조에 접근할 수 있다는 것이죠 앱을 빌드할 필요 없이요 제가 여기서 하는 작업은 Models 폴더, ModelData.swift 아래에 정의된 모델 데이터에 접근할 수 있는 landmark 변수를 생성하는 것입니다 ModelData.landmark 코드는 표시되는 랜드마크 중 하나에 접근할 것이며 구체적으로 첫 번째 랜드마크에 접근할 것이라는 의미입니다 기억하시겠지만 그것은 사하라 사막입니다 앱을 실행하면 표시되는 것과 동일한 랜드마크 목록에 접근할 수 있으며 이를 가져와서 바로 여기 ViewModels 폴더에서 FindPointsOfInterestTool을 정의했습니다 이 도구의 인스턴스를 생성하고 랜드마크를 전달할 수 있습니다 해당 정보를 사용하기 때문입니다 마지막으로 이전과 마찬가지로 지침이 있죠 주의 깊게 살펴보면 두 가지 사소한 코드 변경 사항이 있습니다 첫째, 더 이상 문자열이 아니라 지침 빌더입니다 프롬프트 빌더와 비슷하며 그 안에서 클로저를 전달하고 지침을 제공합니다 눈에 띄는 두 번째 주요 변경 사항은 도구 호출에 매우 중요한 점인데 이 랜드마크에 있는 호텔과 식당을 찾으려면 항상 findPointsOfInterest 도구를 사용해야 한다는 것입니다 이제 이 지침은 관심 지점 응답을 얻으려면 이 도구를 호출해야 한다는 것을 모델에 알려 줍니다 이제 LanguageModelSession을 생성하겠습니다 이전 코드 변경과 비슷하게 LanguageModelSession과 instructions를 작성했지만 tools라는 새로운 인수를 도입했습니다 여기서 tools는 도구 배열일 수 있습니다 pointOfInterestTool이라는 도구 하나만 있습니다 배열이기 때문에 여러 도구를 제공할 수 있으므로 모델이 프롬프트와 지침에 대해 추론하고 어떤 도구를 언제 호출할지 결정하고 응답을 얻을 수 있습니다 따라서 도구를 세션에 포함했습니다 다음으로, 프롬프트를 정의합니다

    여기서는 프롬프트 자체에 대한 변경 사항이 없습니다 마지막으로, 해당 모델을 호출하겠습니다

    여기서도 코드는 변경되지 않습니다 단, 슬라이드에서 간략히 설명한 옵션만 도입합니다 sampling이 greedy로 설정된 이 GenerationOptions를 사용하면 항상 일관되고 반복 가능하며 확정적인 출력을 얻게 됩니다 단, 나머지 프롬프트와 지침이 일관되어야 합니다 여기 캔버스와 출력을 살펴보죠 response가 생성되고 content가 있습니다

    title, description, rationale days가 있습니다 이 날짜 중 하나를 선택해 보죠 day 0, 도착 그리고 활동을 살펴보겠습니다

    activity 0, activity 1 activity 2를 열겠습니다 이제 자세히 보면 activity 1 description 아래에 다음과 같이 되어 있습니다 “Enjoy a traditional Moroccan dinner at Restaurant 1” title에서도 볼 수 있습니다 “Dine at Restaurant 1” 마찬가지로 activity 2의 title은 “Stay at Hotel 1”이고 “Unwind at hotel 1”이네요 이는 도구의 출력으로 모델의 출력에 삽입됩니다 모델은 프롬프트 지침과 랜드마크 이름을 받았고 도구를 호출하며 호텔과 식당 이름을 얻고 이를 다시 전사문에 삽입했으며 이 응답을 생성했습니다 전사문 자체를 살펴보죠

    여기서 제가 하는 작업은 세션 자체에 대한 임시 변수를 생성하고 이를 inspectSession에 캡처하는 것이죠 제가 이렇게 하는 이유는 세션과 전사문을 자세히 살펴보고 도구 호출이 이루어지는 것을 확인하기 위해서입니다 좋습니다 방금 생성한 inspectSession이 있습니다 이제 이러한 속성을 살펴보겠습니다 tools가 보입니다 우리가 제공한 도구 하나가 있습니다 transcript를 보면 이 항목에는 6가지 요소가 있어요 또한 instructions가 있는데 이것은 항상 transcript의 첫 번째 항목입니다 그리고 prompt가 있는데 이는 우리의 초기 요청입니다 그런 다음 toolCalls가 있습니다 모델은 도구를 호출해야 한다고 자율적으로 결정했습니다 그리고 toolOutput이 있습니다 프레임워크는 도구를 실행하고 이 도구 출력을 다시 transcript에 삽입했습니다 마지막으로 response가 있습니다 모델은 원래의 프롬프트와 도구 출력 데이터를 합성하여 최종 응답을 생성했습니다 여기에는 두 개의 도구 호출이 있습니다 식당과 호텔 둘 다에 대해 요청하고 있기 때문입니다 toolCalls 아래에서 이를 확인할 수 있습니다 식당과 호텔에 대한 요청이 있습니다

    멋지네요 코딩 실습 가이드로 돌아가 보죠

    이제 도구의 작동 방식을 알게 되었고, 도구를 정의했고 플레이그라운드에서 도구를 테스트했습니다 이제 ItineraryGenerator.swift 파일을 업데이트하여 도구를 앱에 통합할 준비가 되었습니다 섹션 5.3에서 이 작업을 수행할 것입니다

    ItineraryGenerator.swift의 코드를 변경하겠습니다 이를 복사해 파일에 붙여넣으세요 여기서 볼 수 있듯이 우리가 적용하는 주요 변경 사항은 지침을 업데이트하고 도구 인스턴스를 생성하고 또한 이를 LanguageModelSession에 전달하는 것입니다 Xcode로 가서 ItineraryGenerator.swift를 열어 보겠습니다 또한 찾기 탐색기를 열고 5장으로 설정한 후 코드 변경을 시작하겠습니다

    우리가 해야 할 첫 번째 변경은 물론 지침 업데이트입니다

    이전 지침을 삭제하려고 합니다 새로운 지침이 있기 때문인데 여기에는 우리가 정의한 pointOfInterestTool과 관심 지점을 얻기 위해 모델에 이 도구를 호출하도록 요청하는 추가 텍스트가 포함되어 있기 때문입니다 물론 tools 인수를 사용해 LanguageModelSession도 업데이트해야 합니다

    이는 여러 도구를 수용할 수 있으므로 배열이며 도구에서 이를 전달합니다

    이것이 이니셜라이저에서 변경해야 하는 두 가지 코드입니다 이를 완료했으니 이 주석을 삭제해 변경 사항을 확인할 수 있도록 하겠습니다 마지막 변경 사항은 generateItinerary 메서드에서 진행합니다

    기억하시겠지만 확정적인 출력을 얻으려면 탐욕적 샘플링을 사용할 수 있다고 언급했습니다 기본적으로 무작위 샘플링을 수행합니다 바로 여기 이 session.streamResponse 후 prompt를 전달한 후 generating 인수를 전달한 후 options를 전달할 수 있습니다 누구나 쉽게 읽을 수 있도록 정리해 보겠습니다

    좋습니다 session.streamResponse prompt, generating 인수 마지막으로 GenerationOptions를 포함하는 options가 있고 sampling을 사용하고 greedy로 설정합니다 이것으로 필요한 모든 코드 변경을 마칩니다 이 주석을 삭제하겠습니다

    됐습니다 찾기 탐색기에서 5장의 내용이 보이지 않는다면 모든 코드 변경이 완료되었다는 의미이며 앱을 빌드하고 실행할 준비가 되었습니다

    실행 버튼을 클릭하면 앱이 빌드되고 실행됩니다

    앱이 표시됩니다 표준 사용자 흐름을 살펴보죠 사하라 사막을 클릭합니다 일정 생성 버튼이 보입니다 이 버튼을 클릭합니다 이제 여기에 스트리밍 API가 도구와 함께 포함되며 지침, 프롬프트를 받아 도구 정의와 함께 모델에 전송합니다 여기서 보시는 것처럼 Stay at Hotel 1과 Dine at Restaurant 1이 표시됩니다 이는 도구의 응답으로 세션 전사문에 다시 삽입되었습니다 모델은 지침, 프롬프트 도구 호출의 모든 정보를 사용했습니다 도구 응답은 이를 모두 패키징하고 합성했으며 generable, itinerary generable 형식으로 출력을 생성할 수 있습니다

    훌륭하네요 슬라이드로 돌아가서 요약해 보겠습니다 이 장에서는 모델에 도구 호출 기능을 부여했습니다 맞춤형 도구와 그 인수 및 call 함수를 살펴봤습니다 LanguageModelSession에 도구를 제공하는 방법과 중요하게는 모델에 도구 사용 시점과 방법을 지시하는 방법을 알아봤습니다 마지막으로, 도구를 앱에 통합하여 관심 지점을 가져와 생성된 일정에 포함했습니다 이것으로 도구 호출에 관한 5장을 마칩니다

    이 코딩 실습을 마무리하기 전에 성능을 최적화하고 생성형 기능의 반응성을 높여 주는 몇 가지 핵심 기법을 살펴보겠습니다

    코딩 실습 가이드의 6장 성능 및 최적화를 살펴보겠습니다 이제 앱 기능이 완전히 갖춰졌지만 앱 성능을 높이려면 먼저 어디에 병목 현상이 있는지 파악해야 합니다 측정할 수 없는 것은 최적화할 수 없습니다 이를 위해 Instruments라는 강력한 개발자 도구를 사용합니다

    Xcode로 넘어가 보겠습니다

    이제 조금 다른 것을 해 보죠 실행 버튼을 길게 누르면 몇 가지 옵션이 표시됩니다 실행, 테스트, 프로파일링 분석을 볼 수 있습니다 프로파일링을 클릭하겠습니다 이 옵션은 앱을 빌드한 다음 Xcode Instruments를 실행합니다

    빌드가 끝날 때까지 기다려 보죠 이제 됐네요 이것이 Xcode Instruments입니다 빈 템플릿을 선택한 다음

    Instruments를 열어 둔 후 더하기 기호를 클릭하고 파운데이션 모델을 검색합니다

    이제 앱을 프로파일링할 준비가 되었습니다

    기록을 클릭하면 앱이 실행됩니다 평소처럼 앱을 사용하겠습니다 사용자 입장에서 사하라 사막이 흥미로워 보이네요 제목 설명을 읽어 보니 좋은 것 같네요 일정 생성을 클릭하면 멋진 일정이 표시됩니다 결과가 제게 스트리밍되고 있습니다 전체 내용을 읽고, 다양한 활동을 모두 살펴볼 수 있습니다

    기록을 중지합니다

    이제 Instruments에 기록된 내용을 자세히 살펴보겠습니다

    몇 개의 트랙이 있습니다 각 트랙의 기록 내용을 설명하면서 우리가 해결할 수 있는 잠재적 병목 현상을 식별하겠습니다 첫 번째 트랙은 응답입니다 파란색 막대는 세션 전체를 나타냅니다 사용자가 일정 생성을 클릭한 이후 우리는 세션을 생성하고 모델은 지침과 프롬프트를 받아 출력을 생성합니다 이 모든 것은 파란색 막대로 표현됩니다

    두 번째 행은 애셋 로딩입니다 자세히 살펴보면 세션이 시작된 후 약간의 지연이 발생한 다음 모델이 로드되고 모델 애셋은 세션의 시작부터 모델 로딩이 끝날 때까지 아무런 응답도 생성하지 않으며 이 시간은 약 700밀리초 정도로 보입니다 거의 1초에 해당하죠 세 번째 트랙을 보면 첫 번째 토큰이 생성되는 것을 확인할 수 있습니다 즉, 모든 모델이 로드될 때까지 기다린 다음 토큰 생성 프로세스를 시작합니다 첫 번째 토큰부터 시작해 계속해서 모든 응답을 생성합니다 따라서 성능 향상을 위한 기회가 있습니다 이러한 애셋을 미리 로드할 수 있다면 세션이 시작되는 즉시 생성 프로세스를 시작할 수 있겠죠 이는 우리가 해결해 볼 수 있는 하나의 병목 현상입니다 두 번째 병목 현상은 여기 하단에서 추론 섹션을 선택하려고 합니다 자세히 살펴보면 여기에 최대 토큰 수가 있습니다 현재 1044에 달한다는 것을 알 수 있습니다 이 토큰 수에는 세션에 추가한 모든 것이 포함되죠 여기에는 지침 프롬프트, 도구가 포함됩니다 일정과 관련된 generable 항목이 모두 포함됩니다 여기에는 이 모든 것이 포함되며 토큰 수는 모델 성능에 영향을 미치기 때문에 이를 줄일 수 있는지 알아볼 수 있습니다 이것이 해결을 시도해 볼 수 있는 두 번째 병목 현상입니다 좋습니다 기억하시겠지만 session.respond를 호출하면 OS가 모델을 로드합니다 아직 메모리에 없다면요 사전 준비를 하면 요청하기도 전에 모델을 로드하여 세션을 빠르게 시작할 수 있습니다 앱에서 누군가가 랜드마크를 탭하면 곧 요청을 할 가능성이 꽤 높습니다 이들이 일정 생성 버튼을 누르기 전에 미리 준비하여 모델을 사전에 로드할 수 있습니다 그들이 설명을 다 읽을 때쯤이면 모델이 준비됩니다

    요청 지연 시간을 줄일 수 있는 또 다른 최적화도 살펴보죠 모델에 제공된 generable 구조체는 구조화된 출력 생성에 도움이 될 수 있다는 점을 기억해 보세요 하지만 이 경우 토큰 수가 증가해 초기 처리 시간이 길어질 수 있습니다 또한 3장에서 exampleTripToJapan이라는 예제 일정을 전달했던 것을 기억해 보세요 지침에는 generable 스키마의 전체 예제가 포함되므로 종종 초기에 스키마 정의 자체를 제외할 수 있습니다 이를 통해 공간을 절약하고 모델의 속도를 높일 수 있습니다

    Xcode Instruments 덕분에 앱의 병목 현상을 식별했습니다 이제 앱에서 직접 최적화를 구현해 보겠습니다 첫째, 사용자가 랜드마크를 탭하면 pre-warm 메서드를 호출하여 세션을 사전 준비합니다 이렇게 하면 사용자가 일정을 요청하기도 전에 프레임워크가 모델 로딩을 시작합니다 둘째, 원샷 예제는 매우 자세하기 때문에 프롬프트의 전체 스키마 정의가 중복됩니다 include schema와 prompt를 false로 설정하면 제거할 수 있죠 스트림 응답 호출에서 이 변경을 적용하겠습니다 이렇게 하면 입력 토큰 수가 크게 줄어듭니다

    이제 코딩 실습 가이드로 가서 우리가 적용하는 코드 변경 사항을 살펴보죠 이제 6장, 앱 섹션입니다 첫 번째 부분은 모델 사전 준비입니다 코드 변경 사항은 일정 생성기에 반영됩니다 여기에서 사전 준비를 위한 함수를 추가한 다음 뷰에도 추가합니다 그러면 뷰가 로드될 때 pre-warm 메서드를 호출할 수 있습니다 ItineraryGenerator와 LandmarkTripView에서 이렇게 변경해 보죠 Xcode로 넘어가 보겠습니다 이 Instrument를 열어 두겠습니다 이러한 최적화의 효과를 확인하고 싶기 때문입니다 Xcode로 가서 ItineraryGenerator를 클릭합니다 이것은 이미 열려 있습니다 또한 찾기 탐색기를 사용해 6장을 열겠습니다

    좋습니다

    PREWARM에 대한 첫 번째 변경은 PREWARM 코드를 추가하는 것입니다 PREWARM 모델이라는 플레이스홀더 함수를 정의했습니다 여기서 할 일은 세션에서 pre-warm 메서드를 호출하는 것뿐입니다

    매우 간단하죠

    이제 뷰에서 호출할 수 있는 함수가 있으며 이 함수는 모델을 사전 준비합니다 프롬프트 내용을 미리 알고 있다면 프롬프트 접두사를 사용해 pre-warm 메서드를 업데이트할 수도 있습니다

    session.prewarm 함수 내부에는 prompt prefix라는 선택적 인수가 있는데 여기서 프롬프트를 제공할 수 있어 모델이 사용자가 제공할 수 있는 프롬프트에 대한 지식을 갖추고 이를 사용해 사전 준비할 수 있죠 여기서 우리는 landmark.name에 대한 3일간의 일정을 생성한다는 내용의 클로저와 함께 프롬프트를 전달합니다 이를 통해 성능을 더욱 향상할 수 있습니다 다음으로 변경해야 할 코드는 실제로 LandmarkTripView에 있죠 Views 폴더에 LandmarkTripView가 있습니다 여기서는 모델이 실제로 로드될 때 pre-warm 메서드를 호출하기 위해 작업을 업데이트해야 합니다 여기서 해 보죠

    다시 한번 말씀드리지만 조금 전에 정의한 generator.prewarmModel 함수를 호출하는 것만큼 간단합니다 여기에는 모델 사전 준비를 위한 모든 코드 변경 사항이 포함됩니다 코딩 실습 가이드로 돌아가서 앞서 설명한 두 번째 최적화를 살펴보죠 최대 토큰 수를 줄이는 것입니다 이제 섹션 6.2에서는 프롬프트를 최적화하겠습니다

    여기서 우리가 변경해야 할 코드도 ItineraryGenerator에 있습니다 프롬프트에 include schema라는 추가 인수를 포함하고 false로 설정합니다 이 변경 사항을 적용하고 어떻게 되는지 짧게 다시 설명하죠

    ItineraryGenerator로 돌아갑니다

    prompt, generable options를 전달하는 session.streamResponse가 있습니다 또한 prompt에 include schema라는

    새로운 인수를 포함하고 false로 설정합니다 이것이 모델에 알려 주는 내용은 Instruments에서 exampleTripToJapan을 이미 전달하고 있기 때문에 우리가 전달하는 일정의 스키마를 제외할 수 있다는 것입니다 여기에는 구조와 함께 황금 예제가 포함됩니다 따라서 스키마를 포함하지 않아도 되며 이는 최대 토큰 수를 줄이는 데 도움이 됩니다

    이렇게 변경했으니 이 주석도 삭제하겠습니다 이것으로 6장의 모든 변경을 마칩니다 이제 앱을 다시 한번 프로파일링할 준비가 되었습니다 다시 한번 해 보죠 프로파일링 옵션을 다시 클릭합니다 다시 앱이 빌드되고 잠시 후 프로파일러가 실행됩니다

    Xcode가 빌드되며 프로파일러를 다시 실행했습니다 이제 기록을 시작하면 앱이 다시 실행되고 앱을 사용하는 동일한 프로세스를 다시 거칩니다

    기록을 클릭합니다

    앱을 실행합니다 정확히 동일한 단계를 따릅니다 사하라 사막을 클릭합니다 제목을 읽습니다 제겐 설명이 좋아 보입니다 일정을 생성하고 싶은데 일정이 생성되고 있는 것이 보입니다 좋아 보이네요 일일 계획 식사를 할 식당 머무를 호텔이 있습니다 실행이 완료되도록 하고 프로파일링을 중지하겠습니다

    이전에 했던 것과 똑같이 하면서 출력을 살펴보죠 최적화가 앱에 어떤 영향을 미치는지 확인하겠습니다 가장 먼저 주목해야 할 점은 세션이 시작되기 전에 애셋이 로딩되었다는 것입니다 pre-warm 함수 덕분이죠 사용자가 세부 뷰를 클릭하는 시점에 우리는 이 애셋을 로드했습니다 작업에 pre-warm 함수를 추가해 pre-warm 메서드를 호출했습니다 따라서 사용자가 제목과 설명을 읽고 있을 때 모델이 이미 로드되어 준비되었습니다 여기서 세션의 시작 부분을 자세히 살펴보면 거의 세션이 시작되자마자 출력이 생성되기 시작합니다 모델이 이미 로드되었기 때문에 세션이 시작되었습니다 단어 준비가 시작되고 토큰 생성이 시작되며 응답 속도가 훨씬 더 빨라집니다 우리가 수행한 두 번째 최적화와 그 효과도 살펴보겠습니다 추론 아래에서 최대 토큰 수가 700으로 줄어든 것이 보입니다 이전에는 1,000개였으므로 프롬프트에서 스키마를 제외하여 최대 토큰 수를 700개로 줄였습니다 이는 또한 모델이 초기 토큰을 훨씬 더 빠르게 처리하고 한층 더 빠르게 응답 생성을 시작할 수 있음을 의미합니다

    멋지네요 이 마지막 장에서는 성능을 살펴봤습니다 모델 사전 준비로 앱의 반응성을 높이는 방법과 불필요한 스키마 제외로 프롬프트를 최적화하는 방법을 알아봤습니다 이는 생성형 기능의 성능을 향상하는 간단하면서도 효과적인 두 가지 방법입니다

    이제 우리가 함께 빌드한 앱을 마지막으로 한번 살펴보죠

    Xcode로 돌아가서 빌드하고 실행합니다

    여러분의 컴퓨터에서 실행되는 앱이므로 익숙하게 보일 것입니다 간단한 Swift 랜드마크 목록으로 시작했고 여기서 세렝게티를 선택하면 이 세부 뷰가 표시됩니다 이제 일정 생성을 마지막으로 한번 탭해 보죠

    UI가 실시간으로 자동 빌드됩니다 이것이 4장의 스트리밍 API이며 session.streamResponse와 PartiallyGenerated 콘텐츠를 사용합니다 2장에서는 add generable을 사용해 풍부하고 구조화된 응답을 얻었죠 5장에서는 도구 호출을 사용해 관심 지점을 찾고 모델은 지능적으로 이를 호출하여 데이터를 얻습니다

    오늘 기본 텍스트 생성부터 가이드 생성, 스트리밍, 도구 호출 성능 최적화까지 많은 내용을 다루었지만 아직 살펴볼 내용이 더 많이 있습니다 맞춤형 모델 어댑터 학습 동적 런타임 스키마 자세한 가드레일 및 오류 처리 등 고급 주제를 다룰 시간이 없었습니다 이러한 주제에 대해 자세히 알아보려면 Foundation Models 프레임워크에 대한 다른 WWDC25 비디오 시청을 적극 권장합니다

    Slido를 살펴보면 훌륭한 질문이 많이 있습니다 여러분의 질문에 대한 답변을 찾지 못했다면 개발자 포럼 (developer.apple.com/forums)에서 계속 논의해 주시기 바랍니다 오늘 완성된 샘플 프로젝트는 몇 가지 추가 기능을 포함하여 Foundation Models 프레임워크 문서에서 다운로드할 수 있습니다 마지막으로, 오늘 중으로 설문 조사를 보내 드릴 예정입니다 오늘 세션이 유익하셨기를 바라며 소중한 피드백을 기다리겠습니다 저와 함께 코딩 실습에 참여해 주셔서 정말 감사합니다 곧 다시 뵙겠습니다 안녕히 계세요

Developer Footer

  • 비디오
  • Meet With Apple
  • 파운데이션 모델 프레임워크 코딩 실습
  • 메뉴 열기 메뉴 닫기
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    메뉴 열기 메뉴 닫기
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    메뉴 열기 메뉴 닫기
    • 손쉬운 사용
    • 액세서리
    • Apple Intelligence
    • 앱 확장 프로그램
    • App Store
    • 오디오 및 비디오(영문)
    • 증강 현실
    • 디자인
    • 배포
    • 교육
    • 서체(영문)
    • 게임
    • 건강 및 피트니스
    • 앱 내 구입
    • 현지화
    • 지도 및 위치
    • 머신 러닝 및 AI
    • 오픈 소스(영문)
    • 보안
    • Safari 및 웹(영문)
    메뉴 열기 메뉴 닫기
    • 문서(영문)
    • 튜토리얼
    • 다운로드
    • 포럼(영문)
    • 비디오
    메뉴 열기 메뉴 닫기
    • 지원 문서
    • 문의하기
    • 버그 보고
    • 시스템 상태(영문)
    메뉴 열기 메뉴 닫기
    • Apple Developer
    • App Store Connect
    • 인증서, 식별자 및 프로파일(영문)
    • 피드백 지원
    메뉴 열기 메뉴 닫기
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(영문)
    • Mini Apps Partner Program
    • News Partner Program(영문)
    • Video Partner Program(영문)
    • Security Bounty Program(영문)
    • Security Research Device Program(영문)
    메뉴 열기 메뉴 닫기
    • Apple과의 만남
    • Apple Developer Center
    • App Store 어워드(영문)
    • Apple 디자인 어워드
    • Apple Developer Academy(영문)
    • WWDC
    Apple Developer 앱 받기
    Copyright © 2026 Apple Inc. 모든 권리 보유.
    약관 개인정보 처리방침 계약 및 지침