ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๋ฐ˜์‘ํ˜•



๐Ÿ“– Actor (1) ์ฝ์œผ๋Ÿฌ๊ฐ€๊ธฐ

๐Ÿ“š Actor (2) ์ฝ์œผ๋Ÿฌ๊ฐ€๊ธฐ

 

์•ˆ๋…•ํ•˜์„ธ์š” :) Zedd์ž…๋‹ˆ๋‹ค.

Actor (2) - Actor isolation ๊ธ€์—์„œ Actor isolation์„ ๊ณต๋ถ€ํ•ด๋ดค๋Š”๋ฐ์š”.

์˜ค๋Š˜์€ isolated parameter / nonisolated keyword์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋“œ์‹œ Actor (2) - Actor isolation ๊ธ€์„ ์ฝ๊ณ ์™€์ฃผ์„ธ์š”.

 

# ํ•œ๊ณ„ 

Actor (2) - Actor isolation ๊ธ€์—์„œ BankAccount Actor๋ฅผ ์ •์˜ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.

(extension์— ์žˆ๋˜ Transfer๋ฉ”์†Œ๋“œ๋Š” ์ œ์™ธํ•˜๊ณ  ๋ณด๋„๋กํ•˜์ฃ )

actor BankAccount {
  let accountNumber: Int
  var balance: Double

  init(accountNumber: Int, initialDeposit: Double) {
    self.accountNumber = accountNumber
    self.balance = initialDeposit
  }
  
  func deposit(amount: Double) {
    assert(amount >= 0)
    self.balance = self.balance + amount
  }
}

์œ„ ์ฝ”๋“œ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

 

ํ•œ๊ณ„ 1. deposit๋ฉ”์†Œ๋“œ๋Š” ๋ฐ˜๋“œ์‹œ actor์˜ ์ธ์Šคํ„ด์Šค๋กœ๋งŒ ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ๋‚˜๋Š” ์–ด๋–ค ๊ณ„์ขŒ ์ฃผ๊ณ  ์—ฌ๊ธฐ์— ์ž…๊ธˆํ•ด~ ๋ผ๊ณ  ํ•˜๊ณ ์‹ถ์„ ์ˆ˜ ์žˆ์ฃ . 

func deposit(amount: Double, to account: โœ… BankAccount โœ…) {
  assert(amount >= 0)
  account.balance = account.balance + amount
}

์ฆ‰ ์ด๋Ÿฐ์‹์œผ๋กœ global function์„ ๋งŒ๋“ค๊ณ  ์‹ถ์ง€๋งŒ, ๊ทธ๊ฒŒ ์•ˆ๋ฉ๋‹ˆ๋‹ค.

์™œ์ธ์ง€๋Š” ์•„์‹œ์ฃ !?!? 

๊ธ€์—์„œ ๋ดค๋˜ Transfer์™€ ๋™์ผํ•œ ๊ฒ๋‹ˆ๋‹ค.

func deposit(amount: Double, to account: BankAccount) {
  assert(amount >= 0)
  account.balance = account.balance + amount // Actor-isolated property 'balance' can not be referenced from a non-isolated context
}

balance๋ฅผ ์ฐธ์กฐํ•ด์•ผํ•˜๋Š”๋ฐ, balance๋Š” actor-isolated ํ”„๋กœํผํ‹ฐ์ด๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .

์ด๊ฑด self๋ฅผ ํ†ตํ•ด ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ๋„ ์•„๋‹ˆ์–ด์„œ cross-actor reference์— ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค.

2๋ฒˆ์—์„œ ์ž์„ธํžˆ ๋ณด๋„๋ก ํ•ฉ์‹œ๋‹ค.

 

ํ•œ๊ณ„ 2. actor์™ธ๋ถ€์—์„œ synchronouslyํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” computed property๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.

์ž, BankAccount์— ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ณ , 

