์Šค์ฝ”ํ”„๋Š” ๋ณ€์ˆ˜๊ฐ€ ์‚ด์•„์žˆ๋Š”, ํ˜น์€ ๋ณ€์ˆ˜์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๋ฒ”์œ„์ž„.


#include <stdio.h>

int Func() { // ์Šค์ฝ”ํ”„1 ์‹œ์ž‘(C, C++์€ ์ค‘๊ด„ํ˜ธ๋กœ ์Šค์ฝ”ํ”„๋ฅผ ๊ตฌ๋ถ„ํ•จ)
ย  ย ย ย  ย ย int a = 1;
ย  ย ย ย  ย ย { // ์Šค์ฝ”ํ”„2 ์‹œ์ž‘
ย  ย ย ย  ย ย ย  ย ย ย  ย ย int a = 2;
ย  ย ย ย  ย ย ย  ย ย ย  ย ย printf("์Šค์ฝ”ํ”„2์— ์žˆ๋Š” ๋ณ€์ˆ˜ a์˜ ๊ฐ’์€ %d", a);
ย  ย ย ย  ย ย } // ์Šค์ฝ”ํ”„2 ๋
ย ย ย ย  ย ย ย printf("์Šค์ฝ”ํ”„1์— ์žˆ๋Š” ๋ณ€์ˆ˜ a์˜ ๊ฐ’์€ %d", a);
} // ์Šค์ฝ”ํ”„1 ๋

// Output:
// ์Šค์ฝ”ํ”„2์— ์žˆ๋Š” ๋ณ€์ˆ˜ a์˜ ๊ฐ’์€ is 2
// ์Šค์ฝ”ํ”„1์— ์žˆ๋Š” ๋ณ€์ˆ˜ a์˜ ๊ฐ’์€ is 1
//
// <- ์Šค์ฝ”ํ”„2์—์„œ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ์Šค์ฝ”ํ”„2์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ
// <- ์•ˆ์— ์žˆ๋Š” ์Šค์ฝ”ํ”„2์—์„œ ๋ฐ–์—์žˆ๋Š” ์Šค์ฝ”ํ”„1์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Œ(์œ„์˜ ์˜ˆ์‹œ์—์„œ๋Š” ๊ฑ ๊ท€์ฐฎ์•„์„œ ์•ˆ๋ณด์—ฌ์คŒ)


ํ•จ์ˆ˜๋Š” ์›๋ž˜ ์ƒํƒœ๊ฐ€ ์—†์Œ. ๊ฑ ์ธํ’‹ ๋ฐ›์œผ๋ฉด ์•„์›ƒํ’‹ ๋‚ด๋ฑ‰๋Š”๊ฒŒ ํ•จ์ˆ˜์ž„.


๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ์ ˆ์ฐจํ˜• ์–ธ์–ด์˜ ํ‰๋ฒ”ํ•œย ํ•จ์ˆ˜๋“ค์€ ๋‚ด๋ถ€์— static ๋ณ€์ˆ˜(๊ผผ์ˆ˜)๋ฅผย ์„ ์–ธํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€์ง€ ์•Š์Œ.


์ƒํƒœ๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€์ˆ˜์— ํ• ๋‹นํ•  ์ƒ๊ฐ์กฐ์ฐจ ์•ˆํ•จ(์ƒํƒœ๊ฐ€ ์—†์œผ๋ฉด.. ์ƒํƒœ๋ฅผ ์ €์žฅํ•  ๋ฉ”๋ชจ๋ฆฌ๋„ ํ•„์š”์—†์œผ๋‹ˆ๊นŒ)


์‹ค์ œ๋กœ C์—์„œ๋Š” ํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฅดํ‚ค๋Š” functionํฌ์ธํ„ฐ๊ฐ™์€๊ฑด ์žˆ์–ด๋„ ํ•จ์ˆ˜ ๊ทธ ์ž์ฒด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ณ€์ˆ˜๋Š” ์กด์žฌํ•˜์ง€์•Š์Œ.



