티스토리 뷰

WWDC

[WWDC] Foundation Models 알아보기

yanni13 2025. 6. 26. 00:30

 

이번에 WWDC25에서 애플이 온디바이스 LLM을 직접 앱에 통합할 수 있는 Foundation Models를 공개했다.

이 기술이 어떤 것인지, 어떻게 활용할 수 있는지 애플에서 작성한 샘플코드를 보면서 공부해보고자 한다.

 

 

✏️ 준비물

xcode 26 beta가 설치된 맥북, 아래 링크를 들어가 다운로드 받은 샘플코드가 필요하다!

 

Adding intelligent app features with generative models | Apple Developer Documentation

Build robust apps with guided generation and tool calling by adopting the Foundation Models framework.

developer.apple.com

 

 

 

💡Foundation Models 

 

개발자가 온디바이스 환경에서 직접 LLM(대규모 언어 모델)을 활용할 수 있도록 만든 프레임워크이며 iOS 26 버전부터 사용 가능하다.

 

그래서 iOS 26부터는 openAI, Claude와 같은 생성형 AI를 직접 호출하지 않아도 AI를 사용할 수 있게 되는 것이다.

 

 

 

Foundation Models은  온디바이스 환경에서 실행되기 때문에 사용자 데이터가 private 하게 유지되며 오프라인 상태에서 활용 가능하고 모델이 운영체제 자체에 내장되어 있다고 한다.

 

 

 


  Foundation Models를 앱에 통합하고 최적화 하기

 

 

 

1️⃣ Prompt engineering

LLM에게 원하는 결과를 도출하기 위해 질문이나 요청을 정제하는 작업

 

Prompt engineering은 프롬프트를 어떻게 구성할지, 어떤 방식으로 대화를 유도할지 정하는 과정이다.

Foundation model을 앱에 통합하기 위해 가장 먼저 해야 할 작업이기도 하다.

 

예를 들어 우리가 Chatgpt나 claude랑 대화할 때 내가 질문한 걸 올바른 대답으로 이끌어내기 위해서 프롬프트를 잘 작성해서 학습을 먼저 시켜놓는 게 중요하다!

 

나는 iOS 개발자가 되고 싶어서 swift 공부만 하고 있는데 ~이런 기술 만들어줘!라고 했을 때 python으로 구현을 해준다던가, 자바로 구현해 버리면 일은 여러 번 해야 하는 번거로움이 생길 수 있다.

 

이걸 방지하고자 프롬프트 설계하는 과정이 제일 첫 작업으로 필요하게 되는 것이다!

주로 모델에서 어떤 요청을 줄 건지, 어떤 스타일이나 출력 형식을 원하는지를 작성하면 된다!

 

WWDC25에서는 이 과정을 3-4 줄의 코드로 완성할 수 있으며 Playgrounds를 import 하기만 하면 프롬프트를 작성해준다고 한다

 

 

이건 예시로 한번 작성해 본 코드이다. 

 

let response = try await session.respond(to: "Create To My Persona")

 

위 코드로 Foundation Models를 호출해서 Preview로 바로 확인할 수 있는 과정이다.

응답시간과 나의 페르소나에 대한 정보를 프롬프트로 다 작성해 주는 것을 프리뷰에서 바로 확인할 수 있었다.

 

 

 

2️⃣ Tool calling

LLM이 응답 중 앱의 어떤 기능이 필요하다고 판단되면 모델이 자율적으로 정보를 가져오도록 하는 기능

 

Tools는 모델이 응답 중에 어떤 함수나, 어떤 기능이 필요하다고 판단되면 모델이 맥락에 따라 판단하여 정보를 가져오도록 한다.

예를 들어 모델과 대화를 하다가 MapKit이 필요하다고 판단되면 MapKit Api를 호출하여 결과를 반환한다.

 

이때 응답에 외부 정보를 포함할 수도 있다. 예를 들어 휴대폰 연락처에 있는 사람을 활용하거나, 캘린더에 있는 이벤트를 활용하거나 온라인 콘텐츠까지 활용하여 매우 다양하고 창의적인 아이디어가 나올 수 있다고 한다.

 

 

Tool calling의 주요 특징

1. 요청 중에 코드를 호출하여 외부 데이터에 액세스 할 수 있다.

앞에 설명했던 것처럼 LLM이 자연어 기반으로 연락처나 지도, 캘린더 등등 앱의 기능을 호출할 수 있는 bridge역할을 하기 때문에 내부에서 네트워크 요청, 데이터베이스 조회, CoreData 등등을 활용하여 외부 데이터에 접근할 수 있다.

 

2. 하나의 요청 내에서 tool이 여러 번 호출될 수도 있다.

한 번의 대화로 모델이 충분하다고 판단하지 못할 경우 필요에 따라 여러 번의 tool을 호출할 수도 있다.

 

