1. API ๋ช ์ธ์ ํ์ธํ๊ธฐ
2. PostMan ํ ์คํธ ํ๊ธฐ
Response ํํ๋ฅผ ์ง์ ํ์ธํ๊ธฐ
์ฑ๊ณต - 200 ํ์๊ฐ์ ์ฑ๊ณต
์คํจ - 409 Duplicate : ํด๋น ์ ๋ณด๊ฐ ์์๋
์๋ฒ ํต์ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ์ฌ์ ์ค๋น ๊ณผ์
3. HTTP ํต์ ์ ์ํ plist ์ค์ (http ์๋ฒ๋ก ํต์ ์ ์๋ํ๋ ๊ฒฝ์ฐ ์ค์ ํด์ฃผ๋ฉด ๋จ! https๋ ์ํด์ค๋ ๋จ)
๋ณดํต์ http ์๋ฒ์ ํต์ ํ๋ ค๊ณ ํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค. Apple ์ธก์์ ์ฑ ์์ฒด์ ๋ณด์์ฑ์ ์ํด์ ATS(App Transport Security)๋ผ๋ ์ ์ฑ ์ ํตํด ๊ธฐ๋ณธ์ ์ผ๋ก https ํต์ ์ ํ๋๋ก ์ ๋ํ๊ณ ์๊ธฐ ๋๋ฌธ!
4. APIConstants.swift ์์ฑ : API ์ฃผ์๋ฅผ ๋ชจ์ ๋์ ํ์ผ
์์ (์์น, ์ด๋์) : URI
Base URL๊ณผ ๋๋จธ์ง ๊ฒฝ๋ก๋ฅผ ๋๋์ด ๊ด๋ฆฌํ๋ฉด ํธํจ!
ํ์ ( ์ด๋ค ๊ฒ์ ํ ๊ฒ์ธ์ง ) : HTTP Method
ํํ, ๋ฉ์ธ์ง (์ด๋ฐ ๋ฐ์ดํฐ๊ฐ ์๋ค) : JSON
5. NetworkResult.swift ์์ฑ ( ์๋ฒ ํต์ ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ ์ด๊ฑฐํ )
์๋ฒ ํต์ ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํ์ผ
์๋ฒํต์ ์ ํ ๋ ๋ฐ์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ฉด๋จ
6. ๋ฐ์ดํฐ ๋ชจ๋ธ ์์ฑ ( ์๋ฒํต์ ์ผ๋ก ๋ฐ์ JSON ๋ฐ์ดํฐ๋ฅผ Swift๋ก ๋ฐ๊ฟ ๊ตฌ์กฐ์ฒด ๋ชจ๋ธ)
- ๋๊ฒจ ๋ฐ์ JSON์ Swift ๊ฐ์ฒด ํํ๋ก ์ ์ฌ์ฉํ ์ ์๋๋ก Data Model์ ์์ฑ
- ๊ธฐ๋ณธ์ ์ผ๋ก ๋คํธ์ํฌ ํต์ ๊ฒฐ๊ณผ๋ก ๋์ด์ค๋ JSON ๋ฐ์ดํฐ๋ฅผ ์ฑ์ด ์ดํดํ ์ ์๋๋ก swift ๋ฐ๊พธ์ด์ผํจ ( decode ๊ณผ์ )
Encodable, Decodable ํ๋กํ ์ฝ์ ๋ฌถ์ ๊ฒ = Codable์ ์ฌ์ฉํ๋ฉด ๋จ!
๋ฐ๋ก ๋๊ฐ์ ํ๋กํ ์ฝ์ ์ฑํํ์ง ์์๋ ๋จ
Encodable : ๋ฐ์ดํฐ ๋ชจ๋ธ์ Encodeํด์ data(JSON)์ผ๋ก ๋ณํํ๋ ค๋ฉด Encodable์ด๋ผ๋ ํ๋กํ ์ฝ์ ์ฑํํด์ผํจ
Decodable : data(JSON)์ Decodeํด์ ๋ฐ์ดํฐ ๋ชจ๋ธ๋ก ๋ง๋๋ ค๋ฉด Decodable์ด๋ผ๋ ํ๋กํ ์ฝ์ ์ฑํํด์ผํจ
๋ฐ์ดํฐ ๋ถ๋ถ์ด ์ต์ ๋์ธ ์ด์ : ๋ก๊ทธ์ธ์ด ์ฑ๊ณตํ ๋๋ data๊ฐ ๋์ด์ค๊ณ , ์คํจํ์ ๋๋ data๊ฐ ์๋์ด์ค๊ธฐ ๋๋ฌธ!
7. Service(Request - Response) ์ฝ๋ ์์ฑ
: (Request๋ฅผ ๋ง๋ค๊ณ ๋ณด๋ธ ํ Response๋ฅผ ๋ฐ๊ณ ํด๋ ํ๋ ์๋ฒ ํต์ ์ฝ๋๊ฐ ์๋ ํด๋์ค )
import Foundation
import Alamofire
//(1) ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
class UserService {
static let shared = UserService()
//(2)์ฑ๊ธํต ๊ฐ์ฒด๋ฅผ ์ ์ธํด์ ์ฑ ์ด๋์์๋ ์ง ์ ๊ทผ๊ฐ๋ฅํ๋๋ก ํ๋ค
private init() {}
func login(name: String, email: String, password: String, completion: @escaping(NetworkResult<Any>) -> Void)
{
let url = APIConstants.loginURL //ํต์ ํ API ์ฃผ์
//HTTP Headers : ์์ฒญ ํค๋
let header : HTTPHeaders = ["Content-Type" : "application/json"]
//์์ฒญ ๋ฐ๋
let body : Parameters = [
"name" : name,
"email" : email,
"password" : password
]
//์์ฒญ์ //Request ์์ฑ
//ํต์ ํ ์ฃผ์, HTTP๋ฉ์๋, ์์ฒญ๋ฐฉ์, ์ธ์ฝ๋ฉ๋ฐฉ์, ์์ฒญํค๋
let dataRequest = AF.request(url,
method: .post,
parameters: body,
encoding: JSONEncoding.default,
headers: header)
//request ์์ ,responseData๋ฅผ ํธ์ถํ๋ฉด์ ๋ฐ์ดํฐ ํต์ ์์
dataRequest.responseData{
response in //๋ฐ์ดํฐ ํต์ ์ ๊ฒฐ๊ณผ๊ฐ response์ ๋ด๊ธฐ๊ฒ ๋๋ค
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)
completion(networkResult)
case .failure:
completion(.networkFail)
}
}
}
private func judgeStatus(by statusCode: Int, _ data: Data) -> NetworkResult<Any> {
switch statusCode {
case ..<300 : return isVaildData(data: data)
case 400..<500 : return .pathErr
case 500..<600 : return .serverErr
default : return .networkFail
}
}
//ํต์ ์ด ์ฑ๊ณตํ๊ณ ์ํ๋ ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ค์ด์์๋ ์ฒ๋ฆฌํ๋ ํจ์
private func isVaildData(data: Data) -> NetworkResult<Any> {
let decoder = JSONDecoder() //์๋ฒ์์ ์ค ๋ฐ์ดํฐ๋ฅผ Codable์ ์ฑํ
guard let decodedData = try? decoder.decode(LoginResponse.self, from: data)
//๋ฐ์ดํฐ๊ฐ ๋ณํ์ด ๋๊ฒ๋ Response ๋ชจ๋ธ ๊ตฌ์กฐ์ฒด๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณํํด์ ๋ฃ๊ณ , ๊ทธ ๋ฐ์ดํฐ๋ฅผ NetworkResult Success ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ
else { return .pathErr }
return .success(decodedData as Any)
}
}
8. Service(Request - Response) ์ฝ๋ ํธ์ถ
: ๋ทฐ์ปจํธ๋กค๋ฌ ( ์๋ฒ ํต์ ์ฝ๋๋ฅผ ๋ทฐ์ปจํธ๋กค๋ฌ์์ ํธ์ถ)
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
// ๋ก๊ทธ์ธ ๋ฒํผ์ ๋๋ ์ ๋ ๋ก๊ทธ์ธ ์๋ฒ ํต์ ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
@IBAction func loginButtonTapped(_ sender: Any) {
print("๋ก๊ทธ์ธ")
login()
}
}
extension ViewController {
// ์๋ฒ ํต์ ์ฝ๋๋ฅผ ์ค์ ๋ก ๋ทฐ ์ปจํธ๋กค๋ฌ์์ ํธ์ถํด์ ์ฌ์ฉํ๋ ๋ถ๋ถ์
๋๋ค.
func login() {
// ๊ฐ๊ฐ์ ํ
์คํธ ํ๋์ ์๋ ๊ฐ์ ๋ฐ์์ต๋๋ค.
guard let name = nameTextField.text else { return }
guard let email = emailTextField.text else { return }
guard let password = passwordTextField.text else { return }
// ์๋ฒ ํต์ ์๋น์ค ์ฝ๋๋ฅผ ์ฑ๊ธํค ๋ณ์๋ฅผ ํตํด์ ์ ๊ทผํ๊ณ ์๋ค์.
// ํธ์ถ ํ์ ๋ฐ์ ์๋ต์ ๊ฐ์ง๊ณ , ์ ์ ํ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๊ณ ์์ต๋๋ค.
UserService.shared.login(
name: name,
email: email,
password: password) { response in
switch response {
case .success(let data):
guard let data = data as? LoginResponse else { return }
print(data)
self.alert(message: data.message)
case .requestErr(let err):
print(err)
case .pathErr:
print("pathErr")
case .serverErr:
print("serverErr")
case .networkFail:
print("networkFail")
}
}
}
// ์๋ฆผ์ฐฝ์ ๋์ฐ๋ ํจ์์
๋๋ค.
func alert(message: String) {
let alertVC = UIAlertController(title: message, message: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: "ํ์ธ", style: .default, handler: nil)
alertVC.addAction(okAction)
present(alertVC, animated: true)
}
}
์ด์ ๋ฆฌ
์ถ์ฒ :SOPT30 - ๊นํํ ํํธ์ฅ๋ 4์ฃผ์ฐจ ์ธ๋ฏธ๋