๐
๋ชฉ์ฐจ
iOS์์ ๋คํธ์ํฌ ์์
์ด๋ผ๊ณ ํ๋ฉด ๊ฐ์ฅ ๋ ์ค๋ฅด๋ URLSession, Alamofire๊ฐ ์์ ๊ฒ์ด๋ค. URLSession์ ํ๋ก์ ํธ์ ๋ณต์ก๋๊ฐ ์ฌ๋ผ๊ฐ๊ณ ๊ฐ๋
์ฑ์ด ์์ข์ ๋ฐ๋ฉด, URLSession ๊ธฐ๋ฐ์ Alamofire๋ ๋ณด๋ค ๊ฐ๊ฒฐํ๊ณ ๊ฐ๋
์ฑ์ด ์ข๋ค. ํ์ง๋ง, Alamofire๋ ์ ์ง๋ณด์ & ํ
์คํธ์ ์ ํฉํ๋ค๊ณ ํ์ธํ ์ ์๋ค. ๊ทธ๋์ ์ค๋์ ์ฃผ์ Moya๋ฅผ ์ดํด๋ณผ ๊ฒ์ด๋ค.
๊ฐ๋
- URLSession์ ์ถ์ํ ์ํจ Alamofire๋ฅผ ํ ๋ฒ ๋ ์ถ์ํ์ํจ Networking Library์ด๋ค.
- Enum(์ด๊ฑฐํ)์ ์ฌ์ฉํด์ ๋คํธ์ํฌ ์์ฒญ์ type-safeํ ๋ฐฉ์์ผ๋ก ์บก์ํํ๋ค. (์์ & ๊น๋)
type-safe
- ํด๋น Type์๋ ์ ํด์ง Type๋ง ์ ์ฅ์ด ๊ฐ๋ฅํ๋ค. ๋ผ๋ ์๋ฏธ (๋ค๋ฅธ Type ์๋ผ!! โ)
- ์ฆ, ๋ณ์์ Type์ด ๋ช ํํด์ง๋ค.
ํน์ง
- Alamofire์์ ๋คํธ์ํฌ ๊ณ์ธต์ ๊ตฌ์กฐํํ๋ ๋ฐฉ๋ฒ๊ณผ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค.
- Alamofire Library๋ฅผ Enum ํ์
์ผ๋ก ๋ง๋ค์ด ๋ ์ฌ์ฉ์ฑ๊ณผ ํ
์คํธ์ฑ์ ์ฉ์ดํ๊ฒ ๋ง๋ค์๋ค.
- Enum์ด๊ธฐ ๋๋ฌธ์ Type ์ง์ ์ ํด์ฃผ๊ธฐ ํธํ๋ค.
๊ธฐ์กด ๋คํธ์ํน ๋ฐฉ์ VS Moya

