๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด

Method Dispatch

๊ธ€์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์—, Method Dispatch๊ฐ€ ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•ด ์ •๋ฆฌํ•  ํ•„์š”๊ฐ€ ์žˆ๊ฒ ๋„ค์š”. ๊ณต์‹์ ์ธ ๋ฌธ์„œ๋Š” ์•„๋‹ˆ์ง€๋งŒ ๊ตฌ๊ธ€์— Method Dispatch์˜ ์ •์˜์— ๋Œ€ํ•ด ๊ฒ€์ƒ‰์„ ํ•ด๋ณด๋ฉด,

๐Ÿ’ก how a program selects which instructions to execute when invoking a method

์ด๋ ‡๊ฒŒ ํ•œ ๋ฌธ์žฅ์œผ๋กœ ๋œ ์ •์˜๊ฐ€ ๊ฐ€์žฅ ์ƒ๋‹จ์— ๋‚˜์˜ต๋‹ˆ๋‹ค. ํ•ด์„ํ•ด๋ณด๋ฉด ์–ด๋–ค ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ์„ ๋•Œ, ํ”„๋กœ๊ทธ๋žจ์ด ์–ด๋–ค ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ• ์ง€ ์„ ํƒํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

๋” ์‰ฝ๊ฒŒ ์ด์•ผ๊ธฐํ•ด๋ณด๋ฉด ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ์‹ค์ œ๋กœ ์–ด๋–ค ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š”์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ๋ด๋„ ๋˜๊ฒ ์ฃ ? 

 

Static Dispatch

๊ทธ๋Ÿผ ์ด์ œ ๊ฐ„๋‹จํ•œ ์ƒํ™ฉ์„ ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค.

struct Test {
    func printTest() {
        print("test")
    }
}

let test = Test()
test.printTest()

์ด๋ ‡๊ฒŒ ๊ฐ„๋‹จํ•œ ๊ตฌ์กฐ์ฒด๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค๊ณ , ๋ฉ”์„œ๋“œ๋„ ํ•˜๋‚˜ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. 

 

์ด ๊ตฌ์กฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์–ด๋–ค ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋ ์ง€๋Š” ๋„ˆ๋ฌด๋‚˜ ์ž๋ช…ํ•˜๊ฒ ์ฃ ? Test์•ˆ์— ์žˆ๋Š” printTest๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฐ ๊ฒฐ์ •์€ ์ปดํŒŒ์ผ ํƒ€์ž„์—๋„ ๊ฐ€๋Šฅํ•˜๊ฒ ์ฃ .

 

์šฐ๋ฆฌ๊ฐ€ ์‚ดํŽด๋ณธ ์ •์˜์— ๋”ฐ๋ฅด๋ฉด Method Dispatch๋Š” ์–ด๋–ค ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ• ์ง€ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ์ง€๊ธˆ์€ ์„ ํƒ์ง€๊ฐ€ ํ•˜๋‚˜๋ฐ–์— ์—†์œผ๋‹ˆ๊นŒ์š”.

 

๊ทธ๋ž˜์„œ ์ด๋ ‡๊ฒŒ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์–ด๋–ค ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ Static Dispatch๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋ง ๊ทธ๋Œ€๋กœ ๋™์ ์œผ๋กœ ๊ฒฐ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฑฐ์ฃ .

 

Static Dispatch๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๊ฐ’ํƒ€์ž…์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์‹คํ–‰ํ•  ๋ฉ”์„œ๋“œ๊ฐ€ ํ•ญ์ƒ ๋ช…ํ™•ํ•˜๋‹ˆ๊นŒ์š”.

Dynamic Dispatch

๊ทธ๋Ÿผ ์„ ํƒ์ง€๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ๋˜๋Š” ์ƒํ™ฉ์ด ์žˆ์œผ๋‹ˆ ์ด๋Ÿฐ ๊ฐœ๋…์ด ๋‚˜์™”์„ ํ…๋ฐ ์–ด๋–ค ์ƒํ™ฉ์ผ๊นŒ์š”?