actor BankAccount {
    let accountNumber: Int
    var balance: Double
    let accountName: String โœ…
    
    var displayName: String {
        return self.accountName + "์•ˆ๋…•ํ•˜์„ธ์š”" โœ…
    }
    
    init(accountNumber: Int,
         initialDeposit: Double,
         accountName: String) {
        self.accountNumber = accountNumber
        self.balance = initialDeposit
        self.accountName = accountName
    }
}

accountName์„ ๋ฐ›๊ณ , displayName์€ accountName์— ๋ญ”๊ฐ€๋ฅผ ๋ถ™ํ˜€์„œ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. 

๊ฐ„๋‹จํ•œ computed property๋„ค์š”.

actor BankAccount { ... }

let account = BankAccount(accountNumber: 1,
                          initialDeposit: 100,
                          accountName: "Zedd")
account.displayName // Actor-isolated property 'displayName' can not be referenced from a non-isolated context

actor์™ธ๋ถ€์—์„œ BankAccount ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ , displayName์„ ํ˜ธ์ถœํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค.

Actor (2) - Actor isolation ๊ธ€์—์„œ ๋งํ–ˆ๋“ฏ์ด, actor์— ์ •์˜๋œ

- stored, computed instance properties 

- instance methods 

- instance subscripts

๋Š” ๋ชจ๋‘ actor-isolated ์ƒํƒœ์ž…๋‹ˆ๋‹ค. 


๊ทธ๋ฆฌ๊ณ  ์ง€๊ธˆ account.displayName์€ 

actor ์™ธ๋ถ€์—์„œ actor-isolated ์ •์˜์— ๋Œ€ํ•ด ์ฐธ์กฐํ•˜๋Š”๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— cross-actor reference๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

cross-actor reference๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜ 2๊ฐ€์ง€ ์กฐ๊ฑด ์ค‘ ํ•˜๋‚˜์— ๋ฐ˜๋“œ์‹œ ํ•ด๋‹นํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. 

1. ๋ถˆ๋ณ€ ์ƒํƒœ์— ๋Œ€ํ•œ cross-actor reference. (๊ฐ™์€ ๋ชจ๋“ˆ ๋‚ด์—์„œ๋งŒ) 

2. ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋กœ ์ˆ˜ํ–‰๋˜๋Š” ํ˜•์‹

displayName์€ let์œผ๋กœ ์„ ์–ธ๋˜์–ด์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— 1๋ฒˆ์—๋Š” ํ•ด๋‹น์ด ์•ˆ๋˜๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ๋น„๋™๊ธฐ๋กœ ํ˜ธ์ถœํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, 

actor BankAccount { ... }

let account = BankAccount(accountNumber: 1,
                          initialDeposit: 100,
                          accountName: "Zedd")
await account.displayName โœ…

await๊ณผ ํ•จ๊ป˜ ํ˜ธ์ถœํ•ด์•ผํ•˜๋ฉฐ, ์œ„ ์ฝ”๋“œ๋„ ์–ด๋Š ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ถˆ๋ฆดํ…Œ๋‹ˆ ํ•จ์ˆ˜๋ฅผ async๋กœ ๋งŒ๋“ค๊ฑฐ๋‚˜, async ํ•ธ๋“ค๋Ÿฌ ๋‚ด์—์„œ ํ˜ธ์ถœํ•ด์•ผ๊ฒ ์ฃ . 

๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ๊ฒฐ๋ก ์€ ๋ถˆํŽธํ•˜๋‹ค๋Š”๊ฒ๋‹ˆ๋‹ค.

actor ์™ธ๋ถ€์ด๊ธด ํ•˜์ง€๋งŒ displayName์ •๋„๋Š” ๊ทธ๋ƒฅ synchronouslyํ•˜๊ฒŒ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ์ž–์•„์š”? 

 

ํ•œ๊ณ„ 3. Hashable conform ๋ถˆ๊ฐ€

actor BankAccount {
    ... 
    
    static func someStaticThing() {
        //
    }
}

BankAccount.someStaticThing() โœ…

BankAccout์•ˆ์— ์žˆ๋Š” static ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์†Œ๋“œ๋Š” actor-isolated ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 