๊ธฐ์กด ๋คํธ์ํน ์ฌ์ฉ๋ฒ์ ์ผ์ชฝ ๊ทธ๋ฆผ์ฒ๋ผ Network Layer๋ฅผ ํตํด ์์ ๋กญ๊ฒ ๊ตฌํ๋๊ณ ์๋ค.
๋ฐ๋ผ์, ๊ธฐ์กด ๋คํธ์ํน ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ์ ๋ค์ ๊ฐ์ง๊ณ ์์๋ค.
- ์ App์ ์์ฑํ๊ธฐ ์ด๋ ต๋ค.(์ด๋์๋ถํฐ ์์ํด์ผํ๋๊ฐ?)
- ๊ธฐ์กด App์ ์ ์งํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ ๋ค.(์๋, ๋๋ฌด ์๋ง ์ง์ฐฝ์ด๋ค..)
- ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ ๋ค.(์ด ์์ ์ ๋ค์ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํด?)
Moya๋ ์ค๋ฅธ์ชฝ ๊ทธ๋ฆผ์ฒ๋ผ ๋ณด๋ค ๊น๋ํ Layer๋ฅผ ํตํด ์์ฒด์ ์ผ๋ก ๋คํธ์ํน์ํ์ง ์๊ณ Alamofire๋ฅผ ํตํด ๊ตฌํ๋๋ค.
- ๋ฟ๋ง ์๋๋ผ, Network Layer๋ฅผ Templateํ ์์ผ์ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
Moya์ ์ฅ์ - ์ฌ๋ฐ๋ฅธ API ์๋ํฌ์ธํธ ์ก์ธ์ค๋ฅผ ์ํ ์ปดํ์ผ ์๊ฐ ๊ฒ์ฌ.
- ์ฐ๊ฒฐ๋ ์ด๊ฑฐํ ๊ฐ์ ์ฌ์ฉํ์ฌ ๋ค์ํ ์๋ํฌ์ธํธ์ ๋ช ํํ ์ฌ์ฉ๋ฒ์ ์ ์ํ ์ ์์ต๋๋ค.
- ํ ์คํธ ์คํ ์ ์ผ๊ธ ์๋ฏผ์ผ๋ก ์ทจ๊ธํ๋ฏ๋ก ๋จ์ ํ ์คํธ๊ฐ ๋งค์ฐ ์ฝ์ต๋๋ค.
Flow (์ ๋ง ๊ฐ๋จํ๊ฒ๋ง ์ฌ์ฉ๋ฒ ์ตํ๊ธฐ)
- Pod ์ค์น
- pod init
- pod install
pod 'Moya', '~> 15.0'
- API ํต์ ์ ์ํ Moya > TargetType์ ์ ์
import Foundation
import Moya
enum APIClient {
case users, todos, comments
}
extension APIClient: TargetType {
var baseURL: URL {
switch self {
case .users, .todos, .comments:
return URL(string: "https://jsonplaceholder.typicode.com/")!
}
}
var path: String {
switch self {
case .users:
return "users"
case .todos:
return "todos"
case .comments:
return "comments"
}
}
var method: Moya.Method {
switch self {
case .users, .todos, .comments:
return .get
}
}
var task: Moya.Task {
switch self {
case .users:
return .requestPlain
case .todos:
return .requestPlain
case .comments:
return .requestPlain
}
}
var headers: [String : String]? {
return ["Content-type": "application/json"]
}
}- Json Model Struct ์์ฑ
struct Todos: Codable {
var userId: Int
var id: Int
var title: String
var completed: Bool
}- API ํต์
func getDataFromJsonPlaceHolder() {
let moyaProvider = MoyaProvider<APIClient>()
moyaProvider.request(.todos) { result in
switch result {
case .success(let response):
// guard let todoTitle = try? response.mapJSON() else { return }
guard let todo = try? response.map([Todos].self) else { return }
self.labelText.text = todo[Int.random(in: 1..<10)].title
case .failure(let moyaError):
print(moyaError.errorDescription ?? "Moya API Request Error")
}
}
}
๋ง๋ฌด๋ฆฌ
- URLSession & Alamofire VS Moya ์ฐจ์ด์
- ๊ธฐ์กด์ ์ฌ์ฉํด๋ดค๋ URLSession๊ณผ Alamofire๋ request/response๋ฅผ ํ๋ฉด์ ๋์์ ์ฌ๋ฌ๊ฐ์ง(url, method ๋ฑ)๋ฅผ ์ ๊ฒฝ ์จ์ผํ๋ค. (์ฌ์ฉํ ๋๋ง๋ค ๋ฐ๋ณต ์์ฑ)
- Moya๋ฅผ ๊ณต๋ถํ๊ณ ์ฌ์ฉํด๋ณด๋ฉด์ ํ๋์ ํ์ ์ ๋ค ์ ์ ํด์ค์ผํ๋ค๋ ์์ ์ด ์กฐ๊ธ(?)์ ๊ท์ฐฎ์ ์ ์์ง๋ง, ๊ฐ์ API๋ฅผ ๋ง์ด ์ฌ์ฉํ๊ฒ ๋๋ ํ๋ก์ ํธ๋ผ๋ฉด ์ฌ์ฉํ๋๊ฒ ์ข๋ค๊ณ ์๊ฐ๋๋ค.
- ์๋ฌด๋๋ ๊ฐ์ API์ ๋ํด์ ๋ฐ๋ณต์ ์ผ๋ก ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋นํจ์จ์ ์ผ ์ ์๋ค. ๋ํ, ๋ฐ์ดํฐ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์์ ์ด์ฉ๋ฉด ์ง์ค๋๋ฅผ ๋จ์ด๋จ๋ฆฌ๋ ์์ธ์ด ๋ ์ ์๋ค๊ณ ์๊ฐํ๋ค.
- Moya์ TargetType์์ ์ฌ๋ฌ๊ฐ์ง ํญ๋ชฉ๋ค์ ๋ฏธ๋ฆฌ ์์ฑํด๋๊ณ , ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฉ๋๋ ๋ถ๋ถ์
์ฌ์ฌ์ฉํ๋ค๋ฉด ๋ฐ์ดํฐ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์์ ๋ณด๋ค ์ง์ค๋ ์๊ณ ๊ฐ๋ ์ฑ์ด ์ข์ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค๊ณ ์๊ฐํ๋ค.
- ์คํ๋ ค ๋ด๊ฐ ์ง๊ธ ๋ฐ๋ณต์ ์ผ๋ก ๋งํ๊ณ ์๊ธดํ์ง๋ง ใ ใ ์๋ฌดํผ๊ฐ!! Moya๋ ์ํฉ์ ๋ฐ๋ผ ๋ง์ถฐ ํ์ํ ํ๋ก์ ํธ์ ์ ์ฉํ๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
- ๊ทธ๋ฆฌ๊ณ Moya๋ฅผ ์ข ๋ ํจ์จ์ ์ผ๋ก ์ฐ๊ธฐ ์ํด์
CommonMoyaProvider๋ฅผ ๋ง๋ค์ด์ ๋ชจ๋ API ์ฝ๋์ ์ ์ฉํ๋ ๊ฒ์ด ์ข๋ค๊ณ ์๊ฐํ๋ค.- ex) ๋ชจ๋ api response์ ์ค๋ณต ๋ก๊ทธ์ธ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๋ฐ๋ณต์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ์ง ์๊ธฐ ์ํด Custom ํด์ฃผ๋ ๊ฒ.
- CommonMoyaProvider์๋ Moya TargetType์ ๊ฐ์ง API๋ค์ ๋ชจ๋ ๋ด์ ์ฌ์ฉํ ์ ์๋๋ก Generic ํํ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค. CommonMoyaProvider<T: TargetType>
- ๋ง ๋คํธ์ํฌ ํต์ ์ ์ํด์ Moya๋ ์ฐ๋๊ฒ ์ง์ง ์ข์!! ์ด์ ๋์ ๋ฉ๋ฆฌํธ๋ ์๋ ๋๋์ด ๋ค์๋ค. ๊ทธ๋ฌ๋ ๋ถ๋ช ํ ์ฐ์์๊ฐ ์ข๊ณ ํ์ฉ๋๊ฐ ๋์๊ฑด ํ์ค!ํ๋ค. ์ฝ๋๋ ๊ฐ๊ฒฐํด์ง๊ณ ..?
- ์ด๋ฒ ํฌ์คํ ๋!
References
iOS Networking and Testing | ์ฐ์ํํ์ ๋ค ๊ธฐ์ ๋ธ๋ก๊ทธ
Networking์ ์์ฆ ์ฑ์์ ๊ฑฐ์ ํ์์ ์ธ ์์์
๋๋ค. ์ค์น๋์ด ์๋ ์ฑ๋ค ์ค์ ๋คํธ์ํน์ ์ฌ์ฉํ์ง ์๋ ์ฑ์ ๊ฑฐ์ ์์ ๊ฒ๋๋ค. API ์ถ๊ฐ๊ฐ ์ฝ๊ณ ๋ณ๊ฒฝ์ด ์ฉ์ดํ ๋คํธ์ํน ๋ชจ๋์ ๊ฐ๋ฐํ๋๊ฒ์ด ์ค์ํ ์ด์ ์ฃ . ๋ฏธ๋ ๋ณด์
จ๋์? ์๋ ์ฟ ํผ ๋ผ๋ ์ฃผ์ธ๊ณต์ 16์ด์ ๋ฐ์ฌํ์๋ฅผ ์ทจ๋ํ ๋งํผ ์ฒ์ฌ์ด๋ฉด์ ๋์์ ๋๋จํ ํน์ดํ ์ฌ๋์
๋๋ค. ์ฃผ๋ณ์์ "Are you crazy?" ๋ผ๋ ๋ง์ ์์ฃผ ๋ฃ์ต๋๋ค.

Uploaded by N2T