Thread (쓰레드)?
- Thread 는 컴퓨터 프로세스 내에서 실행되는 실행 흐름의 단위다.
- 프로세스 Process 는 운영체제로부터 자원을 할당받아 실행 중인 프로그램의 인스턴스를 나타내는, 각각의 프로세스는 하나 이상의 쓰레드를 갖을 수 있다.
- Swift 에서의 Thread 종류
- 메인 쓰레드 (Main Thread) : 애플리케이션의 주요 인터페이스 UI 및 UI 업데이트를 담당하느 스레드입니다. UI 요소의 변경은 메인 스레드에서 수행되어야 합니다.
- 백그라운드 쓰레드 (Background Thread) : 메인 스레드 이외에 동시에 작업을 수행하기 위해 생성되는 스레드들을 말한다. 주로 작업을 분산하거나 병렬로 처리할 때 사용된다.
비동기 (Asynchronous)?
동기 (synchronous) vs 비동기 (Asynchronous)
동기 Sync
: 작업이 순차적으로 실행되는 것을 의미한다. 하나의 queue 처럼 FIFO 방식으로 작동된다고 생각하면 된다.
비동기 Async
: 작업이 별도의 쓰레드 또는 백그라운에서 실행되며, 다른 작업을 기다리지 않고 동시에 실행된다. 작업이 완료되면 콜백 (Callback)
혹은 완료 핸들러 (Completion Handler)
를 통해 결과를 처리한다. 메서드 호출 순서대로 작업이 완료된다는 것을 보장하지 않는다. 자동으로 Thread Scheduling을 통해 최적의 성능을 보장한다고 한다. [공식문서]
직렬 (Serial) vs 동시 (Concurrent)
직렬 Serial
: 분산처리 시킨 작업을 오직 한 개의 쓰레드에서만 처리하는 것이다. 예를 들면, A 쓰레드에서 4개의 작업을 분산처리 했는데, 4개의 작업 모두 하나의 같은 쓰레드 B에서만 처리하는것이다.
동시 Concurrent
: 몇개의 쓰레드로 분산할지는 시스템이 정하여 여러개의 쓰레드로 분산 처리 하는 것. 작업들이 유가한 작업 일수록 유용하다.
DispatchQueue
- GCD ( Grand Central Dispatch ) : Apple 플랫폼에서 멀티스레드 프로그래밍을 간단하고 효율적으로 구현하기 위한 기술이다. GCD는 다양한 작업을 관리하고 실행하기 위한 API를 제공하고 병렬성을 활용할 수 있게 한다.
GCD (Grand Central Dispatch) 의 특징
- Queue : GCD는 큐를 사용하여 작업을 관리하고, 세분화하고, 실행할 큐에 따라 작업의 속성이 결정할 수 있다.
- 간편한 비동기 작업 처리 : GCD를 사용하면 비동기적으로 작업을 수행할 수 있다. 개발자가 따로 쓰레드를 관리 해주지 않아도 되게끔 작동한다.
- Queue의 종류에 따라서 다른 동작 방식: Serial Queue, Concurrent Queue, 앞서 말한 직렬 및 동시의 특징에 따른 Queue가 존재한다.
- 콜백 사용
- QoS ( Quality of Service ) 지원 : GCD는 각 큐에 대한 우선순위 설정을 지원하여 시스템이 작업을 최적의 성능을 유지하며 진행할 수 있도록 한다.
DispatchQueue.main vs DispatchQueue.global()
- main 쓰레드는 UI를 담당하는 쓰레드이며, 사용자 인터페이스 및 상호작용을 처리하는 쓰레드이다. 따라서 오래 걸리는 작업을 main 쓰레드에서 진행할 경우, 앱이 멈추거나 끊기는 현상을 볼 수 있다.
- 반명 global은 전역(백그라운드) 스레드이기 때문에, 오래 걸리는 작업을 global에서 처리하여 콜백을 통해 main Thread로 넘겨주는 작업을 주로한다.
- DispatchQueue.global()은 기본적으로 Concurrent 방식이고, Main은 Serail 방식이다.
- 전역 DispatchQueue에서
async
sync
를 사용하여 작업을 추가하면, 해당 작업은 백그라운에서 실행된다.
- 신기한건(?) swift에서는 Thread Scheduling 에 대해서 사용자는 알 수 있는 방법이 없다고 한다. (DispatchQueue를 사용한다면)
- 예시 코드 :
import Foundation
DispatchQueue.global().sync {
print("Synchronous Task")
}
DispatchQueue.global().async {
print("Asynchronous Task")
}
DispatchQueue.global().async {
for i in 1...5 {
print("Background Task \(i)")
print("Current Thread: \(Thread.current)")
}
DispatchQueue.main.async {
print("Background Task Completed, Updating UI")
}
}
print("Hello")
네트워킹 (Networking)
- swift에서의 네트워킹은 주로 URLSession을 사용하여 수행된다.
- 네트워킹은 주로 외부 서버 또는 인터넷 리소스와 데이터를 주고 받는 작업이며, 네트워크 환경에 따라서 작업 소요시간이 달라지기 떄문에, 주로 비동적인 방식으로 처리하는 것이 일반적이다.
- 아래 예시 코드를 통해 더 자세히 알아보자
import Foundation
func fetchData() {
if let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1") {
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
if let httpResponse = response as? HTTPURLResponse {
print("Status code: \(httpResponse.statusCode)")
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let jsonDict = json as? [String: Any] {
print("Received JSON data: \(jsonDict)")
}
} catch {
print("JSON parsing error: \(error.localizedDescription)")
}
}
}
task.resume()
}
}
fetchData()
fetchDate()
함수를 선언한다.
- 주소를 URL 타입으로 타입캐스팅을 한다.
- 영어나 특수한 문자만 사용 가능하고, 한글이나 공백을 포함시 nil을 리턴한다.
- URL에 한글이나 공백이 있을 경우,
String.addingPercentEncoding
을 통해 변환을 해야한다.
URLSession.shared.dataTask
을 분리해서 해석을 하자면
URLSession
: iOS 또는 MacOS에서 네트워크 통신을 처리하기 위한 API
URLSession.shared
: 기본 URLSession 인스턴스를 반환하는 프로퍼티. 해당 인스턴스는 전역에서 공유되는 객체로, 네트워크 작업을 수행하기 위해 사용된다.
URLSession.shared.dataTask(with:completionHandler:)
: URLSession 객체의 메서드로, 지정된 URL에서 데이터를 가져오는 비동적인 작업을 생성한다. with:
매개 변수는 URL을 나타내고, completionHandler:
는 작업이 완료 되었을때 호출되는 클로저다.
- 따라서 해당 코드는 URLSession의 전역 공유 인스턴스를 생성하여, 지정된 URL에서 데이터를 가저오는 비동기적 작업을 생성하였고, 아래 있는 코드 부분에 completionHandler에 해당하는 클로저다.
- ComletionHandler 클로저
- CompletionHandler는 세개의 매개변수를 갖게 된다.
completionHandler: @escaping @Sendable (Data?, URLResponse?, (any Error)?) -> Void
Data?
URLResponse?
Error?
- Data는 말그래도 서버에서 반환된 데이터를 말한다. URLResonpnse는 metadata 즉 헤더, status code, protocol 등등이 반환된다. Error는 Request fail한 경우 nil을 반환한다.
- 해당 URL은 JSon 파일을 반환하기 떄문에, JSON 파일을 파싱하는 과정도 추가하였다.
JSONSerialization
는 JSON 데이터를 다루기 위한 Swift 내장 클래스이다.
JSONSerialization.jsonObject
를 통해 데이터를 JSON Object로 생성하고, 옵션을 줄 수 있지만, 옵션의 대해서는 추후에 더 공부할 예정이다.
- 이후에 데이터의 대한 파싱을 하여 print하는 것이다.
Task.resume()
로 해당 task 실행