[ swift - 비동기 프로그래밍 ]

Yr Yr·2024년 1월 23일

TIL

목록 보기
31/39

✔️ 동기 / 비동기

- 쓰레드(Thread): 컴퓨터 프로그램을 실행하는 데 사용되는 가장 작은 실행 단위. 여러 쓰레드가 동시에 작업을 수행할 수 있으며 이러한 다중 쓰레드 작업은 시스템 자원을 효율적으로 활용하고 병렬적으로 작업을 처리할 수 있도록 도와준다.
- 동기(Synchronous): 한 작업이 시작되면 그 작업이 끝날 때가지 다음 작업은 대기한다. 순서가 중요한 경우에 동기가 사용된다.
- 비동기(Asynchronous): 순차적으로 기다리지 않고 여러 작업이 동시에 진행되는 것을 의미. 여러 작업이 동시에 처리되므로 시스템 자원을 효율적으로 사용할 수 있다. 대표적으로 네트워크 요청, 파일 입출력, 사용자 입력 대기 등과 관련이 있다.
- DispatchQueue: iOS에서 GCD(Grand Central Dispatch)를 사용하여 비동기적으로 작업을 관리하는 데 사용되는 클래스. 다양한 작업을 백그라운드 쓰레드에서 실행하고 메인 쓰레드와 같은 특정 쓰레드에서 실행되도록 예약할 수 있다. 이를 통해 앱의 성능을 향상시키고 사용자 인터페이스의 반응성을 유지할 수 있다.
- SerialQueue(직렬큐) : 작업을 순차적으로 실행하는 큐.
- ConcurrentQueue(병렬큐) : 여러 작업을 동시에 실행할 수 있는 큐.
 * 쓰레드 사용 시, 주의할 점은 UI 업데이트와 관련된 작업은 반드시 메인 쓰레드에서 실행되어야 한다.(DispatchQueue.main.async를 사용)
- 동기/비동기 예제
// 동기
func syncOperation() {
	print("시작")
    
    let queue = DispatchQueue(label: "com.example.queue")
    queue.sync {
    	for i in 1...3 {
        	print("동기 작업 \(i)")
        }
    }
    print("끝")
}
syncOperation()

// 비동기
func asyncOperation(completion: @escapint () -> Void) {
	print("시작")
    
    let queue = DispatchQueue(label: "com.example.queue")
    queue.async {
    	for i in 1...3 {
        	print("비동기 작업 \(i)")
        }
        completion() // 작업 완료 후 콜백 함수 호출
    }
    asyncOperation {
    	print("끝")
    }
}

✔️ Concurrency를 활용한 비동기 프로그래밍

- async: 비동기 작업을 나타내는 함수나 블록을 표시하는 데 사용.
- await: async 함수 내에서 사용되며 비동기 작업의 완료를 기다리고 해당 작업의 결과를 반환한다. 값을 반환하는 함수나 메서드 앞에 사용되며 비동기 작업이 완료될 때까지 실행을 일시중지하고 그 결과를 반환한다.
- Task: 비동기적으로 실행되는 코드 조각. 쓰레드를 직접적으로 다루지 않고도 비동기 코드를 실행하고 관리할 수 있도록 돕는다.
// fetchDataUsingConcurrency 함수를 async로 선언
func fetchDataUsingConcurrency(from url: URL) async throws -> Data {
	// await 키워드를 사용하여 URLSession의 data(from:) 메서드를 호출하고 데이터 다운로드가 완료될 때가지 일시 중단된다.
	let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

// 단일 사용
Task {
    do {
       	guard let url = URL(string: "https://www.example.com/data") { return }
        let data = try await fetchDataUsingConcurrency(from: url)
        print("Received data: \(data)")
    } catch {
        print("Error: \(error)")
      }
    }
    
// 연속된 비동기 처리
Task {
	do {
    	guard let url1 = URL(string: "https://www.example.com/data/1"),
        	  let url2 = URL(string: "https://www.example.com/data/2")
        else { return }
        let data1 = try await fetchDataUsingConcurrency(from: url1)
        print("Received data 1: \(data1)")
        let data2 = try await fetchDataUsingConcurrency(from: url2)
        print("Received data 2: \(data2)")
    } catch {
    	print("Error: \(error)")
    }
}

0개의 댓글