3. tools는 병렬로 호출될 수도 있으며 상태를 저장할 수도 있다.

tool은 async로 호출되기 때문에 tool 간에 병렬 실행이 가능하다.

따라서 비동기 처리 기반으로 구현되어야 하며 모델이 동시에 A, B, C를 실행해서 응답을 캐싱하거나 모은 다음 사용자에게 보여주는 방식으로 구현될 수도 있다.

 

즉, Tool Calling은 모델이 동작할 수 있어야만 작동하는데,  온디바이스 Foundation Model이 항상 사용 가능하다고 가정하긴 했지만 Apple Intelligence가 모든 기기에서 사용 가능한 게 아니다.

 

모델이 동작 불가하면 Tool 자체를 호출할 수 없기 때문에 호환되는 기기나 iOS 버전에 따라 사용 여부가 달라지며 이에 맞게 UI를 처리하는 것이 중요하다고 한다.

 

3️⃣ Streaming output

응답을 한꺼번에 생성하는 게 아니라, 실시간으로 응답을 받아서 사용자에게 점진적으로 보여주는 방식

 

 

Streaming output을 활용한 예시

 

 

 

기존엔 모델이 생성될 때까지 기다린 후 생성이 완료되면 한꺼번에 UI로 보여주는 방식이었지만 Streaming output을 통해 모델이 응답을 생성하면서 바로 반환하기 때문에 실시간으로 바로 보여주는 느낌이 들어서 사용자 입장에서 자연스러운 UI가 보이는 느낌이 든다.

 

이 기술은 chat gpt나 claude를 사용해 봤으면 더 익숙하게 느껴질 것이다. gpt 한테 뭘 물어보면 응답이 될 때까지 기다렸다가 한꺼번에 정보를 띄워주는 게 아니라 생성되는 즉시 반환되는 특징을 가지고 있다. 

 

여기서 gpt는 Token-level Streaming output을 사용하고 있으며 Foundation models는 AsyncSequence를 활용하여 스트리밍 하고 있다고 한다.

 

📍Token-level Streaming output이란?
토큰 단위(텍스트 조각)로 생성된 결과를 실시간으로 순차 전송하는 방식

📍 AsyncSequence란?

비동기적으로 한 번에 하나씩 단계별로 진행할 수 있는 값을 제공(=비동기적으로 값을 연속적으로 생성)

 

 

 

4️⃣ Profiling

Foundation Models가 앱에서 어떻게 동작하는지 성능, 리소스 관점에서 측정하고 시각화할 수 있는 기능

 

시뮬레이터로 앱을 테스트하는 것은 유용하지만 정확한 성능 결과를 얻지 못할 수 있다.

예를 들어 M4 Mac 시뮬레이터는 iphone 7보다 더 빠른 결과를 낼 수 있다. 

 

따라서 모델 자체 응답 시간이나 메모리 사용량을 도출해 내기 위해서 Profiling을 사용하며 애플에서는 foundation models를 활용할 때 실제 디바이스에서 profiling을 실행하라고 강조하고 있다.

 

Profiling은 Foundation Models을 통합 후 실제 프롬프트 실행시간, 응답길이, 성공률, tool call 비율들을 시각적으로 분석하는 도구이다.

 

📍 활용법: Xcode Instruments -> Foundation Models

 

온디바이스 모델이 실제 디바이스에서의 처리 시간, 메모리 사용량, 예측 정확도를 기준으로 분석할 수 있다. 

 

 

 

 

이런 식으로 Instruments를 통해서 비교분석 하고 싶은 것을 스냅샷을 찍어서 성능을 확인할 수 있다.

 

 


사용법 알아보기

 

1️⃣ Sessions

콘텐츠를 생성하는 데 사용되는 단일 context (= LLM과의 하나의 context)

 

session은 모델을 호출할 때마다 기존 인스턴스를 재사용하거나 새 인스턴스를 생성할 수 있다.

let session = LanguageModelSession(model: contentTaggingModel)

 

위와 같이 코드를 작성하게 되면 새로운 세션 인스턴스를 생성할 수 있다.

 

 

self.session = LanguageModelSession(
            tools: [pointOfInterestTool],
            instructions: Instructions {
                "Your job is to create an itinerary for the user."
                
                "Each day needs an activity, hotel and restaurant."
                
                """
                Always use the findPointsOfInterest tool to find businesses \
                and activities in \(landmark.name), especially hotels \
                and restaurants.
                
                The point of interest categories may include:
                """
                FindPointsOfInterestTool.categories
                
                """
                Here is a description of \(landmark.name) for your reference \
                when considering what activities to generate:
                """
                landmark.description
            }
        )

 

애플에서 제공된 샘플 코드를 보면 이런 식으로 모델을 사용하고 있다.

