[TIL] Moya와 RxSwift 활용해 API 요청해보기

Eden·2025년 1월 1일
3

TIL

목록 보기
84/92
post-thumbnail

NetworkManager

  • Moya: API 요청과 관리.
  • RxSwift: 비동기 데이터 스트림 처리.
  • Singleton 패턴: 앱 전역에서 하나의 네트워크 매니저 인스턴스만 사용.
final class NetworkManager {
    static let shared = NetworkManager()
    private init() {}

    private let provider = MoyaProvider<PokemonAPI>()

    func fetch<T: Decodable>(endpoint: PokemonAPI, type: T.Type) -> Single<T> {
        return Single.create { [weak self] single in
            guard let self = self else {
                single(.failure(NSError(domain: "NetworkManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "Self is nil."])))
                return Disposables.create()
            }

            self.provider.request(endpoint) { result in
                switch result {
                case .success(let response):
                    do {
                        let decodedData = try JSONDecoder().decode(T.self, from: response.data)
                        single(.success(decodedData))
                    } catch {
                        single(.failure(error))
                    }
                case .failure(let error):
                    single(.failure(error))
                }
            }

            return Disposables.create()
        }
    }
}

사용 하기

Endpoint 정의

PokemonAPI와 같은 Moya TargetType을 정의한다.

enum PokemonAPI {
    case fetchPokemonList(limit: Int, offset: Int)
}

extension PokemonAPI: TargetType {
    var baseURL: URL {
        return URL(string: "https://pokeapi.co/api/v2")!
    }

    var path: String {
        switch self {
        case .fetchPokemonList(let limit, let offset):
            return "/pokemon?limit=\(limit)&offset=\(offset)"
        }
    }

    var method: Moya.Method {
        return .get
    }

    var task: Task {
        return .requestPlain
    }

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

데이터 가져오기

NetworkManager를 사용해 데이터를 가져온다.

import RxSwift

let disposeBag = DisposeBag()
let endpoint = PokemonAPI.fetchPokemonList(limit: 10, offset: 0)

NetworkManager.shared.fetch(endpoint: endpoint, type: PokemonList.self)
    .subscribe { result in
        switch result {
        case .success(let data):
            print("데이터: \(data)")
        case .failure(let error):
            print("에러: \(error.localizedDescription)")
        }
    }
    .disposed(by: disposeBag)

profile
Frontend🌐 and iOS

2개의 댓글

comment-user-thumbnail
7일 전

오늘 밤 당신의 APIKey를 훔치겠습니다.

1개의 답글