์ฆ‰, actor์™ธ๋ถ€์—์„œ ๋ณ„๋‹ค๋ฅธ ์ œ์•ฝ์—†์ด ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

BankAccount๊ฐ€ Equatable์„ ์ค€์ˆ˜ํ•˜๋„๋ก ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

extension BankAccount: Equatable {
    
    static func == (lhs: BankAccount, rhs: BankAccount) -> Bool {
        return lhs.accountNumber == rhs.accountNumber
    }
}

ํ•„์š”ํ•œ static ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์คฌ์Šต๋‹ˆ๋‹ค. 

accountNumber๋Š” let. ์ฆ‰ ๋ถˆ๋ณ€์ƒํƒœ์˜ ์ ‘๊ทผ์ด์—ˆ๊ณ , ==๋Š” static ๋ฉ”์†Œ๋“œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์œ„ ์ •์˜๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

(๋งŒ์•ฝ ๋น„๊ต์— balance๋ฅผ ๋„ฃ์—ˆ์œผ๋ฉด ์ปดํŒŒ์ผ์ด ์•ˆ๋๊ฒ ์ง€๋งŒ์š”.) 

 

BankAccount๊ฐ€ Hashable์„ ์ค€์ˆ˜ํ•ด์ฃผ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

extension BankAccount: Hashable {

    func hash(into hasher: inout Hasher) {
        hasher.combine(self.accountNumber) // Actor-isolated instance method 'hash(into:)' cannot be used to satisfy a protocol requirement
    }
}

WWDC21 Protect mutable state with Swift actors ๋ฅผ ๋ณด๋ฉด

์˜ค๋ฅ˜๋ฉ”์‹œ์ง€๊ฐ€ ์ด๋ ‡๊ฒŒ ๋‚ฌ๋˜ ๊ฒƒ ๊ฐ™์€๋ฐ..์•„๋ฌดํŠผ Xcode13 Beta 5 ๊ธฐ์ค€์œผ๋กœ 

 Actor-isolated instance method 'hash(into:)' cannot be used to satisfy a protocol requirement


์ด๋ ‡๊ฒŒ ๋‚˜์˜ต๋‹ˆ๋‹ค.

 

์ž ์™œ ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚ ๊นŒ์š”?

Swift ์ปดํŒŒ์ผ๋Ÿฌ : BankAccount๊ฐ€ Hashable์„ ์ค€์ˆ˜ํ–ˆ์–ด? ๊ทธ๋Ÿผ ์ด hash(into:)๋Š” actor์™ธ๋ถ€์—์„œ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ๊ฒ ๊ตฐ...

ํ•˜์ง€๋งŒ hash(into:)๋Š” ๋น„๋™๊ธฐ๊ฐ€ ์•„๋‹ˆ๋‹ˆ๊นŒ actor-isolated๋ฅผ ์œ ์ง€ ํ•  ์ˆ˜ ์—†์–ด! 

Actor-isolated instance method 'hash(into:)' cannot be used to satisfy a protocol requirement


๋„ ๊ทธ๊ฑธ ๋‚˜ํƒ€๋‚ด๊ณ  ์žˆ์ฃ .

actor์˜ instance method๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ actor-isolated ์ƒํƒœ์ธ๋ฐ, 

Actor-isolated์ธ ๋ฉ”์†Œ๋“œ hash(into:)๋Š” protocol requirement๋ฅผ ์ถฉ์กฑํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. 


์ธ๊ฒ๋‹ˆ๋‹ค.

์ด๊ฒŒ 3๋ฒˆ์งธ ํ•œ๊ณ„์ž…๋‹ˆ๋‹ค.

Hashable์„ ์ค€์ˆ˜ํ•  ์ˆ˜ ์—†๋‹ค๋Š”๊ฑด, Set<BankAccount>๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค๋Š” ๊ฑธ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. 

 

# ์›์ธ 