๊ทผ๋ฐ ํ•จ์ˆ˜๋ฅผ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์ทจ๊ธ‰ํ•˜๋ฉด ์กด๋‚˜ ํŽธ๋ฆฌํ•˜๋‹ค๋Š”๊ฑธ ๊นจ๋‹ซ๊ณ  ๊ฒฐ๊ตญ์—” modern C++, C#์œผ๋กœ ๋„˜์–ด์˜ค๋ฉด์„œ functor, lambda๊ฐ™์€ย syntactic sugar๋ฅผ ์ œ๊ณตํ•˜๊ฒŒ๋จ...ย 


(์ด๊ฒŒ ์™œ syntatic sugar๋ƒ๋ฉด ๊ฒฐ๊ตญ ํ•จ์ˆ˜๊ฐ€ ๋ณ€์ˆ˜์— ์ €์žฅ์ด ์•ˆ๋˜๋‹ˆ๊นŒ ๊ทธ ํ•จ์ˆ˜ ๋”ฑ ํ•˜๋‚˜๋ฅผ ๊ฐ–๋Š” class๋ฅผ ์ž„์‹œ๋กœ ๋งŒ๋“ค์–ด์„œ ์ €์žฅํ•˜๋Š” ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•จ)




๊ทผ๋ฐ ํ•จ์ˆ˜๊ฐ€ ์ผ๊ธ‰๊ฐ์ฒด๋ฉด, ์ฆ‰ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์ทจ๊ธ‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ๊ทธ๋ƒฅ ๋ณ€์ˆ˜ ์„ ์–ธ ํ•˜๋“ฏ์ด ํ•จ์ˆ˜ ์ค‘๊ฐ„์— ๋ฟ… ํ•˜๊ณ  ์„ ์–ธ๋  ์ˆ˜ ์žˆ์Œ.


๊ทธ๋Ÿฌ๋ฉด ์Šค์ฝ”ํ”„๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผํ• ๊นŒ??


์ด๊ฑด ์–ธ์–ด๋งˆ๋‹ค ์ ‘๊ทผ ๋ฐฉ์‹์ด ๋‹ค ๋‹ค๋ฆ„. ์˜ˆ๋ฅผ๋“ค์–ด ๋‹ค์Œ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Closure๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ํŽ™ํ† ๋ฆฌ์–ผ์„ ๊ตฌํ˜„ํ•œ ์˜ˆ์‹œ์ž„.


// Closure๋ฅผ ์ด์šฉํ•œ ํŒฉํ† ๋ฆฌ์–ผ ํ•จ์ˆ˜
let FactorialGenerator = function() { // ์Šค์ฝ”ํ”„1
ย  ย ย ย  ย ย let f = 0;
ย  ย ย ย  ย ย return function() { // ์Šค์ฝ”ํ”„2
ย  ย ย ย  ย ย ย  ย ย ย  ย ย if(f == 0) // ์—ฌ๊ธฐ์„œ ์Šค์ฝ”ํ”„1์—์žˆ๋Š” f์— ์ ‘๊ทผ์„ ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ok
ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย f = 1; // ์Šค์ฝ”ํ”„1์— ์žˆ๋Š” f๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜๋„ ์žˆ์„๊นŒ? ok
ย  ย ย ย  ย ย ย  ย ย ย  ย ย else
ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย f *= f+1;
ย  ย ย ย  ย ย ย  ย ย ย  ย ย return f;
ย  ย ย ย  ย ย };
}

let facto = FactorialGenerator();
console.log(facto()); // 1
console.log(facto()); // 2
console.log(facto()); // 6
let facto2 = FactorialGenerator();
console.log(facto2()); // 1
console.log(facto2()); // 2
console.log(facto2()); // 6


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ•จ์ˆ˜ ์ž์‹ ์ด ํฌํ•จ๋œ ๋ฐ”๊นฅ ์Šค์ฝ”ํ”„์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Œ. ์ˆ˜์ •๋„ ํ•  ์ˆ˜ ์žˆ์Œ!



๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ ์ข€ ์• ๋งคํ•œ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•จ.


๋ณ€์ˆ˜๋ž€ ๋†ˆ์€ ์›๋ž˜ ํ•จ์ˆ˜๊ฐ€ ๋ฆฌํ„ด ํ•ด์ฃผ๋ฉด ํ•จ์ˆ˜ ์Šค์ฝ”ํ”„ ๋ฐ–์œผ๋กœ ๋น ์ ธ๋‚˜๊ฐˆ์ˆ˜ ์žˆ๋Š” ๋†ˆ์ž„.ย 


๊ทธ๋Ÿผ ๋ณ€์ˆ˜ํ™” ๋œ ํ•จ์ˆ˜๋ฅผ ๋‹ค๋ฅธ ํ•จ์ˆ˜๊ฐ€ ๋ฆฌํ„ดํ•˜๋ฉด ๋ฆฌํ„ด๋œ ํ•จ์ˆ˜๊ฐ€ ์ ‘๊ทผํ•˜๋˜ ์Šค์ฝ”ํ”„๋Š” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผํ• ๊นŒ?ย 


๋ณ€์ˆ˜ํ™” ๋œ ํ•จ์ˆ˜๊ฐ€ ์ ‘๊ทผํ•˜๊ณ  ๋‹ค๋ฃจ๋˜ ์Šค์ฝ”ํ”„๊ฐ€ ํŒŒ๊ดด๋˜๋ฒ„๋ฆฌ๋ฉด ํ•ด๋‹น ์Šค์ฝ”ํ”„๋ฅผ ์ฐธ์กฐํ•˜๋˜ ํ•จ์ˆ˜๊ฐ€ ๊ธฐ๋Šฅ์„ ์ฝ๊ฑฐ๋‚˜ unsafe ํ•˜๊ฒŒ ๋  ์ˆ˜๋„ย ์žˆ์Œ.


์ด๊ฑธ ํ•ด๊ฒฐํ•  ํ•ฉ๋ฆฌ์ ์ธ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ๋ณ€์ˆ˜ํ™”๋œ ํ•จ์ˆ˜๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ์Šค์ฝ”ํ”„์˜ ์Šค๋ƒ…์ƒท์„ย ๊ฐ™์ด ๋ณ€์ˆ˜์— ์ €์žฅํ•˜๋Š” ๊ฒƒ!


๊ทธ๋ž˜์„œ ์œ„์™€๊ฐ™์ด ๋งˆ์น˜ ํ•จ์ˆ˜๊ฐ€ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ ๊ฐ™์€ ํšจ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ๋จ. ์ด๋ ‡๋“ฏ ๋ณ€์ˆ˜์— ํ•จ๊ป˜ ์ €์žฅ๋˜๋Š” ์Šค์ฝ”ํ”„๋ฅผย ํด๋กœ์ ธ๋ผ๊ณ  ํ•จ.


ํ•œํŽธ ํŒŒ์ด์ฌ์€?


def Test(): # ์Šค์ฝ”ํ”„1
ย  ย ย ย  ย ย x = 1
ย  ย ย ย  ย ย def PrintX(): # ์Šค์ฝ”ํ”„2
ย  ย ย ย  ย ย ย  ย ย ย  ย ย print("์Šค์ฝ”ํ”„2์—์„œ์˜ x์˜ ๊ฐ’:", x) # ๋ฐ”๊นฅ ์Šค์ฝ”ํ”„์— ์žˆ๋Š” x๋ฅผ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ์„๊นŒ? ok!
ย  ย ย ย  ย ย def ModifyX(): # ์Šค์ฝ”ํ”„3
ย  ย ย ย  ย ย ย  ย ย ย  ย ย x = 2 # ์Šค์ฝ”ํ”„1์— ์žˆ๋Š” x๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜๋Š” ์žˆ์„๊นŒ? No!
ย  ย ย ย  ย ย ย  ย ย ย  ย ย print("์Šค์ฝ”ํ”„3์—์„œ์˜ x์˜ ๊ฐ’(์ˆ˜์ •๋จ):", x)
ย  ย ย ย  ย ย PrintX() # 1
ย  ย ย ย  ย ย ModifyX() # 2
ย  ย ย ย  ย ย print("์Šค์ฝ”ํ”„1 ์—์„œ์˜ x์˜ ๊ฐ’(์Šค์ฝ”ํ”„2์—์„œ 2๋กœ ์ˆ˜์ •๋จ):", x) # 1

