지금까지는 API 통신을 위해 Alamofire을 이용하여 데이터를 받아왔다. 하지만 Alamofire은 라이브러리이기 때문에 점차 라이브러리를 줄여가기 위해서 apple이 제공하는 URLSession을 사용하여 API와 통신하고 데이터를 처리해주는 방법에 대해 알아보자.
URLSession을 사용하는 순서는 이와 같다.
1. Configuration 결정
2. Session 생성
3. Request에 사용할 url 설정
4. Task 결정 및 작성
URSession을 통해 데이터를 다운로드하거나 업로드 할 때, URLSessionConfiguration으로 세부적인 동작과 정책을 설정할 수 있음.
세션이 생성된 이후에는 Task를 생성하게 되는데, URLSession을 통해 생성되는 개별 요청이 Task임
Task는 데이터 전달 방식 / 구현 목적에 따라 타입 존재
Task를 생성한 이후에는 suspended 상태이기 때문에 resume메서드를 통해 Task를 시작할 수 있음. 따라서 resume을 호출해야 네트워크 통신을 시작할 수 있음.
네트워크 요청에 대한 정보를표현하는 객체로 네트워크 요청을 하기 위해서는 URLSession이 필요함
URL 로드 요청에 대한 응답과 관련된 메타데이터임.
Task에 대한 completion handler 형태로 응답받을 수 있고, Task가 종료된 시점에 한 번만 호출. 서버로부터 전달받은 data와 HTTP Header, 응답에 대한 메타데이터가 들어간 response, 요청 실패했을 때의 error에 대한 값을 전달받을 수 있음.
Task가 실행되는 동안 발생할 수 있는 다양한 상황에 대해 세부적으로 처리를 하고자 할 때 사용.
서버로부터 최초 응답을 받았을 때, 서버로부터 데이터를 받을 때마다, 데이터 전송을 다 받았을 때의 시점 등에 대한 이벤트 처리 가능.
API를 받아와 받은 API Data를 TableView에 보여주기
먼저 componet 변수를 설정해주고, URLComponets를 통해 url을 만들어주자.
class PersonAPIManager {
static func requestPerson(query: String, completion: @escaping (Person?, APIError?) -> Void) {
let scheme = "https"
let host = "api.themoviedb.org"
let path = "/3/search/person"
let language = "ko-KR"
let key = ""
let query = query.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
var component = URLComponents()
component.scheme = scheme
component.host = host
component.path = path
component.queryItems = [
URLQueryItem(name: "api_key", value: key),
URLQueryItem(name: "query", value: query),
URLQueryItem(name: "page", value: "1"),
URLQueryItem(name: "region", value: language)
]
// URLSession.request(endpoint: component.url!, completion: sucess, fail)
URLSession.shared.dataTask(with: component.url!) { data, response, error in
DispatchQueue.main.async {
guard error == nil else {
print("Failed Request")
completion(nil, .failedRequest)
return
}
guard let data = data else {
print("No Data Returned")
completion(nil, .noData)
return
}
guard let response = response as? HTTPURLResponse else {
print("Unable Response")
completion(nil, .invalidResponse)
return
}
guard response.statusCode == 200 else {
print("Fail Response")
completion(nil, .failedRequest)
return
}
do {
let result = try JSONDecoder().decode(Person.self, from: data)
completion(result, nil)
} catch {
print(error)
completion(nil, .invalidData)
}
}
}.resume()
}
}
이후 error 열거형으로 선언해준 뒤, 각 열거형의 case마다 처리를 해주었다.
enum APIError: Error {
case invalidResponse
case noData
case failedRequest
case invalidData
}
이후 quicktype을 통해 생성한 구조체를 새로운 파일에 선언해주면
struct Person: Codable {
let page, totalPages, totalResults: Int
let results: [Result]
enum CodingKeys: String, CodingKey {
case page, results
case totalPages = "total_pages"
case totalResults = "total_results"
}
}
struct Result: Codable {
let knownForDepartment, name: String
enum CodingKeys: String, CodingKey {
case knownForDepartment = "known_for_department"
case name
}
}
URLSession을 통한 API 통신을 할 수 있게 된다.
이를 tableView에 보여주기 위해 작성하면
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView! {
didSet {
tableView.delegate = self
tableView.dataSource = self
}
}
@IBOutlet weak var lottoLabel: UILabel!
var list: Person = Person(page: 0, totalPages: 0, totalResults: 0, results: [])
override func viewDidLoad() {
super.viewDidLoad()
![](https://velog.velcdn.com/images/qudgus1984/post/7ac6318a-23b4-4244-bf44-e973522801ed/image.png)
PersonAPIManager.requestPerson(query: "kim") { person, errer in
guard let person = person else {
return
}
dump(person)
self.list = person
self.tableView.reloadData()
}
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.results.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = list.results[indexPath.row].name
cell.detailTextLabel?.text = list.results[indexPath.row].knownForDepartment
return cell
}
}
이렇게 kim으로 시작하는 데이터를 받아올 수 있다.