
-
Network 프레임워크로 구조화된 동시성 사용하기
Network 프레임워크는 Apple 플랫폼에서 하위 수준 네트워크 접속을 수행하는 가장 좋은 방법이고 iOS, iPadOS 및 macOS 26에서 구조화된 동시성 코드에 가장 적합한 방법입니다. 연결, 데이터 및 프레임 메시지 전송과 수신, 외부 연결 요청 대기 및 서비스 네트워크 검색 방법을 알아보고, 그 과정에서 중요한 모범 사례도 소개합니다.
챕터
리소스
관련 비디오
WWDC25
WWDC18
-
비디오 검색…
안녕하세요, Scott입니다 오늘 보다 쉽게 네트워킹 코드를 작성할 수 있게 해주는 개선 사항을 소개해 드리게 되어 매우 기쁩니다 네트워킹 코드를 한 줄도 작성해 본 적이 없으시다면 제대로 찾아오셨습니다 코드 작성 경험이 있으시면 새 API 소식을 알려드리죠 연결 생성 방법부터 시작합니다 그리고 이 연결로 데이터의 전송 및 수신 방법을 알아보죠
그리고 수신 연결 수신 방법을 알아보겠습니다 마지막으로 네트워크에서 다른 기기를 찾고 연결하는 방법을 다루겠습니다 연결 생성 방법부터 시작해 보죠 네트워크 프레임워크로 앱에서 안전하고 구성 가능하며 현대적인 연결을 생성할 수 있습니다 소켓, 소켓 주소, 기억하기 어려운 ioctls, 블로킹 작업은 더 이상 사용되지 않습니다 네트워크 프레임워크의 Connect by Name은 여러분을 대신해 이름 변환 작업을 수행합니다 해당 이름을 변환하면 Happy Eyeballs라는 이름이 생겨 가장 잘 변환된 주소를 효율적으로 선택하고 동적으로 연결할 수 있습니다
TLS를 통한 보안이 내장되어 있어 사용자의 개인정보를 보호하기 위해 일반적으로 완전히 다른 종류의 API를 사용하는 또 다른 라이브러리를 애플리케이션에 통합할 필요가 없습니다 또한 네트워크 인터페이스 전환 및 프록시도 지원하므로 Wi-Fi Assist 및 다중 경로 프로토콜과 같은 기능은 다른 작업 없이 그대로 사용 가능합니다
QUIC 등의 최신 전송을 지원하며 내장된 프로토콜과 고유한 프로토콜을 혼합해 메시지가 지점 A에서 B로 전달되지 않는 이유를 디버깅하는 대신 비즈니스 로직 및 사용자 경험에 시간을 투자할 수 있습니다 네이티브 앱과 웹 앱을 모두 지원하는 사용자를 위해 네트워크 프레임워크는 소켓에 대한 강력한 지원도 제공해 단일 서버가 다양한 클라이언트 애플리케이션을 처리합니다
네트워크 프레임워크는 처음부터 구성 가능하게 설계되었습니다 네트워크 프레임워크 사용 시 시간 경과에 따라 네트워크 프로토콜이 발전해 성능과 개인정보 보호가 향상되더라도 익숙한 API 세트가 계속해서 제공됩니다 BSD 소켓 API와 함께 TCP를 사용해 네트워킹 코드를 작성한 적이 있으면 QUIC 등의 프로토콜로 전환 시 전면적인 재작성이 필요합니다 네트워크 프레임워크를 사용하면 QUIC으로의 전환도 점심시간을 이용해 간단히 처리할 수 있습니다 iOS, macOS 26에서는 네트워크 프레임워크가 비동기 작업에 대한 Swift의 강력한 지원 및 구조화된 동시성과 통합됩니다 네트워킹 코드는 나머지 Swift 코드와 원활하게 통합돼 앱을 더 쉽게 구축하고 유지 관리할 수 있습니다 네트워킹을 처음 사용하시는 분들을 위해 익숙하지 않을 수 있는 이 예제의 개념을 소개하겠습니다 걱정하지 마세요, 마지막엔 모두 이해하실 겁니다
앱을 작성 중이고 www.example.com의 포트 1029에 있는 서버와 통신하고 싶다고 해 봅시다 제한되지 않은 네트워크에서 TLS를 사용하고 이 연결만 시도하려고 합니다 엔드포인트는 연결하려는 지점입니다 프로토콜 스택은 연결하려는 방식입니다 매개변수는 도달 방법을 세분화하는 데 도움이 됩니다
NetworkConnection 작성을 위해 이들을 결합하죠 실제 상황의 작동 방법을 예제를 통해 확인해 보시죠
원하는 엔드포인트와 프로토콜 스택으로 NetworkConnection 초기화로 연결합니다 이 예제에서 프로토콜 스택이 TLS라고 지정합니다 TCP와 IP는 추론됩니다 무언가를 맞춤화하고 싶을 때만 지정하면 되지만 기본값은 거의 문제가 없습니다
기본값을 수정하려면 선언적 방법으로 계속 수정합니다 예로 이 연결의 IP 조각화를 꺼보겠습니다
TLS 아래의 TCP, IP 프로토콜을 지정해야 합니다 그리고 IP에 설정된 옵션을 맞춤화해 조각화를 끌 수 있습니다
네트워크 사용량 최소화를 위해 저데이터 모드를 활성화하면 연결 동작을 수정해 제한된 네트워크 인터페이스로 이를 방지하려 합니다
자동으로 작성된 기본 매개변수를 더 이상 사용하지 않아 연결에 대한 매개변수를 수정하도록 코드를 업데이트합니다
프로토콜 스택은 유지하되 맞춤형 매개변수를 추가해 특정 연결 시 네트워크 프레임워크가 저데이터 모드가 아닌 네트워크 인터페이스만 사용하게 지정할 수 있습니다 좋아요! SwiftUI를 인기 있게 한 동일한 선언적 스타일을 통해 이제 네트워킹 코드도 UI 코드와 유사한 느낌입니다
네트워크가 항상 사용 가능하다면 좋겠지만 네트워크 상태는 항상 변합니다 NetworkConnection은 소켓과 달리 변화에 대응하죠
연결이 시작되면 프로토콜 핸드쉐이크가 수행되는 동안 연결은 준비 중 상태로 전환됩니다 프로토콜 핸드쉐이크가 완료되면 준비 상태로 전환됩니다 연결되지 않으면 연결은 준비 중에서 대기 중 상태로 전환됩니다
네트워크 프레임워크가 네트워크 상태 변화를 감지하면 원격 엔드포인트로 연결 시도 중 준비 중 상태로 돌아가죠 연결 상태가 준비되면 데이터를 전송, 수신할 수 있죠
연결이 준비 상태가 되면 오류가 발생하거나 연결이 끊어진 경우 오류와 함께 실패됨 상태로 전환돼 발생 상황을 알려줍니다
연결과 연관된 작업을 종료하거나 취소하면 연결은 취소됨 상태로 전환됩니다 이 기능의 가장 좋은 점은 연결 상태를 알고 싶지 않으면 어떠한 연결 상태도 알 필요가 없는 것입니다 send와 receive를 호출할 수 있고 NetworkConnection은 상태가 준비가 될 때까지 기다린 후 작업을 완료합니다 하지만 연결 상태를 알고 싶으면 사용자 인터페이스 업데이트를 위해 연결 상태 변경 시 호출될 핸들러를 설치할 수 있습니다 이제 연결 방법을 알게 되었습니다 그럼 네트워크에서 데이터를 주고받아보겠습니다
send와 receive 모두 비동기 함수이며 아직 연결을 시작하지 않았다면 둘 다 연결을 시작할 것입니다
send는 데이터 개체를 가져오고 네트워크 프레임워크가 데이터를 처리할 때까지 작업을 일시 중단합니다
TLS와 TCP 모두 스트림 프로토콜이므로 데이터를 수신하면 원하는 바이트 수를 지정해야 합니다 이 예에서 읽고 싶은 바이트 수를 정확하게 지정합니다 receive는 콘텐츠와 메타데이터의 튜플을 반환하지만 이 예에서는 콘텐츠만 원한다고 지정합니다
연결에 오류가 발생하면 두 함수 모두 오류가 발생하죠 예를 들어, 에어플레인 모드가 켜져서 네트워크가 끊어지면 관련 오류를 사용해 전송 중단 이유를 설명할 수 있죠 얼마나 많은 바이트의 데이터를 수신하는지 모를 때가 있습니다 이 예에서는 네트워크에서 이미지를 로드하고 있습니다 내 연결에서 수신한 32비트 정수는 수신해야 할 이미지 데이터의 남아 있는 바이트 수를 알려줍니다 이 값으로 이미지를 완성할 때까지 receive를 반복 호출하죠
마지막 예에서 정확한 바이트 수를 지정하는 receive 버전을 사용했습니다 이 예에서 receive 버전으로 수신할 최소 바이트 수와 최대 바이트 수를 지정할 수 있습니다 이러면 네트워크에서 바이트가 들어오는 대로 코드가 이미지를 구문 분석할 수 있어서 모든 것을 위해 기다릴 필요가 없습니다 TLS 같은 바이트 스트림 프로토콜은 유용하지만 전송 및 수신 바이트를 프레임화해 대신 메시지 단위로 작업하려 하죠 작업하려고 합니다 이 예에서는 이미지 콘텐츠 앞의 바이트 스트림에서 32비트 값을 읽어 이미지 크기를 알아내고 길이 정보로 이미지 프레임화해 인접한 이미지와 구분합니다 스트리밍 프로토콜은 메시지 경계를 유지하지 않아서 이렇게 해야 했습니다 개별 send 연산에 전달된 바이트 수가 연결의 반대편에서 receive 연산으로 다시 전달되는 바이트 수와 반드시 일치하지 않는다는 의미입니다 만약 3개의 데이터 청크로 send를 호출하는 경우 다른 쪽은 한 번에 1바이트씩 수신하거나 한꺼번에 수신하거나 중간 형태로 수신할 수 있죠 그러면 강력하고 네트워크화된 애플리케이션 작성이 복잡해지죠
네트워크 프레임워크가 도움이 됩니다 iOS 및 macOS 26의 새 기능은 내장된 유형, 길이, 값 또는 TLV 프레이머로, 한쪽 끝에서 전송하는 메시지를 다른 쪽에서 정확히 수신하도록 메시지를 프레임화하는 프레이머입니다
TLV는 유형을 인코딩하는 간단한 메시지 프로토콜이며 메시지에 포함된 데이터를 설명하기 위해 사용하고 메시지의 데이터 크기를 나타내는 길이 정보도 포함되죠 다음은 메시지의 실제 내용입니다 일반 네트워크 프로토콜은 TLV를 사용하므로 서버가 이미 사용하는 형식일 수도 있습니다 한 번 시도해 봅시다 이 예에서는 게임 메시지 유형을 전송하고 수신합니다 GameMessage는 열거형이고 메시지 유형으로 사용할 것입니다 메시지의 내용은 게임 캐릭터 또는 게임 동작입니다 TLV 추가는 프로토콜 스택에 추가하기만큼 간단합니다 TLV가 메시지를 저 대신 프레임화하기 때문에 전송 및 수신 인터페이스가 약간 다릅니다
JSONEncoder를 사용해 GameCharacter 구조체 인코딩 후 전송합니다 인코딩된 데이터와 함께 메시지 유형을 지정하고 있다는 점에 유의하세요 이제 TLV를 통한 메시지 수신 방법을 살펴보겠습니다
이전 예와 달리 바이트 스트림 프로토콜을 사용하는 경우 TLV면 수신할 바이트 수를 지정할 필요가 없습니다 메시지를 구문 분석하기 때문이죠 수신한 메시지 유형을 알고 싶은 이유로 메시지와 연관된 콘텐츠와 메타데이터의 튜플을 수신했습니다 TLV의 메타데이터에 유형이 포함됩니다 수신한 콘텐츠 유형을 판별하기 위해 유형을 사용하고 해당 정보로 데이터를 디코딩 후 수신 내용을 인쇄합니다 특히 제어할 수 없는 기존 서버 및 프로토콜을 상호 운용할 때 정말 강력하죠 이제 큰 어려움 없이 바이트를 프레임화했으며 메시지를 전송하고 수신할 수 있습니다 바이트 스트림 프로토콜의 직접 사용보다 훨씬 개선됐죠
하지만 내 개체를 직접 전송할 수 있으면 어떨까요? iOS 및 macOS 26의 새 기능은 코딩 가능한 유형의 전송 및 수신에 대한 지원이며 일부 보일러플레이트 코드를 간소화하는 데 도움을 줍니다
캐릭터를 축소하고 구조체를 GameMessage 열거형으로 이동할 수 있습니다 코더는 내 프로토콜 스택에 추가할 수 있는 프로토콜이며 메시지를 프레임화하고 직접 직렬화하거나 직렬화 해제하지 않아도 코딩 가능한 유형을 전송하고 수신할 수 있도록 합니다 이 코드에서는 게임 메시지를 주고받고 있습니다 그래서 전송하고 수신할 유형과 코더의 데이터 형식화 방식을 사용해 코더를 초기화할 예정입니다 네트워크 프레임워크는 기본 JSON 및 속성 목록 형식을 지원하죠 이 예에서는 JSON을 선택합니다 직접 인코딩을 하지 않아도 게임 메시지를 보낼 수 있죠
연결에서 receive를 호출하면 데이터 개체에서 GameMessage 개체로 이동하기 위한 중간 디코딩 과정 없이 바로 게임 메시지를 반환합니다 추가 작업 없이도 게임 메시지를 주고받을 수 있죠 대량의 맞춤형 네트워킹 코드를 사용해 복잡하게 만들지 않고 앱의 비즈니스 로직과 사용자 집중할 수 있습니다
이제 엔드포인트로 연결하고 연결 시 데이터를 주고받는 방법을 알게 되었습니다 TCP, TLS 등의 바이트 스트림 프로토콜과 프레이밍 프로토콜을 프로토콜 스택에 추가하는 방법을 알아봤습니다 이제 바이트 스트림 대신 메시지로 작업할 수 있죠 그런데 수신 연결을 기다리는 애플리케이션은 어떨까요?
수신 연결은 NetworkListener로 처리되죠 NetworkConnection처럼 프로토콜 스택을 선언해 시작하죠 연결과 달리 리스너에는 send 또는 receive 메서드가 있죠
리스너가 새 연결을 수신한 다음 호출자에게 연결하기 때문이죠 NetworkListener에는 run 메서드가 있어서 제공된 핸들러에게 전달합니다 사용 방법을 알아보죠 NetworkListener를 선언적으로 프로토콜 스택을 지정해 생성합니다 이 예에서 수신 연결은 TLS로 암호화된 GameMessage 개체를 주고받을 수 있습니다
NetworkListener에서 run을 호출하면 전달한 핸들러로 수신 연결이 전달을 시작합니다
NetworkListener는 새로 연결될 때마다 새 하위 작업을 시작합니다 그래서 클로저에서 비동기 작업을 수행할 수 있습니다 리스너를 방해할까 걱정하지 않고 새 수신 연결을 계속 전달하는 데 지장이 없도록 말이죠 새로 연결되면 NetworkConnection에서 메시지 속성을 사용하여 클라이언트로부터 수신하는 메시지를 처리합니다 이미 있었고 새 연결을 수신하도록 코딩한 엔드포인트에 대한 NetworkConnection을 만들었죠 NetworkConnection을 이제 생성하려고 합니다 이전에는 몰랐던 엔드포인트죠 NetworkBrowser로 엔드포인트를 발견하여 연결을 생성할 때 사용할 수 있습니다 올해 iOS 26의 새로운 소식은 Wi-Fi Aware입니다 교차 플랫폼 피어투피어 네트워킹 기술을 사용하면 호환 가능한 여러 기기를 발견하고 연결할 수 있죠 DeviceDiscoveryUI 프레임워크로 Wi-Fi Aware로 근처 기기를 찾고 페어링할 수 있죠 또는 Bonjour 광고 서비스를 찾아볼 수 있습니다 Wi-Fi Aware에 대해 자세히 알아보려면 ‘Wi-Fi Aware로 기기 연결성 강화하기’를 시청해 보세요 근처의 Wi-Fi Aware 또는 Bonjour를 사용해 기기를 찾으려는 경우 NetworkBrowser를 사용하세요 NetworkBrowser는 탐색 설명자를 사용해 설명하고 NetworkConnection처럼 매개변수를 사용해 찾는 방법을 설명합니다 NetworkConnection NetworkListener와 달리 NetworkBrowser는 프로토콜 스택을 사용하지 않죠 NetworkBrowser는 연결하는 데 사용할 수 있는 반환만 수행하기 때문이죠
NetworkBrowser를 생성해 Wi-Fi Aware 서비스인 Tic-Tac-Toe로 근처 기기를 검색합니다 브라우저에서 실행을 호출하면 시작되고 실행을 위해 전달한 핸들러에 엔드포인트 세트를 제공합니다
앱에서는 선호하는 엔드포인트가 없기 때문에 브라우저에서 반환되는 첫 엔드포인트를 선택합니다 엔드포인트로 .finish를 반환하면 브라우저가 실행을 중지합니다 그리고 run에서 엔드포인트가 반환됩니다 그런 다음 엔드포인트로 NetworkConnection을 초기화한 방식과 동일한 방식으로 해당 엔드포인트로 Network Connection을 초기화하죠 이 엔드포인트의 이점은 찾기를 수행하는 브라우저입니다 미리 알고 있을 필요가 없습니다
이러한 모든 새 프로토콜로 앱에서 사용할 프로토콜의 선택 방법이 궁금할 수 있죠 좋은 질문입니다 답은 여러분이 생각하는 것만큼 복잡하지 않습니다 서버 또는 제어할 수 없는 다른 기기와 통신하는 경우 사용할 프로토콜이 이미 선택되었습니다 IPP over TCP 등으로 프린터와 통신할 수 있습니다 다른 기기에서 본인의 앱과 통신하는 경우 TLS나 QUIC보다 Coder 사용을 권합니다
HTTP 네트워킹 수행 중이고 URLSession을 사용 중이면 코드를 변경할 필요가 없습니다 그리고 네트워크 프레임워크 C API를 사용 중이거나 Swift에서 작업 중이고 완료 핸들러 사용을 선호하면 코드를 변경할 필요가 없습니다 우선적으로 이름 기반 연결 지원, 결합성, 이동성 및 내장 보안이 제공됩니다 URLSession을 사용할 때마다 모든 형식의 네트워크 프레임워크에서 지원됩니다
간단히 요약해 보겠습니다 iOS 및 macOS 26의 새 기능은 NetworkConnection NetworkListener NetworkBrowser입니다 NetworkConnection 사용에 대해 알아보았죠 TLV 프레이밍 및 전송 지원으로 Coder 프로토콜을 사용하여 코딩 가능한 유형을 수신합니다 NetworkListener는 들어오는 연결을 수신합니다 NetworkBrowser는 네트워크의 엔드포인트를 검색하죠 이들 덕분에 네트워크 앱이 어느 때보다 쉬워졌습니다 자, 새 API는 처음부터 Swift의 동시성을 기반으로 구축되었습니다 SwiftUI에서 사용자 인터페이스와 유사하게 선언적으로 생성되죠 작업에서 실행되고 실행 중인 작업이 취소되면 자동으로 취소됩니다 새 API로 Swift의 구조화된 동시성 이점을 누려 코드를 더 깔끔하게 만들고 많은 보일러플레이트를 제거하죠 이 모두 동일한 성능과 유연성을 갖추고 있습니다 네트워크 프레임워크는 앱에서 사용하는 기능을 제공하죠 시청해 주셔서 감사합니다
-
-
4:04 - Make a connection with TLS
// Make a connection import Network let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLS() }
-
4:41 - Make a connection with TLS and IP options
// Make a connection import Network let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029) { TLS { TCP { IP() .fragmentationEnabled(false) } } }
-
5:07 - Make a connection with customized parameters
// Make a connection import Network let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029), using: .parameters { TLS { TCP { IP() .fragmentationEnabled(false) } } } .constrainedPathsProhibited(true))
-
7:30 - Send and receive on a connection
// Send and receive on a connection import Network public func sendAndReceiveWithTLS() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLS() } let outgoingData = Data("Hello, world!".utf8) try await connection.send(outgoingData) let incomingData = try await connection.receive(exactly: 98).content print("Received data: \(incomingData)") }
-
8:29 - Send and receive on a connection
// Send and receive on a connection import Network public func sendAndReceiveWithTLS() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLS() } let outgoingData = Data("Hello, world!".utf8) try await connection.send(outgoingData) let remaining32 = try await connection.receive(as: UInt32.self).content guard var remaining = Int(exactly: remaining32) else { /* ... throw an error ... */ } while remaining > 0 { let imageChunk = try await connection.receive(atLeast: 1, atMost: remaining).content remaining -= imageChunk.count // Parse the next portion of the image before continuing } }
-
11:06 - Tic-Tac-Toe game messages
// TicTacToe game messages import Network enum GameMessage: Int { case selectedCharacter = 0 case move = 1 } struct GameCharacter: Codable { let character: String } struct GameMove: Codable { let row: Int let column: Int }
-
11:24 - Send TicTacToe game messages with TLV
// Send TicTacToe game messages with TLV import Network public func sendWithTLV() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLV { TLS() } } let characterData = try JSONEncoder().encode(GameCharacter(character: "🐨")) try await connection.send(characterData, type: GameMessage.selectedCharacter.rawValue) }
-
11:53 - Receive TicTacToe game messages with TLV
import Network public func receiveWithTLV() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { TLV { TLS() } } let (incomingData, metadata) = try await connection.receive() switch GameMessage(rawValue: metadata.type) { case .selectedCharacter: let character = try JSONDecoder().decode(GameCharacter.self, from: incomingData) print("Character selected: \(character)") case .move: let move = try JSONDecoder().decode(GameMove.self, from: incomingData) print("Move: \(move)") case .none: print("Unknown message") } }
-
12:50 - Tic-Tac-Toe game messages with Coder
// TicTacToe game messages with Coder import Network enum GameMessage: Codable { case selectedCharacter(String) case move(row: Int, column: Int) }
-
13:13 - Send TicTacToe game messages with Coder
// Send TicTacToe game messages with Coder import Network public func sendWithCoder() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { Coder(GameMessage.self, using: .json) { TLS() } } let selectedCharacter: GameMessage = .selectedCharacter("🐨") try await connection.send(selectedCharacter) }
-
13:53 - Receive TicTacToe game messages with Coder
// Receive TicTacToe game messages with Coder import Network public func receiveWithCoder() async throws { let connection = NetworkConnection(to: .hostPort(host: "www.example.com", port: 1029)) { Coder(GameMessage.self, using: .json) { TLS() } } let gameMessage = try await connection.receive().content switch gameMessage { case .selectedCharacter(let character): print("Character selected: \(character)") case .move(let row, let column): print("Move: (\(row), \(column))") } }
-
15:16 - Listen for incoming connections with NetworkListener
// Listen for incoming connections with NetworkListener import Network public func listenForIncomingConnections() async throws { try await NetworkListener { Coder(GameMessage.self, using: .json) { TLS() } }.run { connection in for try await (gameMessage, _) in connection.messages { // Handle the GameMessage } } }
-
17:39 - Browse for nearby paired Wi-Fi Aware devices
// Browse for nearby paired Wi-Fi Aware devices import Network import WiFiAware public func findNearbyDevice() async throws { let endpoint = try await NetworkBrowser(for: .wifiAware(.connecting(to: .allPairedDevices, from: .ticTacToeService))).run { endpoints in .finish(endpoints.first!) } // Make a connection to the endpoint }
-
-
- 0:00 - 인사말
네트워크 프레임워크에 대한 최신 소식을 알아보세요. 네트워크에서 연결을 생성하고, 데이터를 주고받으며, 들어오는 연결 수신을 대기하고, 엔드포인트를 검색하는 방법을 이해합니다.
- 0:45 - 연결
네트워크 프레임워크는 앱 네트워킹을 간소화합니다. 효율적인 주소 확인을 위해 ‘Connect by Name’ 및 ‘Happy Eyeballs’와 같은 기능을 제공합니다. TLS 보안이 내장되어 있고 QUIC와 같은 최신 전송 방식을 지원합니다. 네트워크 프레임워크를 사용하면 선언형 API를 사용하여 프로토콜 스택을 생성할 수 있습니다. 프레임워크는 네트워크 인터페이스 전환, 프록시, 연결 상태를 자동으로 처리하여 견고하고 반응성이 뛰어난 연결을 보장합니다. NetworkConnection 객체는 ‘준비’, ‘준비 완료’, ‘대기’, ‘실패’ 또는 ‘취소’와 같은 상태 간 전환을 통해 연결 수명 주기를 관리합니다. 선택적으로 이러한 상태를 모니터링하여 인터페이스를 업데이트할 수 있습니다.
- 7:22 - 전송 및 수신
네트워크 프레임워크에서 데이터를 주고받는 것은 필요할 때 연결을 시작하는 비동기 함수입니다. ‘전송’ 기능은 제공된 데이터가 처리될 때까지 작업을 일시 중단합니다. TLS 및 TCP와 같은 스트림 프로토콜을 사용하여 데이터를 수신하면 바이트 수를 지정해야 합니다. ‘전송’ 또는 ‘수신’하는 동안 오류가 발생할 수 있고 관련된 오류는 중단에 대한 설명을 제공합니다. 이미지 로딩과 같이 데이터 크기를 알 수 없는 시나리오에서는 최소 및 최대 바이트 범위를 지정하여 ‘수신’ 기능을 반복적으로 사용할 수 있습니다. 메시지 처리를 간소화하기 위해 프레임워크는 TLV(Type-Length-Value) 프레이머를 도입하여 메시지를 자동으로 인코딩 및 디코딩함으로써 전송된 내용이 수신된 내용과 정확히 일치하도록 보장합니다. iOS 및 macOS 26에서는 이제 Codable 유형을 직접 주고받는 기능이 지원됩니다.
- 14:22 - 연결 요청 받기
NetworkListener를 사용하면 앱에서 수신되는 연결을 허용할 수 있습니다. 프로토콜 스택으로 초기화되고 ‘실행’을 호출하면 수신되는 각 연결에 대한 새로운 하위 작업을 시작하여 비동기 메시지 처리를 위한 처리기에 전달합니다.
- 16:05 - 다른 기기 등록
iOS 26에서 네트워크 프레임워크는 네트워크 연결의 엔드포인트 검색을 지원하는 NetworkBrowser를 도입합니다. NetworkBrowser는 P2P 네트워킹 기술인 Wi-Fi Aware 또는 Bonjour를 사용하여 근처 기기나 서비스를 찾을 수도 있습니다. 탐색 설명자를 사용하여 특정 서비스를 검색하는 NetworkBrowser를 만들 수 있고 엔드포인트가 검색되면 NetworkConnection을 초기화하는 데 사용할 수 있습니다. Swift의 구조화된 동시성을 위해 구축된 이러한 새 API는 네트워크로 연결된 앱을 더 쉽고 깔끔하게 작성할 수 있게 하여 보일러플레이트 코드를 제거하는 동시에 네트워크 프레임워크의 강력함과 유연성을 제공합니다.