본문 바로가기

iOS 앱 개발자 프로젝트/Swift 문법 정복하기

[Swift] Thread, Asynchronous & Networking

2024년 3월 14일 화이트데이

스레드와 비동기에 대해 알아보고 비동기를 활용하여 서버로부터 데이터를 받아오는 네트워킹에 대해 공부합니다.


 

☑️  Thread

    • 스레드(Thread)는 컴퓨터 프로세스 내에서 실행되는 실행 흐름의 단위. 프로세스는 운영체제로부터 자원을 할당받아 실행 중인 프로그램의 인스턴스를 나타내는데, 각 프로세스는 하나 이상의 스레드를 가질 수 있다.
      •  Swift에서의 스레드 종류
        • 메인 스레드(Main Thread) - App의 주요 인터페이스 및 UI 업데이트를 담당하는 스레드. UI 요소의 변경은 메인 스레드에서 수행
        • 백그라운드 스레드(Background Threads) - 메인 스레드 이외에 동시에 작업을 수행하기 위해 생성되는 스레드들을 일컫는다. 주로 작업을 분산하거나 병렬로 처리할 때 사용

 

☑️  Asynchronous

  • 동기 (Synchronous) vs. 비동기 (Asynchronous)
    • 동기(Sync) : 작업이 순차적으로 실행되는 것을 의미합니다. 한 작업이 끝날 때까지 다음 작업이 기다리며, 작업이 순서대로 실행
    • 비동기(Async) : 작업이 별도의 스레드 또는 백그라운드에서 실행되며, 다른 작업을 기다리지 않고 동시에 실행된다. 작업이 완료되면 콜백(callback) 또는 완료 핸들러(completion handler)를 통해 결과를 처리. 메서드 호출 순서대로 작업이 완료된다는 것이 보장되지 않는다.
      ※  직렬(Serial) vs 동시(Concurrent)
    • 직렬(Serial) : 분산처리 시킨 작업을 오직 한 개의 쓰레드에서만 처리하는 것이 직렬이다. 즉, A 스레드에서 4개의 작업을 분산처리 시켰는데, B 스레드에서만 처리하는 것이다.
    • 동시(Concurrent) : 시스템이 정한 여러 개의 스레드로 분산 처리하는 것. 작업들이 각자 독립적이지만 유사한 작업들일 때 굉장히 유용하다.(예를 들면 테이블뷰 셀 같은 것들을 서버에서 받아오는 것)
    ※  DispatchQueue
    • Grand Central Dispatch(GCD)는 iOS, macOS 등의 Apple 플랫폼에서 멀티스레드 프로그래밍을 간단하고 효율적으로 구현하기 위한 기술. GCD는 다양한 작업을 관리하고 실행하기 위한 강력한 API를 제공하여 병렬성을 활용할 수 있게 해준다.
    ※  GCD의 특징:
    1. 큐(Queue) 기반의 작업 관리: GCD는 큐를 사용하여 작업을 관리한다. 이를 통해 작업을 세분화하고, 실행할 큐에 따라 작업의 속성을 결정할 수 있다.
    2. 간편한 비동기 작업 처리: GCD를 사용하면 비동기적으로 작업을 수행할 수 있다. 이는 프로그래머가 별도의 스레드를 관리하지 않아도 되므로 개발을 간편하게 만들어 준다.
    3. 큐의 종류에 따른 다양한 동작 방식: GCD에는 Serial Queue와 Concurrent Queue가 있다. Serial Queue는 작업이 순차적으로 실행되며, Concurrent Queue는 여러 작업이 동시에 실행될 수 있다.
    4. 콜백을 통한 작업 완료 처리: 작업이 완료되면 콜백(closure)을 사용하여 결과를 처리할 수 있다.
    5. QoS(Quality of Service) 지원: GCD는 각 큐에 대한 우선순위 설정을 지원하여 시스템이 작업을 적절히 관리하고 최적의 성능을 유지할 수 있도록 한다.
    DispatchQueue.main:
    • 주로 앱의 UI 업데이트와 관련된 작업을 처리하는데 사용
    • 메인 스레드에서 동작하며, 주로 사용자 인터페이스(UI)를 업데이트하거나 사용자와의 상호작용을 처리할 때 사용      →  주의해서 사용하지 않으면 UI의 응답성이 떨어질 수 있다. 긴 작업이 메인 스레드에서 실행되면 앱이 멈추거나 뚝뚝 끊기는 현상이 발생할 수 있다.
    DispatchQueue.global():
    • 전역(백그라운드) 스레드에서 작업을 처리하는데 사용
    • 여러 스레드에서 동시에 실행되는 비동기 작업을 처리할 때 유용하다.
    • 전역 DispatchQueue에서 async 또는 sync를 사용하여 작업을 추가하면, 해당 작업은 백그라운드에서 실행된다.

       

// 동기적으로 실행되는 작업
DispatchQueue.global().sync {
    print("Synchronous Task")
}

// 비동기적으로 실행되는 작업
DispatchQueue.global().async {
    print("Asynchronous Task")
}

// 백그라운드에서 비동기 작업 실행
DispatchQueue.global().async {
    // 여기서 백그라운드에서 실행될 작업을 수행합니다.
    for i in 1...5 {
        print("Background Task \(i)")
    }
    
    // 작업이 완료되었음을 메인 스레드로 알립니다.
    DispatchQueue.main.async {
        print("Background Task Completed, Updating UI")
        // UI 업데이트 등을 수행할 수 있습니다.
    }
}

/*
위의 예시는 DispatchQueue.global().async를 사용하여 백그라운드에서 비동기 작업을 
실행하는 코드입니다. 이 코드는 백그라운드에서 1부터 5까지의 작업을 실행한 후, 
해당 작업이 완료된 후에 메인 스레드에서 UI 업데이트를 실행합니다.
*/

 

 

 

☑️   Networking

  • 네트워킹은 외부 서버 또는 인터넷 리소스와 데이터를 주고받는 작업을 의미하며, 비동기적인 방식으로 처리
  • URLSession을 사용하여 네트워크 요청을 보내면, 기본적으로 비동기 방식으로 처리되는데, 이는 해당 코드 블록이 네트워크 요청을 보낸 후 바로 다음 코드로 진행되며, 응답이 도착하면 그에 맞게 처리된다.
// URLSession의 dataTask 함수 정의
func dataTask(
    with url: URL,
    completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void
) -> URLSessionDataTask


// 네트워크 작업을 처리할 함수
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 {
                    // JSON 데이터 파싱
                    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 함수 호출
fetchData()
  •  

'iOS 앱 개발자 프로젝트 > Swift 문법 정복하기' 카테고리의 다른 글

[Swift] Closure, Higher Order Function  (0) 2024.03.16
[Swift] Escaping closure  (0) 2024.03.15
[Swift] Generic  (0) 2024.03.13
[Swift] Extension  (0) 2024.03.13
[Swift] protocol, associatedtype, typealias  (0) 2024.03.13