class Test {
    func printTest() {
        print("test")
    }
}

class TestA: Test {
    override func printTest() {
        print("testA")
    }
}

class TestB: Test {
    override func printTest() {
        print("testB")
    }
}

let tests = [Test(), TestA(), TestB()]

for test in tests {
    test.printTest()
}

์ด๋ฒˆ์—” ๊ธฐ์กด Test ๊ตฌ์กฐ์ฒด๋ฅผ ํด๋ž˜๋กœ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ์ƒ์†ํ•˜๋Š” ๋‘ ํด๋ž˜์Šค TestA, TestB๋ฅผ ์„ ์–ธํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์„ธ ๊ฐœ์˜ ๋‹ค๋ฅธ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐฐ์—ด์— ๋„ฃ์–ด์ฃผ๊ณ  ๋ฐฐ์—ด์„ ์ˆœํšŒํ•˜๋ฉด์„œ printTest๋ฅผ ์‹คํ–‰ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ฆ‰, ๋‹คํ˜•์„ฑ์„ ๋งŒ๋“ค์–ด์ค€ ๊ฒƒ์ด์ฃ . 

 

์—ฌ๊ธฐ์„œ tests ๋ฐฐ์—ด์˜ ํƒ€์ž…์€ ๋ฌด์—‡์ผ๊นŒ์š”?

TestA์™€ TestB๋Š” Test๋ฅผ ์ƒ์†ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ œ์ผ ์ƒ์œ„ ํด๋ž˜์Šค์ธ Test๊ฐ€ ๋ฐฐ์—ด์˜ ์š”์†Œ ํƒ€์ž…์œผ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค. 

for test in tests {
    test.printTest()
}

๊ทธ๋Ÿผ ์ด ์ฝ”๋“œ์—์„œ๋Š” Test ํƒ€์ž…์˜ ๋ฉ”์„œ๋“œ์ธ printTest๊ฐ€ ์„ธ ๋ฒˆ ์‹คํ–‰๋˜์–ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ..!

test
test
test

ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ๊ธฐ๋Œ€ํ–ˆ๋˜ ๋Œ€๋กœ, ๊ทธ๋ฆฌ๊ณ  ์ž˜ ์•Œ๊ณ  ์žˆ๋Š” ๋Œ€๋กœ ์‹ค์ œ ์ถœ๋ ฅ์€ ์ด๋ ‡์Šต๋‹ˆ๋‹ค.

test
testA
testB

์Šค์œ„ํ”„ํŠธ๋Š” ๋ฐฐ์—ด ์š”์†Œ๋“ค์˜ ํƒ€์ž…์ด Test์ธ๋ฐ ์–ด๋–ป๊ฒŒ ์ž์‹ ํด๋ž˜์Šค๋“ค์ธ TestA์™€ TestB๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์—ˆ์„๊นŒ์š”?

 

์ปดํŒŒ์ผ ํƒ€์ž„์—๋Š” ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐฐ์—ด ์š”์†Œ์ค‘ ์–ด๋–ค ์š”์†Œ๊ฐ€ ์–ด๋–ค ํ•˜์œ„ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ธ์ง€ ์•Œ ์ˆ˜ ์—†์œผ๋‹ˆ๊นŒ์š”.. ๊ทธ๋ž˜์„œ ์Šค์œ„ํ”„ํŠธ๋Š” ์ด ์ธ์Šคํ„ด์Šค์—๋Š” ์ด ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์„ ์จ!๋ผ๊ณ  ์ ํ˜€์žˆ๋Š” ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 

 