์ž..ํ•œ๊ณ„์ ๋“ค์„ ๊ฐ„๋‹จํžˆ ์š”์•ฝํ•ด๋ณด๋ฉด,

1. deposit๋ฉ”์†Œ๋“œ๋Š” ๋ฐ˜๋“œ์‹œ actor์˜ ์ธ์Šคํ„ด์Šค๋กœ๋งŒ ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. actor์™ธ๋ถ€์—์„œ synchronouslyํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” computed property๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.

3. Hashable conform ๋ถˆ๊ฐ€

์œ„ 3๊ฐœ๋‹ค ์›์ธ์ด ๋ญ์˜€๋‚˜์š”?! ๋‹ค ๊ทธ๋†ˆ์˜ actor-isolated ๋•Œ๋ฌธ์ธ๊ฒ๋‹ˆ๋‹ค (๋ถ„๋…ธ) 

actor์˜ ์ •์˜๋œ

- stored, computed instance properties 

- instance methods 

- instance subscripts

๋“ค์ด ๊ธฐ๋ณธ์ ์œผ๋กœ actor-isolated ์ƒํƒœ๋ผ๋Š” ์‚ฌ์‹ค์—์„œ ๋น„๋กฏ๋œ ํ•œ๊ณ„์ ๋“ค์ž…๋‹ˆ๋‹ค.

 

๐Ÿ™‹ : ๊ทธ๋ž˜ actor-isolated์ธ ์ƒํƒœ๊ฐ€ ์ค‘์š”ํ•˜๋‹จ๊ฑด ์•Œ๊ฒ ์–ด ใ…Ž ๊ทผ๋ฐ actor-isolated ์•ˆํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆœ ์—†๋‚˜? 

๐Ÿง‘‍๐Ÿ’ป : ใ…‹ใ…‹์Œ‰๊ฐ€๋Šฅ

 

# ๊ฐœ์„ 

๊ทธ๋ž˜์„œ ์ด proposal์€

1. ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์ค‘ ์–ด๋–ค๊ฒƒ์ด isolated์ธ์ง€ ํ‘œ์‹œํ•˜๊ฑฐ๋‚˜

2. ์„ ์–ธ ์ž์ฒด๋ฅผ actor๋กœ ๋ถ€ํ„ฐ isolatedํ•˜์ง€ ์•Š์Œ์œผ๋กœ์จ

actor-isolated๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

# isolated parameter 

ํ•œ๊ณ„์  ์ค‘ 1๋ฒˆ์„ ๊ฐœ์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 

deposit์„  global function์œผ๋กœ ๋งŒ๋“œ๋Š”๊ฑฐ์˜€์ฃ ? 

func deposit(amount: Double, to account: BankAccount) {
  assert(amount >= 0)
  account.balance = account.balance + amount // โŒ Actor-isolated property 'balance' can not be referenced from a non-isolated context
}

์œ„ ์ฝ”๋“œ๋Š” 

actor-isolated property์ธ balance๋Š” non-isolated context์—์„œ ์ฐธ์กฐ๋  ์ˆ˜ ์—†์–ด ใ…Ž ํ•˜๊ณ  ์—๋Ÿฌ๋ฅผ ๋ƒ…๋‹ˆ๋‹ค. 

์ด๊ฒŒ ๋Œ์•„๊ฐ€๊ฒŒ ํ•˜๋ ค๋ฉด ์ด ํ•จ์ˆ˜๊ฐ€ isolated context๋ฅผ ๊ฐ€์ง€๊ฒŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. 

func deposit(amount: Double, to account: โœ… isolated โœ… BankAccount) {
  assert(amount >= 0)
  account.balance = account.balance + amount
}

ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์—  isolated ํ‘œ์‹œ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 

โœ”๏ธ ํ•จ์ˆ˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์ค‘ ํ•˜๋‚˜๊ฐ€ isolated ํ‘œ์‹œ๊ฐ€ ๋˜๋ฉด actor-isolated๊ฐ€ ๋œ๋‹ค.

