ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • useState, ํด๋กœ์ €๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋™์ž‘ํ•œ๋‹ค๊ณ ?
    TECH 2024. 1. 27. 21:48

    ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ํด๋กœ์ €์— ๋Œ€ํ•ด์„œ ๊ฐ„๋‹จํžˆ ์•Œ์•„๋ณด๊ณ ,

    ํด๋กœ์ €๊ฐ€ ํ™œ์šฉ๋˜๋Š” ์˜ˆ์‹œ ์ค‘ ํ•˜๋‚˜์ธ useState์˜ ๋‚ด๋ถ€ ๋™์ž‘ ๋ฐฉ์‹์„ ์ž์„ธํžˆ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

     

     

     

    โœ”๏ธ ํด๋กœ์ €๋ž€?

    ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ค‘์š”ํ•œ ํŠน์„ฑ ์ค‘ ํ•˜๋‚˜๋กœ, ํ•จ์ˆ˜์™€ ๊ทธ ํ•จ์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ๋ ‰์‹œ์ปฌ ํ™˜๊ฒฝ๊ณผ์˜ ์กฐํ•ฉ์ž…๋‹ˆ๋‹ค.

    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„๋ฅผ ๋”ฐ๋ฅด๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ํ˜„์ƒ์ž…๋‹ˆ๋‹ค.

    W3C School์—์„œ๋Š” ํด๋กœ์ €๋ฅผ ํ•จ์ˆ˜๊ฐ€ privateํ•œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค๊ณ  ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

    ์ด ์„ค๋ช…์ด ํด๋กœ์ €์˜ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

     

     


    ์—ฌ๊ธฐ์„œ ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„๋ž€?

    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์€ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์œ„์น˜๊ฐ€ ์•„๋‹Œ ํ•จ์ˆ˜๋ฅผ ์–ด๋””์— ์ •์˜ํ–ˆ๋Š”์ง€์— ๋”ฐ๋ผ ํ•จ์ˆ˜์˜ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

    ์ƒ์œ„ ์Šค์ฝ”ํ”„์— ๋Œ€ํ•œ ์ฐธ์กฐ๋Š” ํ•จ์ˆ˜ ์ •์˜๊ฐ€ ํ‰๊ฐ€๋˜๋Š” ์‹œ์ ์— ํ•จ์ˆ˜๊ฐ€ ์ •์˜๋œ ํ™˜๊ฒฝ์— ์˜ํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.


     

     

    ์ •๋ฆฌ๋ฅผ ํ•ด ๋ณด์ž๋ฉด,

    ¹ ์™ธ๋ถ€ ํ•จ์ˆ˜๋ณด๋‹ค ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ ์‹๋ณ„์ž๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ค‘์ฒฉ ํ•จ์ˆ˜๊ฐ€ ๋” ์˜ค๋ž˜ ์œ ์ง€๋˜๋Š” ๊ฒฝ์šฐ

    ² ์ค‘์ฒฉ ํ•จ์ˆ˜๊ฐ€ ์ด๋ฏธ ์ƒ๋ช… ์ฃผ๊ธฐ๊ฐ€ ์ข…๋ฃŒ๋œ ์™ธ๋ถ€ ํ•จ์ˆ˜์˜ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ

    ์ด ์ค‘์ฒฉ ํ•จ์ˆ˜๋ฅผ ํด๋กœ์ €๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

     

     

    ํด๋กœ์ €์ธ ์ค‘์ฒฉ ํ•จ์ˆ˜

    const x = 10;
    function outerFunc() {
        const x = 1;
        function innerFunc() {
          console.log(x); // 1
        }
        
        innerFunc();
    }
    
    outerFunc();

     

    ํด๋กœ์ €๊ฐ€ ์•„๋‹Œ ์ค‘์ฒฉ ํ•จ์ˆ˜

    const x = 10;
    function outerFunc() {
        const x = 1;
        function innerFunc() {
          const y = 2
          console.log(y); // 2
        }
        
        innerFunc();
    }
    
    outerFunc();

     

     

     

    โœ”๏ธ ํด๋กœ์ €์˜ ํ™œ์šฉ

    ํด๋กœ์ €๋Š” ์ƒํƒœ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

    ๋‹ค์‹œ ๋งํ•ด, ์ƒํƒœ๋ฅผ ์€๋‹‰ํ•˜์—ฌ ์˜๋„์น˜ ์•Š์€ ๋ณ€๊ฒฝ์„ ๋ฐฉ์ง€ํ•˜๊ณ  ํŠน์ • ํ•จ์ˆ˜๋กœ๋งŒ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ํ—ˆ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    let a = 1;
    
    function add() {
        a += 1;
        return a;
    }
    
    console.log(add()); // 2
    console.log(add()); // 3
    console.log(add()); // 4
    a = 999;
    console.log(add()); // 1000

    ์œ„ ์˜ˆ์ œ์™€ ๊ฐ™์ด a๋ฅผ ์ „์—ญ ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ์˜๋„์น˜ ์•Š์€ ์ƒํƒœ ๋ณ€๊ฒฝ์ด ์ด๋ฃจ์–ด์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

     

    const add = (function() {
    	let a = 1;
        return function() {
            a += 1;
            return a;
        }
    })();
    
    console.log(add()); // 2
    console.log(add()); // 3
    console.log(add()); // 4
    console.log(a); // Uncaught ReferenceError: a is not defined

    ์œ„ ์˜ˆ์ œ์™€ ๊ฐ™์ด ํด๋กœ์ €๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ƒํƒœ๊ฐ€ ์˜๋„์น˜ ์•Š๊ฒŒ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก ์€๋‹‰ํ•˜์—ฌ ์ƒํƒœ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

     

     

     

    โœ”๏ธ useState๊ฐ€ ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹

    useState์˜ ๋‚ด๋ถ€ ๋™์ž‘์— ๊ด€๋ จํ•œ ๋‹ค์Œ ๋ฌธ๋‹จ์€ 2019๋…„ JSConf์—์„œ ๋ฐœํ‘œ๋œ React Hooks์™€ useState์— ๋Œ€ํ•œ ๋ฐœํ‘œ๋ฅผ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

     

     

    function useState(initVal) {
        let _val = initVal;
        const state = () => _val;
        const setState = (newVal) => {
            _val = newVal;
        };
        
        return [state, setState];
    }
    
    const [count, setCount] = useState(1);
    console.log(count());
    setCount(2);
    console.log(count());

    ์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ useState ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๊ทธ๋Ÿฌ๋‚˜ ์ƒํƒœ ๊ฐ’์„ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด getter ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ์•„๋‹Œ ๊ธฐ์กด์˜ useState๊ฐ€ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ํŒจํ„ด์ฒ˜๋Ÿผ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

     

     

     

    ๋‹จ๊ณ„์ ์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง์„ ๊ฑฐ์ณ ๋ด…์‹œ๋‹ค.

     

    const React = (function() {
        function useState(initVal) { 
            let _val = initVal; 
            const state = () => _val;
            const setState = (newVal) => { 
                _val = newVal; 
            }; 
            return [state, setState];
        };
        return { useState };
    })();
    
    const [count, setCount] = React.useState(1); 
    console.log(count()); // 1
    setCount(2); 
    console.log(count()); // 2

    ์ฆ‰์‹œ ์‹คํ–‰ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ React ๋ชจ๋“ˆ ๋‚ด์—์„œ useState๋ฅผ ์ •์˜ํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.

     

     

     

    const React = (function () { 
        /* 3๏ธโƒฃ */
        let _val;
        function useState(initVal) { 
            const state = _val || initVal;
            const setState = (newVal) => { 
              _val = newVal; 
            }; 
            return [state, setState]
        }
        /* 2๏ธโƒฃ */
        function render(Component) {
            const C = Component(); 
            C.render(); 
            return C;
        }
            return { useState, render };
    })();
    
    /* 1๏ธโƒฃ */
    function Component() {
        const [count, setCount] = React.useState(1);
        return {
            render: () => console.log(count),
            click: () => setCount(count + 1),
        }
    }
    
    let App;
    App = React.render(Component); // 1
    App.click();
    App = React.render(Component); // 2

    1๏ธโƒฃ ๋ฆฌ์•กํŠธ๋ฅผ ํ‰๋‚ด๋‚ด๊ธฐ ์œ„ํ•œ Component๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

    Component ๋‚ด๋ถ€์—์„œ๋Š” render ๋ฉ”์†Œ๋“œ๋กœ count๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๊ณ , ๋ฒ„ํŠผ ์—ญํ• ์„ ํ•  click ๋ฉ”์†Œ๋“œ๋ฅผ ๋‘์–ด count์˜ ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.


    2๏ธโƒฃ React ๋ชจ๋“ˆ์—๊ฒŒ๋Š” ๋ Œ๋”๋งํ•  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๋ ค ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    React ๋ชจ๋“ˆ ๋‚ด์— render ํ•จ์ˆ˜๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ ํ›„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

     

    3๏ธโƒฃ ๊ทธ๋ฆฌ๊ณ  React ๋ชจ๋“ˆ์˜ useState ๋‚ด์—์„œ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋˜ _val ๋ณ€์ˆ˜๋ฅผ ์ƒ์œ„๋กœ ๋Œ์–ด์˜ฌ๋ ค React ํ•จ์ˆ˜์˜ ์Šค์ฝ”ํ”„๋กœ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค. (ํด๋กœ์ €์˜ ์šฉ๋ฒ• ํ™œ์šฉ)

    _val ๊ฐ’์€ useState ํ•จ์ˆ˜์— ์˜ํ•ด ์ฐธ์กฐ๋˜๊ณ  ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

     

     

     

     

    ์ด useState์—๋Š” ๋ฒ„๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒํƒœ๋ฅผ ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

     

    function Component() {
        const [count, setCount] = React.useState(1);
        const [text, setText] = React.useState("apple");
        return {
            render: () => console.log({count, text}),
            click: () => setCount(count + 1),
            text: word => setText(word)
        };
    };
    
    var App = React.render(Component); // {count: 1, text: 'apple'}
    App.click();
    var App = React.render(Component); // {count: 2, text: 2}
    App.text("banana");
    var App = React.render(Component); // {count: 'banana', text: 'banana'}

    ์ด ๋ฐฉ์‹์˜ useState _val์ด๋ผ๋Š” ๋‹จ ํ•œ ๊ฐœ์˜ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ , count์™€ text ๋‘˜ ๋‹ค _val ๋ณ€์ˆ˜์— ๋ฎ์–ด ์”Œ์›Œ์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

     

     

     

    ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์ธ๋ฑ์Šค(idx)๋ฅผ ๋‘๊ณ , ์ƒํƒœ ๋ฐฐ์—ด(hooks)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    const React = (function () {
        let hooks = [];
        let idx = 0
        function useState(initVal) {
            const state = hooks[idx] || initVal;
            const _idx = idx; // freeze idx using closure
            const setState = (newVal) => {
                hooks[_idx] = newVal;
            };
            idx++
            return [state, setState];
        };
        function render(Component) {
            idx = 0;
            const C = Component();
            C.render();
            return C;
        };
        return { useState, render };
    })();
    
      
    
    function Component() {
        const [count, setCount] = React.useState(1);
        const [text, setText] = React.useState("apple");
        return {
            render: () => console.log({count, text}),
            click: () => setCount(count + 1),
            text: word => setText(word)
        };
    };
    
    var App = React.render(Component); // {count: 1, text: 'apple'}
    App.click();
    var App = React.render(Component); // {count: 2, text: 'apple'}
    App.text("banana");
    var App = React.render(Component); // {count: 2, text: 'banana'}

     

     

     

     

    ๋˜ํ•œ ์—ฌ๊ธฐ์„œ ๋ฆฌ์•กํŠธ ํ›…์ด ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ, ์ค‘์ฒฉ ํ•จ์ˆ˜ ๋‚ด์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ทœ์น™์˜ ์ด์œ ์— ๋Œ€ํ•ด์„œ๋„ ์ž์„ธํžˆ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    function Component() {
        if (Math.random() > 0.5) {
            const [count, setCount] = React.useState(1);
        }
        const [text, setText] = React.useState("apple"); // โฌ…๏ธ
        return {
            render: () => console.log({count, text}),
            click: () => setCount(count + 1),
            text: word => setText(word)
        };
    }

    ๋‹ค์Œ๊ณผ ๊ฐ™์ด useStae๋ฅผ ์กฐ๊ฑด๋ฌธ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ํ™”์‚ดํ‘œ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” useStae์˜ ์ธ๋ฑ์Šค๋Š” 0์ด ๋  ์ˆ˜๋„ ์žˆ๊ณ  1์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ด์™€ ๊ฐ™์€ ๋™์ž‘์€ ์ƒํƒœ๊ฐ€ hooks ๋ฐฐ์—ด ๋‚ด์—์„œ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ์œ„์น˜์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

     

    ๋”ฐ๋ผ์„œ ํ›…์€ ์ƒํƒœ๊ฐ€ ์ผ๊ด€๋œ ์ˆœ์„œ๋กœ ์ €์žฅ๋˜์–ด ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ณ  ์•ˆ์ •์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์ปดํฌ๋„ŒํŠธ์˜ ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ๋งŒ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

     

     

     

    โ˜˜๏ธ ์ฐธ๊ณ 

    ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive โ€• 24์žฅ ํด๋กœ์ €

    Can Swyx recreate React Hooks and useState in under 30 min? - JSConf.Asia

    ๋Œ“๊ธ€

Designed by Tistory.