WWDC25 μ€ν°λ μ¬μ : iOS νμ΄ λ°°μ΄ κ², λ§λ κ², λλ κ²
- #iOS
- #WWDC25
- #Live Activity
- #SpeechAnalyzer
λ€μ΄κ°λ©°
μλ νμΈμ. ν둬 iOS κ°λ°μ λ°μ§λ―Όμ λλ€.
μ ν¬ iOS νμμλ λ§€λ WWDCμμ μμμ§λ μλ‘μ΄ κΈ°μ κ³Ό λ³ν μμμ, λ¨μν νμ΅μ λμ΄ μ€ν κΈ°λ° νμ΅μ λͺ©νλ‘ iOS μ€ν°λλ₯Ό μμνμ΅λλ€.
WWDC 2025μ ν΅μ¬ μΈμ μ νμ΅νκ³ , μ€μ μλΉμ€μΈ ν둬μ±μ μ μ© κ°λ₯ν μμ΄λμ΄λ₯Ό μ§μ λ§λ€μ΄λ³΄λ μ¬μ μ΄μμ΅λλ€. μ΄ κΈμμλ μ ν¬κ° μ΄λ»κ² μ€ν°λλ₯Ό μ΄μνκ³ , 무μμ λ°°μ μΌλ©°, ν둬μ±μ μ΄λ€ κΈ°λ₯λ€μ μ€ννλμ§ κ³΅μ νκ³ μ ν©λλ€.
μ WWDC25 μ€ν°λλ₯Ό μμνλκ°?
WWDCλ iOS κ°λ°μμκ² κ°μ₯ ν° μ΄λ²€νΈμ λλ€. μ ν¬ νμ λͺ©νλ λͺ ννμ΅λλ€.
1. WWDC 2025μμ λ°νλ μ΅μ iOS κΈ°μ κ³Ό νΈλ λλ₯Ό νμ΅νμ¬ νλ«νΌμ λ³νμ λΉ λ₯΄κ² μ μνλ€.
2. νμ΅ν λ΄μ©μ λ°νμΌλ‘ ν둬μ±μ μ§μ μ μ© κ°λ₯ν κΈ°λ₯μ νμνλ€.
3. μμ ννλ‘λΌλ ν둬μ±μ μ€ν μ μ©ν΄λ³΄λ©° μ°λ¦¬ μλΉμ€μ νμ λ§λ κΈ°μ λμ
λ°©μμ κ³ λ―Όν΄λ³Έλ€.
μ ν¬λ μ€ν°λ κΈ°κ° λ΄μ λͺ¨λ μΈμ μ λ§μ€ν°νλ κ²μ΄λ, λΉμ₯ μ€ν μ΄μ λ°°ν¬ν μμ€μ μμ±λλ₯Ό λ§λλ κ²μ λͺ©νλ‘ νμ§ μμμ΅λλ€. λμ , μλ‘μ΄ κΈ°μ μ λΉ λ₯΄κ² κ²μ¦νκ³ μλΉμ€ κ΄μ μμ μλ‘μ΄ μΈμ¬μ΄νΈλ₯Ό μ»λ κ²μ μ§μ€νμ΅λλ€.
μ€ν°λ μ§ν λ°©μ & μΈμ
μ ν¬ iOSνμ μλμ κ°μ΄ μ€ν°λλ₯Ό μ§ννμμ΅λλ€.
1. νμ΅: λͺ¨λ μΈμ μ λ€ λ³΄λ λμ , ν¨μ¨μ μΈ νμ΅μ μν΄ μ½ν μΈ λ₯Ό λ κ°μ§ νΈλμΌλ‘ λλκΈ°
ν΅μ¬ κ³΅ν΅ μΈμ : νμ λͺ¨λκ° μμμΌ ν iOS νλ«νΌμ ν΅μ¬ λ³νλ₯Ό μλ―Έν©λλ€. Platforms State of the Union, Whatβs new in Swift, SwiftUI, UIKit λ±μ΄ μ¬κΈ°μ ν΄λΉνμ΅λλ€. μ΄λ₯Ό ν΅ν΄ ν μ μ²΄κ° μ΅μ κΈ°μ λν₯μ λν 곡ν΅μ μ΄ν΄ κΈ°λ°μ λ€μ§ μ μμμ΅λλ€.
κ°μΈλ³ κ΄μ¬ μΈμ : κ³΅ν΅ μΈμ μΈμ, κ°μ ν둬μ±μ μ μ©ν΄λ³΄κ³ μΆκ±°λ κ°μΈμ μΌλ‘ κ΄μ¬ μλ μΈμ μ μμ λ‘κ² μ νν΄ νμ΅νμ΅λλ€.
2. 곡μ : νμ΅ λ΄μ© 곡μ νκΈ°
μ ν¬λ νμ΅ν λ΄μ©μ λλ£λ€κ³Ό ν¨κ³Όμ μΌλ‘ 곡μ νκΈ° μν΄ κ°μΈλ³ Learning Notesλ₯Ό μμ±νμ΅λλ€.
κ°μ μ€ν°λν μΈμ μ λ§ν¬μ ν¨κ», κ·Έ λ΄μ©μ λ°νμΌλ‘ μ€μ€λ‘ μ§λ¬Έ 3κ°λ₯Ό λ§λ€μ΄ 곡μ νμ΅λλ€.
μ΄ λ°©μμ ν΅ν΄ μΈμ μ ν΅μ¬μ λ κΉμ΄ κ³ λ―Όν μ μμκ³ , νμλ€μ Learning Notesλ₯Ό 보며 μλ‘ λ€λ₯Έ κ΄μ μ νμΈνκ³ μλ‘μ΄ μΈμ¬μ΄νΈλ₯Ό μ»λ κ³κΈ°κ° λμμ΅λλ€.
3. μ μ©: νμ΅μ κ²°κ³Όλ¬Όλ‘ λ§λ λ―Έλ ν΄μ»€ν€
μ ν¬ μ€ν°λμ μ΅μ’ λͺ©νλ ν둬μ±μ μ€ν μ μ©μ΄μμ΅λλ€. μ΄λ₯Ό μν΄ μ€ν°λ νλ°λΆλ μμ΄λμ΄λ₯Ό μ€μ μ½λλ‘ κ΅¬ννλ λ° μ§μ€νμ΅λλ€.
κ·Έλμ νμ΅ν λ΄μ©μ κΈ°λ°μΌλ‘ κ°μ μμ΄λμ΄λ₯Ό ꡬμν΄ λ°ννκ³ , ν ν λ‘ μ κ±°μ³ μ΅μ’ μ£Όμ λ₯Ό μ μ νμ΅λλ€. μ΄μ΄μ βλ―Έλ ν΄μ»€ν€βμ μ΄μ΄ ν둬μ±μ μ§μ κΈ°λ₯μ ꡬννκ³ , κ·Έ κ²°κ³Όλ¬Όμ 곡μ νλ©° μ€ν°λμ μ¬μ μ λ§λ¬΄λ¦¬νμ΅λλ€.
Fromm μ±μ μ μ©ν΄λ³΄κΈ°!
π‘ μμ΄λμ΄ μ μ κΈ°μ€ ν΄μ»€ν€μμ ꡬνν μμ΄λμ΄λ₯Ό μ μ νκΈ° μν΄, μ ν¬λ μΈ κ°μ§ ν΅μ¬ κΈ°μ€μ μ μ©νμ΅λλ€.
λ¨μν WWDC25μμ λ°°μ΄ μλ‘μ΄ κΈ°μ , μ€ν°λ κΈ°λ°μ μ μ©ν΄λ³΄λ κ²μ λμ΄, μ΄ κΈ°μ μ΄ μ€μ μ¬μ©μμ λμ¦λ₯Ό ν΄κ²°ν μ μλμ§, κ·Έλ¦¬κ³ κ°λ°μ μ μ₯μμ κ³ κ° λ§μ‘±λλ₯Ό νμ€ν λμΌ μ μλμ§λ₯Ό μ€μ μ μΌλ‘ κ²ν νμ¬ μ΅μ’ μ£Όμ λ₯Ό μ μ νμ΅λλ€.
μ΄ κΈ°μ€μ λ°λΌ μ μ λ μμ΄λμ΄λ λ€μκ³Ό κ°μ΅λλ€.
- SpeechAnalyzer - μμ±λ©μμ§ λ²μ STT(Speech-to-Text)
- Live Activity - μν°μ€νΈ μ΄λ²€νΈ μλ¦Ό
SpeechAnalyzer
ν둬 μλΉμ€μλ μν°μ€νΈκ° ν¬λ€μκ² μμ± λ©μμ§λ₯Ό 보λ΄λ κΈ°λ₯μ΄ μμ΅λλ€. νμ§λ§ μ΄ κ²½μ°, ν΄μΈ ν¬λ€μ μΈμ΄μ μ₯λ²½μΌλ‘ μΈν΄ μν°μ€νΈκ° νλ λ§μ λ°λ‘ μμλ£μ§ λͺ»νλ λΆνΈν¨μ΄ μμμ΅λλ€.
μ ν¬λ μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν 첫걸μμΌλ‘, WWDC25μμ μκ°λ SpeechAnalyzerλ₯Ό μ μ©νμ¬ μμ± λ©μμ§λ₯Ό ν μ€νΈλ‘ λ³ν(STT)νλ μ€νμ μ§ννμ΅λλ€. μ΄λ² μ€νμ ν΅ν΄, μΆν μ΄ ν μ€νΈλ₯Ό κΈ°λ°μΌλ‘ λ²μ κΈ°λ₯κΉμ§ νμ₯νλ€λ©΄, κ·Έλμ μν΅μ λΆνΈν¨μ λκΌλ ν΄μΈ ν¬λ€μ κ²½νμ ν¬κ² κ°μ ν μ μμ κ²μ΄λΌλ κ°λ₯μ±μ νμΈνμ΅λλ€.

