ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Apple Dev Reference] NSURLSession에 대해서
    앱등이에게 살충제를 뿌린다./Apple Dev Reference 2016. 3. 27. 16:02

    Apple Developer 문서를 번역만 하였습니다.

    어리둥절 주의, 오역 주의, 혈압 주의. - 태클은 환영+무한감사입니다.


    Using NSURLSession

    NSURLSession클래스와 이에 관련된 클래스는 HTTP를 통해 컨텐츠를 다운로드하는 API들을 제공합니다. 이 API는 많은 델리게이트 메소드를 제공하는데, 이 메소드들이 권한 인증도 제공하고 앱이 Suspend상태이거나 Not Running일 때 백그라운드 다운로드까지 할 수있게 해주고 있습니다.


    NSURLSession API를 사용하기 위해서 앱에서는 여러 개의 세션을 만들어 주어야 합니다. 각 세션들은 데이터 전송에 관련된 작업을 나눠서 하게 됩니다. 예를 들어, 웹 브라우저에 뭔가를 쓰고 있다면 앱에서는 브라우저의 창(탭)마다 한 개의 세션을 생성해야 합니다. 앱은 각 세션에 여러 개의 작업을 추가하게 되고 각 작업은 특정 URL에 대한 요청을 나타내는 것이겠죠.(그 URL이 다른 HTTP Redirect를 반환할 지라도말입니다.)


    대부분의 네트워킹 API와 마찬가지로, NSURLSession API도 비동기적입니다. 만약 여러분이 시스템에서 제공하는 디폴트 델리게이트를 사용하신다면, HTTP요청이 끝날 때(성공적으로던 실패해서 error를 리턴하던) 앱에 수신한 데이터를 리턴해주기 위한 completion block을 작성하셔야 합니다. 


     Note : Completion callbacks are primarily intended as an alternative to using a custom delegate. If you create a task using a method that takes a completion callback, the delegate methods for response and data delivery are not called.


    NSURLSession API는 상태(status)와 진행상태(progress)를 나타내는 프로퍼티를 제공하고 델리게이트를 통해서 이 정보를 전달하기도 합니다. 이를 통해 작업을 취소, 재시작, 중지할 수 있고 중지되거나 취소되거나 실패한 작업에 대해서 재시작을 할 수도 있게 해줍니다.



    Understanding URL Session Concepts

    세션의 작업은 3가지에 따라 다른 행동을 하게 됩니다. 3가지는 세션의 타입(Configuration객체에 의해서 결정됨), 작업의 타입 그리고 작업이 생성될 때 앱이 Foreground에 있었는가 여부 입니다. 


    Types of Sessions

    NSURLSession API에서는 3종류 타입의 세션을 제공합니다. Configuration객체에 의해서 결정이 됩니다.

    • Default Session : URL을 다운로드하는 다른 Foundation메소드들과 비슷하게 동작합니다. Disk-based캐시를 사용하고 사용자의 키체인에 Credential정보를 저장합니다.
    • Ephemeral Session : 디스크에 어떤 데이터도 저장하지 않고, 램에 올려져 세션과 연결됩니다. 따라서 앱이 세션을 만료시키면 정보들이 사라지게 됩니다.
    • Background Session : Default Session과 유사합니다. 하나의 프로세스가 모든 데이터 전송을 관리한다는 점을 제외하구요. Background Session은 몇가지 추가 제한적인 사항을 갖고 있는데요, Background Transfer Considerations를 참조하세요.

    Types of Tasks
    NSURLSession 클래스는 세가지 타입의 Task를 제공합니다: data tasks, download tasks and upload tasks
    • Data tasks : NSObject 객체를 사용하여 데이터를 주고 받습니다. Data tasks는 간결하고 주로 앱과 서버간에 상호작용을 합니다. Data tasks는 데이터의 한 Piece를 받으면 이 Piece of data를 앱에 리턴할 수 있고 모든 데이터를 수신하고 한번에 리턴할 수도 있습니다.
    • Download tasks : File형태의 데이터를 이용합니다. 그리고 앱이 Not running상태일 때도 Background 다운로드를 제공합니다.
    • Upload tasks : File형태의 데이터를 전송합니다. 그리고 앱이 Not running상태일 때도 Background 다운로드를 제공합니다.
    Background Transfer Considerations
    NSURLSession클래스는 앱이 Suspended상태일 때 Background 전송을 가능하게 해줍니다. Background 전송은 Configuration객체에서 Background 세션을 사용하도록 지정한 세션에서만 지원이 됩니다.(backgroundSessionConfiguration:메소드에 의해서 리턴되는 Configuration객체)

    Background세션과 관련하여 실제 데이터 전송은 Seperate한 프로세스에 의해서 수행되고 앱의 프로세스를 재시작하는 비용이 높기 때문에, 아래와 같은 제한사항을 가집니다.
    • 세션은 이벤트 전달과 관련한 델리게이트를 반드시 제공해야합니다. (업로드와 다운로드에 있어서 델리게이트는 프로세스의 데이터전송과 같은 작동을 합니다. **이부분은 이해도 안되서 원문 첨부함For uploads and downloads, the delegates behave the same as for in-process transfers)
    • HTTP와 HTTPS프로토콜만 지원됩니다. (커스텀 프로토콜도 안됨)
    • Redirects are always followed.

    • File업로드만 지원됩니다. Data객체나 스트림은 앱이 종료된 뒤에 Fail하게 됩니다.
    • 앱이 Background에 있을 때 Background 전송이 시작(initiated)된다면 Configuration 객체의 discretionary프로퍼티 값은 true로 간주됩니다.

     Note : iOS8 OS X 10.10 이전에서는 Background 세션에서 데이터 전송이 지원되지 않습니다.


    앱이 재실행 될때 앱이 작동하는 방식은 iOS와 OS X에서 미묘한 차이가 있습니다.

    iOS에서 Background 전송이 완료되거나 Credential정보가 필요할 때, 만약 앱이 실행중이 아니라면 iOS에서 자동으로 백그라운드에서 앱을 재실행시킨 뒤 UIApplicationDelegate객체의  application:handleEventsForBackgroundURLSession:completionHandler:메소드를 호출합니다. 이 호출은 앱을 실행하게 만든 세션의 Identifier를 제공합니다. 앱에서는 Completion Handler를 저장하고, 전달받은 Identifier에 해당하는 Configuration객체를 만든 뒤 이 Configuration객체를 가지고 Session객체를 생성해야 합니다. 이 새 Session은 Background에서 진행되고있는 작업들과 자동으로 연결됩니다(reassociated). 나중에 세션이 마지막 Background 다운로드 작업을 마치게 되면 세션델리게이트에 URLSessionDidFinishEventsForBackgroundURLSession: 메시지를 전달합니다. 이 델리게이트 메소드에서는 이전에 저장되어 있던 Completion Handler를 수행하게 되고 이에 따라 OS는 앱을 다시 Suspend시켜도 되겠다고 판단하게 됩니다.


    iOX와 OS X 모두에서, 사용자가 앱을 재실행할 때, 앱에서는 앱의 마지막 실행 순간에 주요한 작업들에 해당하는 Session의 Identifier를 갖고 Background Configuration 객체들을 생성해야 합니다. 이렇게 새로만든 세션들도 위에 설명한 방식과 유사하게 Background에서 진행되고 있던 작업들과 자동으로 연결됩니다.

     Note : 정확히 Identifier하나당 하나의 세션을 생성해야합니다. 


    앱이 Suspended인 상태에서 어떤 작업이 완료되면 완료된 작업과 이 작업에서 다운로드한 파일과 함께 델리게이트의 URLSession:downloadTask:didFinishDownloadingToURL:가 호출됩니다. 


    유사하게 어떤 작업이 Suspended상태에서 Credential을 요구하게 되면 NSURLSession객체는 델리게이트의 URLSession:task:didReceiveChallenge:completionHandler:또는 URLSession:didReceiveChallenge:completionHandler:메소드를 호출하게 됩니다.


    Background세션의 업로드 및 다운로드 작업은 네트워크 오류가 있을 때 자동으로 재시도를 하게됩니다. 이 재시도를 하는데에 네트워크 Reachability를 판단하는 API를 사용하실 필요는 없습니다.


    NSURLSession for Background을 사용하는 예제를 보고싶으신 분들은 Simple Background Transfer를 참고하세요.


    Life Cycle and Delegate Interaction

    여러분이 NSURLSession클래스로 어떤 작업을 하고자 하느냐에 따라, 세션이 어떻게 세션의 델리게이트와 Interact하는지, 어떤 순서로 델리게이트 호출이 이루어 지는지, 서버에서 Redirect를 리턴하면 어떤 일이 일어나는지, 앱에서 실패한 다운로드를 재개하면 어떤 일이 일어나는지등등, 뿐만 아니라 세션의 Life Cycle을 이해하는게 큰 도움이 될 수 있습니다.

    URL Session의 라이프사이클에 대해서는 Life Cycle of a URL Session을 참조하세요.


    NSCopying Behavior

    Session 객체와 Task객체는 NSCopying 프로토콜을 따르고 아래의 내용을 포함합니다.

    • 앱에서 Session or Task 객체를 Copy할 때 여러분은 완전히 같은 객체(the same object)를 리턴받게 됩니다.
    • 앱에서 Configuration 객체를 Copy할 때 여러분은 새로운 사본객체를 얻게 됩니다. 원본객체와 사본객체는 따로 따로 수정도 가능합니다.

    Sample Delegate Class Interface

    아래 코드는 클래스 인터페이스입니다.


    Creating and Configuring a Session

    NSURLSession API는 다양한 Configuration options을 제공합니다.

    • Private storage support for caches, cookies, credentials, and protocols in a way that is specific to a single sesion
    • Authentication, tied to a specific request (task) or group of request(session)
    • File uploads and downloads by URL, which encourages separation of the data (the files' contents) from the metadata(the URL and settings)
    • Configuration of the maximum number of connections per host
    • Per-resource timeouts that are triggered if and entire resource cannot be downloaded in a certain amount of time
    • Minimum and maximum TLS version support
    • Custom proxy dictionaries
    • Control over cookie policies
    • Control over HTTP pipelining behavior
    대부분의 세팅이 각각의 Configuration객체에 담겨있기 때문에 세팅들을 재사용하기가 편합니다. 세션 객체를 초기화할 때 아래를 따르셔야 합니다.
    • A configuration object that governs the behavior of that session and the tasks within it
    • Optionally, a delegate object to process incoming data as it is received and handle other events specific to the session and the tasks within it, such as server authentication, determining whether a resource load request should be converted into a download, and so on
    만약 여러분이 직접 델리게이트를 만들지 않으신다면 NSURLSession객체는 시스템이 제공하는 델리게이트를 사용하게 됩니다. 시스템의 델리게이트를 이용해 쉽게 NSURLSession을 사용할 수가 있게 되는데 이 때는 NSURLSession의 sendAsynchronousRequest:queue:completionHandler:를 사용하게 됩니다.

     Note : 만약 앱이 백그라운드 전송을 사용한다면, 반드시 커스텀 델리게이트를 작성하셔야 합니다. 


    세션객체를 만드셨다면, 새로운 세션을 만들기 전까지 Configuration나 델리게이트를 바꾸실 수 없습니다.

    아래는 Normal, Ephemeral, Background세션을 만드는 예제 코드입니다.


    Background 세션의 Configuration을 제외하고는 Configuration객체를 재사용하여 추가적인 세션을 만들 수 있습니다. (같은 Identifier를 공유하는 두 개의 Background 세션 객체의 작동이 undefined되어 있기 때문입니다.)


    Configuration객체는 언제든 자유롭게 수정할 수 있습니다. 세션을 생성할 때 세션에서는 Configuration객체를 Deep Copy합니다. 그래서 Configuration 객체를 수정하더라도 이미 생성된 세션 객체에는 아무런 영향도 주지 않습니다. 


    Fetching Resources Using System-Provided Delegates

    NSURLSession을 사용하는 가장 빠른 방법은 NSURLConnection의 sendAsynchronousRequest:queue:completionHandler:메소드를 사용하는 겁니다. 이 방법을 사용하려면 여러분은 딱 두 종류의 코드만 작성하시면 됩니다.

    • Configuration객체와 세션 객체를 생성하는 코드
    • 데이터 수신이 완료되었을 때 작동할 Completion Handler
    시스템이 제공하는 델리게이트를 사용하면 하나의 URL 요청당 한 줄의 코드만 있으면 됩니다. 아래는 간단한 예제입니다.


    Fetching Data Using a Custom Delegate

    데이터를 가져오기 위해 커스텀 델리게이트를 사용하신다면, 델리게이트에서는 최소한 아래 메소드는 구현해 주어야 합니다.

    앱에서 URLSession:dataTask:didReceiveData메소드가 종료한 뒤에 데이터를 사용하고자 한다면, 전달받은 데이터를 코드상에서 저장하는 방식을 구현해야합니다.
    예를 들어, 웹 브라우저에서는 데이터를 받으면 이전에 받은 데이터와 합치는 작업을 해야합니다. 이를 위해서 딕셔너리를 사용하여 Task 객체를 NSMutableData객체에 맵핑하는 방법을 선택할 수도 있습니다. 맵핑한 NSMutableData들을 appendData:메소드를 사용해 append해주면 되겠네요.
    아래는 data task를 생성하여 시작하는 예제입니다.


    Downloading Files

    파일 다운로드는 데이터 수신(Retrieving data)과 유사합니다. 앱에서는 아래 델리게이트 메소드를 반드시 구현해야 합니다.

    Background 세션에 다운로드 작업을 등록해두면 앱이 Not running상태일 때에도 다운로드가 계속됩니다. 만약 다운로드 작업을 Standard세션이나 Ephemeral세션에 등록한다면 앱이 재실행될때 다운로드가 계속되게 됩니다.

    앱이 서버와 통신하는동안 사용자가 다운로드를 중지하기를 원하면 앱에서 cancelByProducingResumeData:메소드를 호출함으로써 다운로드 작업을 취소할 수 있습니다. 추후에 앱에서 downloadTaskWithResumeData: 또는 downloadTaskWithResumeData:completionHandler:메소드를 통해 새로운 다운로드 작업을 생성하여 다운로드를 계속 이어나갈 수 있습니다.

    만약 데이터 전송이 실패하면 NSError객체와 함께 델리게이트의 URLSession:task:didCompleteWithError: 메소드가 호출됩니다. 해당 작업이 재시작이 능하다면 해당 객체의 userInfo딕셔너리가 NSURLSessionDownloadTaskResumeData를 키값으로 갖는 데이터를 갖고 있을 텐데요. 이 값을 downloadTaskWithResumeData: 또는 downloadTaskWithResumeData:completionHandler:에 넘겨 새로운 다운로드 작업을 생성하여 재시작할 수 있습니다.

    아래는 어느 정도 큰 파일을 다운로드하는 예제입니다.



    업로드는 생략.

    출처 : https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html

Designed by Tistory.