header-img
Info :

A. ์„ค๋ช…

api ํ†ต์‹  ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์ด ์ƒ๊ธฐ๋Š” ๊ฒƒ ๊ฐ™์•„ base๋กœ ์‚ฌ์šฉํ•  ์ฝ”๋“œ ๋งŒ๋“ฆ. ํ”„๋กœํ† ์ฝœ๋กœ ์ •์˜ํ•ด์„œ ์žฌ์‚ฌ์šฉ์„ฑ ์šฉ์ดํ•˜๋„๋ก ๊ตฌํ˜„ํ•จ. ์›น ์—ฐ๊ฒฐ์—๋Š” Alamofire ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•จ.

 

B. ์ฝ”๋“œ

import Foundation
import Alamofire

protocol BaseService {
    /// api request url
    var url: String { get set }
    var header: HTTPHeaders { get set }
    var param: Encodable? { get set }
    /// Request์— ๋“ค์–ด๊ฐ€๋Š” .put, .get ๋“ฑ method
    var method: HTTPMethod { get set }
    /// Request์— ๋“ค์–ด๊ฐ€๋Š” Parameter encoding ๋ฐฉ์‹
    var encoding: ParameterEncoding? { get set }
}

extension BaseService {
    /// BaseService์— ์ง€์ •ํ•œ ๊ฐ’์œผ๋กœ api ์—ฐ๋™์„ ์ˆ˜ํ–‰ํ•œ ๊ฒฐ๊ณผ(NetworkResult)๊ฐ€ closure ํ•จ์ˆ˜์˜ param์ด ๋จ.
    func serverAction<T>(type: T.Type, completion: @escaping(NetworkResult<Any>) -> Void) where T: Decodable {
        var paramAsDictionary: Parameters? = ["Tmp": "Tmp"]
        do {
            let dictionary = try param?.encode()
            paramAsDictionary = dictionary
        } catch {
            print(error)
        }

        let dataRequest = AF.request(
            url,
            method: method,
            parameters: paramAsDictionary,
            encoding: encoding ?? JSONEncoding.default,
            headers: header
        )

        dataRequest.responseData { response in
            switch response.result {
            case .success:
                guard let statusCode = response.response?.statusCode else { return }
                guard let value = response.value else { return }
                let networkResult = self.judgeStatus(by: statusCode, value, type: T.self)
                completion(networkResult)

            case .failure(let error):
                print("network err : \(error)")
                completion(.networkFail)
            }
        }
    }

    func judgeStatus<T>(by statusCode: Int, _ data: Data, type: T.Type) -> NetworkResult<Any> where T: Decodable {
        switch statusCode {
        case ..<300: return isValidData(data: data, type: T.self)
        case 400..<500:
            return isErrorData(data: data)
        case 500..<600: return .serverErr
        default: return .unRecognizedError
        }
    }

    func isValidData<T>(data: Data, type: T.Type) -> NetworkResult<Any> where T: Decodable {
        let decoder = JSONDecoder()

        guard let decodedData = try? decoder.decode(type, from: data) else {
            return .unRecognizedError
        }
        return .success(decodedData as Any)
    }

    func isErrorData(data: Data) -> NetworkResult<Any> {
        let decoder = JSONDecoder()
        guard let errorData = try? decoder.decode(ServerErrorModel.self, from: data) else {
            return .unRecognizedError
        }
        return .pathErr(errorData)
    }
}

enum NetworkResult<T> {
    /// output data์— ๋งž์ถฐ์„œ ํŒŒ์‹ฑ๊นŒ์ง€ ์™„๋ฃŒ๋œ ๊ฒฝ์šฐ
    case success(T)
    /// network failure๊ฐ€ ์•„๋‹Œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ณ 
    /// api ๋ฌธ์„œ์— ๋ช…์‹œ๋œ ์—๋Ÿฌ data์— ๋งž์ถฐ์„œ ํŒŒ์‹ฑ๊นŒ์ง€ ์™„๋ฃŒ๋œ ๊ฒฝ์šฐ
    case pathErr(T)
    /// code 500~599๋กœ ์„œ๋ฒ„ ์ชฝ ์—๋Ÿฌ์ธ ๊ฒฝ์šฐ
    case serverErr
    /// ๊ธฐ๊ธฐ ๋„คํŠธ์›Œํฌ ๋ฌธ์ œ์ธ ๊ฒฝ์šฐ
    case networkFail
    /**
     1. network failure๊ฐ€ ์•„๋‹Œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์ง€๋งŒ
     api ๋ฌธ์„œ์— ๋ช…์‹œ๋œ ์—๋Ÿฌ data์— ๋งž์ถฐ์„œ ํŒŒ์‹ฑ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ
     2. code๊ฐ€ 200๋Œ€์ด๊ธฐ๋Š” ํ•œ๋ฐ Service ํ˜ธ์ถœ์ชฝ์—์„œ ์ „๋‹ฌํ•ด์ค€
     data ํ˜•์‹์— ๋งž์ถฐ ํŒŒ์‹ฑ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ
     3. code๊ฐ€ 600 ์ด์ƒ์ธ ๊ฒฝ์šฐ */
    case unRecognizedError
}

// codable -> dictionary Type
extension Encodable {
    func encode() throws -> [String: Any] {
        let data = try JSONEncoder().encode(self)
        guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
            throw NSError()
        }

        return dictionary
    }
}

 

C. ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋Š” ์›น์„œ๋ฒ„ ์—ฐ๊ฒฐ ํด๋ž˜์Šค์—์„œ BaseService ์ƒ์† ๋ฐ›์€ ํ›„ url, header, param, method, encoding ๋ณ€์ˆ˜ ์ฑ„์›Œ์ค€ ํ›„ serverAction()๋กœ ๊ฐ ์ผ€์ด์Šค๋ณ„ ๋‚ด์šฉ ๊ตฌํ˜„ํ•ด์ฃผ๋ฉด ๋จ. 

 

Z. ๋ ˆํผ๋Ÿฐ์Šค

์ด๋ถ„๊ฑฐ ์ฐธ๊ณ ํ•ด์„œ ๊ตฌํ˜„ํ•จ : https://roniruny.tistory.com/141

 

[iOS] Alamofire๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์™€ ํ†ต์‹  ํ•ด๋ณด๊ธฐ - GET

์†ํŠธ 4์ฃผ์ฐจ ์„ธ๋ฏธ๋‚˜ ๋ณต์Šต ์ •๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค. ๋‹ค์†Œ ๋‘์„œ์—†๋Š” ๊ธ€์ž„์ด ์˜ˆ์ƒ๋˜์˜ค๋‹ˆ ๊ทธ๋ƒฅ ๋ด์ฃผ์„ธ์˜ค. [ Alamofire๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์™€ ํ†ต์‹  ํ•ด๋ณด๊ธฐ - GET ] ๐Ÿ“š ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” GET ๋ฐฉ์‹์—์„œ๋Š” ์„œ๋ฒ„์—์„œ ์ผ

roniruny.tistory.com

 

๋”๋ณด๊ธฐ
CS/iOS, Swift