์ด ํ…Œ์ด๋ธ”์„ vTable(virtual dispatch table) ์ด๋ผ๊ณ  ํ•˜๋Š”๋ฐ์š”, vTable์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ํฌ์ธํ„ฐ๋Š” ๊ฐ ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ํ•˜๋‚˜์”ฉ ์กด์žฌํ•˜๊ณ , ์Šค์œ„ํ”„ํŠธ๋Š” ๋Ÿฐํƒ€์ž„์— ์–ด๋–ค ์ธ์Šคํ„ด์Šค์—์„œ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์ด ํ…Œ์ด๋ธ”์—์„œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ฐพ์•„ ์‹คํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๊ณผ์ •์„ ๊ฐ„๋‹จํžˆ ๊ทธ๋ ค๋ณผ๊นŒ์š”?

ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฉด, 1) ๋จผ์ € ์ธ์Šคํ„ด์Šค์˜ ๋ฉ”ํƒ€ ํƒ€์ž…์„ ์–ป๊ณ , 2) ํ•ด๋‹น ํƒ€์ž…์ด ๊ฐ€์ง„ vtable์—์„œ ํ˜ธ์ถœํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฉ”์„œ๋“œ์˜ ์ฃผ์†Œ๋ฅผ ์ฐพ์•„, 3) ํ•ด๋‹น ์ฃผ์†Œ๋ฅผ ์ฐพ์•„๊ฐ€ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ๋Ÿฐํƒ€์ž„์— ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ํ…Œ์ด๋ธ”์„ ํ™•์ธํ•ด ์–ด๋–ค ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์„ Dynamic Dispatch๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

 

๋‹ค์ด๋‚˜๋ฏน ๋””์ŠคํŒจ์น˜ ๋•๋ถ„์— ์šฐ๋ฆฌ๋Š” ์˜ค๋ฒ„ ๋ผ์ด๋”ฉ์„ ํ†ตํ•œ ๋‹คํ˜•์„ฑ์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฐ˜๋ฉด์— ๋ชจ๋“  ํด๋ž˜์Šค๋“ค์„ ๋‹คํ˜•์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ…Œ์ด๋ธ”์„ ํ•œ ๋ฒˆ์”ฉ ๋‹ค ํ™•์ธํ•ด์•ผ ํ•˜๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

 

์•ž์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ์ƒ์†์˜ ์—ฌ์ง€๊ฐ€ ์žˆ์–ด ๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์ •์˜๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด Dynamic Dispatch๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํด๋ž˜์Šค๋Š” ๋”ฐ๋กœ ์ตœ์ ํ™”๋ฅผ ํ•ด์ฃผ์ง€ ์•Š๋Š”๋‹ค๋ฉด Dynamic Dispatch๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์ ํ™”์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋Š” ๋‹ค๋ฅธ ํฌ์ŠคํŠธ์—์„œ ๋” ๊นŠ๊ฒŒ ํ•ด ๋ณผ๊ฒŒ์š”!

์ •๋ฆฌ

 

 

์ด๋ ‡๊ฒŒ ๊ฐ„๋‹จํ•˜๊ฒŒ Satic Dispatch์™€ Dynamic Dispatch์— ๋Œ€ํ•ด์„œ ์ •๋ฆฌํ•ด๋ณด์•˜๋Š”๋ฐ์š”,

 

์—ฌ๊ธฐ์„œ ๋“œ๋Š” ์˜๋ฌธ.. ๊ทธ๋Ÿผ Protocol์„ ์ฑ„ํƒํ•ด์„œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•œ ๊ตฌ์กฐ์ฒด๋Š”..? 

 

์ด๋Ÿฐ ๊ฒฝ์šฐ๋„ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•ด ๋ฉ”์„œ๋“œ ์ •์˜๊ฐ€ ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์ผ ์ˆ˜ ์žˆ๋Š”๋ฐ Dynamic Dispatch์ด์ง€ ์•Š์„๊นŒ์š”? ์ด ์˜๋ฌธ์ ์€ ๋‹ค์Œ ํฌ์ŠคํŠธ์—์„œ ํ•ด๊ฒฐํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!