네트워크란 둘 이상의 컴퓨터가 연결되고 소통하는 것을 의미한다.
다음과 같은 개념들을 알고 있어야 한다:
네트워크 통신 코드를 학습하기 전에, 알아야 할 기본 개념들을 먼저 살펴보도록 하자.
JSON (JavaScript Object Notation)은 데이터를 표현하는 형식 중 하나이다.
예를 들어, 이름이 Adam이고 전화번호가 010-1111-2222라는 정보를 다른 누군가에게 전달할 때 어떤 포맷으로 전달하는 것이 좋을지 생각해보자.
네트워크에서 데이터를 주고받을 때는 정해진 형식을 지켜서 데이터를 교환하는 것이 중요하다. 이러한 형식 중 서버와 클라이언트가 가장 많이 사용하는 것이 JSON 형식이다.
예시:
[
{
"name": "Adam",
"phoneNumber": "010-1111-2222"
},
{
"name": "Eve",
"phoneNumber": "010-3333-4444"
},
{
"name": "Abel",
"phoneNumber": "010-5555-6666"
}
]
API (Application Programming Interface)는 프로그램을 개발할 때 원하는 기능들을 제공해주는 창구, 설명서, 도구를 의미한다.
API를 이해하기 위해서는 먼저 API의 I(Interface)가 무엇인지 이해해야 한다. 개발 용어에서 인터페이스는 항상 창구를 의미한다.
내부 구현을 알 필요 없이 제공된 창구를 통해 소통하면 된다는 개념이다.
TV를 컨트롤하기 위한 리모콘을 생각해보자:
서버의 데이터베이스에 모든 유저의 정보가 있다고 가정해보자.
// API Request
{
"name": "Adam"
}
// API Response
{
"name": "Adam",
"phoneNumber": "010-1111-2222",
"Mbti": "ENTJ"
}
iOS 개발자는 이 API 명세를 보고, Request JSON과 Response JSON 형식을 지켜서 서버와 소통하는 코드를 작성하면 된다.
Swift의 인코딩과 디코딩에 대해 알아보자.
Swift의 Codable 프로토콜을 채택한다는 것은 인코딩과 디코딩이 가능함을 의미한다.
예시 코드:
struct PhoneBook: Codable {
let name: String
let phoneNumber: String
}
import Foundation
struct PhoneBook: Codable {
let name: String
let phoneNumber: String
}
let jsonString = """
[
{
"name": "Adam",
"phoneNumber": "010-1111-2222"
},
{
"name": "Eve",
"phoneNumber": "010-3333-4444"
}
]
"""
let jsonData = jsonString.data(using: .utf8)!
let jsonDecoder = JSONDecoder()
do {
let phoneBooks = try jsonDecoder.decode([PhoneBook].self, from: jsonData)
for phoneBook in phoneBooks {
print("name: \(phoneBook.name), phoneNumber: \(phoneBook.phoneNumber)")
}
} catch {
print("JSON 디코딩 실패")
}
URL(Uniform Resource Locators)은 웹에서 특정 위치를 나타내는 주소를 의미한다.
REST API(Representational State Transfer)는 전세계에서 가장 널리 사용되는 API 형식 중 하나이다.
GET https://spartacodingclub.com/users
응답:
[
{
"id": 1,
"name": "Adam",
"email": "adam.doe@example.com"
},
{
"id": 2,
"name": "Eve",
"email": "eve.smith@example.com"
}
]
URLSession은 Swift에서 서버와 통신하기 위해 제공되는 클래스이다.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
private func fetchData() {
let defaultUrlSession = URLSession(configuration: .default)
guard let url: URL = URL(string: "https://reqres.in/api/users/1") else {
print("URL is not correct")
return
}
var request: URLRequest = URLRequest(url: url)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session: URLSession = URLSession(configuration: .default)
session.dataTask(with: request) { (data, response, error) in
let successRange: Range = (200..<300)
guard let data, error == nil else { return }
if let response: HTTPURLResponse = response as? HTTPURLResponse {
print("status code: \(response.statusCode)")
if successRange.contains(response.statusCode) {
guard let userInfo: ResponseData = try? JSONDecoder().decode(ResponseData.self, from: data) else { return }
print(userInfo)
} else {
print("요청 실패")
}
}
}.resume()
}
}
// 데이터 모델
struct UserData: Codable {
let id: Int
let email: String
let firstName: String
let lastName: String
let avatar: URL
enum CodingKeys: String, CodingKey {
case id
case email
case firstName = "first_name"
case lastName = "last_name"
case avatar
}
}
struct SupportData: Codable {
let url: URL
let text: String
}
struct ResponseData: Codable {
let data: UserData
let support: SupportData
}