์ฆ‰, deposit์€ actor ์™ธ๋ถ€์— ์ •์˜๋˜์–ด์žˆ์œผ๋ฏ€๋กœ ์›๋ž˜๋Š” actor-isolated๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

๊ทผ๋ฐ account ํŒŒ๋ผ๋ฏธํ„ฐ์— isolated๋กœ ํ‘œ์‹œํ•˜๊ฒŒ ๋˜๋ฉด์„œ, deposit์€ actor-isolated ํ•จ์ˆ˜๊ฐ€ ๋œ๊ฒ๋‹ˆ๋‹ค.

func deposit(amount: Double, to account: isolated BankAccount) {
  assert(amount >= 0)
  account.balance = account.balance + amount โœ…
}

์›๋ž˜ ์—๋Ÿฌ๊ฐ€ ๋‚ฌ๋˜ ์ € ์ฝ”๋“œ๋„ ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 

์™œ๋ƒ? ์ด์ œ deposit์ด isolated context๋ฅผ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .

๊ทธ๋ž˜์„œ account.balance. ์ฆ‰ actor-isolated ์ƒํƒœ์— ์ง์ ‘ ์ ‘๊ทผ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๊ฒ๋‹ˆ๋‹ค.

 

# nonisolated 

ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ isolated๋กœ ํ‘œ์‹œํ•˜๋Š”๊ฒŒ ๋ชจ๋“  ํ•œ๊ณ„์ ์„ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ๊ฑด ์•„๋‹™๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ํ•œ๊ณ„์  ์ค‘ 2๋ฒˆ์ธ

2. actor์™ธ๋ถ€์—์„œ synchronouslyํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” computed property๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.

๋Š” ์—ฌ์ „ํžˆ ์žˆ์ฃ . ์ด๋Ÿฌํ•œ ํ•œ๊ณ„์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ์œ„ํ•œ nonisolated ํ‚ค์›Œ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

actor BankAccount {
    let accountNumber: Int
    var balance: Double
    let accountName: String
    
    โœ… nonisolated โœ… var displayName: String {
        return self.accountName + "์•ˆ๋…•ํ•˜์„ธ์š”"
    }
        
    init() { ... }
}

nonisolated ํ‚ค์›Œ๋“œ๋Š” ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ํ”„๋กœํผํ‹ฐ๋‚˜ ํ•จ์ˆ˜์˜ ์ •์˜ ์•ž์— ๋ถ™ํž ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

actor์— ์ •์˜๋œ

- stored, computed instance properties 

- instance methods 

- instance subscripts

๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ actor-isolated์ƒํƒœ์ธ๋ฐ, nonisolated๋ฅผ ๋ถ™ํžˆ๊ฒŒ ๋˜๋ฉด ์ด ๋™์ž‘์„ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

actor BankAccount {
    let accountNumber: Int
    var balance: Double
    let accountName: String
    
    nonisolated var displayName: String {
        return self.accountName + "์•ˆ๋…•ํ•˜์„ธ์š”"
    }
}
let account = BankAccount(accountNumber: 1,
                                      initialDeposit: 100,
                                      accountName: "Zedd")
print(account.displayName) // Zedd์•ˆ๋…•ํ•˜์„ธ์š” โœ…

์ฆ‰, ์ด๋ ‡๊ฒŒ displayName์— ๋Œ€ํ•ด ๋™๊ธฐ์  ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

 ๐Ÿคฏ : ์•„ ใ…‹ใ…‹ actor-isolated ๊ฐœ๋‹ต๋‹ตํ–ˆ๋Š”๋ฐ

actor BankAccount {
    nonisolated let accountNumber: Int
    nonisolated var balance: Double
    nonisolated let accountName: String
    
    nonisolated var displayName: String {
        return self.accountName + "์•ˆ๋…•ํ•˜์„ธ์š”"
    }
}

๋‹ค nonisolated ํ•ด๋ฒ„๋ คใ…กใ…ก

๐Ÿง‘‍๐Ÿ’ป : ์‘ ์•ˆ๋ผ

