API(Application Programming Interface)
URL(Uniform Resource Locators): 웹에서 특정 위치를 나타내는 주소protocol: http, https - 인터넷 통신 규약을 의미Domain: 자원이 위치한 서버의 이름, url의 정체성Port: 어떤 서버를 이용할지 번호로 결정 (http - 80, https - 443)Path: 서버에서 제공하는 자원의 경로를 나타냄Query: 자원에 대한 추가적인 매개변수를 전달하는 데 사용됨. 주로 key=value 형식(여러개일 경우 &)Fragment: 자원내에서 특정 부분 가리킴REST API (Representational State Transfer)API 형식 중 하나.State) 를 표현해서 정보를 주고 받는 API 이다.HTTP URL 을 통해서 자원을 명시한다.HTTP Method (GET, POST, PUT, DELETE 등) 를 통해 해당 자원을 어떻게 할 것인지 CRUD 를 결정한다.REST API 도 결국 API 이기 때문에, 데이터를 주고 받는 형식, 창구라고 생각 할 수 있음.URLSessionURLSession은 네트워크 통신을 담당하는 Apple의 기본 클래스 iOS는 기본적으로 HTTP 요청을 직접 처리하지 않고 네트워트 매니저인 URLSession가 처리URLSession
↓
URLSessionTask
↓
dataTask / uploadTask / downloadTask
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
// 서버 데이터를 불러오는 메서드 선언
private func fetchData() {
// 리소스 URL 단순문자열이 아니라 유효한 형식인지 검증된 객체라서 옵셔널임,
// 리소스의 위치를 나타내는 객체
guard let url: URL = URL(string: "https://reqres.in/api/users/1") else {
print("URL is not correct")
return
}
// URLRequest 설정 - 어떤 요청을 보낼 것인가를 정의
var request: URLRequest = URLRequest(url: url)
// GET 메소드 사용 (GET, POST, PUT - 수정, DELETE)
request.httpMethod = "GET"
// json 데이터 형식임을 나타냄,
// HTTP Header는 이 요청의 부가 정보, Content-Type는 내가 보내는 데이터 형식
// GET 요청이라 body가 사실 필요없음
// GET일 때 Content-Type 안 붙이는 경우 많음
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
// URLSession 생성 - 네트워크 환경을 관리하는 객체 (기본 default 세션)
// configuration 종류
let session: URLSession = URLSession(configuration: .default)
// dataTask
session.dataTask(with: request) { (data, response, error) in
// http 통신 response 에는 status code 가 함께오는데, 200번대가 성공을 의미.
let successRange: Range = (200..<300)
// 에러 + 데이터 체크
guard let data, error == nil else { return }
// 타입캐스팅 response는 URLResponse 타입, HTTP 정보를 보려면 HTTPURLResponse로 다운캐스팅해야함
if let response: HTTPURLResponse = response as? HTTPURLResponse{
print("status code: \(response.statusCode)")
// 요청 성공 (StatusCode가 200번대)
if successRange.contains(response.statusCode){
// 요청 성공하면 decode하겠다.
guard let userInfo: ResponseData = try? JSONDecoder().decode(ResponseData.self, from: data) else { return }
print(userInfo)
} else { // 요청 실패 (Status code가 200대 아님)
print("요청 실패")
}
}
}.resume()
}
}
async/await 적용// async - 이 함수는 중간에 멈출 수 있는 함수(이 안에서는 await을 쓸 수 있음)
private func fetchData2() async {
// URL 객체 생성(실패가능성 있으니 옵셔널)
guard let url: URL = URL(string: "https://reqres.in/api/users/1") else {
print("URL is not correct")
return
}
// URLRequest 생성 - 요청 정보 설정
var request: URLRequest = URLRequest(url: url)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
// 세션 생성 - 네크워트 환경 관리자 생성
let session: URLSession = URLSession(configuration: .default)
do {
// await - 이 작업이 끝날때 까지 기다리지만 스레드는 점유 ㄴㄴ
// 네트워크 요청 시작하고 서버 응답 기다림 / 이 함수는 suspend 상태 / 현재 스레드는 다른 작업중 /
// 응답 도착하면 함수가 resume됨 / data와 response 반환
let (data, response) = try await session.data(for: request)
let successRange: Range<Int> = (200..<300)
guard let response: HTTPURLResponse = response as? HTTPURLResponse else { return }
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("요청 실패")
}
} catch {
print(error)
}
}
Synchronous): 한 작업이 끝날 때까지 다음 코드가 실행되지 않는 방식Asynchronous): 작업을 시작만 해두고, 끝날 때까지 기다리지 않고 다음 코드를 실행하는 방식UI가 멈춰서 사용자는 앱이 죽었다고 생각할 수 있음suspend) 될 수 있는 함수suspend(일시 중단)은 스레드를 멈춘다는 뜻이 아니고 현재 함수의 실행만 잠시 멈추고, 스레드는 다른 일을 하게 둠 -> 이게 asyncasync 방식: Swift Concurrency 런타임이 Continuation 객체를 만듦 - 함수 실행 상태를 저장 - 응답 오면 이어서 실행Task는 Swift Concurrency 런타임에 등록되는 작업 단위
생성되면 즉시 실행을 예약 시스템이 적절한 스레드에 배치
현재 스레드를 점유하지 않음
Task{} 자체는 실행 예약이라 언제 실행될지는 보장하지 않음
Task {
await fetchData()
}
@MainActorTask { @MainActor in
label.text = "완료"
}
.high,.medium,.low,.background)Task(priority: .high) {
await fetchData()
}
func anotherFunction() async {
await fetchData()
}
func test() async {
await fetchData()
print("끝")
}
fetchData 끝난 후 "끝" 출력 async 컨텍스트 안에서 기다리기 때문에do/try/catch 문실패할 수 있는 코드는 반드시 표시해야함
throws: 이 함수는 에러를 던질 수 있음
try: 에러 발생 가능
do: 에러 감싸는 블록
catch: 에러 잡기
try 종류
- try: 반드시 처리
- try?: 실패 시 nil
- try!: 실패하면 크래시