728x90
반응형
네이버 Movie API 를 가져와서 서버 통신을 해볼건데
이번에는 Alamofire, Moya가 아닌
Apple에서 자체적으로 제공하는 네트워크 통신 API인 URLSession을 사용해 보려고 한다!
https://developers.naver.com/apps/#/register?defaultScope=search
-> Naver API를 사용할 건데 clientID랑 clientSecret이 필요하다.
🌀 URLSession 이란?
🌀 URLSession은 HTTP/HTTPS를 통해 콘텐츠 및 데이터를 주고받기 위해 API를 제공하는 클래스
1️⃣ Request
- URL 객체와 직접 통신하는 형태
- URLRequest 객체를 직접 만들어서 옵션을 설정해서 통신하는 형태
2️⃣ Response
- Task의 Completion Handler를 통해서 응답 받는 방식
- URLSessionDelegate의 메소드를 통해서 응답 받는 방식
🌀 URLSession API는 총 3가지 유형의 Session을 제공
🌀 URLSession은 request를 보내고 받는 주요 객체인데 이건 URLSessionConfiguration을 통해서 생성할 수 있다.
- URLsession 개체를 사용하여 데이터를 업로드 및 다운로드할 때 사용할 동작과 정책을 정의한다.
- 또한, configure session 프로퍼티에 timeout 값이나 캐싱 정책, 헤더값 등 기타 정보 유형들을 적어줄 수 있다.
- session을 이니셜라이징해주기 전에 적절하게 작성해줘야 한다.
1️⃣ Default Session (기본 세션)
: 디스크가 포함된 글로벌 캐시, 자격 증명 및 쿠키 저장소 개체를 사용하는 개체 생성
2️⃣ Ephemeral Session (임시 세션)
: 캐시, 쿠키 또는 credential과 같이 영구 저장소를 사용하지 않는 세션 구성 개체 생성
3️⃣ Background Session (백그라운드 세션)
: HTTP 및 HTTPS 업로드 또는 다운로드를 백그라운드에서 수행할 수 있는 세션 구성 개체를 생성
🌀 URLSession Task
1️⃣ URLSessionDataTask
: 서버에서 메모리로 데이터를 받아오는 작업 수행
2️⃣ URLSessionUploadTask
: 데이터를 파일로 변환 후 업로드하는 작업 수행
3️⃣ URLSessionDownloadTask
: 데이터를 파일로 변환 후 다운로드하는 작업 수행
🌀 URLSession 통신 단계
1️⃣ Create a URL
2️⃣ Create a URLSession
3️⃣ Give URLSession a task
4️⃣ Start a task
1️⃣ Model 파일 만들어주자
→ JSON 데이터를 decode해서 원하는 데이터를 가져오고 싶으면 struct나 class 형식의 데이터 모델을 만들어줘야 한다.
그리고 해당 데이터 모델은 반드시! 파싱을 하기 위해서는 Codable 프로토콜(JSON 처리에 사용)을 따라야 한다.
🌀 Decodable : JSON -> 모델
🌀 Encodable : 모델 -> JSON
→ Decodable과 Encodable을 모두 합해서 Codable protocol로 통칭하는 것을 typealias라고 한다.
그러니까 위에는 예시지만, 두 개의 프로토콜을 하나로 합한 것....을 의미
Postman에 필수 query값을 넣어주고, Header로 넣어줘야 하는 clientID, clientSecret 값을 넣어주고
GET 요청을 해주면 JSON 형식으로 데이터가 가져와진다.
이 JSON을 긁어서 퀵타입 (quicktype) 에 넣어주면 알아서 데이터 모델을 만들어줍니다.
import Foundation
// MARK: - MovieModel
struct MovieModel: Codable {
let items: [Movie]
}
// MARK: - Item
struct Movie: Codable {
let title: String
let link: String
let image: String
let subtitle, pubDate, director, actor: String
let userRating: String
}
* 꼭 필요한 부분을 제외하고는 지워줬다.
** 내가 필요한 부분은 영화 제목, 평점, 감독, 배우, 이미지, 개봉일
2️⃣ Service 파일을 들여다보며 정리해보자
→ 위에서 말했던 URLSession 통신 단계를 그대로 따라주면 된다.
import Foundation
struct MovieService {
static let shared = MovieService()
// MARK: - baseURL + apiKey
let urlString = "https://openapi.naver.com/v1/search/movie.json?query=lego"
let clientID = APIConstant.clientID
let clientSecret = APIConstant.clientSecret
func fetchMovieData(completion: @escaping (Result<Any, Error>) -> ()) {
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
var requestURL = URLRequest(url: url)
requestURL.addValue(clientID, forHTTPHeaderField: "X-Naver-Client-Id")
requestURL.addValue(clientSecret, forHTTPHeaderField: "X-Naver-Client-Secret")
let dataTask = session.dataTask(with: requestURL) { (data, response, error) in
if error != nil {
print(error!)
return
}
if let safeData = data {
do {
let decodedData = try JSONDecoder().decode(MovieModel.self, from: safeData)
completion(.success(decodedData))
} catch {
print(error.localizedDescription)
}
}
}
dataTask.resume()
}
}
}
1. Create a URL
2. Create a URLSession
: if let ~ 옵셔널 바인딩을 통해서 우리가 만들어 준 URL이 nil값인지 아닌지에 따라 처리를 나눠줄 겁니다.
그 후에 URLSession을 생성해줍니다.
: 우리는 GET HTTP 메소드를 사용할 것이기 때문에 기본적인 default session을 선택해줍니다.
* 통신할 Request 객체에 Header를 추가해줘야 한다!!
: addValue 를 통해서 clientIDd와 cliendSecret값을 Header에 추가해줍니다.
+ default request method는 GET이다. 근데 POST, PUT, DELETE를 할 경우에는 URLRequest를 통해서 처리해주면 된다.
3. Give URLSession a task
: 위에 default session에 3개의 task 중에 URLSessionDataTask를 생성해주는데 위 메소드를 통해서
특정 RequestURL 객체로부터 데이터를 얻어올 수 있다.
: data task가 완료되었을 때 실행 될 completionHandler (data, response, error) 를 작성해줍니다.
: JSONDecoder는 JSON을 decode해주는 클래스
* decode ( [ data type 작성 ], from: [decode 하고 싶은 Data] )
: data type은 꼭 Decodable 프로토콜을 따라야 한다.
MovieModel은 Codable을 따르기 때문에 적어줄 수 있다.
* do { try ~ } catch { ~ } 이건 뭘까?
: decode를 하다가 error가 발생할 수 있는데 이걸 처리해주는 구문이다.
try 뒷부분에 error가 발생할 수 있는 코드를 작성해주고 do로 감싸주고 catch를 통해서 error를 잡아준다.
: try = 한 번 시도해 본다는 것.. error가 나도 한 번 시도를 해보겠다는 뜻이다.
4. Start a task
3️⃣ VC의 movieList에 데이터를 연결해주는 코드를 봐봅시다!
var movieList: [Movie] = []
func getMovieData() {
MovieService.shared.fetchMovieData { (response) in
switch response {
case .success(let movieData):
if let decodedData = movieData as? MovieModel {
self.movieList = decodedData.items
DispatchQueue.main.async {
self.mainCV.reloadData()
}
return
}
case .failure(let movieData):
print("fail", movieData)
}
}
}
: [Movie] 타입을 가진 movieList 배열을 하나 만들어주고 decode한 데이터와 매칭시켜줍니다.
⁉️ 오류가 뜨는데요???
→ 왜냐하면 UI 업데이트 부분은 항상 main thread에서 처리가 이뤄져야 하기 때문이다.
따라서, 아래와 같이 고쳐주면 해결된다.
DispatchQueue.main.async {
self.mainCV.reloadData()
}
4️⃣ CollectionViewCell에 하나하나 매칭시켜주자!
// MARK: - UICollectionViewDataSource
extension MainViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return movieList.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainCVC", for: indexPath) as? MainCVC
else { return UICollectionViewCell() }
cell.setData(image: movieList[indexPath.row].image,
rate: movieList[indexPath.row].userRating,
title: movieList[indexPath.row].title,
director: movieList[indexPath.row].director,
writer: movieList[indexPath.row].director,
star: movieList[indexPath.row].actor,
date: movieList[indexPath.row].pubDate)
return cell
}
}
https://www.raywenderlich.com/3244963-urlsession-tutorial-getting-started
https://developer.apple.com/documentation/foundation/urlsessiontask
URLSession을 통해서 데이터를 받아오는 방법을 공부해봤고,,
다음에는 Download와 Upload하는 방법도 뽀개보쟈.....!
728x90
반응형
'⭐️ 개발 > iOS & Swift' 카테고리의 다른 글
[iOS] iOS15 tableview section header 간격 문제 해결 (1) | 2021.09.28 |
---|---|
[iOS] Storyboard 없이 Navigation Controller로 시작하기 (2) | 2021.09.12 |
[iOS] MVVM 패턴 가볍게 톺아보기 (1) | 2021.08.26 |
[iOS] Storyboard 없이 코드로 프로젝트 시작하기! (0) | 2021.08.23 |
[iOS] Alamofire 가볍게 톺아보기 (0) | 2021.08.22 |