๐Ÿ’ป๐Ÿ’€/๊ฐœ๋ฐœ

[JS] ํด๋กœ์ €(Closure) ํ™œ์šฉํ•˜๊ธฐ

db2 2022. 8. 28. 23:00

ํด๋กœ์ €๋ž€

๋ฐ˜ํ™˜๋˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜์‹œํ‚จ ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜ ํ™˜๊ฒฝ์„ ๋ฌถ์–ด์„œ(closing) ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๋Š” ๊ฐœ๋…์„ ๋งํ•œ๋‹ค.

์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ์ข…๋ฃŒ๋˜์–ด ์ฝœ ์Šคํƒ์—์„œ ์ œ๊ฑฐ๋˜๋ฉด ํ•ด๋‹น ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์„ ์–ธ๋œ ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†๋‹ค. ํ•˜์ง€๋งŒ ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜๋Š” ์ž์‹ ์„ ๋ฐ˜ํ™˜์‹œํ‚จ ํ•จ์ˆ˜๊ฐ€ ์ฝœ ์Šคํƒ์—์„œ ์ œ๊ฑฐ๋˜์–ด๋„ ์—ฌ์ „ํžˆ ๊ทธ ์Šค์ฝ”ํ”„์— ์ ‘๊ทผํ•˜์—ฌ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

์ด๋Š” ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜๋Š” ์ž์‹ ์ด ํ˜ธ์ถœ๋  ๋•Œ๊ฐ€ ์•„๋‹ˆ๋ผ ์„ ์–ธ๋  ๋•Œ์˜ ํ™˜๊ฒฝ(Lexical Environment)์„ ๊ธฐ์–ตํ•˜๊ณ  ํด๋กœ์ € ์Šค์ฝ”ํ”„๋ฅผ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— ์ฝœ ์Šคํƒ์— ๋ฐ˜ํ™˜์‹œํ‚จ ํ•จ์ˆ˜๊ฐ€ ์—†๋”๋ผ๋„ ์Šค์ฝ”ํ”„ ์ฒด์ธ์„ ํ†ตํ•ด ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ดํ•ด๋ฅผ ๋•๊ธฐ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ด๋‹ค.

// inner ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜์‹œํ‚ค๋Š” ํ•จ์ˆ˜
function outer() {
    const outerText = 'I am outer function';

    // ๋ฐ˜ํ™˜๋˜๋Š” ํ•จ์ˆ˜
    return function inner() {
        console.log(outerText);
    }
}

const closureFn = outer();
closureFn(); // I am outer function

11๋ฒˆ์งธ ๋ผ์ธ์—์„œ outer ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ•ด๋‹น ํ•จ์ˆ˜์˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ฝœ ์Šคํƒ์— ์Œ“์ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  outer ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ์ข…๋ฃŒ๋˜๋ฉด closureFn ๋ณ€์ˆ˜์—๋Š” outer ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•œ inner ํ•จ์ˆ˜๊ฐ€ ๋‹ด๊ธฐ๊ฒŒ ๋˜๊ณ , ์ฝœ ์Šคํƒ์—์„œ๋Š” outer ํ•จ์ˆ˜๊ฐ€ ์ œ๊ฑฐ๋œ๋‹ค.

๊ทธ ๋’ค 12๋ฒˆ์งธ ๋ผ์ธ์—์„œ closureFn ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š”๋ฐ, ์ด๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ outer ํ•จ์ˆ˜์— ์„ ์–ธ๋˜์—ˆ๋˜ outerText ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•œ๋‹ค. closureFn ํ•จ์ˆ˜์—๋Š” outerText๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์Šค์ฝ”ํ”„ ์ฒด์ธ์„ ํ†ตํ•ด ๋ณ€์ˆ˜๋ฅผ ์ฐพ์•„์•ผ ํ•˜๋Š”๋ฐ ์ฝœ ์Šคํƒ์—๋Š” ๋”์ด์ƒ outer ํ•จ์ˆ˜๊ฐ€ ์—†๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  closureFn ํ•จ์ˆ˜๋Š” ์ •์ƒ์ ์œผ๋กœ outerText ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด์œ ๋Š” ๋ฐ”๋กœ closureFn ํ•จ์ˆ˜๊ฐ€ ํด๋กœ์ €์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ํด๋กœ์ € ํŒจํ„ด ํ™œ์šฉํ•˜๊ธฐ

๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ฐ๊ด€๋œ ๋ฐ์ดํ„ฐ์™€ ๋™์ž‘์„ ๋ฌถ์–ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๋ก  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋„ ์ด๋ฏธ ํ•œ์ฐธ ์ „๋ถ€ํ„ฐ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค์ง€๋งŒ, ๋ฆฌ์•กํŠธ๋กœ ๊ฐœ๋ฐœํ•˜๋ฉด ํด๋ž˜์Šค๋ฅผ ์“ฐ๊ธฐ๊ฐ€ ์• ๋งคํ•  ๋•Œ๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ตœ๊ทผ์— ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ๊ณ„์† ๊ธฐ์–ตํ•˜๊ธฐ ์œ„ํ•ด ํด๋กœ์ €๋ฅผ ํ™œ์šฉํ–ˆ๋˜ ์‚ฌ๋ก€๊ฐ€ ์žˆ์–ด ๊ณต์œ ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค. ์˜ˆ์‹œ๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ์ž…๋ ฅ๋ฐ›์€ ์ƒˆ ๋น„๋ฐ€๋ฒˆํ˜ธ์™€ ์ƒˆ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ์— ๋Œ€ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ์ด๋‹ค.

๋จผ์ € ์ด๋Ÿฐ ๊ตฌ์กฐ์˜ input์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

function Form() {
    const { validatePassword } = validator(); 
    const handleChange = (e) => {
        const { name, value } = e;
        validatePassword(name, value);
    }

    return (
        <>
            <input type="password" name="password" value={password} onChange={handleChange} />
            <input type="password" name="confirm" value={confirm} onChange={handleChange} />      
        </>
    )
}

์ด ๋•Œ name์ด password์ผ ๋• ๊ทธ ๊ฐ’์„ ์ €์žฅํ•ด๋†“์•„์•ผ confirm ๊ฐ’์ด ์ž…๋ ฅ๋์„ ๋•Œ password์™€ ๋น„๊ตํ•˜์—ฌ ์ผ์น˜ํ•œ์ง€ ๋น„๊ต๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ํด๋กœ์ € ๊ฐœ๋…์„ ํ™œ์šฉํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. ์•„์ฃผ ๊ฐ„๋žตํ•˜๊ฒŒ ๋Š๋‚Œ๋งŒ ๋Š๋‚„ ์ˆ˜ ์žˆ๊ฒŒ ์ž‘์„ฑํ–ˆ๋‹ค.

function validator() {
    let password;

    function validatePassword(name, value) => {
        if(name === 'password') {
            password = value;
        }
        if(name === 'confirm') {
            // password์™€ value๊ฐ€ ๊ฐ™์€์ง€ ๋น„๊ต
        }

    }

    return {
        validatePassword
    }
}

๋‚˜๋Š” ๊ณตํ†ต handleChange ํ•จ์ˆ˜๋ฅผ ์ตœ๋Œ€ํ•œ ๊นจ๋—ํ•˜๊ฒŒ ์œ ์ง€ํ•˜๊ณ  ์‹ถ๊ธฐ๋„ ํ–ˆ๊ณ  ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ•จ์ˆ˜๋“ค๋ผ๋ฆฌ ๋ฌถ์–ด์„œ ๊ด€๋ฆฌํ•˜๋ ค๊ณ  ์ด ๋ฐฉ์‹์„ ํƒํ–ˆ๋Š”๋ฐ, ๊ตณ์ด ํด๋กœ์ €๋กœ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ  ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ•จ์ˆ˜์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ password์™€ confirm ๊ฐ’์„ ํ•จ๊ป˜ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฒƒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค!