생성한 URL을 통하여 URLSession 을 통해 데이터를 받아와보자
이전 내용 반드시 보고오기!
API
- 실습을 하기에 앞서 실습하고 싶은 API를 구해야 한다
- 본 글에서는 TMDB 를 사용하여 영화를 검색한 결과를 불러온다
- 사용하고자 하는 API의 호출 구조를 잘 파악하고, Query 내용도 파악해야 한다
URL 생성하기
let API_KEY = "발급받은 API Key 정보 입력"
var movieSearchURL = URLComponents(string: "https://api.themoviedb.org/3/search/movie?")
// 쿼리 아이템 정의
let apiQuery = URLQueryItem(name: "api_key", value: API_KEY)
let languageQuery = URLQueryItem(name: "language", value: "ko-KR")
let searchQuery = URLQueryItem(name: "query", value: "어벤져스")
// URLComponents 에 쿼리 아이템 추가
movieSearchURL?.queryItems?.append(apiQuery)
movieSearchURL?.queryItems?.append(languageQuery)
movieSearchURL?.queryItems?.append(searchQuery)
- 해당 API의 BaseURL은 movieSearchURL 변수에 URLComponents로 저장한다
- 쿼리는 3가지로 구분된다
- apiQuery → API Key
- languageQuery → 언어 설정 ( 한국어로 검색하기 위해 ko-KR 설정 )
- searchQuery → 검색하고자 하는 검색어 입력 ( 예제에서는 어벤져스 )
- QueryItem을 설정했으면 Components에 추가시켜 준다
URL 얻어오기
- URL을 생성했으면 URL 정보를 얻어와야 하는데 Optional로 정의되어 있기 때문에 옵셔널 바인딩을 이용해 그 값을 가져오도록 한다
guard let requestMovieSearchURL = movieSearchURL?.url else { throw NSError() }
- 일반적으로 else { return } 의 형태지만, 예제에서는 함수내의 구현이 아니기 때문에 Error정보를 던져주기 위하여 throw NSError() 를 사용했다
- URL 정보가 nil 이 아니라면 requestMovieSearchURL 상수에 URL 정보가 저장된다
URLSession Configuration 설정
// configuration 설정 -> default
let config = URLSessionConfiguration.default
// session 설정
let session = URLSession(configuration: config)
- URLSession Configuration을 설정하기 위해 config 상수에 default 로 설정
- session 상수에 해당 configuration을 적용한 URLSession 을 할당한다
URLSessionTask 설정
- 해당 예제에서는 Task 목록중, DataTask를 적용
// dataTask 설정
let dataTask = session.dataTask(with: requestMovieSearchURL) { (data, response, error) in
guard error == nil else { return }
guard let statusCode = (response as? HTTPURLResponse)?.statusCode else { return }
let successRange = 200..<300
guard successRange.contains(statusCode) else { return }
guard let resultData = data else { return }
let resultString = String(data: resultData, encoding: .utf8)
print("resultData -->\(resultData)")
print("resultString -->\(resultString)")
}
dataTask.resume()
- dataTask 상수에 session.dataTask를 적용
- dataTask에는 일반적으로 data 정보, response 정보, error정보 가 들어온다
guard error == nil else { return }
- error 가 nil 일경우 즉, error 상황이 아닐경우에만 다음 코드를 실행하고 error일경우 return으로 종료
guard let statusCode = (response as? HTTPURLResponse)?.statusCode else { return }
let successRange = 200..<300
guard successRange.contains(statusCode) else { return }
- HTTP StateCode 중, 200번대의 코드가 정상적인 상황이기 때문에 200번대의 상황일때만 다음 코드 진행
- response 를 HTTPURLResponse 로 다운캐스팅(as?) 하여 statusCode로 상태코드를 확인할 수 있다
- response의 상태코드가 200번대 일때 다음 코드를 진행하고 그렇지 않으면 return으로 종료
→ 해당 코드는 간단한 예시이지만 각 상태코드 마다 적절한 View를 보여주면 좋을것 같다
guard let resultData = data else { return }
let resultString = String(data: resultData, encoding: .utf8)
print("resultData -->\(resultData)")
// resultData -->8482 bytes
print("resultString -->\(resultString)")
// 실행 결과가 너무 길기 때문에 직접 확인해보는걸 추천!
- data가 nil인지 아닌지 확인하기 위해 바인딩을 통하여 nil 이 아닌경우 다음 코드를 진행
- resultData 상수에는 data에 대한 길이정보가 출력
- resultString 상수에는 해당 데이터를 utf8로 인코딩하여 그 내용을 보여준다
dataTask.resume()
- 위에서 dataTask를 정의했어도 즉각 실행되진 않는다 resume() 메서드를 사용하면 통신을 시작한다
전체코드
let API_KEY = "발급받은 API Key 정보 입력"
var movieSearchURL = URLComponents(string: "https://api.themoviedb.org/3/search/movie?")
// 쿼리 아이템 정의
let apiQuery = URLQueryItem(name: "api_key", value: API_KEY)
let languageQuery = URLQueryItem(name: "language", value: "ko-KR")
let searchQuery = URLQueryItem(name: "query", value: "어벤져스")
// URLComponents 에 쿼리 아이템 추가
movieSearchURL?.queryItems?.append(apiQuery)
movieSearchURL?.queryItems?.append(languageQuery)
movieSearchURL?.queryItems?.append(searchQuery)
// 옵셔널 바인딩
guard let requestMovieSearchURL = movieSearchURL?.url else { throw NSError() }
// configuration 설정 -> default
let config = URLSessionConfiguration.default
// session 설정
let session = URLSession(configuration: config)
// dataTask 설정
let dataTask = session.dataTask(with: requestMovieSearchURL) { (data, response, error) in
guard error == nil else { return }
guard let statusCode = (response as? HTTPURLResponse)?.statusCode else { return }
let successRange = 200..<300
guard successRange.contains(statusCode) else { return }
guard let resultData = data else { return }
let resultString = String(data: resultData, encoding: .utf8)
print("resultData -->\(resultData)")
print("resultString -->\(resultString)")
}
dataTask.resume()