๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐ŸŽ iOS/Swift

[Swift] ํด๋กœ์ €(Closure) vs ๋ธ”๋ก(Block) ํ•จ์ˆ˜ ์บก์ณ๋ฐฉ์‹ ๋น„๊ต

728x90

 

ํด๋กœ์ €(Closure) vs ๋ธ”๋ก(Block) ํ•จ์ˆ˜๋ฅผ ๋น„๊ตํ•ด๋ณด์ž

 

 

Swift์˜ Closure์™€ Objective-C์˜ ๋ธ”๋กํ•จ์ˆ˜๋Š” ์ด๋ฆ„์ด ์—†๋Š” ํ•จ์ˆ˜๋กœ ๊ฐœ๋…์ด ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ๋‘˜์€ ๊ฐ’์„ ์บก์ณํ•˜๋Š” ๋ฐฉ์‹์— ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ญ

 

'๊ฐ’์„ ์บก์ณํ•œ๋‹ค'์˜ ์˜๋ฏธ๋ถ€ํ„ฐ ๋‘˜์˜ ์ฐจ์ด์ ์„ ๋น„๊ตํ•ด์„œ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 


1. Capturing Values: ํด๋กœ์ € ์บก์ณ๋ž€?

๋จผ์ € ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด, closure๋Š” ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ๋ณ€์ˆ˜์ธ runningTotal, amount ๋ผ๋Š” Value ํƒ€์ž…์˜ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—

๋‘ ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ๋‚ด๋ถ€์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ, runningTotal, amount์˜ ๊ฐ’์ด ์บก์ณ๋˜์—ˆ๋‹ค ๋ผ๊ณ  ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด์— message๋ž€ ๋ณ€์ˆ˜๋Š” closure ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์บก์ณ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    var message = "test"
    
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

 

์ฆ‰, makeIncrementer๊ฐ€ ํ˜ธ์ถœ์ด ๋˜๋ฉด makeIncremeter์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์ธ amount์™€ ์ง€์—ญ๋ณ€์ˆ˜์ธ runningTotal์„ incrementer๋ผ๋Š” ํด๋กœ์ €์—์„œ ์บก์ณํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

 

 

 

 


2. Closure์˜ ์บก์ณ ๋ฐฉ์‹

: Closure๋Š” ๊ฐ’์„ ์บก์ณํ•  ๋•Œ, Value/Reference ํƒ€์ž…์— ๊ด€๊ณ„ ์—†์ด ๋ชจ๋‘ Reference Capture ํ•œ๋‹ค.

 

 

์›๋ž˜๋Š” Reference Type์ธ ๊ฒฝ์šฐ์—” ๊ฐ’์„ ์ €์žฅํ•  ๋•Œ ์ฐธ์กฐ(์ฃผ์†Œ๊ฐ’์„ ์ €์žฅ)ํ•˜๊ณ ,

Int, Double, Struct ๊ฐ™์€  Value Type์˜ ๊ฐ’์€ ๊ฐ’์„ ์ €์žฅํ•  ๋•Œ Copy๋˜์–ด ์ €์žฅ๋˜๋Š” ๊ฒƒ์ด ๋‹น์—ฐํ•ฉ๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ, ์œ„์—์„œ ๋ดค๋“ฏ์ด Swift Closure์—์„œ๋Š” ์ด Value Type ๊ฐ’๋„ ์บก์ณํ•  ๋• Reference ์บก์ณ!! ์ฆ‰, '์ฐธ์กฐ' ํ•ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜ ์ฝ”๋“œ์—์„œ closure์•ˆ์—์„œ num์€ Intํ˜•(Value Type)์ž„์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  Reference ์บก์ณ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ closure๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— num ๊ฐ’์„ ๋ฐ”๊พธ๋ฉด closure์—์„œ ์‹คํ–‰ํ•˜๋Š” num์˜ ๊ฐ’๋„ ๋ฐ”๋€๋‹ˆ๋‹ค!!(์ฐธ์กฐํ•˜๋ฏ€๋กœ!!)

var num: Int = 0

print("num check #1 = \(num)")

let closure = {
    print("num check #3 = \(num)")
}

closure()
num = 20
print("num check #2 = \(num)")
closure()

 

์œ„ ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ๊ฐ’

 

