HTTP를 이용한 네트워크 통신을 가능하게 해주는 iOS 개발의 기본 API입니다.
iOS를 개발을 할 때 네트워크 통신을 위해서는 보통 Alamofire라는 프레임워크를 많이 사용하시는데 그 Alamofire가 URLSession을 한 단계 추상화해서 만든 것입니다.
이번 포스팅에서는 URLSession의 개요와 활용하는 기본적인 방법을 정리해보겠습니다.
URLSession을 이해하기 위해서 알아야할 3 (+ 1)가지 객체가 있습니다. 아래 그림과 표로 설명하도록 하겠습니다.
객체 이름 | 역할 |
---|---|
URLSessionConfiguration | 통신 작업의 설정 값을 가지고 있음. URLSession 객체를 만들 때 인자로 전달함. |
URLSession | 실제 네트워크 통신을 실행하는 객체 |
URLSessionTask | 실행할 네트워크 통신 그 자체 |
URLSessionDelegate | 네트워크 통신의 과정에서 실행해야할 코드를 실행해주는 객체 (필수는 아님) |
위 그림에 표시된 과정을 코드로 간략하게 보여드리면 아래와 같습니다.
//✅ configuration 객체 만들기
let config = URLSessionConfiguration.default
//✅ configuration 객체를 인자로 전달해서 URLSession객체 만들기
let session = URLSession(configuration: config)
//✅ task 만들기
let task = session.dataTask(with: requestURL) { (data, response, error) in
print(response)
}
//✅ task 실행하기
task.resume()
위 코드를 보면 URLSessionTask는 URL과 completionHandler를 받는 것을 볼 수 있습니다. 특히 completionHandler는 서버에서 받은 data와 통신의 성공 여부를 담은 response, 마지막으로 error를 인자로 받는 것을 볼 수 있습니다.
또한 URLSessionTask는 객체를 생성함과 동시에 실행되지 않고 resume이라는 메소드를 통해서 실행해주어야 합니다.
통신 작업의 설정 값을 가진 객체인 URLSessionConfiguration는 총 3가지의 유형을 가지고 있습니다.
이름 | 특징 |
---|---|
default | 기본적인 통신 |
ephemeral | 흔적을 남기지 않는 통신으로 브라우저의 시크릿 모드처럼 캐시나 쿠키를 저장하지 않음. |
backgroud | 앱이 백그라운드에 있을 때 통신할 때 사용 |
URLSessionTask도 3가지 옵션이 있습니다.
이름 | 특징 |
---|---|
URLSessionDataTask | 가장 기본적인 통신 방법으로 데이터를 메모리에 저장해서 처리하는 방법입니다. background session에서는 실행할 수 없습니다. |
URLSessionUploadTask | 파일을 업로드할 때 사용합니다. 업로드할 데이터를 Request Body에 담아서 전송할 수 있습니다. |
URLSessionDownloadTask | 파일을 다운로드에서 기기의 디스크에 저장할 때 사용합니다. |
iOS에서는 URL을 단순히 String 객체로 다루지 않고 URL을 위한 전용 객체가 있습니다.
string을 이용해서 만들거나 기존의 baseURL에 더해 만들 수도 있습니다.
//✅ String으로 URL 객체 만들기
let urlString = "https://itunes.apple.com/search?media=music&entity=song&term=Gdragon"
let url = URL(string: urlString)
//✅ baseURL 사용하는 법 = 상대 경로로 URL 쓰기
let baseURL = URL(string: "https://itunes.apple.com")
let relativeURL = URL(
string: "search?media=music&entity=song&term=Gdragon",
relativeTo: baseURL
)
let urlString = "https://itunes.apple.com/search?media=music&entity=song&term=Gdragon"
let url = URL(string: urlString)
url?.absoluteString //👉 String으로 표현된 전체 경로
// = "https://itunes.apple.com/search?media=music&entity=song&term=Gdragon"
url?.scheme //👉 통신방법
// = "http"
url?.host //👉 호스트
// = "itunes.apple.com"
url?.path //👉 경로
// = "/search"
url?.query //👉 쿼리
// = "media=music&entity=song&term=Gdragon"
url?.baseURL //👉 baseURL
// = nil -> 🚫 일반적인 URL 객체에는 없다.
relativeURL?.baseURL
// = "https://itunes.apple.com" -> 💡 상대 경로로 init한 URL 객체는 가지고 있는 property
위 URL 객체가 String보다 더 네트워크 통신에 특화된 객체이기는 하지만 중간에 쿼리문 등을 추가, 수정, 삭제하거나 할 때는 결국 String을 수정하는 것과 큰 차이가 없습니다. 이런 문제를 해결하기 위해서 URL 객체를 한단계 추상해서 URL의 구성 요소를 하나하나 분리해서 object화 시켜놓은 것이 URLCompenents 객체입니다.
//✅ URL components 객체 만들기
var urlComponents = URLComponents(string: "https://itunes.apple.com/search?")
//✅ 각 쿼리들을 QueryItem 객체로 만들 수 있다.
let mediaQuery = URLQueryItem(name: "media", value: "music")
let entityQuery = URLQueryItem(name: "entity", value: "song")
let termQuery = URLQueryItem(name: "term", value: "지드래곤")
//✅ URLComponents 안에 있는 queryItems 배열에 URLQueryItem객체를 추가할 수 있다.
urlComponents?.queryItems?.append(mediaQuery)
urlComponents?.queryItems?.append(entityQuery)
urlComponents?.queryItems?.append(termQuery)
//✅ URL이 자동으로 조립된다!
urlComponents?.string
// = Optional("https://itunes.apple.com/search?media=music&entity=song&term=%EC%A7%80%EB%93%9C%EB%9E%98%EA%B3%A4")
특히 URL에 한글이 들어가면 인코딩 문제가 발생할 수 있는데 완성된 URL을 보면 인코딩이 자동으로 되어 있는 것을 볼 수 있습니다.