훌이
후리스콜링개발
훌이

블로그 메뉴

  • 왈 (iOS APP)
  • Github
전체 방문자
오늘
어제
  • 전체 (171)
    • ⭐️ 개발 (140)
      • JAVA (4)
      • Web (5)
      • iOS & Swift (94)
      • iOS Concurrency (4)
      • Rx (18)
      • Git (6)
      • WWDC (1)
      • Code Refactor (3)
      • Server (1)
    • ⭐️ Computer Science (22)
      • 운영체제 (10)
      • 네트워크 (5)
      • PS (7)
    • 경제시사상식 (8)
    • 기타 등등 (0)

인기 글

최근 글

06-22 19:37

티스토리

hELLO · Designed By 정상우.
훌이

후리스콜링개발

[iOS] URLSession 사용해서 서버 통신해보기 (feat. 네이버 Movie API)
⭐️ 개발/iOS & Swift

[iOS] URLSession 사용해서 서버 통신해보기 (feat. 네이버 Movie API)

2021. 8. 29. 03:21
728x90
반응형

네이버 Movie API 를 가져와서 서버 통신을 해볼건데
이번에는 Alamofire, Moya가 아닌
Apple에서 자체적으로 제공하는 네트워크 통신 API인 URLSession을 사용해 보려고 한다!

 

 

 

 

https://developers.naver.com/apps/#/register?defaultScope=search

 

애플리케이션 - NAVER Developers

 

developers.naver.com

-> 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

 

URLSession Tutorial: Getting Started

In this URLSession tutorial, you’ll learn how to create HTTP requests as well as implement background downloads that can be both paused and resumed.

www.raywenderlich.com

 

https://developer.apple.com/documentation/foundation/urlsessiontask

 

Apple Developer Documentation

 

developer.apple.com

 

https://k-elon.tistory.com/30

 

[iOS] URLSession, URLSessionDataTask 톺아보기

iOS 내에서 HTTP/HTTPS 를 통해 데이터를 주고받기 위해 API를 제공하는 URLSession과 이 작업을 나타내는 URLSessionDataTask에 대해서 톺아보겠습니다. URLSession URLSession은 HTTP/HTTPS를 통해 콘텐츠(데이..

k-elon.tistory.com


 

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
    '⭐️ 개발/iOS & Swift' 카테고리의 다른 글
    • [iOS] iOS15 tableview section header 간격 문제 해결
    • [iOS] Storyboard 없이 Navigation Controller로 시작하기
    • [iOS] MVVM 패턴 가볍게 톺아보기
    • [iOS] Storyboard 없이 코드로 프로젝트 시작하기!
    훌이
    훌이

    티스토리툴바