actor BankAccount {
    nonisolated let accountNumber: Int
    nonisolated var balance: Double // โŒ Nonisolated' can not be applied to stored properties
    nonisolated let accountName: String
    
    nonisolated var displayName: String {
        return self.accountName + "์•ˆ๋…•ํ•˜์„ธ์š”"
    }
}

balance์ชฝ์—์„œ ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š”๋ฐ์š”. ์—๋Ÿฌ๋Š”

Nonisolated' can not be applied to stored properties

์ด๋ ‡๊ฒŒ ๋‚˜์˜ค์ง€๋งŒ..

balance๊ฐ€ let์ด ์•„๋‹Œ var์ด๊ณ  concurrent code์—์„œ data race๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ง‰์•„๋†“์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ใ…Ž

 

nonisolated๋กœ ์ธํ•ด ํ•œ๊ณ„์  ์ค‘ 3๋ฒˆ๋„ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ!

extension BankAccount: Hashable {
    
  โœ… nonisolated โœ… func hash(into hasher: inout Hasher) {
    hasher.combine(accountNumber)
  }
}

์ฐธ๊ณ  (๋‚˜์ค‘์— Xcode 13 ์ •์‹ ๋ฆด๋ฆฌ์ฆˆ ๋˜๋ฉด ํ™•์ธํ•ด๋ณผ ๊ฒƒ.) 

์š” ๋ถ€๋ถ„..proposal์—์„œ๋Š” ๋ณ„๋‹ค๋ฅธ ์–ธ๊ธ‰์€ ์•ˆ๋˜๋Š”๋ฐ ใ…œใ…œ.. Xcode 13 Beta 5์—์„œ ์ปดํŒŒ์ผ์ด ์•ˆ๋ฉ๋‹ˆ๋‹ค. 

์›์ธ์€

Actor-isolated property 'hashValue' cannot be used to satisfy a protocol requirement
Add 'nonisolated' to 'hashValue' to make this property not isolated to the actor

์ธ๋ฐ์š”..

Swift 4.1์—์„œ hashValue๋Š” ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๊ฐ€ ๊ฐ๊ฐ Equatable ๋˜๋Š” Hashable์„ ์ค€์ˆ˜ํ•˜๋ฉด, ๊ผญ ๊ตฌํ˜„ํ•ด์ฃผ์ง€ ์•Š์•„๋„ ๋˜์—ˆ๊ณ ,

ํ•˜๋ฌผ๋ฉฐ ์ง€๊ธˆ์€ hashValue๊ฐ€ deprecated ์ธ ์ƒํƒœ์ธ๋ฐ์š”. 

hashValue ๋ฌธ์„œ ์ฐธ๊ณ  : https://developer.apple.com/documentation/swift/hashable/1540917-hashvalue

์™œ ์ด๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ๋„ค์š” ใ…œใ…œ...

๊ฒฐ๊ตญ hashValue๋„ ์„ ์–ธํ•ด์„œ nonisolated๋กœ ํ•ด์ฃผ๋‹ˆ๊นŒ 

extension BankAccount: Hashable {
    
    nonisolated func hash(into hasher: inout Hasher) {
        hasher.combine(accountNumber)
    }
    
    nonisolated var hashValue: Int {
        return accountNumber.hashValue ^ accountNumber.hashValue &* 16777619
    }
}

์ปดํŒŒ์ผ์ด ๋˜๊ธด ํ•˜๋„ค์š”! ์ฐธ๊ณ ํ•˜์‹œ๊ธธ ใ…Žใ…Ž


Actor์•ˆ์— ์ •์˜๋˜์–ด์žˆ๋Š” ์ธ์Šคํ„ด์Šค ๋ฉ”์†Œ๋“œ๋ฅผ nonisolated๋กœ ํ•˜๊ธฐ ์ „์—๋Š” ์ฃผ์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

extension BankAccount {
    func steal(amount: Double) {
      self.balance -= amount 
    }
}