Test()
# Output:
# ์Šค์ฝ”ํ”„2์—์„œ์˜ x์˜ ๊ฐ’: 1
# ์Šค์ฝ”ํ”„3์—์„œ์˜ x์˜ ๊ฐ’(์ˆ˜์ •๋จ): 2
# ์Šค์ฝ”ํ”„1์—์„œ์˜ x์˜ ๊ฐ’(์Šค์ฝ”ํ”„2์—์„œ 2๋กœ ์ˆ˜์ •๋จ): 1
# <- ์Šค์ฝ”ํ”„ ์•ˆ์—์„œ ์Šค์ฝ”ํ”„ ๋ฐ–์— ์žˆ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜๋ คํ–ˆ์ง€๋งŒ
# <- ํ•ด๋‹น ๋ณ€์ˆ˜์™€ ๋˜‘๊ฐ™์€ ์ด๋ฆ„์˜ ์ง€์—ญ๋ฒˆ์ˆ˜๊ฐ€ ์„ ์–ธ์ด ๋˜์–ด๋ฒ„๋ฆฌ๊ณ 
# <- ์Šค์ฝ”ํ”„ ๋ฐ–์— ์žˆ๋Š” ๋ณ€์ˆ˜๋Š” ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์—ˆ์Œ!(unmutable)


ํŒŒ์ด์ฌ์€ Closure ๋‚ด์˜ ๋ณ€์ˆ˜๋ฅผ ์ฝ์–ด์˜ฌ์ˆ˜๋Š” ์žˆ์ง€๋งŒย ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€๋Š” ๋‹ค๋ฅด๊ฒŒย ์ˆ˜์ •ํ•  ์ˆ˜๋Š” ์—†์Œ!


์œ„์—์„œ ์Šค์ฝ”ํ”„ ๋ฐ–์— ์žˆ๋Š” x๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๊ณ  ํ•˜๋Š” ์ˆœ๊ฐ„ closure๋Š” ํ•ด์ œ๋˜๊ณ  ํ•ด๋‹น statement๋Š” ๊ทธ๋ƒฅ ์ง€์—ญ๋ณ€์ˆ˜ย x๋ฅผ ์„ ์–ธํ•˜๊ณ  2๋กœ ์ดˆ๊ธฐํ™” ์‹œํ‚ค๋Š” statement๋กœ ๋ณ€ํ˜•๋˜๊ฒŒ๋จ.

(ModifyX ํ•จ์ˆ˜ ๋‚ด์— ์žˆ๋Š” x = 2๋Š” x์— 2๋ฅผ ๋Œ€์ž…ํ•˜๋Š” statement๊ฐ€ ์•„๋‹ˆ๋ผ, ํ•ด๋‹น ์Šค์ฝ”ํ”„ ๋‚ด์— x๋ผ๋Š” ๋กœ์ปฌ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ณ  2๋กœ ์ดˆ๊ธฐํ™” ํ•˜๋ผ๋Š” statement์ž„)



์ด๋ ‡๋“ฏ ์–ธ์–ด๋งˆ๋‹ค ์Šค์ฝ”ํ”„๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฐฉ์‹์ด ๋‹ค ๋‹ค๋ฅด๊ณ  ๋ชจ๋‘ ๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์ด ์žˆ์Œ.


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์กด๋‚˜ ๋‚˜์ด๋ธŒํ•œ ์–ธ์–ด์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฌดํ•œํ•œ ์ž์œ ๋„๋ฅผ ์ฃผ๋Š” ๋Œ€์‹  ์˜จ๊ฐ– ์ข…๋ฅ˜์˜ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ์™€ ์ฒœ์ •๋ถ€์ง€๋กœ ์น˜์†Ÿ๋Š” ๋ณต์žก๋„, ๋””๋ฒ„๊น…์˜ ์–ด๋ ค์›€์„ ๊ฐ๋‹นํ•ด์•ผํ•จ.


