모야(Moya)
⎮ Moya가 뭔데?
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
모야 ReadMe를 보면 이렇게 작성되어 있다.
"당신은 똑똑한 개발자입니다. 아마도 URLSession에 직접 접근하는 복잡하고 귀찮은 부분들을 추상화하기 위해 Alamofire를 사용하고 있을 겁니다. 내부의 디테일에는 관심 없고, 깔끔하게 처리하고 싶으니까요. 많은 똑똑한 개발자들처럼, 네트워크 추상화 계층을 직접 만들기 시작합니다. 이름은 아마 APIManager, NetworkModel 같은 걸로 지을 겁니다. 그리고 그 작업들은 항상 눈물로 끝납니다"
Alamofire가 이미 URLSession을 깔끔하게 추상화해서 제공하는 라이브러리인데, 개발자들이 재사용을 위해 자체 네트워크 레이어를 만들어 복잡하게 만든다는 얘기다. 이렇게 하게 되면 Alamofire가 해주는 처리를 중복해서 처리하거나 Alamofire의 장점을 무색하게 만든다.
요약하자면, "NetworkManager 같은거로 고생하면서 추상화하지말고 Moya 써" 이 말인 것 같다.
⎮ Moya 라이브러리 적용하여 작성하기
기본 형태의 Moya는 다음과 같다.
1. enum으로 분기하기
enum WeatherAPI {
case currentWeather(lat: Double, lon: Double)
}
2. Target Type 프로토콜 확장하기
extension WeatherAPI: TargetType {
...
}
* TargetType 프로토콜을 채택해서 각 API의 세부 정보를 명세. 추후 MoyaProvider가 네트워크 요청을 만들 때 사용
3. 확장된 WeatherAPI에 속성 추가
- URL : BaseURL 입력(공통 루트 주소만)
extension WeatherAPI: TargetType {
var baseURL: URL {
return URL(string: "https://api.openweathermap.org/data/2.5")!
}
}
- Path : BaseURL 뒤에 붙는 세부 경로 작성
extension WeatherAPI: TargetType {
...
var path: String {
switch self {
case .currentWeather:
return "/weather"
}
}
}
- Method : HTTP 메서드 작성(get, post, put 등)
extension WeatherAPI: TargetType {
...
var method: Moya.Method {
return .get
}
}
- Task : 서버로 전달할 쿼리 파라미터(바디, 속성 등 주입 가능)
extension WeatherAPI: TargetType {
...
var task: Task {
switch self {
case .currentWeather(let lat, let lon):
let parameters: [String: Any] = [
"lat": lat,
"lon": lon,
"appid": "YOUR_API_KEY",
"units": "metric",
]
return .requestParameters(parameters: parameters, encoding: URLEncoding.default)
}
}
}
- headers : 요청 헤더 설정
extension WeatherAPI: TargetType {
...
var headers: [String : String]? {
return ["Content-Type": "application/json"]
}
}
완성된 전체 코드는 다음과 같다
import Foundation
import Moya
enum WeatherAPI {
case currentWeather(lat: Double, lon: Double)
}
extension WeatherAPI: TargetType {
var baseURL: URL {
return URL(string: "https://api.openweathermap.org/data/2.5")!
}
var path: String {
switch self {
case .currentWeather:
return "/weather"
}
}
var method: Moya.Method {
return .get
}
var task: Task {
switch self {
case .currentWeather(let lat, let lon):
let parameters: [String: Any] = [
"lat": lat,
"lon": lon,
"appid": "YOUR_API_KEY", // <- 실제 API 키로 교체
"units": "metric", // 온도를 섭씨로
"lang": "kr" // 한국어
]
return .requestParameters(parameters: parameters, encoding: URLEncoding.default)
}
}
var headers: [String : String]? {
return ["Content-Type": "application/json"]
}
}
위 코드에서는 request를 보내서 response를 핸들링하는 코드는 없다.
그러면 responses는 어떻게 핸들링할 수 있을까?
⎮ MoyaProvider
모야는 Provider를 제공해준다
MoyaProvider란 네트워크 요청을 실제로 수행하는 객체로,
앞서 작성한 코드로부터 baseURL, Path, Method, Task 정보를 가져온 다음
이를 토대로 URLRequest를 생성해서
내부적으로 URLSession 또는 AF(Alamofire)를 사용해서 요청을 보낸 뒤
결과를 completion 블록에 넘겨준다
이를 코드로 작성해본다면,
let provider = MoyaProvider<WeatherAPI>()
provider.request(.currentWeather(lat: 37.5, lon: 127)) { result in
switch result {
case .success(let response):
do {
let weather = try JSONDecoder().decode(WeatherResponse.self, from: response.data)
print("현재 날씨: \(weather)")
} catch {
print("디코딩 실패: \(error)")
}
case .failure(let error):
print("요청 실패: \(error)")
}
}
이와 같은 단순한 형태로
provider를 만들어주고 response로 넘어온 데이터를 핸들링할 수 있게 된다.
'스파르타코딩 클럽 > 기초' 카테고리의 다른 글
| iOS | AppStore에 재배포하기(업데이트) (0) | 2025.06.24 |
|---|---|
| iOS | AppStore에 배포하기(feat. 한 큐에 바로 성공!) (1) | 2025.06.21 |
| Swift | 유저 디폴트(UserDefaults) 이해하기 (0) | 2025.05.24 |
| Swift | KingFisher(feat. 이미지 캐싱) (0) | 2025.05.17 |
| Swift | CocoaPods 설치하기 (0) | 2025.04.26 |