안녕하세요! 피피아노입니다 🎵
오늘은 iOS 앱을 만들면서 Open API를 연결하는 방법에 대해서 정리를 해보려고 합니다.
처음 접하면 좀 복잡하기도 하고 저도 헷갈리는 부분들이 있어서 이번 기회에 확실하게 정리해보려고 합니다 :)
그럼 바로 시작할게요!
API 발급 받기
먼저 API를 연결하려면 가장 중요한 API 키를 발급 받겠습니다.
저는 영화진흥위원회에서 영화 순위 API를 가져와서 제 프로젝트에 넣어보겠습니다.
네트워킹
자 그런 다음에 네트워킹을 해줘야 합니다.
1단계 : URL 만들기
먼저 1단계로 URL을 만들어주겠습니다.
func getData() {
guard let url = URL(string: movieURL) else { return }
}
*if let 을 사용해서 만들어도 되지만 guard let ~ else를 사용하면 { }이 없어서 가독성이 좋기 때문에 저는 guard let ~ else를 사용하겠습니다.
2단계 : URLSession 만들기
그 다음 2단계로 URLSession을 만들어주겠습니다.
URLSession을 만들기 전 잠깐 공식 문서를 확인해보겠습니다.
An object that coordinates a group of related, network data transfer tasks.
해석해보면
"관련된 네트워크 데이터 전송 작업 그룹을 조정하는 개체" 라고 합니다.
URLSession을 만들 때는 위와 같은 형식으로 만들면 됩니다.
The URLSession class and related classes provide an API for downloading data from and uploading data to endpoints indicated by URLs. Your app can also use this API to perform background downloads when your app isn’t running or, in iOS, while your app is suspended. You can use the related URLSessionDelegate and URLSessionTaskDelegate to support authentication and receive events like redirection and task completion.
URLsession 클래스와 관련 클래스는 URLsession에서 데이터를 다운로드하고 URLs로 표시된 엔드포인트로 데이터를 업로드하기 위한 API를 제공합니다. 또한 앱이 실행되지 않거나 iOS에서 앱이 일시 중단된 상태에서 이 API를 사용하여 백그라운드 다운로드를 수행할 수 있습니다. 관련 URLsessionDelegate 및 URLsessionTaskDelegate를 사용하여 인증을 지원하고 리디렉션 및 작업 완료와 같은 이벤트를 받을 수 있습니다.
https://developer.apple.com/documentation/foundation/urlsession
func getData() {
guard let url = URL(string: movieURL) else { return }
let session = URLSession(configuration: .default)
}
}
3단계 : URLSession을 인스턴스에게 task주기
네트워킹 3단계는 URLSession을 인스턴스에게 task주기입니다.
https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask
이번에도 공식 문서를 살펴보고 가겠습니다.
Creates a task that retrieves the contents of the specified URL, then calls a handler upon completion.
지정된 URL의 내용을 검색한 다음(create), 완료되면 handelr(클로저)를 호출하는 task를 생성합니다.
func dataTask(
with url: URL,
completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void
) -> URLSessionDataTask
*클로저 앞에 @escaping이 있으면 함수의 작업이 완료된 후에 클로저가 호출됩니다.
completionHandler 부분을 후행 클로저로 작성해주겠습니다.
func getData() {
guard let url = URL(string: movieURL) else { return }
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error in
if error != nil {
print("Error fetching movie data: \(error)")
return
}
guard let JSONdata = data else { return }
}
}
4단계 : task를 resume()
마지막 4단계로 task를 resume() 해주겠습니다.
https://developer.apple.com/documentation/foundation/urlsessiontask/1411121-resume
작업이 일시 중단된 경우 다시 시작하는 메서드로, 새로 초기화된 작업은 일시 중단된 상태에서 시작되므로 이 메서드를 호출해서 작업을 시작해야 합니다.
func getData() {
guard let url = URL(string: movieURL) else { return }
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error in
if error != nil {
print("Error fetching movie data: \(error)")
return
}
guard let JSONdata = data else { return }
}
task.resume()
}
그 다음으로 파싱을 쉽게 하기 위해서 MovieData형 구조체를 만들어주겠습니다.
struct MovieData: Codable {
let boxOfficeResult: BoxOfficeResult
}
struct BoxOfficeResult: Codable {
let dailyBoxOfficeList: [DailyBoxOfficeList]
}
struct DailyBoxOfficeList: Codable {
let movieNm: String
let audiCnt: String // Audience count
let audiAcc: String // Accumulated audience count
let rank: String
}
에러 핸들링
func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable
MovieData형 프로퍼티 만들어 decodedData 저장
tableView(_:cellForRowAt:)에서 decodeData를 사용하기 위해서 소스를 수정하겠습니다.
func getData() {
guard let url = URL(string: movieURL) else { return }
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error in
if let error = error {
print("Error fetching movie data: \(error)")
return
}
guard let data = data else {
print("No data received from API")
return
}
let dataString = String(data: data, encoding: .utf8)
// print(dataString) // For debugging purposes
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(MovieData.self, from: data)
print("First movie name: \(decodedData.boxOfficeResult.dailyBoxOfficeList[0].movieNm)") // Debug
self.movieData = decodedData
// Update the UI on the main thread
DispatchQueue.main.async {
self.table.reloadData()
}
} catch let decodingError {
print("Error decoding JSON data: \(decodingError)")
}
}
task.resume()
}
날짜 자동 조회
그리고 이제 마지막으로 앱을 실행하면 자동으로 어제 날짜로 자동 조회하는 함수를 추가해주겠습니다.
저는 함수 이름은 makeYestdayString으로 했고, 어제 년 4자리, 월 2자리, 일 2자리 문자열로 리턴하게 만들었습니다.
func makeYesterdayString() -> String {
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMdd"
let yesterdayString = formatter.string(from: yesterday)
return yesterdayString
}
실행 해보기
실행 해보면 아직 디자인은 없어서 밋밋하지만 영화 누적 관람 수 순서대로 잘 출력되는 것을 확인할 수 있습니다!
'Apple > iOS' 카테고리의 다른 글
[iOS] RESTful API 완벽 이해하기 (0) | 2024.07.22 |
---|---|
[iOS] Core Data는 뭘까? (0) | 2024.05.24 |
[iOS] 화면 전환 방식 (Present, NavigationController + Source, NavigationController + Segue) (0) | 2024.03.24 |
[iOS] AutoLayout 쉽게 이해하기 (0) | 2023.12.30 |
[iOS] Tab Bar Controller (2) | 2023.12.02 |