[iOS/Swift] URL Session

임주희·2022년 10월 8일
0

URL Session

  • 특정한 url을 이용하여 데이터를 다운로드하고 업로드하기 위한 API
  • 앱에서 서버와 통신하기 위한 API


URL Session Configuration

URL 세션에 대한 동작 및 정책을 정의하는 구성 개체

  • URL Session 인스턴스 생성
  • URL Session 개체를 사용하여 데이터를 업로드, 다운로드할 때 사용할 동작 및 정책을 정의
  • 타임아웃 시간 값, 캐싱 정책등을 설정


URL Session

관련된 네트워크 데이터 전송 작업 그룹을 조정하는 개체

URL Session 유형

  • 공유 세션 (Shared Session)
    URLSession.Shared()
    - 기본 요청하기 위한 세션
    - 싱글톤으로 사용
    - 맞춤 설정은 불가하지만 쉽게 만들어 사용 가능

  • 기본 세션 (Default Session)
    URLSession(configuration: .default)
    - 공유 세션과 유사하게 작동하지만, 직접 원하는 설정을 할 수 있음
    - 순차적으로 데이터를 처리하기 위한 Delegate 지정 가능
    - 캐시와 쿠키, 사용자 인증 정보 등을 디스크에 저장

  • 임시 세션 (Ephemeral Session)
    URLSession(configuration: .ephemeral)
    - 공유 세션과 유사하지만 캐시, 쿠키, 사용자 인증 정보(자격 증명)등을 디스크에 저장하지 않음
    - 메모리에 올려 세션을 연결하고 세션 만료시 데이터가 사라짐.

  • 백그라운드 세션 (Background Session)
    URLSession(configuration: .background)
    - 앱이 실행되지 않는 동안 백그라운드에서 컨텐츠 업로드 및 다운로드 수행


URL Session Task

  • URLSessionDataTask
    • 데이터 객체를 사용하여 데이트를 요청하고 응답 받음
    • 주로 짧고 빈번하게 요청할 때 사용
  • URLSessionUploadTask
    • DataTask와 유사
    • 데이터 객체 또는 파일 형태의 데이터를 업로드하는 작업을 수행
    • 앱이 실행되지 않았을때 백그라운드 업로드를 지원
  • URLSessionDownloadTask
    • 데이터를 다운로드 받아서 파일 형태로 저장하는 작업을 수행
    • 앱이 실행중이지 않은 때에는 백그라운드 다운로드 및 업로드 를 지원
  • URLSessionStreamTask
    • TCP/IP에 연결을 생성할 때 사용
  • URLSessionWebSocketTask
    • 웹소켓 프로토콜 표준을 통해 통신
    • TCP 및 TLS를 통해 메시지를 교환



URL Session을 사용하여 네트워크 통신을 해보자.

GET

  1. 기본적인 GET 통신

    [GET] https://reqres.in/api/users/2

// URL 생성
guard let url: URL = URL(string: "https://reqres.in/api/users/2") else {
    debugPrint("URL is not correct")
    return
}

// URLRequest 설정
var request: URLRequest = URLRequest(url: url)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

// URLSession 생성 (기본 세션)
let session: URLSession = URLSession(configuration: .default)

// dataTask
session.dataTask(with: request) { (data, response, error) in
    let successRange: Range = (200..<300)
    
    // 통신 성공
    guard let data: Data = data,
            error == nil
    else { return }
    
    if let response: HTTPURLResponse = response as? HTTPURLResponse{
        debugPrint("status code: \(response.statusCode)")
        
        // 요청 성공 (StatusCode가 200번대)
        if successRange.contains(response.statusCode){
            
            // decode
            guard let userInfo: UserResponse = try? JSONDecoder().decode(UserResponse.self, from: data) else { return }
            debugPrint(userInfo)
            
        } else { //요청 실패 (Status code가 200대 아님)
            guard let errorMesaage: ErrorMessage = try? JSONDecoder().decode(ErrorMessage.self, from: data) else { return }
            debugPrint("ErrorMessage", errorMesaage)
        }
    }
    
}.resume()

  1. Query parameters가 포함된 GET 통신

    [GET] https://reqres.in/api/users?page=2

// URLComponents 생성
guard var urlComponents: URLComponents = URLComponents(string: "https://reqres.in/api/users") else {
    debugPrint("cannot create URLComponents")
    return
}

// query parameters 만들기
var queryItems: [URLQueryItem] = []
queryItems.append(URLQueryItem(name: "page", value: "2"))
urlComponents.queryItems = queryItems

// Url 생성 (path query가 포함된 url)
guard let url: URL = urlComponents.url else {
    debugPrint("Failed to created URL from components.")
    return
}
print("url : \(url)") //https://reqres.in/api/users?page=2


// URLRequest 설정
var request: URLRequest = URLRequest(url: url)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

// URLSession 생성 (기본 세션)
let session: URLSession = URLSession(configuration: .default)

// dataTask
session.dataTask(with: request) { (data, response, error) in
    let successRange: Range = (200..<300)
    
    // 통신 성공
    guard let data: Data = data,
          error == nil
    else { return }
    
    if let response: HTTPURLResponse = response as? HTTPURLResponse{
        debugPrint("status code: \(response.statusCode)")
        
        // 요청 성공 (StatusCode가 200번대)
        if successRange.contains(response.statusCode){
            
            // decode
            guard let userList: UserListReponse = try? JSONDecoder().decode(UserListReponse.self, from: data) else { return }
            debugPrint(userList)
            
        } else { //요청 실패 (Status code가 200대 아님)
            guard let errorMesaage: ErrorMessage = try? JSONDecoder().decode(ErrorMessage.self, from: data) else { return }
            debugPrint("ErrorMessage", errorMesaage)
        }
    }
    
}.resume()

POST

url: https://reqres.in/api/login
request body :
{ "email": "eve.holt@reqres.in",
"password": "cityslicka" }

// URL 생성
guard let url: URL = URL(string: "https://reqres.in/api/login") else {
    debugPrint("URL is not correct")
    return
}

// parameters 생성 (서버로 보낼 정보)
let parameters: [String : Any] = ["email": "eve.holt@reqres.in",
                                  "password": "cityslicka"]

// paramters를 JSON으로 encode
guard let jsonData = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
    return
}

// URLRequest 설정
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type") // the request is JSON
request.addValue("application/json", forHTTPHeaderField: "Accept") // the response expected to be in JSON format
request.httpBody = jsonData //requestBody 넣기


// URLSession 생성 (기본 세션)
let session: URLSession = URLSession(configuration: .default)

// dataTask
session.dataTask(with: url) { data, response, error in
    let successRange: Range = (200..<300)
    
    // 통신 성공
    guard let data: Data = data,
          error == nil
    else { return }
    
    if let response: HTTPURLResponse = response as? HTTPURLResponse {
        debugPrint("status code: \(response.statusCode)")
        
        // 요청 성공 (StatusCode 200번대)
        if successRange.contains(response.statusCode){
            
            // decode
            guard let loginReponse: LoginResponse = try? JSONDecoder().decode(LoginResponse.self, from: data) else { return }
            debugPrint(loginReponse)
            
        } else { //요청 실패 (Status code가 200대 아님)
            guard let errorMesaage: ErrorMessage = try? JSONDecoder().decode(ErrorMessage.self, from: data) else { return }
            debugPrint("ErrorMessage", errorMesaage)
        }
        
    }
}.resume()

#
URL Session Configuration을 사용하여 타임아웃 시간을 설정할 수도 있다.

...

// URLSessionConfiguration 생성
let configuration: URLSessionConfiguration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30 // 타임 아웃 설정

//  URLSession 생성
let session: URLSession = URLSession(configuration: configuration)

...

0개의 댓글