self๋ฅผ ํ†ตํ•ด balance์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์œ„ ์ฝ”๋“œ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๋Š”๋ฐ, ์ด๊ฑธ nonisolated๋กœ ํ•ด๋ฒ„๋ฆฌ๋ฉด

extension BankAccount {
    โœ… nonisolated โœ… func steal(amount: Double) {
      self.balance -= amount // ๐Ÿšจ error: actor-isolated property 'balance' can not be referenced on non-isolated parameter 'self'
    }
}

์—๋Ÿฌ๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. balance๊ฐ€ actor-isolated ํ”„๋กœํผํ‹ฐ์ธ๊ฑด ๋งž์ง€๋งŒ, ์š” ๋ฉ”์†Œ๋“œ๊ฐ€ actor-isolated๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ์—์š”! 

๊ทธ๋Ÿฌ๋‹ˆ๊นŒ self์—ฌ๋„ ๋”์ด์ƒ ์ ‘๊ทผ์„ ๋ชปํ•˜๊ฒŒ ๋˜๋Š”๊ฒƒ์ด์ฃ . 

 

๊ทธ๋ฆฌ๊ณ  ํ•˜๋‚˜ ๋”! Actor (2) - Actor isolation ๊ธ€์—์„œ 

actor BankAccount {
    let accountNumber: Int
    ...
}

// ๋‹ค๋ฅธ ๋ชจ๋“ˆ
func outside_moudle_method() โœ… async โœ… { 
    let account = BankAccount(accountNumber: 1, initialDeposit: 10) 
    print(โœ… await โœ… account.accountNumber) โœ… 
}

๋ถˆ๋ณ€ ์ƒํƒœ์— ๋Œ€ํ•œ cross-actor reference๋Š” ๊ฐ™์€ ๋ชจ๋“ˆ ๋‚ด์—์„œ๋งŒ ์ ์šฉ์ด ๋˜์—ˆ๊ณ ,

์œ„ ์ฝ”๋“œ ์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ๋Š” accountNumber๊ฐ€ ๋ถˆ๋ณ€ ์ƒํƒœ์—ฌ๋„ ๋น„๋™๊ธฐ๋กœ ์ฐธ์กฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

actor BankAccount {
    public nonisolated let accountNumber: Int
    ...
}

// ๋‹ค๋ฅธ ๋ชจ๋“ˆ
func outside_moudle_method() { 
    let account = BankAccount(accountNumber: 1, initialDeposit: 10) 
    print(account.accountNumber) โœ… 
}

ํ•˜์ง€๋งŒ accountNumber๊ฐ€ nonisolated๋ฉด ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ๋„ ๋™๊ธฐ์ ์œผ๋กœ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

nonisolated์˜ ๊ธฐ๋Šฅ์œผ๋กœ ๋ณด๋ฉด ๋‹น์—ฐํ•œ๊ฑฐ์ฃ ?!

 

ํœด! ์˜ค๋Š˜ ๊ณต๋ถ€ํ•œ ๋ถ€๋ถ„๋„ Improved control over actor isolation๋ฅผ ๋งŽ์ด ์ฐธ๊ณ ํ–ˆ์–ด์š” ใ…Žใ…Ž 

ํ‹€๋ฆฐ ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€ ๋‹ฌ์•„์ฃผ์„ธ์š”. 

๋‹ค์Œ๊ธ€์€ ์•„๋งˆ๋„ Sendable์ด ๋˜์ง€ ์•Š์„๊นŒ! 

 

 

 

๋ฐ˜์‘ํ˜•

'Swift > Concurrency' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Combine โ†’ Swift Concurrency(async/await)๋กœ ๋ฐ”๊พธ๊ธฐ (feat. ๋Š๋‚€์ )  (3) 2022.01.25
Actor (4) - Sendable  (3) 2021.10.11
Swift ) Actor (2) - Actor isolation  (7) 2021.08.23
Swift ) Actor (1)  (5) 2021.08.22
[Swift Concurrency] Async/await  (11) 2021.03.25