Swift

SwiftUI OpenAPI 적용시키기

Thor_yeom 2023. 2. 14. 00:54

오늘은 간단하게 OpenAPI를 활용하여 영화 순위를 만들어보겠습니다. 사이트는 영화진흥회를 이용했습니다.

영화진흥회 API 사이트

영화 진흥회 상단에 있는 로그인 -> 키 발급 후 이용 할 수 있습니다 ( 키 발급은 3일정도 걸리는거 같습니다...), 로그인후 상단에 OPEN API -> 기본 요청 URL사용 ( 끝단에 .json으로 변경후 사용 ) 

주소창에 http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json

엥? 스러울수 있습니다.. 아니왜 안나타나지?  사이트 하단에 보면 요청 예시 ( 응답 예시라고 되어있음...)

응답 예시라 읽고 요청 예시라 부른다...

예시를 보면 .json 뒤에 ?( 물음표 ) 가 붙고 key 값 있는데, 로그인하고 발급 받은 키 값을 적고, &(그리고를 뜻함) targetDt(조회하고자 하는 날짜를 yyyy.mm.dd형식으로 입력)= (원하는 날짜를 적으면 된다) 

요청 예시

요청 예시로 불러들인 것을 보면 1위 ~ 10위까지 나오는 것을 확인할 수 있다. 

자. 그렇다면 이제 워밍업은 끝났으니 키 발급을 받고 원하는 날짜의 json 파일을 받아보자 

 

 

 

키 발급/관리 -> 키 발급 받기

사용 목적과 관리명을 적고 키 발급을 누르면 발급 완료! 

요청 예시랑 똑같이 요청 주소 ?key=( 발급받은 키 )&targetDt= ( 원하는 날짜 )

여윽시 아바타...

자 이제 준비는 끝났다 이제 XCode를 키고 적용시켜보자

 

가장 먼저 할것은 모델을 만들어주는 것이다. JSON으로 모델을 어떻게 만들죠...? 손 코딩 해야되나요?ㅠ 걱정하지 마시라 우리에겐 구글신이 있다. 

 

JSON을 파일을 구조체로 모델화 시켜주는 사이트이다.

https://app.quicktype.io/ 

이렇게 JSON 데이터를 넣으면 로딩이 걸린다. 왜냐하면 상단에 주석도 인식을 하기 때문에 주석을 삭제해주고 다시 하면 모델이 만들어진다.

 

짜란!

 

이걸 그대로 복사해서 XCode에 모델을 만들어줘도 된다. 참고로 구조체로 정의된 네이밍은 사용자가 편하게 바꿔서 사용할 수 있다.

 

파일 생성 -> TodosResponse -> Movie로 바꿔줌

 

struct DailyBoxOfficeList를 보면 여러가지 항목들이 있는데, 그중에서 내가 원하는 것만 골라서 사용하기위해 사용하지 않는 것들은 삭제해준다. ( Codingkeys가 뭐여... Codable은 또 뭐고... 기둘기둘 ) 

quicktype과 Xcode 비교

 

// MARK: - TodosResponse
struct Movie: Codable {
    let boxOfficeResult: BoxOfficeResult?
}

// MARK: - BoxOfficeResult
struct BoxOfficeResult: Codable {
    let boxofficeType, showRange: String?
    let dailyBoxOfficeList: [DailyBoxOfficeList]?
}

// MARK: - DailyBoxOfficeList
struct DailyBoxOfficeList: Codable {
    let rank: String? // 순위
    let movieNm, openDt: String? // 영화 이름, 오픈일자
}

// ObservableObject: 값이 변경될 때마다 View에 알려줌 Class전용 프로토콜
class MovieStore: ObservableObject {
    // DailyBoxOfficeList가 하나씩 담기는 변수를 만들어준다.
    // @Published : movies가 변경되면 자동으로 View에 변화됐다는것을 알려줌
    @Published var movies: [DailyBoxOfficeList] = []
}

생소한 ObservableObject@Published 나왔는데 쫄거 없이 변화될때 view에 알려주기위한 프로토콜과 프로퍼티 래퍼(@)라고 알고있으면 됩니다. 자세한 내용을 알고싶으시면 블로그를 통해 확인 할 수 있습니다.

https://nsios.tistory.com/120 

 