๋งŒ์•ฝ, ํด๋กœ์ €๋ฅผ ํ†ตํ•ด Reference ์บก์ณ๊ฐ€ ์•„๋‹Œ Copy ์บก์ณ๋ฅผ ํ•˜๊ณ ์‹ถ๋‹ค๋ฉด, (๊ฐ’ ๋ณ€๊ฒฝ ์•ˆ๋˜๊ฒŒ ํ•˜๊ณ  ์‹ถ๋‹ค!)

์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด copyํ•  ๋ณ€์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ list๋กœ ์„ ์–ธํ•ด์ฃผ๋ฉด ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋„ ํด๋กœ์ € ๋‚ด๋ถ€์˜ ๊ฐ’์ด ๋ณ€ํ•˜์ง€ ์•Š๊ณ  ๋ณ€๊ฒฝ์ด ์•ˆ๋ฉ๋‹ˆ๋‹ค.

var num: Int = 0
print("num check #1 = \(num)")

let closure = { [num] in
    print("num check #3 = \(num)")
}

closure()
num = 20
print("num check #2 = \(num)")
closure()

๊ฒฐ๊ณผ๊ฐ’

 

 

 

 


3. Block์˜ ์บก์ณ ๋ฐฉ์‹

๋ฐ˜๋ฉด์—, Block์€ ๊ฐ’์„ ์บก์ณํ•  ๋•Œ

Value Type์ผ ๊ฒฝ์šฐ ๊ฐ’์„ ๋ณต์‚ฌํ•˜์—ฌ Captureํ•˜๊ณ ,

Reference Type์ผ ๊ฒฝ์šฐ Reference Captrue๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.

 

Objective-C์˜ Block ํ•จ์ˆ˜๋Š” Value Type์ผ ๊ฒฝ์šฐ ์ฐธ์กฐ๊ฐ€ ์•„๋‹Œ "๋ณต์‚ฌ"๋กœ ๊ฐ’์„ ์บก์ณํ•ฉ๋‹ˆ๋‹ค.

 

๋”ฐ๋ผ์„œ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ Objective-C๋กœ ์ž‘์„ฑํ•˜์˜€์„ ๋•Œ, ๊ฐ’์ด ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

- (void)doSomething {
    int num = 0;
    NSLog(@"num check #1 = %d", num);
    
    void (^testBlock)(void) = ^{
        NSLog(@"num check #3 = %d", num);
    };
    
    testBlock();
    num = 20;
    NSLog(@"num check #2 = %d", num);
    testBlock();
}

๊ฒฐ๊ณผ ํ™”๋ฉด

 

Value Type์€ ๊ฐ’์„ ๋ณต์‚ฌํ•˜์—ฌ ์บก์ณํ•˜๋ฏ€๋กœ ๋ธ”๋กํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์„ ๋•Œ, Copy ์บก์ณ๊ฐ€ ์•„๋‹Œ Reference ์บก์ณ๋ฅผ ํ•˜๊ณ ์‹ถ๋‹ค๋ฉด, (๊ฐ’ ๋ณ€๊ฒฝ ๋˜๊ฒŒ ํ•˜๊ณ  ์‹ถ๋‹ค!)

์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•˜๊ณ ์ž ํ•˜๋Š” ๋ณ€์ˆ˜ ์•ž์— __block ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

- (void)doSomething {
    __block int num = 0;
    NSLog(@"num check #1 = %d", num);
    
    void (^testBlock)(void) = ^{
        NSLog(@"num check #3 = %d", num);
    };
    
    testBlock();
    num = 20;
    NSLog(@"num check #2 = %d", num);
    testBlock();
}

๊ฒฐ๊ณผ ํ™”๋ฉด

 

 

 


Closure vs Block ์„ ํ‘œ๋กœ ์š”์•ฝํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.๐Ÿ˜Š

  Closure (Swift) Block (Objective-C)
Value Type Reference Capture Value Copy Capture
Reference Type Reference Capture Reference Capture
Value Type์ผ ๋•Œ
Reference Capture -> Value Copy Capture ๋ณ€๊ฒฝ
Closure List   
Value Type์ผ ๋•Œ
Value Copy Capture -> Reference Capture ๋ณ€๊ฒฝ
  __block

 

๋ฐ˜์‘ํ˜•