위 코드에서는 설정이 완료된 세션을 만드는 방식으로 tools와 instructions이 미리 설정되어 있고 self.session을 통해 해당 세션에 내용들을 저장함으로써 이후 generate()로 텍스트 생성 요청을 보낼 수 있다.

 

각 session은 lifecycle을 잘 제어하는 것이 중요하다 하나의 session으로 너무 많은 요청을 보내면 overflow가 발생가능하다.

 

gpt에서도 하나의 채팅에 너무 많은 정보를 요청하게 되면 토큰 초과로 유료 결제를 하거나 다음 채팅으로 다시 채팅을 시작해야 한다.

이런거 ㅋ ㅋ..

 

sessions도 이와 같은 맥락을 가진다.

lifecycle을 제대로 관리하지 못하면 하나의 session에서 내부 context가 계속해서 쌓이게 되고 결국 이상한 방향으로 대화가 빠지거나, 이전 대화를 잘 기억하지 못하는 경우가 발생한다.

 

심한 경우는 LanguageModelSession.GenerationError.exceedContextWindowSize( : )라는 에러를 내면서 앱이 종료될 수도 있다!

 

따라서 일정 길이 이후 새 세션으로 교체하거나, 필요한 context가 사라졌을 때 메모리를 해제하는 게 중요하다.

 

2️⃣ Generable

swift를 사용하여 모델이 구조화된 데이터를 생성하도록 하는 쉬운 방법

 

 

Generable은 struct와 enum 구조체와 열거형에 적용할 수 있는 매크로이며 모델에서 구조화된 출력을 얻는 방법을 제공한다.

 

활용예시

 

 

매크로는 컴파일 시간에 스키마를 생성하고, 모델은 이를 사용하여 예상되는 구조를 생성할 수 있다. 또한 session에 요청할 때 자동으로 호출되는 초기화 프로그램을 생성한다. 

 

이 말을 쉽게 설명하자면 @Generable을 붙이면 "이 타입은 이런 구조야"라고 모델한테 알려주는 가이드역할을 해서 조금 더 정확한 정보를 모델이 이해할 수 있도록 한다.

 

@Generable은 온디바이스 환경 LLM에서 output을 얻기 가장 좋은 방법이다.

 

아래와 같이 Persona에 대한 구조체를 만들어보았다.

@Generable
struct Persona: Equatable {
    let id: UUID
    @Guide(description: "An exciting name for your persona")
    let name: String
    let age: Int
    let gender: String
    let location: String
    let interests: [String]
}
📍 @Guide란 뭘까?
모델이 해당 필드를 더 잘 이해하고 의미 있게 생성할 수 있도록 하는 것

 

구조체에 대한 응답을 더 세밀하게 제어하고 싶다면 Guide 매크로를 사용하여 속성 값에 제약 조건을 걸 수 있다.

 

위와 같이 Persona에 대한 데이터 구조가 있다고 가정했을 때 Guide안에 설명을 넣어주면 모델이 입력에 영향을 준다.

즉 Guide가 붙은 필드는 추가 설명까지 참고해서 값을 생성하기 때문에 원하는 필드 위에다가 @Guide를 붙여주면 됨!

 

위에 예시로 따지자면 더 흥미로운 이름을 가진 persona에 맞는 출력값을 낼 수 있을 것이다.

 

3️⃣ Dynamic schemas

실행 시점에 스키마를 동적으로 정의하여 모델이 그에 맞게 출력을 생성하도록 하는 방식

 

@Generable컴파일 타임에 정의된 swift 유형으로부터 고정된 타입을 정의하는 방식이다. 내부적으로는 Foundation Models는 스키마를 처리하고, GeneratedContent를 사용자 유형의 인스턴스로 변환한다.

 

반면 Dynamic schema는 @Generable와 매우 유사하게 작동하지만 훨씬 더 많은 제어 기능을 제공한다고 한다.

앱 실행 중에 스키마를 완전히 제어하고 모델이 출력한 결과가 GeneratedContent(Foundation Models)라는 구조화된 타입으로 반환하는데, 이걸 직접 탐색하고 값들을 꺼내볼 수 있게 접근할 수 있다.

 

 

 

앞서 설명한 내용을 요약하면 위에 그림과 같다!

 

 

이번 포스팅에서는 WWDC25에서 소개된 내용을 바탕으로 어떤 기능이고 어떻게 활용할 수 있고, 사용법 등을 알아봤는데, 다음 포스팅에는 이 Foundation Model을 어떻게 활용하는지 프로젝트에 코드를 반영해 보면서 느낀 것들 위주로 작성해 봐야겠다.

 

 


참고

https://developer.apple.com/documentation/foundationmodels

https://www.youtube.com/watch?v=XuX66Oljro0&list=LL&index=1&t=184s

https://www.youtube.com/?v=6Wgg7DIY29E

 

'WWDC' 카테고리의 다른 글

[WWDC] CreateML에 대해서 알아보기  (0) 2025.03.22
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함