SFSpeechRecognizer: μμ± μΈμ μλΉμ€μ κ°μ©μ±μ νμΈνκ³ μμ± μΈμ νλ‘μΈμ€λ₯Ό μμνλλ° μ¬μ©νλ κ°μ²΄ SFSpeechRecognitionTask: μμ± μΈμ μ§ν μν©μ λͺ¨λν°λ§νκΈ° μν μμ κ°μ²΄
λ¨Όμ SFSpeechRecognizerλ₯Ό νκ΅μ΄(ko-KR)λ‘ μ΄κΈ°νν©λλ€. transcribeLocalFile ν¨μκ° νΈμΆλλ©΄, νμΌμ΄ μ€μ λ‘ μ‘΄μ¬νκ³ μ§μλλ μ€λμ€ νμ(m4a, mp3 λ±)μΈμ§ λ¨Όμ κ²μ¦μ μ§ννκ³ , μ ν¨ν νμΌμμ΄ νμΈλλ©΄, SFSpeechURLRecognitionRequestλ₯Ό μμ±νμ¬ λ³νμ μμ²ν©λλ€.
μ΄λ shouldReportPartialResultsλ₯Ό falseλ‘ μ€μ νκΈ° λλ¬Έμ, λ³ν μμ μ μ€κ° κ²°κ³Ό μμ΄ μ΅μ’ ν μ€νΈλ§ λ°ννκ² λ©λλ€. recognitionTaskλ₯Ό ν΅ν΄ λΉλκΈ°μ μΌλ‘ λ³νμ΄ μμλλ©°, μμ μ΄ μ±κ³΅μ μΌλ‘ μλ£λλ©΄ result.bestTranscription.formattedStringμ ν΅ν΄ κ°μ₯ μ νν νκ΅μ΄ ν μ€νΈλ₯Ό μΆμΆν©λλ€.
private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ko-KR"))
private var recognitionTask: SFSpeechRecognitionTask?
private func transcribeLocalFile(at url: URL) {
guard let speechRecognizer = speechRecognizer else { return }
// νμΌ μ‘΄μ¬ λ° μ κ·Ό κ°λ₯μ± νμΈ
guard FileManager.default.fileExists(atPath: url.path) else {
showTranscriptionResult("μ€λμ€ νμΌμ μ°Ύμ μ μμ΅λλ€.")
return
}
// μ§μλλ μ€λμ€ νμ νμΈ
let supportedExtensions = ["wav", "m4a", "mp3", "aac", "caf"]
let fileExtension = url.pathExtension.lowercased()
guard supportedExtensions.contains(fileExtension) else {
showTranscriptionResult("μ§μλμ§ μλ μ€λμ€ νμμ
λλ€. (μ§μ νμ: wav, m4a, mp3, aac, caf)")
return
}
let request = SFSpeechURLRecognitionRequest(url: url)
request.shouldReportPartialResults = false
recognitionTask = speechRecognizer.recognitionTask(with: request) { [weak self] result, error in
DispatchQueue.main.async {
if let result = result {
if result.isFinal {
let koreanText = result.bestTranscription.formattedString
if koreanText.isEmpty {
self?.showTranscriptionResult("μμ±μ μΈμν μ μμ΅λλ€.")
} else {
self?.showTranscriptionResult(koreanText)
}
}
}
}
}
}
SpeechAnalyzerλ ν₯μλ μ νλμ μλλ₯Ό 보μ¬μ£ΌμμΌλ©°, κΈλ‘λ² ν¬λ€μ΄ μμ± λ©μμ§ λ΄μ©μ λ μ½κ² μ΄ν΄νλ λ° ν° λμμ΄ λ κ²μΌλ‘ κΈ°λλμμ΅λλ€.
Live Activity
ν둬μ±μμ μν°μ€νΈκ° ν¬λ€μ μν μλ‘μ΄ μ΄λ²€νΈλ₯Ό μμ±νμ λ(μ: κΉμ§ λΌμ΄λΈ λ°©μ‘ μκ³ , μ€νμ μ΄λ²€νΈ μμ), ν¬λ€μ΄ μ΄ μ€μν μκ°μ λμΉμ§ μκ³ μ€μκ°μΌλ‘ νμΈνλ κΈ°λ₯μ΄ νμνμ΅λλ€.
1) ActivityAttributes μ μ
public struct EventCountdownAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
public var remainingTime: TimeInterval
public init(remainingTime: TimeInterval) {
self.remainingTime = remainingTime
}
}
public var eventTitle: String
public var eventContent: String
public var eventDate: Date
public var artiName: String
public var totalDuration: TimeInterval
public var startDate: Date
}
κ³ μ λ°μ΄ν°(Attributes)μ μ€μκ° λ°μ΄ν°(ContentState)λ₯Ό λΆλ¦¬νλ κ²μ΄ μ€μ!
2) Activity μμνκΈ°
func startActivity(
title: String,
content: String,
artiName: String,
eventDate: Date
) async {
guard ActivityAuthorizationInfo().areActivitiesEnabled else {
return
}
let attributes = EventCountdownAttributes(
eventTitle: title,
eventContent: content,
eventDate: eventDate,
artiName: artiName
)
let initialState = EventCountdownAttributes.ContentState(
remainingTime: eventDate.timeIntervalSinceNow
)
let activity = try Activity.request(
attributes: attributes,
content: ActivityContent(state: initialState, staleDate: nil),
pushType: nil
)
}
Activity.request()λ‘ Live Activity μμ!
3) Activity μ λ°μ΄νΈνκΈ°
// 1μ΄λ§λ€ μλ μ
λ°μ΄νΈ
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
Task {
let remaining = eventDate.timeIntervalSinceNow
let newState = EventCountdownAttributes.ContentState(
remainingTime: floor(remaining)
)
await activity.update(
ActivityContent(state: newState, staleDate: Date())
)
}
}
μκ°μ μ΄ λ¨μλ‘ νμνκΈ° μν΄ Timerλ₯Ό μ΄μ©ν΄ 1μ΄ κ°κ²©μΌλ‘ μ λ°μ΄νΈ μ§ν! (μ°Έκ³ : Appleμ λ°°ν°λ¦¬ ν¨μ¨ λ¬Έμ λ₯Ό κ³ λ €νμ¬ 60μ΄ κ°κ²©μ κΆμ₯ν©λλ€.)

