Swift Concurrency Task 알아보기

고라니·2024년 4월 5일
0

TIL

목록 보기
67/67

토이프로젝트에서 CompletionHandler를 통해 비동기 함수를 처리해주었는데 여러 단점이 있었고 Swift Cuncurrency를 습득해서 효과적으로 해결 할 수 있었다.
그런데 async 메서드는 비동기 컨텍스트 내부에서만 await를 통해 호출 할 수 있었고 viewdidLoad 같은 일반함수에서는 바로 호출이 불가했다.
이런 상황에서 Task {} 블럭 내에서 호출하는것이 가능한데, 오늘은 이 Task에 대해 알아볼도록 하겠다.

먼저 관련된 개념부터 다시한번 살펴보자


비동기 코드

  • 비동기 코드는 바로 실행되지 않는다.
  • 다음 라인의 코드 실행을 막지 않는다.

이전에도 비동기에대해서 알아보았는데 핵심은 기다려주지 않는다였다.

비동기 작업을 수행하기 위해 많이 쓰이는 두 가지 방식

(이 두가지만 있는건 아니지만 일반적으로 많이 사용된다.)

  • GCD: 새로운 스레드에 비동기 작업을 할당한다.
  • Concurrency: 비동기 메서드를 서스펜드시킨다. -> 해당 스레드의 제어권을 시스템에 부여 -> 시스템은 해당 스레드가 적절한 다른 작업을 수행하도록 한다. -> 비동기 작업이 완료되면 시스템은 다시 스레드의 제어권을 비동기 함수에 부여한다. (단, 이 때의 스레드는 처음 스레드와 동일할 것이라는 보장x)

이 둘을 비교했을 때 왜 Concurrency 방법이 더 효과적이라고 표현할까?

스레드를 차단하는 대신 제어권을 포기하고 작업을 중지/재개 할 수 있는 개념 도입이 어떤 차이를 만들 수 있을 까?

  • GCD는 비동기 함수를 실행하기 위해 필요시 스레드를 계속 생성, 이 때 코어의 개수보다 많은 스레드가 생성되고 block되는 스레드가 많아지면 메모리 스케쥴링 오버헤드 등 여러 문제점이 발생할 수 있다.

  • Concurrency는 CPU 코어 수만큼만 스레드를 만들고, 스레드를 차단하지 않고 효율적으로 작업을 전환하도록 한다.

즉 GCD는 비동기 함수를 수행 할 때마다 다른 스레드에 작업을 할당하는데 이 때 할당할 스레드가 없다면 새로 만들어서 할당하게 되고 결국 너무 많은 스레드가 생성되어 오버헤드가 발생할 수 있는것이다. 반면 Concurrency는 다른 스레드에 작업을 할당하는게 아니고 중단/재개 시켜 너무 많은 스레드가 만들어지지 않고 자원을 효율적으로 사용할 수 있다는 것이다.


Async 함수 호출하기

이 글을 작성하게 된 이유이다. Async 함수를 호출하기 위한 조건들이 있다.

  • async 코드는 동시 concurrency 컨텍스트에서만 실행 가능하다.
  • viewDidLoad 같은 일반 함수에서는 바로 async 함수를 호출 할 수 없다.
  • async 함수를 호출하기 위해서는 해당 함수를 호출하는 함수 또한 async함수 or Task {} 를 통해 수동으로 concurrency 컨텍스트를 제공할 때 가능하다.

Task

Task는 비동기 작업의 단위

  • Task는 인스턴스를 생성할 때 해당 작업을 수행하는 클로저를 제공한다.
    : 이 클로저는 비동기 적으로 수행할 코드가 작성된다.
func someFunction() {
	Task {
    	// 비동기 적으로 수행할 코드
    }
}
  • Task는 생성되자 마자 실행될 수 있음
    : 생성과 동시에 자동으로 제공된 클로저(비동기 적으로 수행할 코드)가 실행된다.
  • 생성한 후에는 해당 인스턴스를 사용하여 작업을 상호작용 할 수 있다.
    : Task를 대기 시키거나 취소
  • Task에 대한 참조를 기다리지 않고도 해당 작업이 완료되기를 기다리거나 작업을 취소할 수 있다.
    : Task가 실행되는 동안에도 다른 코드가 실행될 수 있고 상호작용할 수 있다.
  • But! Task에 대한 참조를 버리면 해당 Task의 완료를 기다리거나 취소하는 능력을 읽는다.
    : Task에 대한 참조를 유지 해햐만 Task의 상태를 추적or취소 가능, 참조를 버리면 생명주기 제어 X

즉 생성되자마자 실행되고, 인스턴스를 통해 상태를 추적하고 취소가 가능하고, 해당 작업의 완료를 기다리지 않고 다른 작업이 가능하다. 하지만 참조를 유지하지 않으면 해당 Task의 생명주기 제어가 불가하다.


마치면서

Task에 대해 좀더 알아볼 내용들이 있는데 그 내용은 다음에 Actor와 함께 정리해보도록 하겠다!
비동기 처리를 위해 Task를 잘 활용하자


참고 링크
https://developer.apple.com/documentation/swift/task,
https://sujinnaljin.medium.com/swift-actor-%EB%BF%8C%EC%8B%9C%EA%B8%B0-249aee2b732d

profile
🍎 무럭무럭

0개의 댓글