nyancoder

WWDC 2021 - Protect mutable state with Swift actors 본문

WWDC/WWDC 2021

WWDC 2021 - Protect mutable state with Swift actors

nyancoder 2021. 6. 29. 01:49

원본 영상: https://developer.apple.com/videos/play/wwdc2021/10133/

 

이 장에서는 Swift에서 새로 지원되는 Actor의 필요성과 활용에 대해서 알아봅니다.

 

기존 방식의 문제점

둘 이상의 스레드에서 동일 데이터에 접근할 때, 동시성 안정성이 보장되지 않아 예상하지 못한 결과를 얻을 수 있습니다.

기존에 이러한 문제를  컴파일 단계에서 회피하기 위한 수단으로 value타입을 사용하는 방법도 있습니다.

이 이외에 여러 스레드에서 동시에 접근되어야 하는 데이터가 손상되지 않도록 하기 위해서 아래의 방법을 사용할 수 있지만, 컴파일 단계에서 검증하는데 어려움이 있는 경우가 있었습니다.

  • Atomic
  • Lock
  • Serial dispatch queues

 

Actor

  • Actor는 class나 struct, enum 들과 같은 하나의 새로운 타입입니다.
  • Actor내의 함수 호출은 모두 동기 호출이므로 중간에 다른 함수 호출이 끼어들 수 없습니다.
  • 외부에서의 함수 호출은 비동기 호출로 이루어지며, async 키워드를 통한 비동기 처리와 마찬가지로 함수 호출의 결과를 받아 순서대로 처리하기 위해서 await 키워드를 사용할 수 있습니다.

 

Actor reentrancy

위의 예제에서 Actor 내의 image(from:) 함수에서 downloadImage(from:) 함수를 호출했을 때 현재 actor에서 수행 중인 작업은 일시정지가 됩니다. 그렇기 때문에 downloadImage(from:)의 결과를 받을 때까지 다른 작업이 동일 함수를 호출하여 cache의 상태를 변경할 수 있습니다. 위의 예제에서는 동일 url을 연속으로 두 번 호출한 경우, 두 번째 작업이 첫 번째 다운로드 작업이 끝나기 전에 실행되어 cache의 결과를 참조하지 않고 다운로드를 두 번 수행할 수 있습니다.

따라서 아래의 항목들을 유의해서 Actor를 다루어야 합니다.

  • Actor내에서의 상태 변경은 동기화되어 이루어집니다.
  • 하지만 Actor내의 한 작업의 실행이 일시 정지된 동안 다른 작업이 상태를 변경할 수 있습니다.
  • 때문에 await 구문 이후에서는 변수의 값이 예상대로인지 확인을 해야 할 필요가 있습니다.

 

Actor isolate

  • 변수의 접근은 항상 actor를 통해 이루어지는 것이 보장됩니다.
  • 변수의 접근이 하나의 스레드에서 접근되는 것이 보장됩니다.
  • nonisolated 키워드를 통해 특정 함수는 Actor의 내에 선언되어 있어도 Actor의 밖에서 선언된 것처럼 다룰 수 있습니다. 이런 경우 Actor의 상수에는 접근이 가능하지만 변수에 접근하는 경우 오류가 발생할 수 있습니다.

  • Actor내부의 상태를 변경할 수 있는 객체를 리턴하는 것을 막기 위해서, Sendable 프로토콜을 통해 Actor의 내부의 값이 전달됩니다.

 

Sendable

  • 동시성을 보장해주기 위해서 각 Actor의 외부로 전달할 수 있는 값은 Sendable 조건을 만족시켜야 합니다.
  • 값 타입, Actor, 불변 클래스, 내부적으로 동기화 처리가 된 클래스, @Sendable 함수 타입이 이에 해당됩니다.
  • @Sendable Closure는 변수를 캡처할 수 없으며, Sendable을 만족하는 값 만을 가질 수 있습니다.
  • @Sendable은 Actor내의 함수를 동기로 실행할 수 없습니다.

Main actor

기존에 사용하던 DispatchQueue.main.async 함수를 호출하던 방식 대신 함수 앞에 @MainActor를 추가하여 함수가 메인 스레드에서 실행되도록 보장할 수 있습니다.

타입에도 @MainActor를 붙일 수 있으며, 해당 타입 내의 모든 함수와 속성은 MainActor의 것이 됩니다.

다른 Actor와 마찬가지로 원하지 않는 함수는 nonisolated 키워드를 붙여 Actor외부의 함수처럼 사용할 수 있습니다.

 

목차: https://nyancoder.tistory.com/2

Comments