본문 바로가기
스파르타코딩 클럽/팀프로젝트

팀프로젝트3 [날씨 앱 만들기(2) - Moya 라이브러리 사용기]

by UDDT 2025. 5. 25.



날씨 데이터

     메인화면에서 현재 날씨, 강수확률, 5일 예보 날씨 등의 데이터는 서버로부터 받아와야 한다.

  https://openweathermap.org/api

 

Weather API - OpenWeatherMap

Please, sign up to use our fast and easy-to-work weather APIs. As a start to use OpenWeather products, we recommend our One Call API 3.0. For more functionality, please consider our products, which are included in professional collections.

openweathermap.org

 

   우리는 OpenWeatherMap이라는 OpenAPI를 사용하여 데이터를 받아오기로 했다

 

   서버로부터 데이터를 받아오기 전, PostMan을 사용하여 Response가 정상적으로 잘 넘어오는지 테스트를 했다

   

 이후 API 명세를 팀원들과 함께 분석하면서, 어떤 데이터를 써야하는지 체크했다

 모야를 사용하여 WeatherAPI 구현하기

    어떤 데이터가 필요한지 나왔으니, 요청할 URL을 정리해봤다.

https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}&units=metric
https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}&units=imperial
https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={API key}&units=metric
https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={API key}&units=imperial

 

 

  위의 URL을 보면, 같은 URL 형태에서 path의 weather가 변하고

  query의 lat, lon, units가 변하는 것을 알 수 있다.

 

   따라서 이번 프로젝트에서는 Moya라는 라이브러리를 사용해서 네트워크 매니저를 구현해보고자 한다

  https://uddt.tistory.com/281

 

Swift | 모야(Moya)가 모야요?

모야(Moya)⎮ Moya가 뭔데? https://github.com/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 모야 R

uddt.tistory.com

 

   먼저 enum으로 케이스를 분기했다

// MARK: 날씨 타입 열거형
enum WeatherAPI {
    case currentCelsius(lat: String, lon: String)
    case currentFahrenheit(lat: String, lon: String)
    case forecastCelsius(lat: String, lon: String)
    case forecastFahrenheit(lat: String, lon: String)
}

 

    아래의 예시처럼 lat과 lon을 주입받을 수 있도록 했다

 

    그리고 이 열거형을 확장해서 

import Foundation
import Moya

// MARK: 날씨 타입 열거형(연관값으로 lat, lon 주입)
// 나중에 WeatherType을 초기화할 때 값을 주입해줄 수 있음
enum WeatherAPI {
    case currentCelsius(lat: String, lon: String)
    case currentFahrenheit(lat: String, lon: String)
    case forecastCelsius(lat: String, lon: String)
    case forecastFahrenheit(lat: String, lon: String)
}

// MARK: WeatherType 확장
extension WeatherAPI: TargetType {
    // 기본 URL
    var baseURL: URL {
        return URL(string: "https://api.openweathermap.org")!
    }

    // case에 따라 path 분기
    var path: String {
        switch self {
        case .currentCelsius, .currentFahrenheit: return "/data/2.5/weather"
        case .forecastCelsius, .forecastFahrenheit: return "/data/2.5/forecast"
        }
    }

    // 모든 case가 get 메서드 사용
    var method: Moya.Method {
        return .get
    }

    // task가 딕셔너리 타입이라서 순서를 보장하지는 않지만, 쿼리 파라미터는 순서와 상관이 없음
    // requestPlain으로 request를 그대로 반환하도록(없으면 빈값을 반환하도록 설정)
    var task: Task {
        guard let apiKey = Bundle.main.infoDictionary?["APIKey"] as? String else {
            assertionFailure("APIKey 누락 - Info.plist 확인 요망")
            return .requestPlain
        }

        switch self {
        case .currentCelsius(let lat, let lon):
            return .requestParameters(parameters: [
                "lat": lat,
                "lon": lon,
                "appid": apiKey,
                "units": "metric"
            ], encoding: URLEncoding.queryString)
        case .currentFahrenheit(let lat, let lon):
            return .requestParameters(parameters: [
                "lat": lat,
                "lon": lon,
                "appid": apiKey,
                "units": "imperial"
            ], encoding: URLEncoding.queryString)
        case .forecastCelsius(let lat, let lon):
            return .requestParameters(parameters: [
                "lat": lat,
                "lon": lon,
                "appid": apiKey,
                "units": "metric"
            ], encoding: URLEncoding.queryString)
        case .forecastFahrenheit(let lat, let lon):
            return .requestParameters(parameters: [
                "lat": lat,
                "lon": lon,
                "appid": apiKey,
                "units": "imperial"
            ], encoding: URLEncoding.queryString)
        }
    }

    var headers: [String: String]? {
        return ["Content-Type": "application/json"]
    }
}

 

   다음과 같이 코드를 작성했다.

  WeatherAPI는 Provider를 생성해서 추후 데이터를 핸들링하게 될 것이다.

최근댓글

최근글

skin by © 2024 ttuttak