[SwiftUI] Published, ObservableObject

SwiftUI를 공부하다보면 @Published 라는 키워드를 보게될거에요 이와 같이 언급되는게 ObservableObject죠 ObservableObject는 필수구현을 필요로 하지않는 프로토콜이에요 Combine에 속한 기능이구요 클래스

nsios.tistory.com

https://yeomir.tistory.com/16

 

어서와 @ObservedObject 처음이지?

@ObservaedObect 너란 녀석... 정복하고 싶다 @ObservaedObect를 서치하다 보면 @StateObject라는것이 같이 보일 것이다. 비교해가면서 알아보자 일단 @ObservaedObect가 무엇인가? 공식문서에서 찾아보면 관찰가

yeomir.tistory.com

 

 

자. 이제 그럼 모델도 만들었고, 변화 됐을때 view에 전달해줄 Store도 만들었으니 view에 적용해볼까? 라고 생각하셨다면 큰일납니다... JSON파일을 그래도 가져 올수 없기때문에  decoding을 해줘야 합니다. 

아니 decoding은 또 뭔데!!!  

쉽게 말해 JSON파일이 name : String으로 되어있으니 이것을 XCode에서 사용할 수 있도록 바꿔줘야 한다는 겁니다. 왜냐하면 JSON은 데이터를 표시하는 데이터 표현 방법중 한가지로 필터링을 거쳐서 사용해야 한다는 말씀...

 

여러가지 방법이 있겠지만 제가 사용한 Parsing입니다. 더 좋은 코드가 있다면 댓글 굽신..

class MovieJSonParsing {
    
    // throws : 오류가 발생하면 꺼짐
    func fetchData(url: String) async throws -> [DailyBoxOfficeList] {
        
        //url을 옵셔널 바인딩해서 사용
        guard let url = URL(string: url) else { return [] }
        
        let datas = try await URLSession.shared.data(from: url)
        
        let movies = try JSONDecoder().decode(Movie.self, from: datas.0)
        print("영화 배열 : \(movies)")
        return movies.boxOfficeResult?.dailyBoxOfficeList ?? []
    }
}

 

 

자 이제 드디어 모델을 만들었으니 contentview에 적용해보자 

 

리스트를 만들고 movie 배열에 있는 것들을 하나씩 보여주려고 했지만 오류가 발생했다.

 

ForEach를 사용할때는 id: \.self 값을 추가해서 고유하게 만들어줘야 한다. 그렇지만 또 DailyBoxOfficeList가 Hashable하지 않다고 뜬다.

 

 

DailyBoxOfficeList : Hashable 프로토콜을 채택하면 오류 해결 완!

 

엥? 왜 아무것도 안보이지?? 

첫 화면이 떴을때 데이터를 받아와야 하니까 .onAppear를 이용해서 화면이 나타났을때 데이터가 나올수 있게 설정 

변수 url을 생성하고 JSON을 불러온 주소를 넣어준다. 

Good!!!

 

아니 근데 왜... Text안에 String값을 옵셔널 바인딩 해줬나요??  그건 말이다... 모델을 만들때 옵셔널(?) 로 만들어 줬기 때문이란다..

아니 그니까 왜 옵셔널로 만들었냐구요!!! 

데이터를 가져올때는 가져오는 데이터가 유실되거나 통신이 끊길 수도 있기때문에 옵셔널로 안전하게 가져오는 것이 팁이란다. 만약에 옵셔널로 처리해 놓지 않으면 앱이 바로 꺼지지 때문에 그것을 방지하기 위함이지...

 

만약 이렇게 했는데도 preview에 정보가 나오지 않는다면...

target -> info-> App Transport Security Settings 생성 그리고 왼쪽에 보이는 화살표 내리고 + 버튼 누르면 Allow Arbitrary Loads 이것을 YES로 바꿔주기

SwiftUI로 OpenAPI 불러오는 방법을 알아봤는데... 참 쉽죠잉? 

 

 

처음이 어렵지 여러번 하나보면 익숙하게 하실 수 있으실 겁니다.

재능없다고 생각하지 마시고 위축되지 마시고 옆에 있는 사람이랑 비교하지 마시고 꾸준히 하시다보면 좋은 결과 있다고 장담합니다. 

 

모두 화이팅!!