스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
Swift Async 알고리즘 소개
Apple의 최신 오픈 소스 Swift 패키지인 Swift Async 알고리즘을 확인하세요. Zip, Merge 및 Throttle을 비롯하여 AsyncSequence와 함께 사용할 수 있는 이 패키지의 알고리즘을 알아보겠습니다. 이러한 알고리즘을 사용하여 멋진 메시징 앱을 빌드하는 과정을 확인하시기 바랍니다. 또한 다양한 AsyncSequence 결합 및 Swift Clock 유형 사용을 통해 시간 경과에 따른 값으로 작업하기 위한 모범 사례를 공유합니다. 이 세션을 최대한 활용하려면 ‘Meet AsyncSequence(AsyncSequence 소개)'를 시청하시기 바랍니다.
리소스
관련 비디오
WWDC22
WWDC21
-
다운로드
♪ ♪
안녕하세요 Philippe이라고 합니다 Swift는 계속 성장 중인 오픈 소스 패키지 카탈로그인데요 새로운 추가된 내용을 직접 소개하게 되어 기쁩니다 Swift Async Algorithms 이 패키지는 Swift Collections Swift Algorithms와 같은 다른 패키지들과 유사합니다 이 패키지는 AsyncSequence 프로토콜을 사용해 시간에 따라 값을 처리하는 일련의 알고리즘인데요 본론으로 들어가기 전에 AsyncSequence 프로토콜을 한 번 상기해 봅시다 이 프로토콜은 비동기 생성값을 기술할 수 있게 해주는데요 Sequence와 유사하나 두 가지 차이점이 있습니다 반복자 다음 함수는 Swift 동시성을 사용해 값을 전달하기 때문에 비동기 함수입니다 Swift의 던지기 효과를 통해 잠재적인 장애를 해결하죠 Sequece에서처럼 for-await-in 구문으로 이걸 반복할 수 있고요 즉, Sequence를 사용할 줄 알면 AsyncSequence 사용은 어렵지 않습니다 AsyncSequence를 도입하면서 Sequence에서 찾아볼 수 있는 모든 툴을 비동기 버전으로 추가했습니다 map, filter, reduce 같은 알고리즘이 있죠 그러나 이 패키지는 한 단계 더 발전했습니다 고급 알고리즘을 통합하고 강력한 걸 제공하고자 시계와 상호 운용되죠 Swift 동시성을 늘리는 AsyncSequence 알고리즘의 오픈 소스 패키지입니다 작년 Swift Algorithms 패키지를 소개했고 그 사용 사례를 증명하고자 메시징 앱을 만들었습니다 해당 패키지로 할 수 있는 풍부하고 강력한 것들을 보여줄 수 있는 사례였죠 우리는 Swift 동시성을 통해 앱 마이그레이션 기회가 많이 생겼다고 판단하였습니다 비동기 알고리즘을 몇 가지 보여드리기 위해 우리가 사용했던 것들과 어떻게 실행되는지 보여드리도록 하겠습니다 먼저, 우리에게는 다중 입력 AsyncSequence로 작동하는 특정 알고리즘들이 있습니다 이 알고리즘들은 AsyncSequence를 다양한 방식으로 결합하는데요 하지만 하나의 공통점은 AsyncSequence가 다중으로 입력되지만 단일 출력된다는 점입니다
Zip 알고리즘에는 친숙하실텐데요 이 알고리즘은 각 베이스에서 결과 튜플을 생성하기 위해 다중 입력을 취하고 그것을 반복합니다 입력물 각각은 Zip이 구조를 이루고 있는 베이스고요 비동기 Zip 알고리즘은 표준 라이브러리에서 Zip과 유사하게 작동하나 동시에 베이스 각각을 반복하고 반복 시 오류가 발생하면 다시 던집니다 반복과 오류 다시 던지기를 동시에 하는 것은 더 복잡해질 수 있습니다 하지만 Swift Async Algorithms은 메시징 앱에서 그걸 모두 다룰 수 있었죠 녹화 영상 미리 보기를 생성하며 효율적인 저장과 전송을 위해 영상을 다양한 크기로 트랜스코딩하면서 비동기 조정하는 코드가 이전에도 있었는데요 Zip을 통해 트랜스코딩 영상을 다른 서버로 전송할 때 미리 보기를 생성할 수 있게 됐습니다 Zip은 동기성이라 트랜스코딩이나 미리 보기가 둘 다 지연되지 않습니다 하지만 여기서 끝이 아닙니다 Zip 자체가 어떤 쪽에서 먼저 값을 생성하는지 더 선호하는 것이 없이 때문에 영상이나 미리 보기 둘 중 아무 거나 먼저 생성되고 어느 쪽이든 간에 다른 쪽이 튜플을 완료할 때까지 기다릴 겁니다 Zip은 튜플을 구축하기 위해 서로를 기다릴 수 있기 대문에 함께 업로드될 수 있도록 짝을 기다릴 수 있습니다 우리는 입력 메시지를 AsyncSequence로 모델링하는 것이 꽤 타당할 것이라는 결론을 내렸습니다 AsyncSequence는 명령을 보존하여 콜백을 메시지 비동기 시퀀스로 바꿀 수 있기 때문에 메시지 처리에 비동기 스트림을 사용하기로 결정했습니다 우리가 처리해야 할 필요한 특색 중 하나는 다양한 계정을 지원해야 한다는 점이었습니다 각 계정에서 입력 메시지의 AsyncSequence를 만들었으나 막상 구현하려고 하니 하나의 AsyncSequence로 처리해야 했거든요 즉, AsyncSequence 병합 알고리즘이 필요했습니다 감사하게도, 이번 패키지에는 그 이름도 적절한 "Merge" 알고리즘이 갖춰져 있는데요 이 알고리즘은 다중 AsyncSequence를 동시에 반복한다는 점에서 Zip과 비슷하게 작동하나 짝을 이루는 튜플 대신 베이스가 동일 요소 타입을 공유해야 하며 베이스 AsyncSequence를 해당 요소의 특이 AsyncSequence 하나에 병합합니다 병합 알고리즘은 반복 시 한 쪽 계정에서 먼저 생성된 요소를 취하죠 모든 베이스 AsyncSequence가 반복자에서 아무것도 도출하지 않을 때까지 반복은 계속 됩니다 베이스에서 오류가 발생한다면 다른 반복은 취소됩니다 이를 통해 메시지의 AsyncSequence를 취하고 병합할 수 있죠 이 결합 알고리즘은 값 생성 시 동시에 작동하지만 간혹 시간과 상호 작용하는 게 유용할 때가 있습니다 이번 패키지는 특정 알고리즘을 도입해 Swift 내 새로운 Clock API를 이용함으로써 시간과 작동합니다 시간 그 자체는 굉장히 복잡한 주제로 Swift 5.7의 Clock, Instant, Duration 타입은 시간을 안전하고 일관되게 하는 일련의 API입니다
Clock 프로토콜은 두 개의 프리미티브를 정의합니다 주어진 순간 이후 일어나는 방법과 지금이라는 개념을 생성하는 방법을요 시계에는 여러 가지 구조가 들어가 있는데 흔히 쓰이는 구조 중 두 가지는 바로 ContinuousClock과 SuspendingClock입니다 전자는 스톱워치처럼 시간 측정 시 사용 가능하며 사물 상태 측정 여부와는 상관 없이 시간은 흘러 갑니다 반면, 후자에서는 이름이 뜻하듯 머신이 정지하면 멈추죠 우리는 데드라인 이후 경고를 무시할 수 있도록 앱에서 새로운 시계 API를 사용하였는데요 지연하고자 하는 초의 수를 구체적으로 가리키는 duration 값을 추가해 데드라인을 만들 수 있었습니다 작동 실행 경과 시간을 측정하는 방법도 있고요 여기서 아까 말씀드렸던 두 가지 시계 구조를 사용하겠습니다
아래 디스플레이에서는 잠재적 작업 경과 시간의 측정 결과를 보여줍니다 이 두 시계의 주요 차이점은 머신이 정지했을 때의 반응에서 나타나는데요
오래 실행되는 작업의 경우 지금 우리가 한 것처럼 작업이 정지될 수 있습니다 하지만 실행을 재개하면 머신이 정지되어 있는 동안 ContinuousClock은 계속 작동하지만 SuspendingClock은 그렇지 않습니다 보통 이 차이는 주요 특징이 실행 시간을 중단함으로써 애니메이션과 같은 것들을 예상한대로 작동하게하는 주요 세부 사항이 될 수 있습니다 만약 애니메이션처럼 머신이 시간과 상호 작용해야 한다면 SuspendingClock을 사용하세요
사람과 관련된 태스크를 측정하는 것이라면 ContinuousClock이 적합할 겁니다 즉, 절대적 지속 구간에 따라 지연시켜야 하는 인간과 관련된 일에서는 후자를 사용하세요 신형 패키지에서는 시간과 관련하여 이벤트가 전개되는 개념들을 처리하기 위해 이 타입들을 사용합니다 우리는 메시징 앱을 통해 이벤트를 정확히 통제하기 위해 이 타입들이 굉장히 도움된다는 사실을 발견했습니다 상호 작용 제한 시간을 측정해 메시지를 효과적으로 버퍼링했죠 우리가 가장 시간을 많이 활용하는 분야는 메시지 검색이었습니다 우리는 결과 채널을 관리하는 컨트롤러를 만들었죠 이 채널은 검색 태스크에서 UI로 검색 결과를 모읍니다 검색 태스크 자채에는 시간과 관련된 구체적인 특성이 필요했죠 서버에서 발송된 메시지 검색 제한 시간을 측정하려 했습니다
Debounce 알고리즘은 반복 시 다음 값을 내기 전 정지 기간을 대기합니다 이벤트가 빨리 올 수도 있지만 값을 처리 하기 전에 정지 기간 동안 대기하고자 한다는 거죠 검색 필드의 유저 입력이 빠르게 바뀔 때 우리는 검색 컨트롤러가 각 변화의 검색 요청을 급하게 하길 원치 않습니다 대신에 특정 타이핑이 완료되려고 할 때까지의 정지 기간 동안 대기하길 원하는 거죠 Debounce 알고리즘은 기본적으로 ContinuousClock을 사용할 겁니다 이 경우 아무 일이 일어나지 않는 특정 기간 동안 대기하기 대기할 수 있돌고 입력을 디바운싱할 수 있습니다 시간과 지속 기간은 디바운싱에서뿐만 아니라 다른 알고리즘에서도 사용될 수 있습니다 우리가 정말 유용하다고 발견한 분야는 바로 대량의 메시지를 서버로 전송하는 것이었습니다 Swift 알고리즘 패키지에는 값을 나누는 일련의 알고리즘이 있는데요 Swift Async Algorithms 패키지에서도 이들을 제공합니다 다양한 시계 및 지속 기간과 상호 운용하는 버전들도 추가되었음은 물론이고요 특정 청킹 알고리즘들을 통해 카운트, 시간, 콘텐츠에 따라 통제가 가능합니다 만약 여기서 오류가 발생하면 다시 던져지기 때문에 오류와 관해서는 안전한 코드립니다 우리는 메시지 청크가 특정 경과 시간마다 직렬화되어 전송될 수 있도록 "chunked(by:)" API를 사용했습니다 이 방식으로 클라이언트가 보낸 효율적인 패키지를 받았죠 대량 메시지를 50밀리초마다 입력할 때도 이 API를 사용할 수 있었습니다 누군가 신나서 너무나 빠르게 입력할 때도 서버에 전송된 요청이 나뉘어졌죠 컬렉션이나 시퀀스로 작업할 때는 요소를 게으르게 처리하는 게 유용하며 잘 작동합니다 AsyncSequence는 Swift 표준 라이브러리에서 이런 작동 방식과 유사하게 작동하죠 하지만 레이지 알고리즘처럼 종종 컬렉션 세계로 돌아가야 할 때가 있습니다 신규 패키지는 AsyncSequence로 컬렉션을 구축하기 위한 일련의 이니셜라이저를 제공합니다 이들을 통해 유한하다고 알려진 AsyncSequence를 입력하여 딕셔너리, 집합, 배열을 구축할 수 있습니다 컬렉션 이니셜라이저는 바로 메시지 초기화로 변환되고 데이터 타입을 배열로 유지할 수 있게 해줍니다 Swift 동기성 사용을 위해 최신 정보를 사용할 수 있는 특색이 다양했기 때문에 굉장히 도움이 되었습니다 또, 기존 데이터 구조를 유지함으로써 앱의 일부를 점차 타당한 곳으로 마이그레이션할 수 있었습니다 지금까지 Swift Async Algorithm 패키지의 하이라이트 중 극소수만 보여드렸는데요 우리가 오늘 본 것보다 훨씬 더 많은 알고리즘이 있습니다 다중 AsyncSequence를 결합하는 것부터 시간에 따른 제한을 측정하고 값을 나누는 알고리즘까지 굉장히 다양하지만 우리 앱에서만 사용하게 되는 알고리즘들이었습니다 이 패키지에는 이보다 훨씬 많은 것들이 들어 있죠 버퍼링하고 리듀스 알고리즘 조인 알고리즘부터 인젝션 알고리즘까지 더욱 다양합니다 Swift Async Algorithms 패키지는 시간에 따라 처리할 수 있도록 알고리즘 집함을 사용하고 이를 앱에 도움이 될 수 있는 광범위한 고급 기능으로 확대합니다 한 번 써보세요 이 패키지로 여러분들이 무엇을 하려 하실지 기대됩니다 그리고 그런 열정은 공유되죠 이 패키지는 여러분과 함께 개발하는 것입니다 시청해 주셔서 감사합니다 나머지 세션도 즐겨보세요 ♪ ♪
-
-
2:01 - The messaging app
struct Account { var messages: AsyncStream<Message> } actor AccountManager { var primaryAccount: Account var secondaryAccount: Account? } protocol MessagePreview { func displayPreviews(_ manager: AccountManager) async }
-
3:16 - Zip
// upload attachments of videos and previews such that every video has a preview that are created concurrently so that neither blocks each other. for try await (vid, preview) in zip(videos, previews) { try await upload(vid, preview) }
-
5:09 - Merge
// Display previews of messages from either the primary or secondary account for try await message in merge(primaryAccount.messages, secondaryAccount.messages) { displayPreview(message) }
-
6:37 - Suspending Clock
// Sleep until a given deadline let clock = SuspendingClock() var deadline = clock.now + .seconds(3) try await clock.sleep(until: deadline)
-
6:56 - Suspending Clock vs. Continuous Clock
let clock = SuspendingClock() let elapsed = await clock.measure { await someLongRunningWork() } //Elapsed time reads 00:05.40 let clock = ContinuousClock() let elapsed = await clock.measure { await someLongRunningWork() } //Elapsed time reads 00:19.54
-
8:34 - Control searching messages
// Control searching messages class SearchController { let searchResults = AsyncChannel<SearchResult>() func search<SearchValues: AsyncSequence>(_ searchValues: SearchValues) where SearchValues.Element == String }
-
9:16 - Debounce
let queries = searchValues .debounce(for: .milliseconds(300)) for await query in queries { let results = try await performSearch(query) await channel.send(results) }
-
10:21 - Chunked by
let batches = outboundMessages.chunked( by: .repeating(every: .milliseconds(500)) ) let encoder = JSONEncoder() for await batch in batches { let data = try encoder.encode(batch) try await postToServer(data) }
-
11:22 - Conversions in initializers
// Create a message with awaiting attachments to be encoded init<Attachments: AsyncSequence>(_ attachments: Attachments) async rethrows { self.attachments = try await Array(attachments) }
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.