ํŒŒ์ด์ฌ์€ ๋ณธ๋”” ์‹ฌํ”Œํ•จ, ์•„๋ฆ„๋‹ค์›€์„ ๋‚ด์ƒˆ์šฐ๋Š” ์–ธ์–ด(Zen of python!)๋ผ ์•„์˜ˆ ์ž๊ธฐ ์Šค์ฝ”ํ”„ ๋ฐ–์˜ ๋ณ€์ˆ˜๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋„๋ก ํ•ด์„œ ๊นจ๋—ํ•˜๊ณ  ์˜์กด์„ฑ ์ ์€ ํ”„๋กœ๊ทธ๋žจ์„ ์งœ๋„๋ก ๊ฐ•์ œํ•จ.



๊ทธ๋Ÿผ ํŒŒ์ด์ฌ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ™์€ Closure๋ฅผ ๊ตฌํ˜„ํ• ๊นŒ?


def FactorialGenerator():
ย  ย ย ย  ย ย def Factorial():
ย  ย ย ย  ย ย ย  ย ย ย  ย ย if Factorial.f == 0:
ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย Factorial.f = 1
ย  ย ย ย  ย ย ย  ย ย ย  ย ย else:
ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย Factorial.f *= Factorial.f + 1
ย  ย ย ย  ย ย ย  ย ย ย  ย ย return Factorial.f
ย  ย ย ย  ย ย Factorial.f = 0
ย  ย ย ย  ย ย return Factorial

f = FactorialGenerator()
print(f()) # 1
print(f()) # 2
print(f()) # 6
f2 = FactorialGenerator()
print(f2()) # 1
print(f2()) # 2
print(f2()) # 6


ํŒŒ์ด์ฌ์˜ ํ•จ์ˆ˜๋Š” ๊ฐ์ฒด์ž„. ํŒŒ์ด์ฌ์—์„œ๋Š” ๊ฐ์ฒด์— ์•„๋ฌด ๋•Œ๋‚˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Œ. ์ฆ‰, ํŒŒ์ด์ฌ์˜ ํ•จ์ˆ˜๋Š” ๊ฑ ๊ฐ์ฒด๋ผ์„œย ์ง„์งœ๋กœ ๊ฐ์ฒด์ฒ˜๋Ÿผ ์ƒํƒœ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Œ!


์‚ฌ์‹ค ์ด๋ ‡๊ฒŒ ํ•จ์ˆ˜์— ์ถ”๊ฐ€๋œ ํ”„๋กœํผํ‹ฐ๋ฅผย Closure๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋Š”ย ํ™•์‹ ์ด ์ข€ ์•ˆ๊ฐ. ์•„๋งˆ ๋‚ด ์ƒ๊ฐ์—” Closure๋ผ๊ณ  ์•ˆ๋ถ€๋ฅด๋Š”๊ฑฐ ๊ฐ™์Œ.


์ฐธ๊ณ ๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ•จ์ˆ˜๋„ ํŒŒ์ด์ฌ์ฒ˜๋Ÿผ ๊ฐ์ฒด์ด๊ณ  ํ”„๋กœํผํ‹ฐ๋ฅผ ๋™์ ์œผ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ธฐ๋•Œ๋ฌธ์— ์œ„ ํŒŒ์ด์ฌ์ฒ˜๋Ÿผ ๋˜‘๊ฐ™์ด ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์Œ. ์ด๋ ‡๊ฒŒ ๋Ÿฐํƒ€์ž„์—์„œ ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ ์ดย ๋ฐ”๋กœ ์Šคํฌ๋ฆฝํŠธ ์–ธ์–ด์˜ ์žฅ์ ์ธ ๋“ฏ ํ•จ.