본문 바로가기

iOS+/Swift

URLSession을 이용한 네트워킹 작업

개요

이 글은 URLSession으로 네트워킹 작업을 수행하는 데 알아야 하는 관련 개념들을 정리한다

 

간단하게 정리해보면 다음과 같다

URLSession을 통해 네트워킹 작업을 수행할 때, URLRequest가 이용된다

URLRequest는 요청에 필요한 정보들을 가진 객체인데, URL이 필요하다

URL은 URLComponents를 통해 관리될 수 있다

 

  • URL, URLComponents, URLRequest
  • URLSession

 

URL과 URLComponents 그리고 URLRequest

URL, URLComponents, URLRequest는 전부 Foundation 프레임워크에 포함되어 있고 네트워킹 작업을 수행하는 데 이용된다

 

URL은 요청에 이용되는 주소를 나타내며, URLComponents를 통해 URL객체를 통해 관리한다

그리고 이를 통해 만들어진 URL을 URLRequest에서 사용한다

URL

URL은 주소 문자열을 표현하고, URL의 구성 요소에 접근할 수 있도록 도와주는 구조체다

URLComponents

URLComponents는 URL의 구성 요소를 분석하거나 생성할 때 사용된다

 

  • URL
  • Scheme : HTTP 또는 HTTPS
  • Host : 요청의 도메인 이름
  • Path : 도메인 뒤에 오는 리소스의 상세 경로
  • URLQueryItem : 쿼리 파라미터를 추가
import Foundation

var components = URLComponents()
components.scheme = "https"
components.host = "www.example.com"
components.path = "/search"
components.queryItems = [
    URLQueryItem(name: "q", value: "swift")
]

if let url = components.url {
    print(url) // "<https://www.example.com/search?q=swift>"
}

URLRequest

URLRequest는 HTTP Request을 표현하며, HTTP 메서드, 헤더, 바디 등을 설정하고 URLSession을 사용하여 네트워크 요청을 보낼 때 활용된다

 

  • URL
  • HTTP Method
  • Header Field
  • Body Data(httpBody)

 

예시

URLComponents를 통해 URL을 수정 후 URLRequest 생성

import Foundation

// URL 생성
let url = URL(string: "<https://www.example.com/path?query=value>")

// URLComponents를 사용하여 URL 수정
var components = URLComponents(url: url!, resolvingAgainstBaseURL: false)
components?.queryItems?.append(URLQueryItem(name: "newQuery", value: "newValue"))

// URLRequest 생성
var request = URLRequest(url: (components?.url)!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

URLRequest의 httpBody에 데이터를 추가

import Foundation

// URLRequest 생성
var request = URLRequest(url: URL(string: "<https://www.example.com/path>")!)
request.httpMethod = "POST"

// 바디 데이터 생성
let bodyData: [String: Any] = ["key1": "value1", "key2": "value2"]

// 바디 데이터를 JSON으로 변환
if let jsonData = try? JSONSerialization.data(withJSONObject: bodyData, options: []) {
    request.httpBody = jsonData
}

// "Content-Type" 헤더를 "application/json"으로 설정
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

 

URLSession

URLSession은 이전에 설명한 URLRequest를 실제로 네트워크 요청을 처리하는 데 사용되는 주요 클래스다

 

기본적인 설정이 갖춰진 URLSession은 URLSession.shared로 사용할 수도 있고, URLSessionConfiguration을 만들어서 따로 생성할 수도 있다

 

URLSession은 다음과 같이 여러 URLSessionTask를 설정하고 수행시키는 팩토리로 생각할 수 있다

 

https://www.coursera.org/learn/working-with-data-in-ios

 

URLSessionTask

URLSessionTask는 URLSession 객체가 수행하는 작업을 나타내는 추상 클래스다(이 클래스 자체는 직접 사용되지 않으며, 대신 이 클래스의 세 가지 구체적인 하위 클래스가 사용된다)

 

  • URLSessionDataTask : GET 요청, 데이터를 메모리에 직접 로드.
  • URLSessionUploadTask : POST 또는 PUT 요청.
  • URLSessionDownloadTask : 주로 큰 파일을 백그라운드에서 다운로드할 때 사용.

URL, URLRequest 등을 인자로 사용하여 Data(Swift에서 사용되는 바이너리 데이터타입)를 얻는다

URLSessionDataTask

기존에는 Callback 방식으로 비동기 작업을 수행했으나, Swift Concurrency 형식의 코드를 작성할 수도 있다

 

아래 예시들은 각 방식을 사용해서 URLSessionTask를 수행하여 Data를 얻는 예시다

 

 

URLSession.shared.dataTask(with:completionHandler:)

 

func fetch(url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        completion(data, response, error)
    }
    task.resume()
}

if let url = URL(string: "<https://jsonplaceholder.typicode.com/todos/>") {
    fetch(url: url) { data, response, error in
        if let error = error {
            print("Failed to fetch data: \\(error)")
        } else if let data = data {
            print("Data received, length: \\(data.count) bytes")
        }
    }
}

 

URLSession.shared.data(from:)

(Data, URLResponse)가 메서드의 반환 값이다!

 

func fetch(url: URL) async throws -> (Data, URLResponse) {
    let (data, response) = try await URLSession.shared.data(from: url)
    return (data, response)
}

Task {
    do {
        let url = URL(string: "<https://jsonplaceholder.typicode.com/todos/>")!
        let (data, _) = try await fetch(url: url)
        print("Data received, length: \\(data.count) bytes")
    } catch {
        print("Failed to fetch data: \\(error)")
    }
}

 

URLSessionConfiguration

대부분의 상황에 잘 동작하는 URLSession.shared 말고,

세션의 동작을 더 세밀하게 제어하기 위해 URLSession 객체를 생성할 때, URLSessionConfiguration 객체를 사용하여 세션의 동작을 구성할 수 있다

 

let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration)

 

  • .default  : 기본 세션 구성. 디스크에 데이터를 캐싱.
  • .ephemeral : 임시 세션 구성. 디스크에 어떤 데이터도 저장하지 않음.
  • .background : 백그라운드 세션 구성. 앱이 실행되지 않는 동안에도 데이터 전송 지속 가능.

 

마무리

URLSession을 통해 서버로 요청을 보내기 위해, URL과 URLRequest 등을 인자로 전달한다

이때 이전부터 사용되던 Callback 방식과 Swift concurrency를 이용한 방식으로 요청을 수행하는 방법을 정리했다

 

이렇게 얻은 결과 데이터인 Data를 알맞은 형태로 JSON Deserialization를 수행하여, 앱에서 사용할 수 있는 모델로 변환이 필요하다

이 과정에 대해선 추후 Codable과 관련된 글을 작성하며 정리할 예정이다

'iOS+ > Swift' 카테고리의 다른 글

Swift Concurrency  (0) 2025.01.26
Codable Protocol  (0) 2025.01.15
ARC(Automatic Reference Counting)  (0) 2025.01.05
Transferable  (0) 2024.09.08
Swift 명령어와 Swift Package  (0) 2024.06.16