안녕하세요~ 개발하는 윤기사입니다!!
오늘 포스팅은 오픈소스 라이브러리 중 API 통신을 쉽게 하도록 도와주는 "Moya"를 준비해 왔습니다!
Moya가 모야?
Moya는 URLSession을 추상화한 Alamofire를 다시 추상화한 프레임워크로 Network Layer를 템플릿화 해서 재사용성을 높이고, 개발자가 request, response에만 신경을 쓰도록 해줍니다. 아래 그림과 같이 말이죠!
Moya 라이브러리에 가장 좋은 점은 코드가 가독성이 높고, 쉽게 사용 가능하다는 점이었습니다!
바로 시작해 보도록 하시죠!
저는 TMDB Open API를 이용했습니다!!
Movie Lists -> Popular를 이용했어요!
https://developer.themoviedb.org/reference/movie-popular-list
Popular
Get a list of movies ordered by popularity.
developer.themoviedb.org
해당 API의 Response 값을 확인해 주고... 이 Response 값을 이용해서 DTO를 만들어주도록 하겠습니다!
{
"page": 1,
"results": [
{
"adult": false,
"backdrop_path": "/628Dep6AxEtDxjZoGP78TsOxYbK.jpg",
"genre_ids": [
28,
53
],
"id": 575264,
"original_language": "en",
"original_title": "Mission: Impossible - Dead Reckoning Part One",
"overview": "Ethan Hunt and his IMF team embark on their most dangerous mission yet: To track down a terrifying new weapon that threatens all of humanity before it falls into the wrong hands. With control of the future and the world's fate at stake and dark forces from Ethan's past closing in, a deadly race around the globe begins. Confronted by a mysterious, all-powerful enemy, Ethan must consider that nothing can matter more than his mission—not even the lives of those he cares about most.",
"popularity": 4167.922,
"poster_path": "/NNxYkU70HPurnNCSiCjYAmacwm.jpg",
"release_date": "2023-07-08",
"title": "Mission: Impossible - Dead Reckoning Part One",
"video": false,
"vote_average": 7.7,
"vote_count": 1621
},
...
{
"adult": false,
"backdrop_path": "/2vFuG6bWGyQUzYS9d69E5l85nIz.jpg",
"genre_ids": [
28,
12,
878
],
"id": 667538,
"original_language": "en",
"original_title": "Transformers: Rise of the Beasts",
"overview": "When a new threat capable of destroying the entire planet emerges, Optimus Prime and the Autobots must team up with a powerful faction known as the Maximals. With the fate of humanity hanging in the balance, humans Noah and Elena will do whatever it takes to help the Transformers as they engage in the ultimate battle to save Earth.",
"popularity": 674.774,
"poster_path": "/gPbM0MK8CP8A174rmUwGsADNYKD.jpg",
"release_date": "2023-06-06",
"title": "Transformers: Rise of the Beasts",
"video": false,
"vote_average": 7.5,
"vote_count": 3384
}
],
"total_pages": 40527,
"total_results": 810535
}
🍎 QuickType.io를 이용하면 Json Type을 Swift에서 사용할 수 있게 변환해 줍니다!! 꿀팁!
Convert JSON to Swift, C#, TypeScript, Objective-C, Go, Java, C++ and more<!-- --> • quicktype
{ "people": [ { "name": "Atticus", "high score": 100 }, { "name": "Cleo", "high score": 900 }, { "name": "Orly" }, { "name": "Jasper" } ] } Provide sample JSON files, URLs, JSON schemas, or GraphQL queries.
quicktype.io
1️⃣ TMDB API Response DTO 설정
import Foundation
struct TmdbDTO: Codable {
let page: Int
let results: [MovieDetail]
let totalPages, totalResults: Int
enum CodingKeys: String, CodingKey {
case page, results
case totalPages = "total_pages"
case totalResults = "total_results"
}
}
// MARK: - Result
struct MovieDetail: Codable {
let adult: Bool
let backdropPath: String
let genreIDS: [Int]
let id: Int
let originalLanguage: OriginalLanguage
let originalTitle, overview: String
let popularity: Double
let posterPath, releaseDate, title: String
let video: Bool
let voteAverage: Double
let voteCount: Int
enum CodingKeys: String, CodingKey {
case adult
case backdropPath = "backdrop_path"
case genreIDS = "genre_ids"
case id
case originalLanguage = "original_language"
case originalTitle = "original_title"
case overview, popularity
case posterPath = "poster_path"
case releaseDate = "release_date"
case title, video
case voteAverage = "vote_average"
case voteCount = "vote_count"
}
}
enum OriginalLanguage: String, Codable {
case en = "en"
case es = "es"
case pt = "pt"
}
2️⃣ API Target enum 선언
- TMDBService라는 enum을 만들어줍니다.
import Foundation
import Moya
enum TMDBService {
case popularMovies(page: Int)
}
3️⃣ TargetType 설정
Moya는 MoyaProvider<TargetType>으로 request를 수행하기 때문에, API가 TargetType 프로토콜을 구현해야 합니다!
extension을 만들어 TMDBService이 TargetType 프로토콜을 채택하도록 하고, 아래와 같은 프로퍼티들을 구현합니다.
extension TMDBService: TargetType {
var baseURL: URL {
return URL(string: "https://api.themoviedb.org/3")!
}
var path: String {
switch self {
case .popularMovies:
return "/movie/popular"
}
}
var method: Moya.Method {
return .get
}
var task: Task {
switch self {
case .popularMovies(let page):
return .requestParameters(parameters: [
"api_key": EndPoint.api_key,
"page": page,
"language": "en"
], encoding: URLEncoding.queryString)
}
}
var sampleData: Data {
return Data()
}
var headers: [String: String]? {
return ["Content-type": "application/json"]
}
}
- baseURL: base가 되는 도메인
- path: 도메인 뒤에 추가되는 path (/movie 등)
- method: HTTP method (GET, POST, PUT, DELETE)
- sampleData: 테스트용 Mock Data
- task: request에 사용될 파라미터
- requestPlain: no param
- requestParameters(parameter: , encoding: )
- headers: HTTP Header
- Content-type : "application/json" or "application/x-www-form-urlencoded"
4️⃣ API 통신하기 - Request 보내고, Response 처리하기
func getMovieTitle(_ completion: @escaping (String) -> () ) {
let provider = MoyaProvider<TMDBService>()
provider.request(.popularMovies(page: 1)) { result in
switch result {
case .success(let response):
do {
let movies = try JSONDecoder().decode(TmdbDTO.self, from: response.data)
let moviesTitleList = movies.results.map { details in
details.originalTitle
}
let movieTitle = moviesTitleList.randomElement() ?? "영화 제목 없음."
completion(movieTitle)
} catch {
print("error")
}
case .failure(let error):
print(error.localizedDescription)
}
}
}
5️⃣ Response 값 이용하기
getMovieTitle { [weak self] title in
guard let self else { return }
print(title)
}
GitHub - Moya/Moya: Network abstraction layer written in Swift.
Network abstraction layer written in Swift. Contribute to Moya/Moya development by creating an account on GitHub.
github.com
'iOS_오픈소스 라이브러리😎' 카테고리의 다른 글
[iOS_OpenSource] 안내문구 쉽게 띄우기 (Toast) _ 4 (30) | 2023.01.18 |
---|---|
[iOS_OpenSource] 로딩뷰(LoadingView) 쉽게 만들기 (JGProgressHUD) _ 3 (30) | 2023.01.12 |
[iOS_OpenSource] CodeBase로 쉽게 View 만들기 (Then) _ 2 (0) | 2022.08.28 |
[iOS_OpenSource] AutoLayout 쉽게 하기 (SnapKit) _ 1 (0) | 2022.08.26 |