내일배움캠프 iOS

UIKit) TIL # 41 팀 프로젝트 - 영화상영정보 앱, API 분석

yjuni22 2024. 12. 16. 20:47

팀 프로젝트에서 역할분담을 하여
API 호출 역할을 맡게 되었다.

 

1. API 분석하기

API https://developer.themoviedb.org/reference/movie-upcoming-list

 

Upcoming

Get a list of movies that are being released soon.

developer.themoviedb.org

위의 사이트를 통해 API 를 받아와야 한다.

우선 회원가입을 하고 Key를 부여받아야 사용할 수 있다.

 

키값을 예시 주소 뒤에 붙이고 지역언어 등을 붙여 API 를 분석하기 위해 포스트맨으로 테스트 해보았다.

 

POSTMAN 활용

 

- 포스트맨으로 API가 잘 받아져 오는 것을 확인.

- 어떤 데이터들이 주어지는 지 체크

- 필요한 데이터를 뽑아 구조체로 변환

 

qucitype io 를 사용하여 JSON데이터를 스위프트에서 사용 가능하도록 구조체로 변환 시켰다.

 

그 중 영화 앱에서 필요한 정보들만 받아오기 위해

데이터를 선별하여 구조체로 변환하였다.

 

JSON 데이터에서 필요한 부분만 정리하여 구조체로 변환

// MARK: - MovieData Model
struct MovieData: Codable {
    let page: Int
    let results: [Movie]
}

// MARK: - Results
struct Movie: Codable {
    let title, enTitle, overview, posterPath, releaseDate: String?
    let voteAverage: Double?
    
    enum CodingKeys: String, CodingKey {
        case title
        case enTitle = "original_title"
        case overview
        case posterPath = "poster_path"
        case releaseDate = "release_date"
        case voteAverage = "vote_average"
    }
}

2. 네트워킹 코드 구현

네트워킹 코드를 구현하기 전에

하드코딩으로 인한 실수 방지와, 여러가지 API 데이터를 받을 수 있도록

겹치는 baseURL 과 QueryItem을 설정하고 Path 열거형을 통해 다른 주소에 쉽게 접근할 수 있도록

NameSpace를 생성하였다.

public enum MovieAPI {
    static let baseURL = "https://api.themoviedb.org/3/"
    static let apiKey = "1axxxxxxxxxxxx"
    
    static let urlQueryItems: [URLQueryItem] = [
        URLQueryItem(name: "api_key", value: apiKey),
        URLQueryItem(name: "language", value: "ko-KR")
    ]
    enum Path: String {
        case nowPlaying = "movie/now_playing"
        case upcoming = "movie/upcoming"
        case popular = "movie/popular"
        case search = "search/movie"
    }
}

 

🚨트러블 슈팅

문제:

이미지의 경우 API 에서 path 값만 나와 따로 URL 확인이 어려움,

"poster_path" :  /1E5baAaEse26fej7uHcjOgEE2t2.jpg

 

위와 같이 Path 값만 주어 네트워킹 과정에서 이미지를 어떻게 불러와야 할 지 의문이 들었다.

 

해결과정:

 

해결 방안을 찾다보니 API 사이트 내 Guides 탭에서 이미지 관련 내용이 있었다.

 

 

지금까지 사용했던 API 들은 주소 전체를 줘서 사용하기 쉬웠지만 이 사이트의 경우 다르다는 것을 알게 되었다.

 

이러한 형태에 맞게 네트워킹을 하기 위해 또 하나의 NameSpace를 생성하였다.

받아오는 path 값을 통해 구현하기 쉽도록 메서드를 정의하여 구현하였다.

/// 이미지 URL
struct MovieImage {
    static let imageBaseURL = "https://image.tmdb.org/t/p/"
    static func movieImageURL(size: Int, posterPath: String) -> String {
        return "\(imageBaseURL)w\(size)\(posterPath)"
    }
}

네트워킹 관련 코드 ( Alamofire 사용 )

 

 private func makeURL(path: String) -> URL? {
        guard var urlComponents = URLComponents(string: MovieAPI.baseURL + path) else { return nil }
        urlComponents.queryItems = MovieAPI.urlQueryItems
        return urlComponents.url
    }
    
    /// 네트워크 요청 메서드
    func fetchDataByAlamofire<T: Decodable>(path: MovieAPI.Path, completion: @escaping (Result<T, AFError>) -> Void) {
        guard let url = makeURL(path: path.rawValue) else {
            print("잘못된 URL")
            return
        }
        
        AF.request(url).responseDecodable(of: T.self) { response in
            switch response.result {
            case .success(let data):
                completion(.success(data))
            case .failure(let error):
                completion(.failure(error))
            }
        }
    }

 

NameSpac를 활용하여 네트워킹을 쉽게 할 수 있도록 다음과 같이 네트워킹 코드를 구현하였다.