μ ν¬λ Live Activityμ Dynamic Islandλ₯Ό νμ©νμ¬, μν°μ€νΈκ° μ΄λ²€νΈλ₯Ό μμνλ©΄ ν¬λ€μ μ κΈνλ©΄μ΄λ λ€μ΄λλ―Ή μμΌλλμ κ΄λ ¨ μ λ³΄κ° μ€μκ° μλ¦ΌμΌλ‘ λ¨λλ‘ κ΅¬ννμ΅λλ€. μ΄λ₯Ό ν΅ν΄ ν¬λ€μ μ΄λ²€νΈ μμκΉμ§ λ¨μ μκ°μ νμΈνκ±°λ λ°λ‘ μ±μΌλ‘ μ§μ νλ λ±, μν°μ€νΈμ λ κ°κΉκ² μν΅ν μ μλ κ²½νμ μ€νν΄ λ³΄μμ΅λλ€.
λ§μΉλ©°
μ΄λ² μ€ν°λμ ν΅μ¬μ λ¨μν μ§μμ μλ νμ΅μ΄ μλ, μ€νκ³Ό μ μ©μ΄μμ΅λλ€. μ ν¬λ State of the UnionλΆν° Swiftμ μλ‘μ΄ κΈ°λ₯κΉμ§ ν΅μ¬μ μΈ λ³νλ₯Ό ν¨κ» νμ΅νκ³ , κ³§λ°λ‘ βμ΄κ²μ ν둬μ±μ μ΄λ»κ² μΈ μ μμκΉ?βλΌλ νμ€μ μΈ μ§λ¬Έμ λμ‘μ΅λλ€.
SpeechAnalyzerλ₯Ό μ΄μ©ν μμ± λ©μμ§ λ³ν, Live Activityλ₯Ό νμ©ν λ§€λμ μλ¦Ό κΈ°λ₯ λ±μ κ·Έ μ§λ¬Έμ λν μ ν¬μ 첫 λ²μ§Έ λλ΅μ΄μμ΅λλ€. λΉλ‘ μ§§μ ν΄μ»€ν€μ ν΅ν μ€νμ μΈ μ μ©μ΄μμ§λ§, μ΄ κ³Όμ μ ν΅ν΄ ν μ μμ΄ μ΅μ κΈ°μ μ λν 곡ν΅μ μ΄ν΄λ₯Ό λ€μ§κ³ , μλΉμ€ κ΄μ μ μλ‘μ΄ μΈμ¬μ΄νΈλ₯Ό μ»λ κ°μ§ μ±κ³Όλ₯Ό κ±°λμμ΅λλ€.
무μλ³΄λ€ μ΄λ² μ€ν°λλ μ ν¬μκ² κΈ°μ μ ν¨κ» νꡬνλ μ¬λ―Έμ λ¨κΈ°κ°μ μμ μ±κ³Όλ₯Ό λ§λ€μ΄λ³΄λ μ±μ·¨κ°μ μ겨주μμ΅λλ€. νλ‘¬μ± μ¬μ©μλ€μκ² λ κ°μΉ μλ κΈ°λ₯μ μ 곡νκΈ° μν΄ μ ν¬ iOS νμ μμΌλ‘λ κ³μν΄μ μ€ννκ³ λμ νκ² μ΅λλ€.
κ°μ¬ν©λλ€!