<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>스타트업 엔지니어링</title>
    <link>https://sueng.tistory.com/</link>
    <description>개발자로 일하고 있습니다. 
엔지니어링 관련된 개인적인 관심을 기록하는 블로그입니다.</description>
    <language>ko</language>
    <pubDate>Thu, 16 Jul 2026 18:52:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>엔디엘디(NdLd)</managingEditor>
    <image>
      <title>스타트업 엔지니어링</title>
      <url>https://tistory1.daumcdn.net/tistory/1576482/attach/f979d040bc9e46d3b8072f7216ae0602</url>
      <link>https://sueng.tistory.com</link>
    </image>
    <item>
      <title>코드 예제로 보는 바닐라 자바스크립트 vs 리엑트 제이에스</title>
      <link>https://sueng.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리엑트를&amp;nbsp;처음&amp;nbsp;배우는&amp;nbsp;분이라면&amp;nbsp;이미&amp;nbsp;기본적인&amp;nbsp;자바스크립트(Vanilla&amp;nbsp;Javascript)는&amp;nbsp;사용할&amp;nbsp;줄&amp;nbsp;아실&amp;nbsp;텐데요.&amp;nbsp;본격적으로&amp;nbsp;리엑트&amp;nbsp;에이에스(ReactJs)를&amp;nbsp;배우기&amp;nbsp;전에&amp;nbsp;코드&amp;nbsp;예제를&amp;nbsp;통해서&amp;nbsp;바닐라&amp;nbsp;자바스크립트와&amp;nbsp;리엑트&amp;nbsp;제이에스가&amp;nbsp;어떻게&amp;nbsp;다른지를&amp;nbsp;살펴보는&amp;nbsp;것은&amp;nbsp;두고두고&amp;nbsp;도움이&amp;nbsp;되는&amp;nbsp;좋은&amp;nbsp;경험이&amp;nbsp;될&amp;nbsp;겁니다.&amp;nbsp;먼저&amp;nbsp;간단한&amp;nbsp;자바스크립트로&amp;nbsp;버튼이&amp;nbsp;클릭될&amp;nbsp;때마다&amp;nbsp;Like&amp;nbsp;숫자를&amp;nbsp;하나씩&amp;nbsp;올려주는&amp;nbsp;html&amp;nbsp;페이지를&amp;nbsp;하나&amp;nbsp;만들어&amp;nbsp;보겠습니다.&amp;nbsp;그다음에&amp;nbsp;동일한&amp;nbsp;동작을&amp;nbsp;하는&amp;nbsp;ReactJs&amp;nbsp;코드를&amp;nbsp;작성하려고&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1.&amp;nbsp;바닐라&amp;nbsp;자바스크립트&amp;nbsp;코드&amp;nbsp;예제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제에&amp;nbsp;사용할&amp;nbsp;html은&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;단&amp;nbsp;3줄의&amp;nbsp;엘리먼트를&amp;nbsp;표시하고&amp;nbsp;있습니다.&amp;nbsp;맨&amp;nbsp;첫줄의&amp;nbsp;h1은&amp;nbsp;제목&amp;nbsp;역할을&amp;nbsp;하고&amp;nbsp;있습니다.&amp;nbsp;Like라고&amp;nbsp;되어&amp;nbsp;있는&amp;nbsp;버튼이&amp;nbsp;있고&amp;nbsp;p&amp;nbsp;태그로&amp;nbsp;버튼을&amp;nbsp;클릭한&amp;nbsp;횟수를&amp;nbsp;표시하려고&amp;nbsp;합니다.&amp;nbsp;지금은&amp;nbsp;엘리먼트는&amp;nbsp;만들어져&amp;nbsp;있지만&amp;nbsp;코드를&amp;nbsp;작성하지&amp;nbsp;않아서&amp;nbsp;버튼을&amp;nbsp;클릭해도&amp;nbsp;아무런&amp;nbsp;반응을&amp;nbsp;하지&amp;nbsp;않고&amp;nbsp;있죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;바닐라_자바스크립트_예제.jpg&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuEuJc/btr9ppQL0wF/XSoTwiYTFMmWVAeq7K2ehk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuEuJc/btr9ppQL0wF/XSoTwiYTFMmWVAeq7K2ehk/img.jpg&quot; data-alt=&quot;바닐라 자바스크립트 기본&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuEuJc/btr9ppQL0wF/XSoTwiYTFMmWVAeq7K2ehk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuEuJc%2Fbtr9ppQL0wF%2FXSoTwiYTFMmWVAeq7K2ehk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;474&quot; data-filename=&quot;바닐라_자바스크립트_예제.jpg&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;바닐라 자바스크립트 기본&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제에&amp;nbsp;사용된&amp;nbsp;html&amp;nbsp;코드는&amp;nbsp;아래와&amp;nbsp;같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681141755250&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;head&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;h1&amp;gt;Hi Vanilla JS&amp;lt;/h1&amp;gt;
&amp;lt;div&amp;gt;
    &amp;lt;button id=&quot;like_btn&quot;&amp;gt;Like&amp;lt;/button&amp;gt;
    &amp;lt;p id=&quot;like_count_text&quot;&amp;gt;0 Likes&amp;lt;/p&amp;gt;    
&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;script&amp;gt;

&amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.1.&amp;nbsp;엘리먼트&amp;nbsp;가져오기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;html로&amp;nbsp;작성된&amp;nbsp;엘리먼트를&amp;nbsp;가져오기&amp;nbsp;위해서는&amp;nbsp;자바스트립트를&amp;nbsp;사용해서&amp;nbsp;엘리먼트를&amp;nbsp;가져와야&amp;nbsp;합니다.&amp;nbsp;button과&amp;nbsp;p&amp;nbsp;태그가&amp;nbsp;각각&amp;nbsp;id를&amp;nbsp;가지고&amp;nbsp;있어서&amp;nbsp;document.getElementById를&amp;nbsp;사용해서&amp;nbsp;엘리먼트를&amp;nbsp;가져옵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1681141793358&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
    let btn = document.getElementById(&quot;like_btn&quot;);
    let count_text = document.getElementById(&quot;like_count_text&quot;);
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;엘리먼트를&amp;nbsp;가져&amp;nbsp;왔으니&amp;nbsp;이벤트&amp;nbsp;핸들러&amp;nbsp;함수를&amp;nbsp;작성하고&amp;nbsp;이벤트를&amp;nbsp;등록합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.2. 이벤트 핸들러 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버튼을 클릭할 때마다 변수인 like_count 값을 1 씩 증가시킵니다. 그리고 그 값을 콘솔에 로그로 표시해 보겠습니다.&lt;br /&gt;아래&amp;nbsp;코드를&amp;nbsp;추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1681141826085&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    let like_count = 0;
    function btn_licked() {
        like_count++;
        console.log(`Like clicked ${like_count} times!`);
    }

    btn.addEventListener(&quot;click&quot;, btn_licked);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;버튼을&amp;nbsp;클릭할&amp;nbsp;때마다&amp;nbsp;콘솔에&amp;nbsp;로그가&amp;nbsp;표시되는&amp;nbsp;것을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;바닐라_자바스크립트_버튼_클릭.jpg&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lEIe1/btr9nmUxkup/EA3ZWULh2ib9QoJ6b75IZ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lEIe1/btr9nmUxkup/EA3ZWULh2ib9QoJ6b75IZ1/img.jpg&quot; data-alt=&quot;바닐라 자바스크립트 버튼 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lEIe1/btr9nmUxkup/EA3ZWULh2ib9QoJ6b75IZ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlEIe1%2Fbtr9nmUxkup%2FEA3ZWULh2ib9QoJ6b75IZ1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;548&quot; data-filename=&quot;바닐라_자바스크립트_버튼_클릭.jpg&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;바닐라 자바스크립트 버튼 클릭&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만&amp;nbsp;화면에는&amp;nbsp;아직도&amp;nbsp;0&amp;nbsp;Likes라고&amp;nbsp;표시가&amp;nbsp;되고&amp;nbsp;있네요.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.3.&amp;nbsp;텍스트&amp;nbsp;업데이트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트를&amp;nbsp;업데이트&amp;nbsp;하기위해서는&amp;nbsp;버튼&amp;nbsp;클릭&amp;nbsp;이벤트&amp;nbsp;핸들러에&amp;nbsp;텍스트를&amp;nbsp;업데이트하는&amp;nbsp;코드를&amp;nbsp;추가해야&amp;nbsp;합니다.&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;btn_clicked&amp;nbsp;함수를&amp;nbsp;수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1681141899907&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    function btn_licked() {
        like_count++;
        console.log(`Like clicked ${like_count} times!`);

        count_text.innerText = `${like_count} Likes`;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;이제&amp;nbsp;버튼을&amp;nbsp;클릭하면&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;콘솔에&amp;nbsp;로그가&amp;nbsp;찍히면서&amp;nbsp;텍스트에&amp;nbsp;있는&amp;nbsp;수자도&amp;nbsp;같이&amp;nbsp;변경되는&amp;nbsp;것을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;바닐라_자바스크립트_버튼_클릭2.jpg&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;543&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MMAqP/btr9dYN1AOQ/HnjOjkO5QyrwaSVL5jWi6k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MMAqP/btr9dYN1AOQ/HnjOjkO5QyrwaSVL5jWi6k/img.jpg&quot; data-alt=&quot;바닐라 자바스크립트 버튼 클릭2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MMAqP/btr9dYN1AOQ/HnjOjkO5QyrwaSVL5jWi6k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMMAqP%2Fbtr9dYN1AOQ%2FHnjOjkO5QyrwaSVL5jWi6k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;724&quot; height=&quot;543&quot; data-filename=&quot;바닐라_자바스크립트_버튼_클릭2.jpg&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;543&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;바닐라 자바스크립트 버튼 클릭2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.&amp;nbsp;리엑트&amp;nbsp;제이에스&amp;nbsp;코드&amp;nbsp;예제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서&amp;nbsp;바닐라&amp;nbsp;자바스크립트로&amp;nbsp;작성된&amp;nbsp;예제&amp;nbsp;코드를&amp;nbsp;리엑트&amp;nbsp;제이에스로&amp;nbsp;작성해&amp;nbsp;보려고&amp;nbsp;합니다.&amp;nbsp;ReactJs를&amp;nbsp;사용하는&amp;nbsp;경우에는&amp;nbsp;일반적으로&amp;nbsp;html&amp;nbsp;엘리먼트를&amp;nbsp;미리&amp;nbsp;생성해&amp;nbsp;두지&amp;nbsp;않습니다.&amp;nbsp;우선&amp;nbsp;먼저&amp;nbsp;예제에&amp;nbsp;사용할&amp;nbsp;코드를&amp;nbsp;보겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1681141958326&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div id=&quot;root&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;script&amp;gt;
    
&amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위&amp;nbsp;html을&amp;nbsp;브라우저로&amp;nbsp;읽어들이면&amp;nbsp;아무것도&amp;nbsp;표시되지&amp;nbsp;않을&amp;nbsp;겁니다.&amp;nbsp;그냥&amp;nbsp;아무것도&amp;nbsp;업이&amp;nbsp;하얀&amp;nbsp;화면만&amp;nbsp;보일&amp;nbsp;겁니다.&amp;nbsp;그게&amp;nbsp;정상입니다.&lt;br /&gt;&lt;br /&gt;참고로&amp;nbsp;실제로&amp;nbsp;ReactJs로&amp;nbsp;개발을&amp;nbsp;할&amp;nbsp;때는&amp;nbsp;이&amp;nbsp;글에서&amp;nbsp;설명하는&amp;nbsp;방식으로&amp;nbsp;개발을&amp;nbsp;하지&amp;nbsp;않습니다.&amp;nbsp;여기서는&amp;nbsp;이&amp;nbsp;글의&amp;nbsp;목적인&amp;nbsp;바닐라&amp;nbsp;자바스크립트와&amp;nbsp;비교를&amp;nbsp;하기&amp;nbsp;위해서&amp;nbsp;예제&amp;nbsp;코드를&amp;nbsp;작성하고&amp;nbsp;있다는&amp;nbsp;점을&amp;nbsp;꼭&amp;nbsp;참고&amp;nbsp;바랍니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1.&amp;nbsp;리엑트&amp;nbsp;제이에스&amp;nbsp;추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ReactJs를&amp;nbsp;사용하기&amp;nbsp;위해서는&amp;nbsp;2개의&amp;nbsp;자바스크립트&amp;nbsp;파일을&amp;nbsp;추가해야&amp;nbsp;합니다.&amp;nbsp;아래&amp;nbsp;2&amp;nbsp;라인을&amp;nbsp;html의&amp;nbsp;head&amp;nbsp;영역에&amp;nbsp;추가합니다.&amp;nbsp;ReactJs&amp;nbsp;API는&amp;nbsp;크게&amp;nbsp;react와&amp;nbsp;react-dom으로&amp;nbsp;나뉘어&amp;nbsp;있습니다.&amp;nbsp;두&amp;nbsp;종류의&amp;nbsp;API를&amp;nbsp;모두&amp;nbsp;사용하기&amp;nbsp;위해서&amp;nbsp;2개의&amp;nbsp;js&amp;nbsp;파일을&amp;nbsp;로드를&amp;nbsp;하는&amp;nbsp;것입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1681141984200&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    &amp;lt;script crossorigin src=&quot;https://unpkg.com/react@18/umd/react.production.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script crossorigin src=&quot;https://unpkg.com/react-dom@18/umd/react-dom.production.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;이렇게&amp;nbsp;파일을&amp;nbsp;추가하면&amp;nbsp;React&amp;nbsp;오브젝트와&amp;nbsp;ReactDOM&amp;nbsp;오브젝트를&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있게&amp;nbsp;됩니다.&amp;nbsp;콘솔에서&amp;nbsp;React.&amp;nbsp;을&amp;nbsp;타이핑해&amp;nbsp;보세요.&amp;nbsp;그러면&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;함수&amp;nbsp;목록이&amp;nbsp;나옵니다.&amp;nbsp;콘솔에서&amp;nbsp;ReactDOM.&amp;nbsp;도&amp;nbsp;타이핑해&amp;nbsp;보세요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ReactJs_함수목록.jpg&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coHvbK/btr9qA5yFlU/wtA8TfhfBj7QRfUWkShUHK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coHvbK/btr9qA5yFlU/wtA8TfhfBj7QRfUWkShUHK/img.jpg&quot; data-alt=&quot;ReactJs 함수 목록 보기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coHvbK/btr9qA5yFlU/wtA8TfhfBj7QRfUWkShUHK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoHvbK%2Fbtr9qA5yFlU%2FwtA8TfhfBj7QRfUWkShUHK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;578&quot; data-filename=&quot;ReactJs_함수목록.jpg&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ReactJs 함수 목록 보기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.2.&amp;nbsp;엘리먼트&amp;nbsp;생성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React의&amp;nbsp;createElement를&amp;nbsp;사용해서&amp;nbsp;우리가&amp;nbsp;사용할&amp;nbsp;엘리먼트를&amp;nbsp;만들&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;만들어진&amp;nbsp;엘리먼트는&amp;nbsp;ReactDOM의&amp;nbsp;render&amp;nbsp;API를&amp;nbsp;사용해서&amp;nbsp;DOM에&amp;nbsp;추가하게&amp;nbsp;됩니다.&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;코드를&amp;nbsp;추가합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1681142043418&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
    let root = document.getElementById(&quot;root&quot;);
    let h1 = React.createElement('h1', null, &quot;Hi ReactJs&quot;);
    let btn = React.createElement('button', null, &quot;Like&quot;);
    let text = React.createElement('p', null, &quot;0 Likes&quot;);

    let div = React.createElement('div', null, '', [btn, text]);

    ReactDOM.render([h1, div], root);
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;화면에&amp;nbsp;ReactJs로&amp;nbsp;생성한&amp;nbsp;엘리먼트가&amp;nbsp;잘&amp;nbsp;표시되네요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;리엑트_제이에스_엘리먼트생성.jpg&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N4Qz0/btr9m829QLe/kV9nf0Ihana7smK5xdFJU0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N4Qz0/btr9m829QLe/kV9nf0Ihana7smK5xdFJU0/img.jpg&quot; data-alt=&quot;리엑트 제이에스 엘리먼트 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N4Qz0/btr9m829QLe/kV9nf0Ihana7smK5xdFJU0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN4Qz0%2Fbtr9m829QLe%2FkV9nf0Ihana7smK5xdFJU0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;725&quot; height=&quot;478&quot; data-filename=&quot;리엑트_제이에스_엘리먼트생성.jpg&quot; data-origin-width=&quot;725&quot; data-origin-height=&quot;478&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;리엑트 제이에스 엘리먼트 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바닐라&amp;nbsp;자바스크립트로&amp;nbsp;작성된&amp;nbsp;html과&amp;nbsp;React로&amp;nbsp;생성된&amp;nbsp;엘리먼트의&amp;nbsp;차이&amp;nbsp;중&amp;nbsp;하나는&amp;nbsp;button과&amp;nbsp;p&amp;nbsp;엘리먼트에&amp;nbsp;id가&amp;nbsp;없다는&amp;nbsp;것입니다.&amp;nbsp;이것은&amp;nbsp;예제를&amp;nbsp;위해서&amp;nbsp;의도적으로&amp;nbsp;id를&amp;nbsp;넣지&amp;nbsp;않은&amp;nbsp;것이고&amp;nbsp;원한다면&amp;nbsp;간단히&amp;nbsp;넣을&amp;nbsp;수도&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.3.&amp;nbsp;이벤트&amp;nbsp;핸들러&amp;nbsp;작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전&amp;nbsp;자바스크립트로&amp;nbsp;이벤트&amp;nbsp;핸들러를&amp;nbsp;넣기&amp;nbsp;위해서는&amp;nbsp;id를&amp;nbsp;사용해서&amp;nbsp;엘리먼트를&amp;nbsp;가져와야&amp;nbsp;했습니다.&amp;nbsp;하지만&amp;nbsp;ReactJs를&amp;nbsp;사용하는&amp;nbsp;경우는&amp;nbsp;그렇게&amp;nbsp;하지&amp;nbsp;않고&amp;nbsp;엘리먼트를&amp;nbsp;생성하면서&amp;nbsp;바로&amp;nbsp;이벤트&amp;nbsp;핸들러를&amp;nbsp;추가할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;코드를&amp;nbsp;추가해&amp;nbsp;줍니다.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681142105604&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
&amp;lt;script&amp;gt;
    let root = document.getElementById(&quot;root&quot;);
    let h1 = React.createElement('h1', null, &quot;Hi ReactJs&quot;);
    let like_count = 0;

    let text = React.createElement('p', null, `${like_count} Likes`);
    let btn = React.createElement('button', {
        onClick: () =&amp;gt; {
            like_count++;
            console.log(`Like clicked ${like_count} times!`);
        }
    }, &quot;Like&quot;);
    let div = React.createElement('div', null, '', [btn, text]);

    ReactDOM.render([h1, div], root);
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이렇게&amp;nbsp;하고&amp;nbsp;나면&amp;nbsp;버튼이&amp;nbsp;클릭될&amp;nbsp;때마다&amp;nbsp;콘솔에&amp;nbsp;로그가&amp;nbsp;나오는&amp;nbsp;것을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;한번&amp;nbsp;확인해&amp;nbsp;보세요.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.4&amp;nbsp;텍스트&amp;nbsp;업데이트&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는&amp;nbsp;클릭된&amp;nbsp;숫자만큼&amp;nbsp;표시되는&amp;nbsp;텍스트를&amp;nbsp;변경해야&amp;nbsp;합니다.&amp;nbsp;이&amp;nbsp;부분이&amp;nbsp;조금&amp;nbsp;코드가&amp;nbsp;지저분해지는데요.&amp;nbsp;이것은&amp;nbsp;이후&amp;nbsp; ReactJs를&amp;nbsp;제대로&amp;nbsp;사용하게&amp;nbsp;되면&amp;nbsp;깔끔하게&amp;nbsp;정리가&amp;nbsp;될&amp;nbsp;것입니다.&amp;nbsp;코드를&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;수정합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1681142132446&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
&amp;lt;script&amp;gt;
    let root = document.getElementById(&quot;root&quot;);
    let h1 = React.createElement('h1', null, &quot;Hi ReactJs&quot;);
    let like_count = 0;

    let text = React.createElement('p', null, `${like_count} Likes`);
    let btn = React.createElement('button', {
        onClick: () =&amp;gt; {
            like_count++;
            console.log(`Like clicked ${like_count} times!`);
            let text = React.createElement('p', null, `${like_count} Likes`);
            let div = React.createElement('div', null, '', [btn, text]);
            ReactDOM.render([h1, div], root);
        }
    }, &quot;Like&quot;);
    let div = React.createElement('div', null, '', [btn, text]);

    ReactDOM.render([h1, div], root);
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;추가된&amp;nbsp;코드를&amp;nbsp;보면&amp;nbsp;onClick&amp;nbsp;함수&amp;nbsp;안에서&amp;nbsp;text와&amp;nbsp;div를&amp;nbsp;새로&amp;nbsp;생성해서&amp;nbsp;reder&amp;nbsp;함수를&amp;nbsp;호출하는&amp;nbsp;것을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이&amp;nbsp;부분을&amp;nbsp;JSX를&amp;nbsp;사용하면&amp;nbsp;어떻게&amp;nbsp;변경이&amp;nbsp;되는지&amp;nbsp;보도록&amp;nbsp;하겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3.&amp;nbsp;리엑트에서&amp;nbsp;JSX&amp;nbsp;사용하기&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.1.&amp;nbsp;JSX를&amp;nbsp;사용해서&amp;nbsp;코드&amp;nbsp;수정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리엑트&amp;nbsp;제이에스에서&amp;nbsp;중요한&amp;nbsp;요소&amp;nbsp;중에&amp;nbsp;하나가&amp;nbsp;JSX를&amp;nbsp;사용한다는&amp;nbsp;것입니다.&amp;nbsp;앞서&amp;nbsp;예제까지는&amp;nbsp;모두&amp;nbsp;자바스크립트&amp;nbsp;스펙&amp;nbsp;안에서&amp;nbsp;구현이&amp;nbsp;되었기&amp;nbsp;때문에&amp;nbsp;별도의&amp;nbsp;변환이&amp;nbsp;없이&amp;nbsp;코드를&amp;nbsp;실행할&amp;nbsp;수&amp;nbsp;있었습니다.&amp;nbsp;하지만&amp;nbsp;JSX는&amp;nbsp;자바스크립트&amp;nbsp;스펙이&amp;nbsp;아니기&amp;nbsp;때문에&amp;nbsp;별도의&amp;nbsp;변환툴을&amp;nbsp;사용해서&amp;nbsp;자바스크립트로&amp;nbsp;변환을&amp;nbsp;해야&amp;nbsp;브라우저에서&amp;nbsp;에러&amp;nbsp;없이&amp;nbsp;실행이&amp;nbsp;됩니다.&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;JSX를&amp;nbsp;사용해서&amp;nbsp;코드를&amp;nbsp;수정해&amp;nbsp;보겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1681142159520&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
&amp;lt;script&amp;gt;
    let root = document.getElementById(&quot;root&quot;);
    let Greeting = () =&amp;gt; &amp;lt;h1&amp;gt;Hi ReactJs&amp;lt;/h1&amp;gt;;
    let like_count = 0;

    let Text = () =&amp;gt; &amp;lt;p id='like_count_text'&amp;gt;{like_count} Likes&amp;lt;/p&amp;gt;;
    let Btn = () =&amp;gt; &amp;lt;button id='like_btn' onClick={() =&amp;gt; {
        like_count++;
        console.log(`Like clicked ${like_count} times!`);
        ReactDOM.render([Greeting(), Div()], root);
    }}&amp;gt;Like&amp;lt;/button&amp;gt;

    let Div = () =&amp;gt; &amp;lt;div&amp;gt;
            &amp;lt;Btn /&amp;gt;
            &amp;lt;Text /&amp;gt;
        &amp;lt;/div&amp;gt;;

    ReactDOM.render([Greeting(), Div()], root);
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;코드를&amp;nbsp;저장하고&amp;nbsp;브라우저에서&amp;nbsp;새로고침을&amp;nbsp;하면&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;에러가&amp;nbsp;납니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;리엑트_제이에스_JSX에러.jpg&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C2hMD/btr9pZEnkZG/YhLhy4EhCyqOgPgnpapBU1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C2hMD/btr9pZEnkZG/YhLhy4EhCyqOgPgnpapBU1/img.jpg&quot; data-alt=&quot;리엑트 에이에스 JSX 에러&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C2hMD/btr9pZEnkZG/YhLhy4EhCyqOgPgnpapBU1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC2hMD%2Fbtr9pZEnkZG%2FYhLhy4EhCyqOgPgnpapBU1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;731&quot; height=&quot;299&quot; data-filename=&quot;리엑트_제이에스_JSX에러.jpg&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;리엑트 에이에스 JSX 에러&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.2.&amp;nbsp;바벨&amp;nbsp;추가하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게&amp;nbsp;JSX로&amp;nbsp;작성된&amp;nbsp;코드를&amp;nbsp;브라우저가&amp;nbsp;이해할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;자바스크립트로&amp;nbsp;수정을&amp;nbsp;해&amp;nbsp;주기&amp;nbsp;위해서&amp;nbsp;사용하는&amp;nbsp;것이&amp;nbsp;바벨입니다.&amp;nbsp;아래와&amp;nbsp;같이&amp;nbsp;바벨&amp;nbsp;자바스크립트를&amp;nbsp;헤더에&amp;nbsp;추가합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1681142211204&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
&amp;lt;head&amp;gt;
    &amp;lt;script crossorigin src=&quot;https://unpkg.com/react@18/umd/react.production.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script crossorigin src=&quot;https://unpkg.com/react-dom@18/umd/react-dom.production.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;script에&amp;nbsp;type을&amp;nbsp;text/babel로&amp;nbsp;추가합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1681142235460&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script type=&quot;text/babel&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;저장하고&amp;nbsp;브라우저를&amp;nbsp;새로&amp;nbsp;고침해&amp;nbsp;봅니다.&amp;nbsp;에러&amp;nbsp;없이&amp;nbsp;잘&amp;nbsp;동작하는&amp;nbsp;것을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이&amp;nbsp;글에서&amp;nbsp;사용한&amp;nbsp;html&amp;nbsp;파일&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/UWgG4/btr9mRHhbhX/S163Q5m99w4IGARkrm9iGK/reactBasic.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;reactBasic.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>소프트웨어 개발</category>
      <category>ReactJs기초</category>
      <category>리엑트제이에스 기초</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/17</guid>
      <comments>https://sueng.tistory.com/17#entry17comment</comments>
      <pubDate>Tue, 11 Apr 2023 00:59:15 +0900</pubDate>
    </item>
    <item>
      <title>맥에 홈브루로 NodeJs 설치하고  NodeJs 버전 관리하기</title>
      <link>https://sueng.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번&amp;nbsp;글에서는&amp;nbsp;맥오에스에서&amp;nbsp;홈브루로&amp;nbsp;NodeJs를&amp;nbsp;설치하고&amp;nbsp;버전&amp;nbsp;관리를&amp;nbsp;하는&amp;nbsp;방법을&amp;nbsp;알아보겠습니다.&amp;nbsp;요즘&amp;nbsp;백엔드&amp;nbsp;개발을&amp;nbsp;NodeJs로&amp;nbsp;하는&amp;nbsp;것이&amp;nbsp;아주&amp;nbsp;큰&amp;nbsp;흐름으로&amp;nbsp;자리&amp;nbsp;잡고&amp;nbsp;있는&amp;nbsp;것&amp;nbsp;같습니다.&amp;nbsp;개발환경으로&amp;nbsp;맥북이나&amp;nbsp;아이맥을&amp;nbsp;사용하는&amp;nbsp;경우&amp;nbsp;노드를&amp;nbsp;설치하게&amp;nbsp;되는&amp;nbsp;것은&amp;nbsp;기본이&amp;nbsp;되겠죠.&amp;nbsp;그리고&amp;nbsp;여러&amp;nbsp;프로젝트를&amp;nbsp;하다&amp;nbsp;보면&amp;nbsp;여러&amp;nbsp;개의&amp;nbsp;노드&amp;nbsp;버전을&amp;nbsp;사용하게&amp;nbsp;되고요.&amp;nbsp;이&amp;nbsp;두&amp;nbsp;경우&amp;nbsp;홈브루를&amp;nbsp;사용해서&amp;nbsp;어떻게&amp;nbsp;관리를&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있는지가&amp;nbsp;이번&amp;nbsp;글의&amp;nbsp;주제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1.&amp;nbsp;홈브루&amp;nbsp;NodeJs&amp;nbsp;버전&amp;nbsp;확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NodeJs는&amp;nbsp;어떤&amp;nbsp;버전이&amp;nbsp;있는지&amp;nbsp;확인해&amp;nbsp;보고&amp;nbsp;홈브루는&amp;nbsp;어떤&amp;nbsp;버전을&amp;nbsp;지원하고&amp;nbsp;있는지를&amp;nbsp;확인해&amp;nbsp;보려고&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.1.&amp;nbsp;NodeJs&amp;nbsp;버전&amp;nbsp;종류&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NodeJs의&amp;nbsp;버전은&amp;nbsp;크게&amp;nbsp;현재(Current)&amp;nbsp;버전과&amp;nbsp;LTS(Long&amp;nbsp;Term&amp;nbsp;Support)&amp;nbsp;버전으로&amp;nbsp;나뉩니다.&amp;nbsp;이는&amp;nbsp;NodeJs&amp;nbsp;공식&amp;nbsp;홈페이지에&amp;nbsp;가서&amp;nbsp;보면&amp;nbsp;확인을&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있는데요.&amp;nbsp;이&amp;nbsp;글을&amp;nbsp;쓰는&amp;nbsp;현재&amp;nbsp;LTS버전은&amp;nbsp;18.15.0버전이고&amp;nbsp;Current&amp;nbsp;버전은&amp;nbsp;19.8.1입니다.&amp;nbsp;실제로는&amp;nbsp;NodeJs는&amp;nbsp;버전을&amp;nbsp;Current,&amp;nbsp;&amp;nbsp;Active&amp;nbsp;LTS,&amp;nbsp;Maintenance&amp;nbsp;3가지&amp;nbsp;종류로&amp;nbsp;구분해서&amp;nbsp;관리하고&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.1.1.&amp;nbsp;Current&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이저&amp;nbsp;변경사항이&amp;nbsp;아니고&amp;nbsp;버전&amp;nbsp;호환성을&amp;nbsp;망가트리는&amp;nbsp;변경이&amp;nbsp;아닌&amp;nbsp;내용이&amp;nbsp;적용되고&amp;nbsp;있는&amp;nbsp;버전입니다.&amp;nbsp;NodeJs&amp;nbsp;소스의&amp;nbsp;main&amp;nbsp;브랜치의&amp;nbsp;내용이&amp;nbsp;반영되는&amp;nbsp;버전이라고&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;버전의&amp;nbsp;라이프&amp;nbsp;사이클이&amp;nbsp;비교적&amp;nbsp;짧게&amp;nbsp;유지됩니다.&amp;nbsp;19.x&amp;nbsp;버전의&amp;nbsp;경우&amp;nbsp;2022-10-18에&amp;nbsp;시작을&amp;nbsp;해서&amp;nbsp;2023-06-01까지&amp;nbsp;밖에&amp;nbsp;버전관리를&amp;nbsp;하지&amp;nbsp;않습니다.&amp;nbsp;그래서&amp;nbsp;가능하면&amp;nbsp;상용버전에는&amp;nbsp;사용하지&amp;nbsp;않는&amp;nbsp;것이&amp;nbsp;좋습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.1.2.&amp;nbsp;Active&amp;nbsp;LTS&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LTS&amp;nbsp;팀에서&amp;nbsp;검토한&amp;nbsp;새로운&amp;nbsp;기능,&amp;nbsp;버그&amp;nbsp;수정&amp;nbsp;등이&amp;nbsp;포함된&amp;nbsp;버전입니다.&amp;nbsp;기능이나&amp;nbsp;수정사항이&amp;nbsp;적절한지&amp;nbsp;판단이&amp;nbsp;되고&amp;nbsp;안정적이라는&amp;nbsp;것이&amp;nbsp;확인이&amp;nbsp;된&amp;nbsp;경우&amp;nbsp;포함이&amp;nbsp;됩니다.&amp;nbsp;또한&amp;nbsp;버전을&amp;nbsp;유지하는&amp;nbsp;기간도&amp;nbsp;깁니다.&amp;nbsp;18.x&amp;nbsp;버전의&amp;nbsp;경우&amp;nbsp;2022-04-19에&amp;nbsp;시작을&amp;nbsp;해서&amp;nbsp;2025-04-30까지&amp;nbsp;버전을&amp;nbsp;관리합니다.&amp;nbsp;상용&amp;nbsp;소프트웨어를&amp;nbsp;개발하는데&amp;nbsp;사용하기&amp;nbsp;적적한&amp;nbsp;버전입니다.&amp;nbsp;참고로&amp;nbsp;LTS&amp;nbsp;버전은&amp;nbsp;짝수로&amp;nbsp;되어&amp;nbsp;있습니다.&amp;nbsp;홀수&amp;nbsp;버전은&amp;nbsp;LTS&amp;nbsp;버전으로&amp;nbsp;승격이&amp;nbsp;되지&amp;nbsp;않습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.1.3.&amp;nbsp;Maintenance&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LTS 버전이 Actvie한 기긴을 지나게 되면 Maintenance 기간으로 들어가게 됩니다. 이때는 심각한 버그에 대한 수정 사항과 보안 관련 업데이트만 추가가 됩니다. 간혹 새로운 기능도 추가되는 경우가 있지만 다음 버전으로 마이그레이션을 하는데 도움이 되는 경우 미리 추가하는 경우가 대부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;전체적으로&amp;nbsp;버전의&amp;nbsp;라이프&amp;nbsp;사이클을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;그래프를&amp;nbsp;공식&amp;nbsp;홈페이지에서&amp;nbsp;가져왔습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;NodeJs_버전_라이프사이클.jpg&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mpeZW/btr88saPl5F/uqKliSs90VGDZkHzL4BrI1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mpeZW/btr88saPl5F/uqKliSs90VGDZkHzL4BrI1/img.jpg&quot; data-alt=&quot;NodeJs 버전 라이프 사이클&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mpeZW/btr88saPl5F/uqKliSs90VGDZkHzL4BrI1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmpeZW%2Fbtr88saPl5F%2FuqKliSs90VGDZkHzL4BrI1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1676&quot; height=&quot;848&quot; data-filename=&quot;NodeJs_버전_라이프사이클.jpg&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;848&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NodeJs 버전 라이프 사이클&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.2.&amp;nbsp;홈브루에서&amp;nbsp;지원하는&amp;nbsp;NodeJs&amp;nbsp;버전&amp;nbsp;확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서&amp;nbsp;알아본&amp;nbsp;NodeJs&amp;nbsp;버전은&amp;nbsp;공식&amp;nbsp;홈페이지에서&amp;nbsp;확인한&amp;nbsp;버전이었는데요.&amp;nbsp;홈브루에서는&amp;nbsp;어떤&amp;nbsp;버전을&amp;nbsp;설치할&amp;nbsp;수&amp;nbsp;있을지는&amp;nbsp;홈브루&amp;nbsp;명령어를&amp;nbsp;사용해서&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;터미널에서&amp;nbsp;brew&amp;nbsp;search&amp;nbsp;node라고&amp;nbsp;명령어를&amp;nbsp;실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681141185993&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % brew search node
==&amp;gt; Formulae
libbitcoin-node       node-build            node@14               nodebrew
linode-cli            node-sass             node@16               nodeenv
llnode                node@10               node@18               nodenv
node                  node@12               node_exporter         ode

==&amp;gt; Casks
capslocknodelay              nodebox                      nodeclipse&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행한&amp;nbsp;결과에서&amp;nbsp;보면&amp;nbsp;node라고&amp;nbsp;되어&amp;nbsp;있는&amp;nbsp;것이&amp;nbsp;있고&amp;nbsp;node&amp;nbsp;뒤에&amp;nbsp;@가&amp;nbsp;붙어서&amp;nbsp;node@18로&amp;nbsp;보이는&amp;nbsp;것이&amp;nbsp;있습니다.&amp;nbsp;그냥&amp;nbsp;node로&amp;nbsp;되어&amp;nbsp;있는&amp;nbsp;것은&amp;nbsp;최신버전으로&amp;nbsp;Current&amp;nbsp;버전을&amp;nbsp;말하고&amp;nbsp;@뒤에&amp;nbsp;붙어&amp;nbsp;있는&amp;nbsp;숫자는&amp;nbsp;특정&amp;nbsp;NodeJs&amp;nbsp;버전을&amp;nbsp;의미합니다.&amp;nbsp;터미널&amp;nbsp;명령어&amp;nbsp;결과에서&amp;nbsp;보시면&amp;nbsp;알겠지만&amp;nbsp;홈브루에서는&amp;nbsp;Current&amp;nbsp;버전과&amp;nbsp;짝수&amp;nbsp;버전(LTS&amp;nbsp;버전)만&amp;nbsp;지원하고&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.&amp;nbsp;맥에서&amp;nbsp;홈브루로&amp;nbsp;NodeJs&amp;nbsp;설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맥에서&amp;nbsp;홈브루로&amp;nbsp;NodeJs를&amp;nbsp;설치하는&amp;nbsp;것은&amp;nbsp;아주&amp;nbsp;간단합니다.&amp;nbsp;brew&amp;nbsp;install&amp;nbsp;명령어만&amp;nbsp;입력하면&amp;nbsp;되니까요.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1.&amp;nbsp;홈브루로&amp;nbsp;NodeJs&amp;nbsp;설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째로&amp;nbsp;홈르루에서&amp;nbsp;지원하는&amp;nbsp;최신버전&amp;nbsp;NodeJs를&amp;nbsp;설치해&amp;nbsp;보겠습니다.&amp;nbsp;터미널에&amp;nbsp;brew&amp;nbsp;install&amp;nbsp;node를&amp;nbsp;실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681141235173&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % brew install node
Running `brew update --auto-update`...
==&amp;gt; Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==&amp;gt; New Formulae
arjun                 thriftgo              trust-dns             wxlua

==&amp;gt; Fetching node
==&amp;gt; Downloading https://ghcr.io/v2/homebrew/core/node/manifests/19.8.1
######################################################################## 100.0%
==&amp;gt; Downloading https://ghcr.io/v2/homebrew/core/node/blobs/sha256:baaac8a39fb91928842b74890985fbb176f9c5769
==&amp;gt; Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:baaac8a39fb91928842b748
######################################################################## 100.0%
==&amp;gt; Pouring node--19.8.1.ventura.bottle.tar.gz
   /usr/local/Cellar/node/19.8.1: 2,357 files, 56.7MB
==&amp;gt; Running `brew cleanup node`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치되는&amp;nbsp;과정이&amp;nbsp;보이는데요.&amp;nbsp;지금&amp;nbsp;글을&amp;nbsp;쓰고&amp;nbsp;있는&amp;nbsp;현재의&amp;nbsp;최신버전인&amp;nbsp;19.8.1&amp;nbsp;버전의&amp;nbsp;node가&amp;nbsp;설치되는&amp;nbsp;것을&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;설치된&amp;nbsp;node의&amp;nbsp;버전을&amp;nbsp;확인해&amp;nbsp;봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681141271918&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % node -v
v19.8.1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예상대로&amp;nbsp;버전은&amp;nbsp;19.8.1입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.2.&amp;nbsp;홈프루로&amp;nbsp;다른&amp;nbsp;버전&amp;nbsp;NodeJs&amp;nbsp;설치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈브루에서&amp;nbsp;node의&amp;nbsp;다른&amp;nbsp;버전을&amp;nbsp;설치할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;특히나&amp;nbsp;상용으로&amp;nbsp;운영될&amp;nbsp;소프트웨어를&amp;nbsp;개발하고&amp;nbsp;있다면&amp;nbsp;Active&amp;nbsp;LTS&amp;nbsp;버전을&amp;nbsp;설치해서&amp;nbsp;실행하는&amp;nbsp;것이&amp;nbsp;좋습니다.&amp;nbsp;우선&amp;nbsp;설치&amp;nbsp;가능한&amp;nbsp;버전을&amp;nbsp;알아보기&amp;nbsp;위해서&amp;nbsp;brew&amp;nbsp;search&amp;nbsp;node&amp;nbsp;명령어를&amp;nbsp;실행해&amp;nbsp;봅니다.&amp;nbsp;이&amp;nbsp;글에선&amp;nbsp;18.x&amp;nbsp;버전을&amp;nbsp;설치해&amp;nbsp;보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681141315114&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % brew install node@18 
==&amp;gt; Downloading https://formulae.brew.sh/api/formula.jws.json
######################################################################## 100.0%
==&amp;gt; Fetching node@18
==&amp;gt; Downloading https://ghcr.io/v2/homebrew/core/node/18/manifests/18.15.0-1
Already downloaded: /Users/ken/Library/Caches/Homebrew/downloads/4b9fd970d9076f6842dfa69804d5c7e23c2008da12f36d600539c60f13982057--node@18-18.15.0-1.bottle_manifest.json
==&amp;gt; Downloading https://ghcr.io/v2/homebrew/core/node/18/blobs/sha256:971d9e3c187e07010cace1ed4060fea6e1e399
Already downloaded: /Users/ken/Library/Caches/Homebrew/downloads/50a0bc2b58a49f6ab48969827d437bb854f109a8e40035e8a490ad48bccc1c51--node@18--18.15.0.ventura.bottle.1.tar.gz
==&amp;gt; Pouring node@18--18.15.0.ventura.bottle.1.tar.gz
==&amp;gt; Caveats
node@18 is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have node@18 first in your PATH, run:
  echo 'export PATH=&quot;/usr/local/opt/node@18/bin:$PATH&quot;' &amp;gt;&amp;gt; ~/.zshrc

For compilers to find node@18 you may need to set:
  export LDFLAGS=&quot;-L/usr/local/opt/node@18/lib&quot;
  export CPPFLAGS=&quot;-I/usr/local/opt/node@18/include&quot;
==&amp;gt; Summary
   /usr/local/Cellar/node@18/18.15.0: 2,343 files, 56.6MB
==&amp;gt; Running `brew cleanup node@18`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치된&amp;nbsp;노드를&amp;nbsp;확인해&amp;nbsp;보겠습니다.&amp;nbsp;&amp;nbsp;명령어는&amp;nbsp;/usr/local/opt/node@18/bin/node&amp;nbsp;-v&amp;nbsp;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681141343290&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % /usr/local/opt/node@18/bin/node -v
v18.15.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.&amp;nbsp;맥에서&amp;nbsp;NodeJs&amp;nbsp;버전관리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서서&amp;nbsp;node&amp;nbsp;19.x&amp;nbsp;버전과&amp;nbsp;18.x&amp;nbsp;버전을&amp;nbsp;설치해&amp;nbsp;보았습니다.&amp;nbsp;하지만&amp;nbsp;18.x&amp;nbsp;버전을&amp;nbsp;실행하기&amp;nbsp;위해서는&amp;nbsp;그냥&amp;nbsp;node라고&amp;nbsp;명령어를&amp;nbsp;치는&amp;nbsp;대신에&amp;nbsp;/usr/local/opt/node@18/bin/node라고&amp;nbsp;길게&amp;nbsp;명령어를&amp;nbsp;쳐야&amp;nbsp;합니다.&amp;nbsp;이렇게&amp;nbsp;되면&amp;nbsp;개발하는&amp;nbsp;동안에&amp;nbsp;괭장히&amp;nbsp;귀찮겠죠.&amp;nbsp;만일&amp;nbsp;새로&amp;nbsp;설치한&amp;nbsp;버전을&amp;nbsp;기본&amp;nbsp;node로&amp;nbsp;사용하고&amp;nbsp;싶다면&amp;nbsp;PATH&amp;nbsp;환경변수를&amp;nbsp;설정해&amp;nbsp;줘야&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;우선&amp;nbsp;현재&amp;nbsp;맥에서&amp;nbsp;사용하고&amp;nbsp;있는&amp;nbsp;shell이&amp;nbsp;무엇인지&amp;nbsp;확인해&amp;nbsp;봅니다.&amp;nbsp;명령어는&amp;nbsp;echo&amp;nbsp;$0입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681141380902&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % echo $0
-zsh&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제&amp;nbsp;맥은&amp;nbsp;zsh를&amp;nbsp;사용하고&amp;nbsp;있습니다.&amp;nbsp;에디터로&amp;nbsp;~/.&amp;nbsp;zshrc를&amp;nbsp;열어&amp;nbsp;아래&amp;nbsp;라인을&amp;nbsp;추가합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사용하시는 쉘에따라서 파일이 좀 다릅니다. &lt;br /&gt;bash: ~/.bashrc &lt;br /&gt;zsh: ~/.zshrc &lt;br /&gt;ksh: ~/.profile&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681141497119&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export PATH=&quot;/usr/local/opt/node@18/bin:$PATH&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&amp;nbsp;source&amp;nbsp;~/.zshrc&amp;nbsp;를&amp;nbsp;실행합니다.&amp;nbsp;~/.&amp;nbsp;zshrc는&amp;nbsp;새로&amp;nbsp;터미널을&amp;nbsp;열거나&amp;nbsp;새로&amp;nbsp;로그인할&amp;nbsp;때&amp;nbsp;자동으로&amp;nbsp;실행되므로&amp;nbsp;매번&amp;nbsp;해&amp;nbsp;줄&amp;nbsp;필요는&amp;nbsp;없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제&amp;nbsp;node를&amp;nbsp;실행해&amp;nbsp;보니다.&amp;nbsp;새로&amp;nbsp;설치된&amp;nbsp;NodeJs&amp;nbsp;버전이&amp;nbsp;표시되는&amp;nbsp;것을&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>소프트웨어 개발</category>
      <category>nodejs 설치</category>
      <category>노드 설치</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/16</guid>
      <comments>https://sueng.tistory.com/16#entry16comment</comments>
      <pubDate>Tue, 11 Apr 2023 00:46:45 +0900</pubDate>
    </item>
    <item>
      <title>맥오에스 홈브루 설치, 디렉토리 구조 이해하기</title>
      <link>https://sueng.tistory.com/15</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;홈브루(Homebrew)는&amp;nbsp;주로&amp;nbsp;개발자들이&amp;nbsp;애플&amp;nbsp;맥오에스(Apple&amp;nbsp;macOS)를&amp;nbsp;사용하게&amp;nbsp;되면&amp;nbsp;필수적으로&amp;nbsp;사용하게&amp;nbsp;되는&amp;nbsp;프로그램인데요.&amp;nbsp;홈브루를&amp;nbsp;아직&amp;nbsp;설치해&amp;nbsp;보지&amp;nbsp;않은&amp;nbsp;경우&amp;nbsp;설치부터&amp;nbsp;홈브루&amp;nbsp;디렉터리&amp;nbsp;구조와&amp;nbsp;추가적인&amp;nbsp;프로그램&amp;nbsp;설치(패키지&amp;nbsp;설치)까지&amp;nbsp;단계적으로&amp;nbsp;해&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;하겠습니다.&amp;nbsp;우선&amp;nbsp;홈브루란&amp;nbsp;무엇인지부터&amp;nbsp;이야기를&amp;nbsp;해야겠죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;homebrew_install.jpg&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpsbdp/btr9poRQu7k/n3Xe78EyQQBJa3yW3cnyzK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpsbdp/btr9poRQu7k/n3Xe78EyQQBJa3yW3cnyzK/img.jpg&quot; data-alt=&quot;홈브루 설치 at 공식 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpsbdp/btr9poRQu7k/n3Xe78EyQQBJa3yW3cnyzK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcpsbdp%2Fbtr9poRQu7k%2Fn3Xe78EyQQBJa3yW3cnyzK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1300&quot; height=&quot;960&quot; data-filename=&quot;homebrew_install.jpg&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;960&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;홈브루 설치 at 공식 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1.&amp;nbsp;맥오에스(macOS)&amp;nbsp;홈브루란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈브루(Homebrew)는 애플 맥오에스(Apple macOS)에서 기본적으로 제공하지 않는 소프트웨어 패키지를 쉽게 설치할 수 있도록 도와주는 프로그램입니다. 저는 사용해 보지는 않았지만 현재 홈브루는 맥오에스뿐 아니라 리눅스 환경에서도 사용가능하다고 공식 홈페이지에서 안내를 하고 있습니다. 설치 정보는 공식 홈페이지에도 나와 있으니 간단히 설치만 하고 싶으시면 공식 홈페이지를 통해서 명령어를 복사해서 실행하시면 됩니다.&lt;/p&gt;
&lt;figure id=&quot;og_1681139492725&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Homebrew&quot; data-og-description=&quot;The Missing Package Manager for macOS (or Linux).&quot; data-og-host=&quot;brew.sh&quot; data-og-source-url=&quot;https://brew.sh/&quot; data-og-url=&quot;https://brew.sh/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dszZHq/hySdmKo6SC/F0D5vnr88FgEUIaFoKodT1/img.png?width=1200&amp;amp;height=560&amp;amp;face=0_0_1200_560,https://scrap.kakaocdn.net/dn/5usrD/hySeXhVN9i/eruXeHlP5ldrDWYFW2mjok/img.png?width=1200&amp;amp;height=560&amp;amp;face=0_0_1200_560&quot;&gt;&lt;a href=&quot;https://brew.sh/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://brew.sh/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dszZHq/hySdmKo6SC/F0D5vnr88FgEUIaFoKodT1/img.png?width=1200&amp;amp;height=560&amp;amp;face=0_0_1200_560,https://scrap.kakaocdn.net/dn/5usrD/hySeXhVN9i/eruXeHlP5ldrDWYFW2mjok/img.png?width=1200&amp;amp;height=560&amp;amp;face=0_0_1200_560');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Homebrew&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The Missing Package Manager for macOS (or Linux).&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;brew.sh&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.&amp;nbsp;1&amp;nbsp;홈브루는&amp;nbsp;개발자들이&amp;nbsp;많이&amp;nbsp;사용합니다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로&amp;nbsp;맥오에스를&amp;nbsp;사용하시는&amp;nbsp;분들&amp;nbsp;보다는&amp;nbsp;개발자들이&amp;nbsp;주로&amp;nbsp;설치해서&amp;nbsp;사용하게&amp;nbsp;됩니다.&amp;nbsp;그&amp;nbsp;이유는&amp;nbsp;개발자들이&amp;nbsp;주로&amp;nbsp;사용하는&amp;nbsp;프로그램들이&amp;nbsp;유닉스나&amp;nbsp;리눅스에&amp;nbsp;동작하는&amp;nbsp;것이&amp;nbsp;많은데요.&amp;nbsp;이&amp;nbsp;프로그램을&amp;nbsp;애플이&amp;nbsp;맥오에스에&amp;nbsp;기본으로&amp;nbsp;설치를&amp;nbsp;해&amp;nbsp;주지&amp;nbsp;않기&amp;nbsp;때문입니다.&amp;nbsp;다행인&amp;nbsp;것은&amp;nbsp;맥오에스가&amp;nbsp;유닉스와&amp;nbsp;유사하기&amp;nbsp;때문에&amp;nbsp;프로그램의&amp;nbsp;소스를&amp;nbsp;다운로드하여서&amp;nbsp;컴파일을&amp;nbsp;해서&amp;nbsp;설치를&amp;nbsp;하는&amp;nbsp;것이&amp;nbsp;가능한데요.&amp;nbsp;이&amp;nbsp;과정을&amp;nbsp;홈브루가&amp;nbsp;대신해&amp;nbsp;주게&amp;nbsp;되어&amp;nbsp;개발에&amp;nbsp;필요한&amp;nbsp;거의&amp;nbsp;모든&amp;nbsp;프로그램을&amp;nbsp;홈브루&amp;nbsp;명령어만으로&amp;nbsp;설치하는&amp;nbsp;것을&amp;nbsp;가능하게&amp;nbsp;해&amp;nbsp;주는&amp;nbsp;것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.2&amp;nbsp;홈브루는&amp;nbsp;개발에&amp;nbsp;필요한&amp;nbsp;거의&amp;nbsp;모든&amp;nbsp;프로그램&amp;nbsp;설치가&amp;nbsp;가능합니다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈프루에서는&amp;nbsp;설치&amp;nbsp;가능한&amp;nbsp;프로그램을&amp;nbsp;홈브루&amp;nbsp;포뮬러(Homebrew&amp;nbsp;Formulae)라고&amp;nbsp;합니다.&amp;nbsp;여기에는&amp;nbsp;gcc,&amp;nbsp;Python,&amp;nbsp;NodeJs,&amp;nbsp;Java&amp;nbsp;등&amp;nbsp;프로그래밍&amp;nbsp;언어,&amp;nbsp;wget,&amp;nbsp;curl&amp;nbsp;등의&amp;nbsp;유틸리티도&amp;nbsp;있습니다.&amp;nbsp;구글의&amp;nbsp;자바스크립트&amp;nbsp;엔진인&amp;nbsp;V8도&amp;nbsp;설치할&amp;nbsp;수&amp;nbsp;있고요.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://formulae.brew.sh/formula/&quot;&gt;홈브루 포뮬라(Homebrew Formulae) 리스트 보기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난&amp;nbsp;30일&amp;nbsp;동안&amp;nbsp;홈브루를&amp;nbsp;통해&amp;nbsp;설치된&amp;nbsp;상위&amp;nbsp;10개의&amp;nbsp;포뮬러&amp;nbsp;리스트입니다.&lt;/p&gt;
&lt;table style=&quot;color: #666666; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff;&quot;&gt;순위&lt;/td&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff; text-align: right;&quot;&gt;포뷸라&lt;/td&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff; text-align: right;&quot;&gt;인스톨 수&lt;/td&gt;
&lt;td style=&quot;background-color: #9b9b9b; color: #ffffff; text-align: right;&quot;&gt;비율&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;openssl@1.1&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;16,615&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;1.56%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;sqlite&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;16,386&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;1.53%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;ca-certificates&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;15,877&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;1.49%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;xz&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;14,531&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;1.36%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;icu4c&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;14,198&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;1.33%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;6&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;glib&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;12,015&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;1.13%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;readline&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;11,448&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;1.07%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;8&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;pcre2&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;11,377&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;1.07%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;9&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;libpng&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;11,082&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;1.04%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #dcdddd;&quot;&gt;10&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;freetype&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;10,618&lt;/td&gt;
&lt;td style=&quot;background-color: #f0f0f0; text-align: right;&quot;&gt;0.99%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.&amp;nbsp;macOS&amp;nbsp;홈브루(Homebrew)&amp;nbsp;설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맥오에스에서&amp;nbsp;홈브루를&amp;nbsp;설치하는&amp;nbsp;것은&amp;nbsp;실제로&amp;nbsp;매우&amp;nbsp;간단합니다.&amp;nbsp;간단히&amp;nbsp;말하면&amp;nbsp;&lt;a href=&quot;https://brew.sh/&quot;&gt;홈브루&amp;nbsp;공식&amp;nbsp;홈페이지&lt;/a&gt;&amp;nbsp;Install&amp;nbsp;Homebrew라고&amp;nbsp;쓰여&amp;nbsp;있는&amp;nbsp;바로&amp;nbsp;밑에&amp;nbsp;있는&amp;nbsp;명령어를&amp;nbsp;실행하기만&amp;nbsp;하면&amp;nbsp;됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1&amp;nbsp;터미널&amp;nbsp;열기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키보드에서&amp;nbsp;커맨드키와&amp;nbsp;스페이스(command+space)&amp;nbsp;키를&amp;nbsp;같이&amp;nbsp;눌어서&amp;nbsp;스폿라이트를&amp;nbsp;실행합니다.&amp;nbsp;스폿라이트&amp;nbsp;입력창에&amp;nbsp;terminal이라고&amp;nbsp;입력한&amp;nbsp;후&amp;nbsp;엔터키를&amp;nbsp;눌러서&amp;nbsp;터미널을&amp;nbsp;실행합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.2&amp;nbsp;공식&amp;nbsp;홈페이지에서&amp;nbsp;설치&amp;nbsp;명령어&amp;nbsp;복사하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈브로&amp;nbsp;공식&amp;nbsp;페이지에&amp;nbsp;가면&amp;nbsp;제일먼저&amp;nbsp;보이는&amp;nbsp;것이&amp;nbsp;홈브루&amp;nbsp;설치하는&amp;nbsp;명령어입니다.&amp;nbsp;오른쪽에&amp;nbsp;복사하기&amp;nbsp;버튼을&amp;nbsp;눌어서&amp;nbsp;명령어를&amp;nbsp;복사합니다.&amp;nbsp;바로&amp;nbsp;명령어를&amp;nbsp;복사하고&amp;nbsp;싶으신&amp;nbsp;분을&amp;nbsp;위해서&amp;nbsp;아래&amp;nbsp;명령어를&amp;nbsp;복사해&amp;nbsp;두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681139756117&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.3&amp;nbsp;터미널에서&amp;nbsp;복사한&amp;nbsp;명령어&amp;nbsp;실행하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 열어둔 터미널에 복사한 명령어를 붙여 넣기를 합니다. 엔터키를 누르면 홈브루 설치가 시작됩니다. 이때&amp;nbsp;홈브루를&amp;nbsp;설치하기&amp;nbsp;위해서&amp;nbsp;sudo&amp;nbsp;비밀번호를&amp;nbsp;입력할&amp;nbsp;겁니다.&amp;nbsp;비번을&amp;nbsp;입력해서&amp;nbsp;홈브루&amp;nbsp;설치를&amp;nbsp;계속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681139805765&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % /bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
==&amp;gt; Checking for `sudo` access (which may request your password)...
Password:&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.4&amp;nbsp;홈브루&amp;nbsp;설치&amp;nbsp;확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가&amp;nbsp;완료되면&amp;nbsp;터미널에&amp;nbsp;brew&amp;nbsp;info라는&amp;nbsp;명령어를&amp;nbsp;실행합니다.&amp;nbsp;아래와&amp;nbsp;비슷한&amp;nbsp;내용이&amp;nbsp;나오면&amp;nbsp;설치가&amp;nbsp;완료된&amp;nbsp;것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681139835408&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % brew info
8 kegs, 10,887 files, 160.4MB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3.&amp;nbsp;홈브루&amp;nbsp;디렉토리&amp;nbsp;구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;홈브루의 디렉토리 구조를 알면 홈브루를 사용하면서 겪게 되는 문제점들을 이해하고 해결하는 데 많은 도움이 됩니다. 구조를 이해하기 위해서 wget을 홈브루를 사용해서 설치해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 실행해서 wget을 설치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681139888691&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install wget&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;설치가 완료되면 which wget이라고 명령어를 실행합니다. 이 명령어는 wget 이 설치된 위치를 알려줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681139910231&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac ~ % which wget
/usr/local/bin/wget&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wget이&amp;nbsp;/usr/local/bin&amp;nbsp;디렉터리에&amp;nbsp;설치되었다는&amp;nbsp;것을&amp;nbsp;알&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;터미널에서&amp;nbsp;/usr/local/bin로&amp;nbsp;이동을&amp;nbsp;해서&amp;nbsp;ls&amp;nbsp;-l&amp;nbsp;wget&amp;nbsp;명령어를&amp;nbsp;실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681139934621&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac bin % ls -l wget
lrwxr-xr-x  1 ken  admin  32  7 Apr 13:04 wget -&amp;gt; ../Cellar/wget/1.21.3_1/bin/wget&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제&amp;nbsp;/usr/local/bin에&amp;nbsp;있는&amp;nbsp;wget이&amp;nbsp;실제로는&amp;nbsp;/usr/local/Cellar/wget/1.21.3_1/bin/wget이라는&amp;nbsp;것을&amp;nbsp;알게&amp;nbsp;되었습니다.&amp;nbsp;실제로&amp;nbsp;홈브루는&amp;nbsp;프로그램을&amp;nbsp;/usr/local/Cellar&amp;nbsp;디렉터리에&amp;nbsp;설치를&amp;nbsp;하고&amp;nbsp;/usr/local/bin&amp;nbsp;디렉터리에&amp;nbsp;씸볼릭&amp;nbsp;링크를&amp;nbsp;걸어서&amp;nbsp;실행이&amp;nbsp;되도록&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;디렉터리를&amp;nbsp;/usr/local로&amp;nbsp;이동후&amp;nbsp;ls&amp;nbsp;-l을&amp;nbsp;해&amp;nbsp;봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1681139961764&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ken@kMac local % ls -l
total 0
drwxrwxr-x   2 ken  admin    64  3 Apr 21:55 Caskroom
drwxrwxr-x  16 ken  admin   512  7 Apr 13:04 Cellar
drwxrwxr-x   3 ken  admin    96  7 Apr 10:58 Frameworks
drwxr-xr-x  23 ken  admin   736  3 Apr 22:00 Homebrew
drwxrwxr-x  32 ken  admin  1024  7 Apr 13:04 bin
drwxrwxr-x   8 ken  admin   256  7 Apr 13:04 etc
drwxrwxr-x  32 ken  admin  1024  7 Apr 13:04 include
drwxrwxr-x  49 ken  admin  1568  7 Apr 13:04 lib
drwxrwxr-x  18 ken  admin   576  7 Apr 13:04 opt
drwxrwxr-x   3 ken  admin    96  7 Apr 10:58 sbin
drwxrwxr-x  14 ken  admin   448  7 Apr 13:04 share
drwxrwxr-x   3 ken  admin    96  3 Apr 21:55 var&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서&amp;nbsp;주요하게&amp;nbsp;봐야할&amp;nbsp;것은&amp;nbsp;디렉터리의&amp;nbsp;소유주입니다.&amp;nbsp;디렉터리의&amp;nbsp;소유주가&amp;nbsp;모두&amp;nbsp;ken이라고&amp;nbsp;하는&amp;nbsp;사용자로&amp;nbsp;되어&amp;nbsp;있어서&amp;nbsp;ken이&amp;nbsp;brew&amp;nbsp;명령어를&amp;nbsp;사용해서&amp;nbsp;새로운&amp;nbsp;포뮬러를&amp;nbsp;설치하거나&amp;nbsp;제거하는&amp;nbsp;것이&amp;nbsp;가능하게&amp;nbsp;된&amp;nbsp;것입니다.&amp;nbsp;그렇지&amp;nbsp;않았으면&amp;nbsp;매번&amp;nbsp;sudo&amp;nbsp;명령어를&amp;nbsp;사용해야&amp;nbsp;할&amp;nbsp;거고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서 홈브루란 무엇이고 홈브루를 설치하는 방법과 홈브루 디렉터리 구조까지 살펴보았습니다. 특히 디렉터리 구조를 알고 있으면 나중에 홈부루를 사용하는 과정에서 겪게 되는 문제점을 빨리 이해하고 해결하는 데 많은 도움이 될 것입니다.&lt;/p&gt;</description>
      <category>소프트웨어 개발</category>
      <category>맥오에스</category>
      <category>홈브루</category>
      <category>홈브루 설치</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/15</guid>
      <comments>https://sueng.tistory.com/15#entry15comment</comments>
      <pubDate>Tue, 11 Apr 2023 00:21:25 +0900</pubDate>
    </item>
    <item>
      <title>깃(git) 실전 가이드</title>
      <link>https://sueng.tistory.com/14</link>
      <description>&lt;p&gt;소프트웨어 버전 관리 툴인 깃을 10년 가까이 사용해 오면서 깃에 많이 익숙해 진 건 사실입니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;하지만 언젠가는 한번 전체적인 기능을 리뷰를 해 보는 시간을 갖어야겠다고 생각했죠.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;깃을 사용하는데 필요한 실전 가이드 목록을 소개합니다.&lt;/p&gt;&lt;ol style=&quot;list-style-type: decimal;&quot;&gt;&lt;li&gt;&lt;a href=&quot;https://tech.10000lab.xyz/git/how-git-is-different.html&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;깃은 뭐가 다른가?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://tech.10000lab.xyz/git/using-git-as-you-work.html&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;깃과 함께 개발하기&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://tech.10000lab.xyz/git/git-commit-discipline.html&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;깃 커밋 가이드&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://tech.10000lab.xyz/git/git-rebase-workflow.html&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;깃 리베이스 사용하기&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://tech.10000lab.xyz/git/git-tips-you-need.html&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;깃 유용한 팁&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://tech.10000lab.xyz/git/important-git-terms.html&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;깃 용어 정리&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://tech.10000lab.xyz/git/git-cheat-sheet.html&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;깃 필수 명령어&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;생각보다 내용이 좀 깁니다.&lt;/div&gt;&lt;div&gt;그래도 소프트웨어 개발을 할 때 피해갈 수 없는 관문이기도 하니 이 기회에 잘 읽고 많은 도움 받기를 기대합니다.&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>소프트웨어 개발</category>
      <category>깃가이드</category>
      <category>버전관리</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/14</guid>
      <comments>https://sueng.tistory.com/14#entry14comment</comments>
      <pubDate>Tue, 27 Nov 2018 22:04:51 +0900</pubDate>
    </item>
    <item>
      <title>ES6 자바스크립트 소개</title>
      <link>https://sueng.tistory.com/13</link>
      <description>&lt;h2&gt;&amp;nbsp;ES6 소개&lt;/h2&gt;&lt;p&gt;자바스크립트는 2009년에 이크마스크립트 2009(ECMAScript 2009)가 발표된 후 2015년에 새로운 표준을 발표하게 됩니다. 새로 발표된 이크마스크립트 6(ECMAScript 6, ECMAScript 2015, ES6)는 프로그래밍을 좀 더 유연하고 편하게 할 수 있는 다수의 기능을 포함하고 있습니다. 현재 주요 자바스크립트 엔진에서는 대부분의 기능을 구현한 상태입니다. 각 브라우저별 구현 상태는 &lt;a href=&quot;http://(http://kangax.github.io/es5-compat-table/es6/&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;ES6 호환 테이블&lt;/a&gt;에서 확인 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;최근 상당한 인기를 끌고 있는 &lt;a href=&quot;https://nodejs.org&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;Node.js&lt;/a&gt;를 배우기 위해서는 ES6에 새로 추가된 기능을 알아두는 것이 여러모로 유용합니다. 특히나 이미 자바스크립트로 프로그래밍을 하는데 익숙하신 분들은 ES6에 추가된 기능을 한번 쭉 훌어보는 것만으로 도움이 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99A6EC495BE81D6614&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99A6EC495BE81D6614&quot; width=&quot;820&quot; height=&quot;397&quot; filename=&quot;ecmascript6.png&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;이번 글에서는 ES6에 추가된 기능을 뽑아서 간략하게 설명을 하려고 합니다. 목록과 내용은 &lt;a href=&quot;https://github.com/lukehoban/es6features&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;Luke Hoban의 글&lt;/a&gt;에서 가져왔고 새로 작성한 내용과 번역으로 옮겨 놓은 내용이 섞여 있습니다.&lt;/p&gt;
&lt;p&gt;전체 ES6의 내용을 보시려면 &lt;a href=&quot;http://www.ecma-international.org/ecma-262/6.0/&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;ES6 표준&lt;/a&gt;을 참고하세요.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;계속해서 살펴 보게될 ES6의 기능은 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;- 화살표 함수&lt;/p&gt;
&lt;p&gt;- 클라스&lt;/p&gt;
&lt;p&gt;- 확장 오브젝트 리터럴&lt;/p&gt;
&lt;p&gt;- 템프릿 스트링&lt;/p&gt;
&lt;p&gt;- 디스트럭처링&lt;/p&gt;
&lt;p&gt;- 기본 함수 파라미터&lt;/p&gt;
&lt;p&gt;- 함수 나머지 파라미터&lt;/p&gt;
&lt;p&gt;- 전개 문법&lt;/p&gt;
&lt;p&gt;- let + const&lt;/p&gt;
&lt;p&gt;- for..of&lt;/p&gt;
&lt;p&gt;- 이터레이션 프로토콜&lt;/p&gt;
&lt;p&gt;- 제너레이터&lt;/p&gt;
&lt;p&gt;- 유니코드&lt;/p&gt;
&lt;p&gt;- 모듈&lt;/p&gt;
&lt;p&gt;- 모듈 로더&lt;/p&gt;
&lt;p&gt;- Map, Set(WeakMap, WeakSet)&lt;/p&gt;
&lt;p&gt;- 프록시&lt;/p&gt;
&lt;p&gt;- 심볼&lt;/p&gt;
&lt;p&gt;- 새로운 라이브러리 추가 기능&lt;/p&gt;
&lt;p&gt;- 이진수, 팔진수&lt;/p&gt;
&lt;p&gt;- 프로미스&lt;/p&gt;
&lt;p&gt;- 리플렉트 API&lt;/p&gt;
&lt;p&gt;- 테일 콜 옵티마이제이션&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;ES 6 새로운 기능&lt;/h2&gt;&lt;p&gt;ES 6의 새로운 기능을 하나씩 살펴 보도록 하겠습니다.&lt;/p&gt;&lt;h3&gt;화살표 함수&lt;/h3&gt;&lt;p&gt;화살표 함수는 ES 6에 추가된 기능중에 단연 가장 많이 사용되는 기능입니다. 화살표 함수(Arrow function)를 사용하면 콜백 함수를 만들 때 간략하면서도 유용하게 사용할 수 있습니다. 예를 보겠습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;
const prices = [100, 200, 300];
// function callback
const changed = prices.map(function (p) {
  return p + 200;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;배열에 있는 값을 받아서 200을 더한 후 새로운 배열을 생성하는 코드입니다. prices.map에 일반 함수를 인자로 넣었습니다.&lt;/p&gt;
&lt;p&gt;간단히 보면 위처럼 `function (p)`부분을 `(p) =&amp;gt;` 변경하면 화살표 함수가 됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const prices = [100, 200, 300];&lt;/p&gt;
&lt;p&gt;const changed = prices.map((p) =&amp;gt; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return p + 200;&lt;/p&gt;
&lt;p&gt;});&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;단순하게 보면 function이라는 키워드를 지우고 파리미터 목록 다음에 화살표(`=&amp;gt;`)를 넣는다고 생각해도 되고요.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;함수의 내용이 하나의 익스프레션으로 표현이 되는 경우는 중괄호를 없애고 좀 더 간략하게 사용할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;
&lt;p&gt;const prices = [100, 200, 300];&lt;/p&gt;
&lt;p&gt;let changed = prices.map(p =&amp;gt; p + 200);&lt;/p&gt;
&lt;p&gt;console.log(changed);&lt;/p&gt;
&lt;p&gt;changed = prices.map((p, index) =&amp;gt; p + 200 + index);&lt;/p&gt;
&lt;p&gt;console.log(changed);&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이때 익스프레션을 이벨류에이션한 값이 화살표 함수의 리턴 값이 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;일반 함수와 화살표 함수의 차이이면서 꼭 기억해야할 중요한 점은 `this`를 다루는 방식입니다.&lt;/p&gt;
&lt;p&gt;함수를 콜백으로 전달할 때 this는 콜백 함수 자신을 의미합니다. 그래서 보통은 아래와 같이 self라고 하는 변수를 하나 생성해서 사용합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function HelloEs6() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; this.name = &quot;ES 6&quot;;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// const self = this 로 해서 콜백에서는 self를 사용&lt;/p&gt;
&lt;p&gt;HelloEs6.prototype.sayHello = function () {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; const self = this;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; setTimeout( function () {&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;white-space:pre&quot;&gt;	&lt;/span&gt;console.log('Hello ' + self.name);&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }, 500);&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;const es6 = new HelloEs6();&lt;/p&gt;
&lt;p&gt;es6.sayHello();&lt;/p&gt;
&lt;p&gt;// Hello ES 6&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;`화살표 함수`&amp;nbsp; 에서 `this`는 자신을 둘러싸고 있는 컨텍스트의 this를 의미합니다. 그래서 별도로 self라는 변수를 만들지 않고 바로 this를 사용할 수 있습니다. 아래 예에서 setTimeout의 파라이터인 화살표 함수에서 사용한 this는 `ES 6 Arrow`가 됩니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function HelloEs6Arrow() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; this.name = &quot;ES 6 Arrow&quot;;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// this.name 을 사용&lt;/p&gt;
&lt;p&gt;HelloEs6Arrow.prototype.sayHello = function () {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; setTimeout( ()&amp;nbsp; =&amp;gt; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; console.log('Hello ' + this.name);&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }, 500);&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;const es6Arrow = new HelloEs6Arrow();&lt;/p&gt;
&lt;p&gt;es6Arrow.sayHello();&lt;/p&gt;
&lt;p&gt;// Hello ES 6 Arrow&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [&lt;a href=&quot;https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;MDN Arrow Functions&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;클라스&lt;/h3&gt;&lt;p&gt;ES6에서는 `class` 키워드를 사용해서 클라스를 생성하는 문법이 추가되었습니다. 이 방법은 전통적인 오브젝트 오리엔티드 언어들이 클라스를 정의하는 방식과 유사합니다. 아무래도 많은 개발자들이 좀 더 편하게 느낄 수 있는 방식이기도 합니다. 기억해야하는 점은 `class` 키워드를 사용하는 문법은 코드를 작성하는 문법적인 편리성만 제공한다는 것입니다. 내부 인터프리터는 전과 동일하게 포로토타입에 기반한 오브젝트 오리엔티드 방식을 유지하고 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;상속이 가능하고 `super`를 사용해서 부모의 메써드 호출이 가능합니다. 객체화, 스태틱 메써드, 생성자 등을 지원합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;ES5에서 프로토타입 문법을 사용해서 클라스를 생성하려면 function 키워드를 사용해서 함수를 생성하고 prototype에 프라퍼티를 추가하는 방식으로 클라스를 구현할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function Product(productId, product, numReview) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; this.productId = productId;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; this.product = product;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; this.numReview = numReview;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Product.prototype.getProduct = function () {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return this.productId + ': ' + this.product;&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Product.moreReview = function (product1, product2) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return (product1.numReview &amp;gt;= product2.numReview) ? product1: product2;&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;const product1 = new Product(1, 'iPhone', 50);&lt;/p&gt;&lt;p&gt;const product2 = new Product(2, 'Android', 53);&lt;/p&gt;&lt;p&gt;const moreReview = Product.moreReview(product1, product2);&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;console.log(moreReview.getProduct());&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;위의 코드와 동일한 코드를 `class` 키워드를 사용해서 작성면 아래와 같습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;class Product {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; constructor (productId, product, numReview) {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; this.productId = productId;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; this.product = product;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; this.numReview = numReview;&lt;/p&gt;&lt;p&gt;&amp;nbsp; }&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; getProduct () {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; return this.productId + ': ' + this.product;&lt;/p&gt;&lt;p&gt;&amp;nbsp; };&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; static moreReview (product1, product2) {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; return (product1.numReview &amp;gt;= product2.numReview) ? product1: product2;&lt;/p&gt;&lt;p&gt;&amp;nbsp; };&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;const product1 = new Product(1, 'iPhone', 50);&lt;/p&gt;&lt;p&gt;const product2 = new Product(2, 'Android', 53);&lt;/p&gt;&lt;p&gt;const moreReview = Product.moreReview(product1, product2);&lt;/p&gt;
&lt;p&gt;console.log(moreReview.getProduct());&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Java나 C++등 다른 언어를 사용하시던 분이시라면 좀 더 친숙한 느낌을 받을 수 있습니다. 게다가 매번 prototype에 프라퍼티를 추가하는 형식으로 코딩을 하는 것 보다 훨씬 간결해 보여서 좋습니다. class를 상속받는 서브 클라스는 `extends` 키워드를 사용합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;class ProductWithOS extends Product {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; constructor (productId, product, os, numReview) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; super(productId, product, numReview);&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; this.os = os;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp; getProduct () {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return this.productId + ': ' + this.product + '(' + this.os + ')';&lt;/p&gt;
&lt;p&gt;&amp;nbsp; };&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;const product1 = new ProductWithOS(1, 'iPhone 7', 'iOS', 50);&lt;/p&gt;
&lt;p&gt;const product2 = new ProductWithOS(2, 'Galaxy S7', 'Android', 53);&lt;/p&gt;
&lt;p&gt;const moreReview = ProductWithOS.moreReview(product1, product2);&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;console.log(moreReview.getProduct());&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;서브클라스는 constructor에서 `super()`를 통해서 부모 클라스의 생성자를 호출합니다. getProduct는 함수를 다시 정의하면서 오버라이드 되었습니다. `class`와 `extends`를 사용한 클라스 정의와 상속은 직관적이고 구조적인 오브젝트 오리엔티드 프로그래밍을 하려는 많은 개발자들에게 희소식이 아닐 수 없네요.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [MDN Classes](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;확장 오브젝트 리터럴&lt;/h3&gt;
&lt;p&gt;오브젝트 리터럴은 중괄호({})를 사용해서 오브젝트를 생성하는 문법입니다. 멤버의 이름인 키(key)와 값을 쌍으로 이루진 오브젝트 멤버를 저장할 수 있습니다. ES6에 추가된 확장 오브젝트 리터럴은 변수나 함수를 오브젝트 멤버로 저장하는 간편한 방법을 제공합니다. 멤버의 키를 바로 지정하는 대신에 계산된 값으로 지정할 수 있습니다. 세터와 게터를 사용해서 오브젝트 프라퍼티를 읽거나 저장할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;아래 예에서와 같이 newProduct 오브젝트를 생성시 `const newProduct = {product, numReview}`로 지정할 수 있습니다. 일반적인 오브젝트 문법으로 변경을 하면 `const newProduct = {product: product, numReview: numReview}`와 같습니다. ES5에서라면 오브젝트 프라퍼티 이름을 지정해 주고 `:`를 찍고 값을 넣어줘야합니다. ES6에서는 오브젝트 리터럴인 중괄호에 변수를 넣으면 변수의 이름으로 키를 갖는 프라퍼티를 생성해 줍니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const product = 'iPhone';&lt;/p&gt;
&lt;p&gt;const numReview = 5;&lt;/p&gt;
&lt;p&gt;const newProduct = {product, numReview};&lt;/p&gt;
&lt;p&gt;console.log(newProduct);&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;프라퍼티와 마찬가지로 확장 오브젝트 리터럴로 함수도 추가할 수 있습니다. 역시 함수 이름과 동일한 키로 멤버를 생성해 줍니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const name = 'iPhone';&lt;/p&gt;
&lt;p&gt;const price = 100;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;const newProduct = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; getProductName() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return name;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; },&lt;/p&gt;
&lt;p&gt;&amp;nbsp; getPrice() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return price;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//ES5로 작성한 newProduct 오브젝트&lt;/p&gt;
&lt;p&gt;const newProductES5 = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; getProductName: function () {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return name;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; },&lt;/p&gt;
&lt;p&gt;&amp;nbsp; getPrice: function() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return price;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;ES5에서는 오브젝트의 프라퍼티 이름으로 계산된 값을 넣기 위해서는 오브젝트를 생성한 후 괄호([])를 사용해서 이름을 지정할 수 있었습니다. ES6의 오브젝트 리터럴에서는 오브젝트 생성시 바로 계산된 값으로 이름을 지정하는 것이 가능해졌습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const name = 'iPhone';&lt;/p&gt;
&lt;p&gt;const product = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; [name + '_color']: 'blue',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; [name + '_screen']: '4.7 inch'&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;console.log(product.iPhone_color);&lt;/p&gt;
&lt;p&gt;console.log(product.iPhone_screen);&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;게터(getter)와 세터(setter)는 오브젝트의 멤버함수를 프라퍼티처럼 사용할 수 있도록 해 줍니다. 오브젝트로부터 가져와야하는 데이터가 연산을 거친 후에 받을 수 있는 것이면 멤버 함수로 구현을 하게 됩니다. 오브젝트를 사용하는 쪽에서는 이 함수로부터 리턴 받은 값을 변수에 저장된 값과 비료를 하려면 `obj.productFullName() === 'Android:Galaxy S7'`처럼 코드를 작성해야합니다. 게다가 값을 넣을 때는 다른 함수를 사용해서 `obj.setProductFullName('iOS:iPhone 7')` 이렇게 해야합니다. 함수 이름을 정하는 규칙을 정해서 할 수는 있지만 직관적이지 않고 번거롭기만 합니다. 아래는 ES6를 사용한 예입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const product = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; os : 'iOS',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; name: 'iPhone 7',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; get productFullName () {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return this.os + ':' + this.name;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; },&lt;/p&gt;
&lt;p&gt;&amp;nbsp; set productFullName (fullName) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; let names = fullName.split(':');&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; this.os = names[0];&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; this.name = names[1];&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;console.log(product.productFullName);&lt;/p&gt;
&lt;p&gt;product.productFullName = 'Android:Galaxy S7';&lt;/p&gt;
&lt;p&gt;console.log(product.os);&lt;/p&gt;
&lt;p&gt;console.log(product.name);&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Object_literals&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;MDN Grammar and types: Object literals&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;템프릿 스트링&lt;/h3&gt;
&lt;p&gt;ES6에는 편리하면서도 강력한 기능을 제공하는 스트링 리터럴이 추가 되었습니다. 이 문법은 기존의 작은 따옴표(')나 큰 따옴표(&quot;) 대신에 백틱(\`)을 사용합니다. 기존 스트링 리터럴과 탈리 템프릿 스트링 리터럴은 변수나 익스프레션을 스트링 안에 넣을 수 있습니다. `$(expression)`처럼 사용하면 이 부분을 실제 변수의 값이나 익스프레션의 결과로 치환을 해 줍니다. 마치 탬플릿 언어를 사용하는 것처럼 말이죠. 또한 여러 라인에 걸쳐서 스트링을 만들 수도 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const product = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; os : 'iOS',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; name: 'iPhone 7',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; get productFullName () {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; // ES6 Template String&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return `${this.os}: ${this.name}`;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; },&lt;/p&gt;
&lt;p&gt;&amp;nbsp; set productFullName (fullName) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; let names = fullName.split(':');&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; this.os = names[0];&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; this.name = names[1];&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;console.log(product.productFullName);&lt;/p&gt;
&lt;p&gt;product.productFullName = 'Android:Galaxy S7';&lt;/p&gt;
&lt;p&gt;// Multi lines&lt;/p&gt;
&lt;p&gt;const result =`&amp;nbsp; &amp;nbsp;*** Product ***&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;* OS : ${product.os}&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;* Name : ${product.name}&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;* FullName: ${product.os + ':' + product.name}`;&lt;/p&gt;
&lt;p&gt;console.log(result);&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;템플릿 스트링 관련해서 추가로 알고 넘어갈 내용으로는 태그드 템플릿이 있습니다. 템플릿 스트링의 내용을 인자로 받아서 필요한 연산을 한 후 스트링이나 다른 오브젝트를 리턴하는 함수를 구현합니다. 그리고 이 함수를 템프릿 스트링 앞에 배치합니다. 함수의 인자로는 `$(expression)` 앞 뒤로 나뉘는 스트링을 배열로 갖는 파라미터와 각 익스프레션이 순대대로 들어갑니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const product = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; os : 'iOS',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; name: 'iPhone 7'&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;function addCompany(strings, nameExp, osExp) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; const str0 = strings[0]; // &quot;The &quot;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; const str1 = strings[1]; // &quot; OS is &quot;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; let company;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; if (osExp === 'iOS')&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; company = 'Apple';&lt;/p&gt;
&lt;p&gt;&amp;nbsp; else&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; company = 'Samsung';&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return `${str0}${nameExp}${str1}${osExp} and made by ${company}.`;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;//${product.name}과 ${product.os}로 나뉜 2개의 string&lt;/p&gt;
&lt;p&gt;const taggedString = addCompany`The ${product.name} OS is ${product.os}`;&lt;/p&gt;
&lt;p&gt;console.log(taggedString);&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [MDN Template Strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;디스트럭처링&lt;/h3&gt;&lt;p&gt;디스트럭처링은 여러 값을 패킹(pack)에서 가지고 있는 변수에서 언패킹(unpack)을 해서 다른 변수에 값을 할당하는 문법입니다. 정확히는 디스트럭처링 어사인먼트라고 해야합니다. 배열에서는 값을 오브젝트에서는 프라퍼티를 언패킹할 수 있습니다. 먼저 배열 디스트럭처링을 살펴 보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;변수를 선언하면서 바로 할당하거나 이미 선언된 변수에 디스트럭처링을 할 수 있습니다. 배열의 갯수가 할당 받을 변수의 갯수보다 적은 경우에 기본 값을 지정할 수 있습니다. 배열을 언패킹할때 앞에 일부는 각각 변수에 할당하고 나머지는 하나의 변수에 배열로 저장할 수 있습니다. 이는 나머지 패턴(rest pattern)을 통해서 지정할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const phones = ['iPhone', 'Android', 'featurePhone', 'Others'];&lt;/p&gt;
&lt;p&gt;// 변수를 선언하면서 바로 할당&lt;/p&gt;
&lt;p&gt;let [phone1, phone2, phone3, phone4] = phones;&lt;/p&gt;
&lt;p&gt;console.log(phone1); // iPhone&lt;/p&gt;
&lt;p&gt;console.log(phone2); // Android&lt;/p&gt;
&lt;p&gt;console.log(phone3); // featurePhone&lt;/p&gt;
&lt;p&gt;console.log(phone4); // Others&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// 이미 선언된 변수에 할당&lt;/p&gt;
&lt;p&gt;let first, second, others;&lt;/p&gt;
&lt;p&gt;[first, second] = phones; // 2개 이후 나머지는 무시됨.&lt;/p&gt;
&lt;p&gt;console.log(first); // iPhone&lt;/p&gt;
&lt;p&gt;console.log(second); // Android&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;[phone1, phone2, phone3='Unknown'] = [second, first];&lt;/p&gt;
&lt;p&gt;console.log(phone1); // Android&lt;/p&gt;
&lt;p&gt;console.log(phone2); // iPhone&lt;/p&gt;
&lt;p&gt;console.log(phone3); // Unknown&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// 나머지 패턴&lt;/p&gt;
&lt;p&gt;[first, second, ...others] = phones;&lt;/p&gt;
&lt;p&gt;console.log(phone1); // iPhone&lt;/p&gt;
&lt;p&gt;console.log(phone2); // Android&lt;/p&gt;
&lt;p&gt;console.log(others); // ['featurePhone', 'Others']&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;오브젝트 디스트럭처링도 변수를 선언하면서 혹은 이미 선언된 변수에도 가능합니다. 특별히 변수 선언 후에 디스트럭처링 저장을 하는 경우에는 꼭 압뒤로 (....)처럼 괄호를 넣어 주어야합니다. 라인의 시작에 있는 중괄호({)는 블럭의 시작으로 해석이 되기때문입니다.&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const iphone = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; name: 'iPhone 7',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; os: 'iOS'&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;const android = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; name: 'Galaxy S7',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; os: 'Android'&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;let {name, os} = iphone;&lt;/p&gt;
&lt;p&gt;console.log(name);&amp;nbsp; // iPhone 7&lt;/p&gt;
&lt;p&gt;console.log(os);&amp;nbsp; &amp;nbsp; // iOS&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// 괄호를 꼭 해 줘야합니다.&lt;/p&gt;
&lt;p&gt;({name, os} = android);&lt;/p&gt;
&lt;p&gt;console.log(name);&amp;nbsp; &amp;nbsp;// Galaxy S7&lt;/p&gt;
&lt;p&gt;console.log(os);&amp;nbsp; &amp;nbsp; &amp;nbsp;// Android&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;디스트럭처링을 하면서 바로 다른 변수에 저장을 할 수도 있습니다. 매칭되는 키가 없는 경우에 사용할 기본 값을 지정할 수도 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const iphone = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; name: 'iPhone 7',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; os: 'iOS'&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// 다른 이름으로 저장&lt;/p&gt;
&lt;p&gt;let {name: phoneName, os: phoneOS} = iphone;&lt;/p&gt;
&lt;p&gt;console.log(phoneName);&amp;nbsp; // iPhone 7&lt;/p&gt;
&lt;p&gt;console.log(phoneOS);&amp;nbsp; &amp;nbsp; // iOS&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// 기본값 지정&lt;/p&gt;
&lt;p&gt;let {name, os, color='Blue'} = iphone;&lt;/p&gt;
&lt;p&gt;console.log(name);&amp;nbsp; &amp;nbsp;// iPhone 7&lt;/p&gt;
&lt;p&gt;console.log(os);&amp;nbsp; &amp;nbsp; &amp;nbsp;// iOS&lt;/p&gt;
&lt;p&gt;console.log(color);&amp;nbsp; // Blue&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [MDN Destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;기본 함수 파라미터&lt;/h3&gt;&lt;p&gt;함수를 정의할 때 파라미터에 기본 값을 지정할 수 있습니다. 함수가 호출될 때 파라미터를 넣지 않았거나, `undefined`로 값이 들어오면 기본 값으로 파라미터가 세팅됩니다. ES5를 사용할 때는 파라미터에 기본 값을 넣기 위해서는 파라미터를 확인하고 기본 값을 넣는 코드를 추가해야했습니다. 파라미터를 입력하지 않으면 파라미터가 `undefined`가 되기때문에 `param === undefined`처럼 비교하여 기본 값을 지정하는 코드를 사용했습니다. 간단하게는 `||`를 사용해서 기본 값을 지정하기도 했죠.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function totalPrice(price, itemCount) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; // ES5 : itemCount 가 undefined 이면 1&lt;/p&gt;
&lt;p&gt;&amp;nbsp; itemCount = itemCount || 1;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return price * itemCount;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;console.log(totalPrice(100, 2)); // 100 * 2&lt;/p&gt;
&lt;p&gt;console.log(totalPrice(100));&amp;nbsp; &amp;nbsp; // 100 * 1&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;기본 함수 파라미터를 사용하면 함수의 파라미터를 정할 때 기본 값을 지정할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function totalPrice(price, itemCount=1) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return price * itemCount;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;console.log(totalPrice(100, 2)); // 100 * 2&lt;/p&gt;
&lt;p&gt;console.log(totalPrice(100));&amp;nbsp; &amp;nbsp; // 100 * 1&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;기본 파라미터로는 숫자뿐 아니라 스트링, 함수, 디스트럭처링 된 변수 등이 들어갈 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;//함수로 지정&lt;/p&gt;
&lt;p&gt;function totalPrice(price, itemCount=defaultCount()) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return price * itemCount;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;function defaultCount() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return 1;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;console.log(totalPrice(100));&amp;nbsp; &amp;nbsp; // 100 * 1&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//오브젝트 디스트럭처링, 배열 디스트럭처링&lt;/p&gt;
&lt;p&gt;function setPhone({name, os} = {name: 'iPhone 7', os: 'iOS'}, [price, count] = [200, 2]) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; //오브젝트 확장 리터럴로 세팅&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; name, os, price, count&lt;/p&gt;
&lt;p&gt;&amp;nbsp; };&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;console.log(setPhone());&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;참고: [Default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;함수 나머지 파라미터&lt;/h3&gt;
&lt;p&gt;함수 파라미터의 이름 앞에 `...`를 붙이면 파라미터의 개수에 관계없이 지정된 이름에 배열로 담아 줍니다. 나머지 파라미터 앞에 있는 파라미터를 제외한 나머지 파라미터만 배열로 주기때문에 이름도 나머지 파라미터입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function createCart(id, name='Unknown', ...products) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; const count = products.length;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; id, name, count,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; products&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;let cart = createCart(1, 'Good Customer', 'iPhone 7', 'Galaxy S7', 'Charger');&lt;/p&gt;
&lt;p&gt;console.log(cart);&lt;/p&gt;
&lt;p&gt;//{&quot;id&quot;:1,&quot;name&quot;:&quot;Good Customer&quot;,&quot;count&quot;:3,&quot;products&quot;:[&quot;iPhone 7&quot;,&quot;Galaxy S7&quot;,&quot;Charger&quot;]}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//파라미터가 주어지지 않아도 나머지 파라미터는 빈 배열로 생성됩니다.&lt;/p&gt;
&lt;p&gt;cart = createCart(2);&lt;/p&gt;
&lt;p&gt;console.log(cart);&lt;/p&gt;
&lt;p&gt;//{&quot;id&quot;:2,&quot;name&quot;:&quot;Unknown&quot;,&quot;count&quot;:0,&quot;products&quot;:[]}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//나머지 파라미터를 디스트럭처링하는 예제입니다.&lt;/p&gt;
&lt;p&gt;function createCartOnly2(id, name='Unknown', ...[product1, product2]) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; const count = 2;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; id, name, count,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; products2: [product1, product2]&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;//디스트럭처링 갯수를 넘는 파라미터는 무시됩니다.&lt;/p&gt;
&lt;p&gt;cart = createCartOnly2(3, 'New Customer', 'iPhone 7', 'Galaxy S7', 'Charger');&lt;/p&gt;
&lt;p&gt;console.log(cart);&lt;/p&gt;
&lt;p&gt;//{&quot;id&quot;:3,&quot;name&quot;:&quot;New Customer&quot;,&quot;count&quot;:2,&quot;products2&quot;:[&quot;iPhone 7&quot;,&quot;Galaxy S7&quot;]}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;나머지 파라미터를 보면 `arguments` 오브젝트와 기능이 유사한 것처럼 보입니다. 하지만 중요한 차이점이 있습니다.&lt;/p&gt;
&lt;p&gt;- 나머지 파라미터는 파라미터 이름이 지정되지 않은 나머지 파라미터만 포함하고 있습니다. 반면 arguments는 모든 파라미터를 포함하고 있습니다.&lt;/p&gt;
&lt;p&gt;- 나머지 파라미터는 자바스크립트 `배열(Array)`입니다. 따라서 배열의 여러가지 메써드를 사용할 수 있습니다. `sort`, `map`, `forEach` 등을 말입니다. 하지만 arguments는 배열이 아니기때문에 배열이 가진 기능을 사용할 수 없습니다.&lt;/p&gt;
&lt;p&gt;아래 예제는 `arguments`를 사용해서 createCart()를 구현한 예입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function createCart(id, name='Unknown') {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; const count = arguments.length - 2;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; const args = Array.from(arguments).splice(2);&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; id, name, count,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; products: args&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;let cart = createCart(1, 'Good Customer', 'iPhone 7', 'Galaxy S7', 'Charger');&lt;/p&gt;
&lt;p&gt;console.log(cart);&lt;/p&gt;
&lt;p&gt;//{&quot;id&quot;:1,&quot;name&quot;:&quot;Good Customer&quot;,&quot;count&quot;:3,&quot;products&quot;:[&quot;iPhone 7&quot;,&quot;Galaxy S7&quot;,&quot;Charger&quot;]}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;참고: [Rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;전개 문법&lt;/h3&gt;
&lt;p&gt;전개 문법(spread syntax)은 배열이나 스트링처럼 이터레이션이 가능한 데이터를 개별 데이터로 펼쳐서(전개, spread) 전달해 주는 기능입니다. 이터러블한 변수 이름 앞에 `...`를 붙여 사용합니다. 함수 인자의 경우 `values`라는 배열을 함수 인자로 `someFunction(...values)`처럼 넣을 수 있습니다. 또한 배열이나 오브젝트를 생성할 때도 사용할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// 1. 함수 전체 인자로 사용한 예&lt;/p&gt;
&lt;p&gt;function createCart(id, name, count) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; id, name, count&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;const product = [1, 'iPhone 7', 3];&lt;/p&gt;
&lt;p&gt;// Spread Syntax&lt;/p&gt;
&lt;p&gt;let cart = createCart(...product);&lt;/p&gt;
&lt;p&gt;console.log(cart);&lt;/p&gt;
&lt;p&gt;//{&quot;id&quot;:1,&quot;name&quot;:&quot;iPhone 7&quot;,&quot;count&quot;:3}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// 2. 함수 일부 인자로 사용한 예&lt;/p&gt;
&lt;p&gt;const selection = ['Galaxy S7', 5];&lt;/p&gt;
&lt;p&gt;cart = createCart(2, ...selection);&lt;/p&gt;
&lt;p&gt;console.log(cart);&lt;/p&gt;
&lt;p&gt;//{&quot;id&quot;:2,&quot;name&quot;:&quot;Galaxy S7&quot;,&quot;count&quot;:5}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;배열 리터럴에서도 전개 문법을 사용할 수 있습니다. 배열의 복사나 여래개의 배열을 하나로 합치는 데도 이용할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const product1 = ['iPhone 7', 'iOS'];&lt;/p&gt;
&lt;p&gt;const product2 = ['Galaxy S7', 'Android'];&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//배열 리터럴에서 사용&lt;/p&gt;
&lt;p&gt;const products = ['iPhone X', 'iOS', ...product1, 'Galaxy 9', 'Android'];&lt;/p&gt;
&lt;p&gt;console.log(products);&lt;/p&gt;
&lt;p&gt;//[&quot;iPhone X&quot;,&quot;iOS&quot;,&quot;iPhone 7&quot;,&quot;iOS&quot;,&quot;Galaxy 9&quot;,&quot;Android&quot;]&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//배열 복사&lt;/p&gt;
&lt;p&gt;const copied = [...products];&lt;/p&gt;
&lt;p&gt;console.log(copied);&lt;/p&gt;
&lt;p&gt;//[&quot;iPhone X&quot;,&quot;iOS&quot;,&quot;iPhone 7&quot;,&quot;iOS&quot;,&quot;Galaxy 9&quot;,&quot;Android&quot;]&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//2개의 배열을 연결할 때&lt;/p&gt;
&lt;p&gt;const two_products = [...product1, ...product2];&lt;/p&gt;
&lt;p&gt;console.log(two_products);&lt;/p&gt;
&lt;p&gt;//[&quot;iPhone 7&quot;,&quot;iOS&quot;,&quot;Galaxy S7&quot;,&quot;Android&quot;]&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;오브젝트도 전개 문법을 사용할 수 있습니다. 배역의 예와 마찬가지고 생성, 복사, 합치는 것이 가능합니다. 주의할 점은 오브젝트의 키가 동일한 경우 앞에 있는 오브젝트의 키의 내용은 뒤에 있는 오브젝트의 것으로 덮어 써집니다. 아래 예제에서 결과를 보실 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;const product1 = {name: 'iPhone 7', os: 'iOS'};&lt;/p&gt;
&lt;p&gt;const product2 = {name: 'Galaxy S7', type: 'Smart Phone'};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//오브젝트 리터럴에서 사용&lt;/p&gt;
&lt;p&gt;const products = {id: 3, ...product1};&lt;/p&gt;
&lt;p&gt;console.log(products);&lt;/p&gt;
&lt;p&gt;//{&quot;id&quot;:3,&quot;name&quot;:&quot;iPhone 7&quot;,&quot;os&quot;:&quot;iOS&quot;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//오브젝트 복사&lt;/p&gt;
&lt;p&gt;const copied = {...product2};&lt;/p&gt;
&lt;p&gt;console.log(copied);&lt;/p&gt;
&lt;p&gt;//{&quot;name&quot;:&quot;Galaxy S7&quot;,&quot;type&quot;:&quot;Smart Phone&quot;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;//2개의 오브젝트를 합칠 때&lt;/p&gt;
&lt;p&gt;const two_products = {...product1, ...product2};&lt;/p&gt;
&lt;p&gt;console.log(two_products);&lt;/p&gt;
&lt;p&gt;//{&quot;name&quot;:&quot;Galaxy S7&quot;,&quot;os&quot;:&quot;iOS&quot;,&quot;type&quot;:&quot;Smart Phone&quot;}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;참고: [Spread Operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;let + const&lt;/h3&gt;&lt;p&gt;`let`은 블록 스코프를 갖는 변수를 정의할 수 있습니다. 글로벌 스코프이거나 함수 단위 스코프를 갖는 `var`와는 스코프에서 차이가 있습니다. var는 같은 글로벌 혹은 함수 내부에서도 중괄호({ })로 구분되는 블록을 벗어나도 변수가 유지됩니다. 하지만 let은 블록 안에서만 유효합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function priceCheck() {&lt;/p&gt;&lt;p&gt;&amp;nbsp; let price1 = 200;&lt;/p&gt;&lt;p&gt;&amp;nbsp; var price2 = 200;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; if (true) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; let price1 = 300;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; var price2 = 300;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; console.log(price1);&amp;nbsp; //300&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; console.log(price2);&amp;nbsp; //300&lt;/p&gt;&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; //if 블록 안의 price1과 밖의 price1은 서로 다른 변수 입니다.&lt;/p&gt;&lt;p&gt;&amp;nbsp; console.log(price1);&amp;nbsp; //200&lt;/p&gt;&lt;p&gt;&amp;nbsp; console.log(price2);&amp;nbsp; //300&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;priceCheck();&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;`const`는 스코프는 let과 동일한 범위를 갖는 상수를 정의할 수 있습니다. 여기서 상수는 const로 정의된 변수에 다른 것을 다시 어사인할 수 없다는 것입니다. 하지만 이 const 변수가 레퍼런스하고 있는 오브젝트의 내용은 얼마든지 변경이 가능합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;const PI = 3.14;&lt;/p&gt;
&lt;p&gt;//아래 코드는 Uncaught TypeError: Assignment to constant variable 를 발생합니다.&lt;/p&gt;
&lt;p&gt;//PI = 4;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;const product = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; name: 'Galaxy S7',&lt;/p&gt;
&lt;p&gt;&amp;nbsp; os : 'Android'&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;// product가 레퍼런스를 하고 있는 오브젝트 내용을 변경하는 것은 가능합니다.&lt;/p&gt;
&lt;p&gt;product.name = 'Galaxy 9';&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [let statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let), [const statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;for...of&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;`for...of` 스테이트먼트를 사용하여 이터러블한 오브젝트를 루프를 돌 수 있습니다. String, Array와 Array처럼 동작하는 arguments나 NodeList, TypedArray, Map, Set 등의 오브젝트에 사용할 수 있습니다. 추가로 사용자 정의 이터러블 오브젝트에서 사용 가능합니다.(사용자 정의 이터러블 프로토콜은 다음에 설명합니다.)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;let iterable = [10, 20, 30];&lt;/p&gt;
&lt;p&gt;for (let vaule of interable) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; value += 1;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; colsole.log(value);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;// 11&lt;/p&gt;
&lt;p&gt;// 21&lt;/p&gt;
&lt;p&gt;// 31&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;참고 : [MDN for...of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;이터레이션 프로토콜&lt;/h3&gt;&lt;p&gt;자바스크립트 `이터레이션 프로토콜`을 사용하여 오브젝트를 이터레이션이 가능하게 할 수 있습니다. 이터레이션이 가능한 오브젝트가 되면 for...of 스테이트먼트에서 사용 가능하게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이터러블한 오브젝트가 되기 위해서는 이터레이터 함수를 리턴하는 메써드를 구현해야합니다. `@@interator`를 키로 하는 메써드를 구현하면 됩니다. 키는 `@@interator`를 직접 사용하는 대신 `Symbol.interator`로 사용하면 됩니다.&lt;/p&gt;
&lt;p&gt;이터레이터는 `next()` 메써드를 구현합니다. `next()` 메써드는 `done`과 `value` 프라퍼티를 갖는 오브젝트를 리턴합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;let fibonacci = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; [Symbol.iterator]() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; let pre = 0, cur = 1;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; next() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [pre, cur] = [cur, pre + cur];&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return { done: false, value: cur }&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;for (var n of fibonacci) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; // truncate the sequence at 1000&lt;/p&gt;
&lt;p&gt;&amp;nbsp; if (n &amp;gt; 1000)&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; break;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; console.log(n);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참조: [MDN for...of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;제너레이터&lt;/h3&gt;&lt;p&gt;간단히 말해서 제너레이터는 `function*`과 `yield`를 사용해서 이터레이터를 구현한 것과 같습니다. 할수를 정의할 때 function*를 사용하면 제너레이터가 리턴됩니다. 이터레이터의 `next`외에 추가로 `return`와 `throw` 메써드를 호출할 수 있습니다. next는 yield 익스프레션 값을 리턴합니다.return은 파라미터로 주어진 값을 리턴하면서 제너레이터를 종료합니다. throw는 제너레이터에 에러를 전달합니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;var fibonacci = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; [Symbol.iterator]: function*() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; var pre = 0, cur = 1;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; for (;;) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; var temp = pre;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; pre = cur;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; cur += temp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; yield cur;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;for (var n of fibonacci) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; // truncate the sequence at 1000&lt;/p&gt;
&lt;p&gt;&amp;nbsp; if (n &amp;gt; 1000)&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; break;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; console.log(n);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참조: [MDN Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;유니코드&lt;/h3&gt;&lt;p&gt;전체 유니코드를 지원합니다. 스트링 안에서 유니코드를 표현할 수 있는 새로운 방식이 추가되었습니다. RegExp에는 코드 포인트를 처리하기 위해 `u` 모드가 추가되었습니다. 추가로 21bit 코드 포인트 레벨에서 스트링을 처리하는 API가 추가되었습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// same as ES5.1&lt;/p&gt;
&lt;p&gt;&quot; &quot;.length == 2&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// new RegExp behaviour, opt-in ‘u’&lt;/p&gt;
&lt;p&gt;&quot; &quot;.match(/./u)[0].length == 2&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// new form&lt;/p&gt;
&lt;p&gt;&quot;\u{20BB7}&quot;==&quot; &quot;==&quot;\uD842\uDFB7&quot;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// new String ops&lt;/p&gt;
&lt;p&gt;&quot; &quot;.codePointAt(0) == 0x20BB7&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// for-of iterates code points&lt;/p&gt;
&lt;p&gt;for(var c of &quot; &quot;) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; console.log(c);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참조: [MDN RegExp.prototype.unicode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;모듈&lt;/h3&gt;&lt;p&gt;콤포넌트를 정의할 수 있도록 모듈을 지원합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// lib/math.js&lt;/p&gt;
&lt;p&gt;export function sum(x, y) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return x + y;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;export var pi = 3.141593;&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// app.js&lt;/p&gt;
&lt;p&gt;import * as math from &quot;lib/math&quot;;&lt;/p&gt;
&lt;p&gt;alert(&quot;2π = &quot; + math.sum(math.pi, math.pi));&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// otherApp.js&lt;/p&gt;
&lt;p&gt;import {sum, pi} from &quot;lib/math&quot;;&lt;/p&gt;
&lt;p&gt;alert(&quot;2π = &quot; + sum(pi, pi));&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;추가적으로 `export default`와 `import *`:&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// lib/mathplusplus.js&lt;/p&gt;
&lt;p&gt;import * from &quot;lib/math&quot;;&lt;/p&gt;
&lt;p&gt;export var e = 2.71828182846;&lt;/p&gt;
&lt;p&gt;export default function(x) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return Math.log(x);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// app.js&lt;/p&gt;
&lt;p&gt;import ln, {pi, e} from &quot;lib/mathplusplus&quot;;&lt;/p&gt;
&lt;p&gt;alert(&quot;2π = &quot; + ln(e)*pi*2);&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;import statement&lt;/a&gt;], [&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;export statement&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;모듈 로더&lt;/h3&gt;&lt;p&gt;모듈 로더는 아래 기능을 지원합니다.:&lt;/p&gt;
&lt;p&gt;- Dynamic loading&lt;/p&gt;
&lt;p&gt;- State isolation&lt;/p&gt;
&lt;p&gt;- Global namespace isolation&lt;/p&gt;
&lt;p&gt;- Compilation hooks&lt;/p&gt;
&lt;p&gt;- Nested virtualization&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;기본 모듈 로더는 설정이 가능합니다. 또한 별도로 구분되어 있거나 정해진 컨텍스트 내에서 새 로더를 구성하는 것도 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// Dynamic loading – ‘System’ is default loader&lt;/p&gt;
&lt;p&gt;System.import('lib/math').then(function(m) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; alert(&quot;2π = &quot; + m.sum(m.pi, m.pi));&lt;/p&gt;
&lt;p&gt;});&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// Create execution sandboxes – new Loaders&lt;/p&gt;
&lt;p&gt;var loader = new Loader({&lt;/p&gt;
&lt;p&gt;&amp;nbsp; global: fixup(window) // replace ‘console.log’&lt;/p&gt;
&lt;p&gt;});&lt;/p&gt;
&lt;p&gt;loader.eval(&quot;console.log('hello world!');&quot;);&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// Directly manipulate module cache&lt;/p&gt;
&lt;p&gt;System.get('jquery');&lt;/p&gt;
&lt;p&gt;System.set('jquery', Module({$: $})); // WARNING: not yet finalized&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;Map, Set(WeakMap, WeakSet)&lt;/h3&gt;&lt;p&gt;일반적인 알고리즘에서 많이 사용되는 데이터 구조가 추가되었습니다. WeakMap과 WeakSet은 weak reference를 지원해서 메모리 릭을 방지할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// Sets&lt;/p&gt;
&lt;p&gt;var s = new Set();&lt;/p&gt;
&lt;p&gt;s.add(&quot;hello&quot;).add(&quot;goodbye&quot;).add(&quot;hello&quot;);&lt;/p&gt;
&lt;p&gt;s.size === 2;&lt;/p&gt;
&lt;p&gt;s.has(&quot;hello&quot;) === true;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// Maps&lt;/p&gt;
&lt;p&gt;var m = new Map();&lt;/p&gt;
&lt;p&gt;m.set(&quot;hello&quot;, 42);&lt;/p&gt;
&lt;p&gt;m.set(s, 34);&lt;/p&gt;
&lt;p&gt;m.get(s) == 34;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// Weak Maps&lt;/p&gt;
&lt;p&gt;var wm = new WeakMap();&lt;/p&gt;
&lt;p&gt;wm.set(s, { extra: 42 });&lt;/p&gt;
&lt;p&gt;wm.size === undefined&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// Weak Sets&lt;/p&gt;
&lt;p&gt;var ws = new WeakSet();&lt;/p&gt;
&lt;p&gt;ws.add({ data: 42 });&lt;/p&gt;
&lt;p&gt;// Because the added object has no other references, it will not be held in the set&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참조: [&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;Map&lt;/a&gt;], [&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;Set&lt;/a&gt;], [&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;WeakMap&lt;/a&gt;], [&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;WeakSet&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;프록시&lt;/h3&gt;&lt;p&gt;오브젝트에 새로 정의된 기능(함수)를 수행할 수 있도록 합니다. 원래 오브젝트의 동작을 중간에 가로채거나, 오브젝트를 가상화, 로깅을 하는데 사용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// Proxying a normal object&lt;/p&gt;
&lt;p&gt;var target = {};&lt;/p&gt;
&lt;p&gt;var handler = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; get: function (receiver, name) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return `Hello, ${name}!`;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;var p = new Proxy(target, handler);&lt;/p&gt;
&lt;p&gt;p.world === 'Hello, world!';&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// Proxying a function object&lt;/p&gt;
&lt;p&gt;var target = function () { return 'I am the target'; };&lt;/p&gt;
&lt;p&gt;var handler = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; apply: function (receiver, ...args) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return 'I am the proxy';&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;var p = new Proxy(target, handler);&lt;/p&gt;
&lt;p&gt;p() === 'I am the proxy';&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;프록시에서 수행 가능한 모든 목록은 아래와 같습니다.:&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;var handler =&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp; get:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; set:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; has:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; deleteProperty:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; apply:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; construct:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; getOwnPropertyDescriptor:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; defineProperty:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; getPrototypeOf:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; setPrototypeOf:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; enumerate:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; ownKeys:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; preventExtensions:...,&lt;/p&gt;
&lt;p&gt;&amp;nbsp; isExtensible:...&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [MDN Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;심볼&lt;/h3&gt;&lt;p&gt;오브젝트의 키로 사용될 수 있는 기본 타입입니다. 오브젝트의 키로 `string`을 사용할 수도 있지만 `symbol`도 사용할 수 있게 추가되었습니다. 파라미터로 `description`을 추가할 수 있지만 필수는 아닙니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;var MyClass = (function() {&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; // module scoped symbol&lt;/p&gt;
&lt;p&gt;&amp;nbsp; var key = Symbol(&quot;key&quot;);&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; function MyClass(privateData) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; this[key] = privateData;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; MyClass.prototype = {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; doStuff: function() {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ... this[key] ...&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp; };&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; return MyClass;&lt;/p&gt;
&lt;p&gt;})();&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;var c = new MyClass(&quot;hello&quot;)&lt;/p&gt;
&lt;p&gt;c[&quot;key&quot;] === undefined&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [MDN Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;새로운 라이브러리 추가 기능&lt;/h3&gt;
&lt;p&gt;Math + Number + String + Array + Object APIs&lt;/p&gt;
&lt;p&gt;라이브러리에 새로운 기능이 다수 추가되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;
&lt;p&gt;Number.EPSILON&lt;/p&gt;
&lt;p&gt;Number.isInteger(Infinity) // false&lt;/p&gt;
&lt;p&gt;Number.isNaN(&quot;NaN&quot;) // false&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Math.acosh(3) // 1.762747174039086&lt;/p&gt;
&lt;p&gt;Math.hypot(3, 4) // 5&lt;/p&gt;
&lt;p&gt;Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&quot;abcde&quot;.includes(&quot;cd&quot;) // true&lt;/p&gt;
&lt;p&gt;&quot;abc&quot;.repeat(3) // &quot;abcabcabc&quot;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Array.from(document.querySelectorAll('*')) // Returns a real Array&lt;/p&gt;
&lt;p&gt;Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior&lt;/p&gt;
&lt;p&gt;[0, 0, 0].fill(7, 1) // [0,7,7]&lt;/p&gt;
&lt;p&gt;[1, 2, 3].find(x =&amp;gt; x == 3) // 3&lt;/p&gt;
&lt;p&gt;[1, 2, 3].findIndex(x =&amp;gt; x == 2) // 1&lt;/p&gt;
&lt;p&gt;[1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]&lt;/p&gt;
&lt;p&gt;[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;].entries() // iterator [0, &quot;a&quot;], [1,&quot;b&quot;], [2,&quot;c&quot;]&lt;/p&gt;
&lt;p&gt;[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;].keys() // iterator 0, 1, 2&lt;/p&gt;
&lt;p&gt;[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;].values() // iterator &quot;a&quot;, &quot;b&quot;, &quot;c&quot;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Object.assign(Point, { origin: new Point(0,0) })&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number), [Math](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math), [Array.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), [Array.of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of), [Array.prototype.copyWithin](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin), [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;이진수, 팔진수&lt;/h3&gt;&lt;p&gt;이진수(`b`)와 팔진수(`o`)가 뉴머릭 리터럴에 추가되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;
&lt;p&gt;0b111110111 === 503 // true&lt;/p&gt;
&lt;p&gt;0o767 === 503 // true&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;프로미스&lt;/h3&gt;&lt;p&gt;어싱크 프로그래밍에 사용할 수 있는 라이브러리입니다.&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function timeout(duration = 0) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return new Promise((resolve, reject) =&amp;gt; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; setTimeout(resolve, duration);&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; })&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;var p = timeout(1000).then(() =&amp;gt; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return timeout(2000);&lt;/p&gt;
&lt;p&gt;}).then(() =&amp;gt; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; throw new Error(&quot;hmm&quot;);&lt;/p&gt;
&lt;p&gt;}).catch(err =&amp;gt; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return Promise.all([timeout(100), timeout(200)]);&lt;/p&gt;
&lt;p&gt;})&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;More info: [MDN Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;리플렉트 API&lt;/h3&gt;&lt;p&gt;런타임 레벨에서 오브젝트에 리플렉션 API를 제공합니다. 프록시의 트랩 목록과 동일한 API를 제공합니다. 프록시를 구현할 때 유용하게 사용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;// No sample yet&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [MDN Reflect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;테일 콜 옵티마이제이션&lt;/h3&gt;&lt;p&gt;자바스크립트 인터프리터 구현과 관련된 사항입니다. 함수의 리턴하기 전 마지막 해야할 일이 함수를 이벨류에이션하는 것이라면 ES6 인터프리터는 테일 콜 옵티마이제이션을 할 수 있습니다. 마지막 호출되는 함수는 로컬 변수를 따로 가지고 있지 않아야 합니다. 이 경우 별도의 스택 프레임을 만들지 않기때문에 메모리 사용량이 줄어들게 됩니다. 특히나 리컬시브 함수인 경우에는 스택 오버플로우 에러를 방지할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;p&gt;function factorial(n, acc = 1) {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; 'use strict';&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; if (n &amp;lt;= 1) return acc;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; return factorial(n - 1, n * acc);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;// Stack overflow in most implementations today,&lt;/p&gt;
&lt;p&gt;// but safe on arbitrary inputs in ES6&lt;/p&gt;
&lt;p&gt;factorial(100000)&lt;/p&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;참고: [ES6 tail calls](http://benignbemine.github.io/2015/07/19/es6-tail-calls/)&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>자바스크립트</category>
      <category>ecmascript2015</category>
      <category>ES3</category>
      <category>자바스크립트</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/13</guid>
      <comments>https://sueng.tistory.com/13#entry13comment</comments>
      <pubDate>Sun, 11 Nov 2018 17:43:24 +0900</pubDate>
    </item>
    <item>
      <title>비트코인 코어(Bitcoin Core) 소스 분석에 도움이 되는 자료 모음</title>
      <link>https://sueng.tistory.com/12</link>
      <description>&lt;h3&gt;비트코인 개발자 문서&lt;/h3&gt;&lt;p&gt;링크 : &lt;a href=&quot;https://bitcoin.org/en/developer-documentation&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;https://bitcoin.org/en/developer-documentation&lt;/a&gt;&lt;/p&gt;&lt;p&gt;비트코인 org에서 제공하는 문서&lt;/p&gt;&lt;h3&gt;비트코인 에지 워크숍 튜토리얼&lt;/h3&gt;&lt;p&gt;링크 :&amp;nbsp;&lt;a href=&quot;https://bitcoinedge.org/tutorials&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;https://bitcoinedge.org/tutorials&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Dev++2017에서 발표된 튜토리얼 모음&lt;/p&gt;&lt;h3&gt;비트코인 완전 정복(Mastering Bitcoin) 2nd Edition&lt;/h3&gt;&lt;p&gt;링크:&amp;nbsp;&lt;a href=&quot;https://github.com/bitcoinbook/bitcoinbook&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;https://github.com/bitcoinbook/bitcoinbook&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;Mastering Bitcoin 2판 영문 책&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>블록체인</category>
      <category>블록체인</category>
      <category>비트코인</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/12</guid>
      <comments>https://sueng.tistory.com/12#entry12comment</comments>
      <pubDate>Sun, 15 Apr 2018 23:19:16 +0900</pubDate>
    </item>
    <item>
      <title>나이가 들면 뇌세포는 생산이 안되는 걸까?</title>
      <link>https://sueng.tistory.com/11</link>
      <description>&lt;p&gt;오랫동안 들어오고 자연스럽게 받아들였던 말들이 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;사람이 나이가 들면 뇌세포는 더 이상 새로 만들어 지지 않는다.&lt;/p&gt;&lt;p&gt;나이가 들면 기억력이 감퇴하는 건 생물학적으로 당연하다.&lt;/p&gt;&lt;p&gt;뇌세포가 점점 사라져서 더 노력해도 예전처럼은 안될꺼야.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.cell.com/cell-stem-cell/fulltext/S1934-5909(18)30121-8&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;최근에 발표된 한 연구&lt;/a&gt;에따르면 어쩌면 이 말들은 사실이 아닐 수도 있습니다.&lt;/p&gt;&lt;p&gt;나이가 70이 되어도 여전히 새로운 뇌세포가 만들어지고 있다는 점이 발견되었기때문이죠.&lt;/p&gt;&lt;p&gt;더군다다 20대와도 세포로만 봤을 때는 차이가 없다는 내용입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;뇌에서 사람의 기억과 관련된 중요한 기능을 담당하는 부분은 해마(Hippocampus)인데요.&lt;/p&gt;&lt;p&gt;20대의 뇌와 70대의 뇌를 비교했을 때 해마에서 새로운 세포의 숫자가 거의 동일하다는 것입니다.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99E043355AC9AE1213&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99E043355AC9AE1213&quot; width=&quot;820&quot; height=&quot;448&quot; filename=&quot;hippocampsi_image.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;20대의 해마(위)와 70대의 해마(아래)에 있는 새로운 세포의 수사 거의 동일하다고 합니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;이미지 출처 : &lt;a href=&quot;https://www.sciencenews.org/article/human-brains-make-new-nerve-cells-and-lots-them-well-old-age&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;사이언스뉴스&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;10대, 20대를 거치면서 뇌세포가 나이가 들수록 점점 줄어든다는 말은 별 신경쓸 이야기가 아니었죠.&lt;/p&gt;&lt;p&gt;하지만 더 나이가 들어 40대를 지나게 되면 자연스럽게 나오는 말이 있습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;나이가 드니까 역시 예전처럼 머리가 돌아가지 않네.&lt;/p&gt;&lt;p&gt;예전에는 기억력 하나는 좋았는데, 뇌도 나이가 드니 어쩔 수 없군.&lt;/p&gt;&lt;p&gt;이제는 새로운 공부를 하기는 글렀어. 더 이상 머리가 바쳐주지를 않네.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;어쩌면 무의적으로 나오는 이런 말들은 오랜기간에 걸쳐 나에게 익숙해진 뇌에관한 사실때문일 겁니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;나이가 들면 뇌는 더 이상 세포를 생성하지 않는다.&lt;/p&gt;&lt;p&gt;어릴 때 가지고 있던 세포들이 죽어가면서 숫자가 줄어들기만 한다.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;사실관계보다 이미 나를 길들이고 있는 이런 말이 더 무서운게 아닐까요?&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이번 연구의 특이점은 다른 연구에 비해서 많은 양의 증거를 제시했다는 점입니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;연구에 사용한 사람의 뇌는 14살에서 79살의 28명의 것이라고 하고요.&lt;/p&gt;&lt;p&gt;일반 기증자의 뇌가 아닌 과거 병력이나 약물 복용 여부에 관한 데이터도 확인된 것이라고 하고요.&lt;/p&gt;&lt;p&gt;반대로 뇌 세포는 더 이상 생산되지 않는다는 연구결과도 발표되고 있습니다.&lt;/p&gt;&lt;p&gt;아직 어떤 것이 옳다는 단정을 할 수 있는 단계는 아니라고 하네요.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;하지만 예전처럼 나이가 들면 무조건 머리가 안돌아가고 뇌가 죽어간다는 핑게는 대지 말아야할 것 같습니다.&lt;/p&gt;&lt;p&gt;연구 결과에는 한가지 전제가 있습니다.&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;70세의 뇌이지만, 건강한 70세라는 겁니다.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;뇌도 몸의 일부이니 전체적으로 몸이 건강해야 뇌가 가지고 있는 기능을 잘 발휘할 수 있겠죠.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;나이가 들어 머리가 나빠지는 것은 어쩔 수 없다는 고정관념은 이제 의심을 해 봐야합니다.&lt;/p&gt;&lt;p&gt;과학자들이 70대가 되어도 20대와 똑같이 새로운 뇌 세포가 있다고 하니까요.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;나이가 들어 근육양은 줄어들었지만, 뇌 세포만큼은 20대처럼 항상 생생하다는 말 믿어보시죠!&lt;/p&gt;</description>
      <category>뇌과학</category>
      <category>기억력</category>
      <category>뇌과학</category>
      <category>해마</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/11</guid>
      <comments>https://sueng.tistory.com/11#entry11comment</comments>
      <pubDate>Sun, 8 Apr 2018 14:58:51 +0900</pubDate>
    </item>
    <item>
      <title>롱제티 - 석양을 보러 가는 여행 (시드니 근교)</title>
      <link>https://sueng.tistory.com/10</link>
      <description>&lt;p&gt;롱제티(Long Jetty)는 시드니에서 북쪽으로 약 1시간 20분을 달리면 나오는 작은 마을입니다.&lt;/p&gt;&lt;p&gt;센트럴 코스트(Central Coast)지역에 위치하고 있으면서 관광객들이 많이 찾는 엔트란스(The Entrance)와 아주 가깝게 위치하고 있죠.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;제티(Jetty)라는 단어는 배를 대고 사람들이 내리고 탈 수 있는 선착장 같은 곳을 의미합니다.&lt;/p&gt;&lt;p&gt;지금부터 100년도 더 전인 1915년에 와이용으로 사람들을 실어 나르는 페리를 위해서 만들어 졌습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;페리가 들어올 수 있는 깊이까지 연결을 하기위해서는&amp;nbsp;길이가 무려 315미터나 되어야했죠.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9918243A5AC8D6D40E&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9918243A5AC8D6D40E&quot; width=&quot;820&quot; height=&quot;617&quot; filename=&quot;longjetty_03.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;롱제티에서 마을쪽을 바라본 모습&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9991D63A5AC8D67519&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9991D63A5AC8D67519&quot; width=&quot;820&quot; height=&quot;855&quot; filename=&quot;longjetty_01.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;롱제티 나무다리 위로 막 올라서서&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;호수를 끼고 있는 작은 마을&lt;/h2&gt;&lt;p&gt;자연 스럽게 제티 근방의 마을은 롱제티라고 불리게 되었습니다.&lt;/p&gt;&lt;p&gt;물위로 쭉 뻗어 있는 제티&amp;nbsp;3개가 약 600 미터 정도의 간격을 두고 만들어져 있습니다.&lt;/p&gt;&lt;p&gt;이 제티가 있는 곳은 바다가 아니라 터가라 호수(Tuggerah Lake)인데요.&amp;nbsp;&lt;/p&gt;&lt;p&gt;엔트란스를 통해서 바다와 연결되어 있는 내륙에 있는 커다란 바닷물로 되어 있는 호수죠.&lt;/p&gt;&lt;p&gt;롱제티도 예전에는 관광객을 위한 카라반 파크, 숙소, 롤러스케이트장 등이 있었지만 지금은 다 문을 닫았고요.&amp;nbsp;&lt;/p&gt;&lt;p&gt;1990년대 초만 하더라도 금융 서비스 기관들이 여럿 들어차 있어서 번성을 했었습니다. 지금은 역시 다 문을 닫은 상태입니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;대신 현대적인 가구, 중고 가구 상점들이 들어서면서 조금 다시 활력을 얻어가고는 있죠.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9931F03A5AC8DB4A1E&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9931F03A5AC8DB4A1E&quot; width=&quot;820&quot; height=&quot;680&quot; filename=&quot;longjetty_07.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;롱제티 100년을 기념하는 안내&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99B9173A5AC8DB5913&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99B9173A5AC8DB5913&quot; width=&quot;820&quot; height=&quot;523&quot; filename=&quot;longjetty_08.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;옛 롱제티 모습 : 롱제티 100년을 기념하는 안내판에서&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;페리를 타던 곳에서 석양을 바라보는 곳으로&lt;/h2&gt;&lt;p&gt;특히 주말이면 이곳을 찾는 관광객들이 끊이지를 않습니다. 롱제티를 찾아서 넓은 호수를 바라보는 기분은 하루 중 어느때는 평안한 느낌을 주기에 충분하죠.&lt;/p&gt;&lt;p&gt;호수를 바라볼 수 있게 배치된 의자들과 가족끼리 가벼운 바베큐를 즐길 수 있는 시설도 잘 마련되어 있어요.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9934573E5AC8DA641B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9934573E5AC8DA641B&quot; width=&quot;820&quot; height=&quot;1093&quot; filename=&quot;longjetty_06.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;롱제티에 오니 내 다리도 따라서 롱~~~&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9943153B5AC8E4E405&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9943153B5AC8E4E405&quot; width=&quot;820&quot; height=&quot;854&quot; filename=&quot;longjetty_13.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;해가 너무 밝아요.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;세개의 제티중에서 호수를 바라봤을 때 제일 오른쪽에 위치한 것이 가장 긴데요.&lt;/p&gt;&lt;p&gt;일일히 다 걸어볼 시간이나 체력이 없다면 바로 이곳으로 오는게 좋습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;호수를 향해 놓인 나무위를 걸으면서 호수를 바라보고요.&lt;/p&gt;&lt;p&gt;얕은 물에 다니는 물고기를 보고 있으면 그냥 마음이 편해지면서 왜 여길 사람들이 찾는 지 자연스럽게 알게됩니다.&lt;/p&gt;&lt;p&gt;운이 좋다면 저처럼 물위를 날개치듯 헤험치는 가오리를 만날 수도 있어요.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99A019355AC8D9812A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99A019355AC8D9812A&quot; width=&quot;820&quot; height=&quot;634&quot; filename=&quot;longjetty_05.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;사진보다 실제로 보면 더 신기해요.&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9992CB3B5AC8E25006&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9992CB3B5AC8E25006&quot; width=&quot;820&quot; height=&quot;550&quot; filename=&quot;longjetty_10.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;펠리컨은 엔트런스의 명물이기도 하죠.&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;하지만 무엇보다 이곳을 찾는 사람들은 해가 막 지기전 1~2시간을 맞춰 오는 경우가 많습니다.&lt;/p&gt;&lt;p&gt;석양을 보기 위한 것이죠.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/993F553D5AC8DD9C10&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F993F553D5AC8DD9C10&quot; width=&quot;820&quot; height=&quot;775&quot; filename=&quot;jetty_12.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;해가 질 때쯤 제티 끝으로 걸어가는 사람&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99C3E93D5AC8DDB706&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99C3E93D5AC8DDB706&quot; width=&quot;820&quot; height=&quot;819&quot; filename=&quot;jetty_09.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;벌써 붉은 색을 내는 군요.&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9911773D5AC8DDC626&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9911773D5AC8DDC626&quot; width=&quot;820&quot; height=&quot;615&quot; filename=&quot;jetty_11.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;아직 이글거리네요.&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/990C583D5AC8DDD616&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F990C583D5AC8DDD616&quot; width=&quot;820&quot; height=&quot;615&quot; filename=&quot;jetty_10.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;마지막 붉은 빛깔&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9983C83A5AC8D69B33&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9983C83A5AC8D69B33&quot; width=&quot;820&quot; height=&quot;615&quot; filename=&quot;longjetty_02.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;마지막 사라지기전 폭팔하는 붉음&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;꼭 제티에 나가지 않더라도 가족들 간, 친구들간에 모여 석약을 바라보며 샴페인, 와인을 함께 나누는 사람들도 꽤 있네요.&lt;/p&gt;&lt;p&gt;아이들을 위한 작은 놀이터도 있는데요.&lt;/p&gt;&lt;p&gt;놀이터에서 바라보는 마지막 노을도 꽤 운치있었습니다.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99B8313F5AC8E13D29&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99B8313F5AC8E13D29&quot; width=&quot;820&quot; height=&quot;574&quot; filename=&quot;longjetty_11.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;어디를 가든 아이들을 위한 놀이터는 있어요.&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99C85B3F5AC8E15228&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99C85B3F5AC8E15228&quot; width=&quot;820&quot; height=&quot;636&quot; filename=&quot;longjetty_12.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;노을을 바라보며 타는 미끄럼틀&lt;/p&gt;&lt;/blockquote&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;다음에는 좀 더 일찍 나와서 유미나비치를 먼저 들리기로 했습니다.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;근처에 있는 맛있는 식당에서 늦은 점심으로 빅브렉퍼스트도 하나 시켜 먹고 롱제티로 오려고요.&lt;/p&gt;</description>
      <category>호주여행,맛집</category>
      <category>롱제티</category>
      <category>시드니</category>
      <category>해외여행</category>
      <category>호주</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/10</guid>
      <comments>https://sueng.tistory.com/10#entry10comment</comments>
      <pubDate>Sun, 8 Apr 2018 00:35:07 +0900</pubDate>
    </item>
    <item>
      <title>[블록체인] 해시함수 이해 4 - 특성 3 - 퍼즐 게임을 만들 수 있다==코인 마이닝 문제 출제</title>
      <link>https://sueng.tistory.com/9</link>
      <description>&lt;p&gt;블록체인에 사용되는 해시함수는 무엇이고 어떤 특성을 가지고 있는지 알아보고 있습니다.&lt;/p&gt;&lt;p&gt;그 네번째 마지막 글로 해시 함수의 특성 3 - 퍼즐 게임을 만들 수 있다입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이전 글은 아래 링크에서 보실 수 있습니다.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/6&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인]해시함수 이해1 - 해시함수란?&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/7&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 2 - 특성 1 - 충돌이 거의 발생하지 않는다.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/8&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 3 - 특성 2 - 원본 내용을 알 수 없다&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이글에서 말하는 해시 퍼즐 게임이 비트코인 채굴자(마이너)들이 푸는 문제와 같은 종류입니다.&lt;/p&gt;&lt;p&gt;흔히 암호를 푼다고 하는데요.&amp;nbsp;&lt;/p&gt;&lt;p&gt;알고보면 암호를 푼다기 보다는 랜덤하게 값을 입력해서 원하는 해시가 나오는지 확인하는 작업을 반복하는 겁니다.&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;모래밭에서 금조각 찾기라고 할 수 있는데요.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;금속 탐지기나 심지어는 사금 채취하듯 물에 흘려보내면서 찾는 등 어떤 기술 도입을 전혀 할 수 없다는거죠.&lt;/p&gt;&lt;p style=&quot;text-align: left; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9935A93E5ABF1DB536&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9935A93E5ABF1DB536&quot; width=&quot;820&quot; height=&quot;820&quot; filename=&quot;017550-150ppp.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://&amp;quot;https://www.freepik.com/free-vector/businessman-and-maze-illustration_764814.htm&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;Designed by Freepik&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;문제는 이런식입니다.&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;256 bits 결과를 내는 SHA256 해시의 결과가 아래와 같은 입력값을 찾으시오.&lt;/p&gt;&lt;p&gt;해시 :&amp;nbsp; '38744961f4eda323853183a6f6bc135434347285158efaaba7b9280fdb569a95'&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;해답을 찾는 지름길이 없다&lt;/h2&gt;&lt;p&gt;해시의 특성중 &lt;a href=&quot;http://blog.10000lab.xyz/7&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;충돌이 일어나지 않는다&lt;/a&gt;와 해시 &lt;a href=&quot;http://blog.10000lab.xyz/8&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;결과로 입력을 원본을 알 수 없다&lt;/a&gt;는 것이 있습니다.&lt;/p&gt;&lt;p&gt;예를들어 숫자 256으로 나누어서 나머지 값을 해시 결과로 갖는 해시함수가 있다고 하죠.&lt;/p&gt;&lt;p&gt;해시 결과 10일 입력을 찾으라는 문제를 내면 어떻게 하시겠어요?&lt;/p&gt;&lt;p&gt;256 + 10&lt;/p&gt;&lt;p&gt;256 X 2&amp;nbsp;+ 10&lt;/p&gt;&lt;p&gt;256 X 3 + 10&lt;/p&gt;&lt;p&gt;....&lt;/p&gt;&lt;p&gt;아주 간단한 공식으로 바로 해결이 됩니다.&lt;/p&gt;&lt;p&gt;이런 해시는 사용불가입니다.&lt;/p&gt;&lt;p&gt;여기서 예로들고 있는 SHA256은 아직까지는 이런 지름길이 없는 것으로 알려져 있습니다.&lt;/p&gt;&lt;p&gt;무조건 어떤 값을 넣어서 해시를 계산해 보고 해답과 일치하는 지를 봐야하는 거죠.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;그래도 뭔가 꼼수를 부릴 수 있지 않을까?&lt;/h2&gt;&lt;p&gt;가능합니다.&lt;/p&gt;&lt;p&gt;해시 결과를 미리 계산해서 저장해 두는 데이터 베이스를 만드는 거죠.&lt;/p&gt;&lt;p&gt;일단 최대한 많이 만들고, 계속 만들어 둡니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;그리고 문제로 출제되는 해시와 이미 저장된 것과 일치되는 것이 나오면 계산할 필요도 없이 바로 답을 알게되는 거죠.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이를 방지하기 위해서 실제 어플리케이션에는 좀 더 다른 방법으로 문제를 출제합니다.&lt;/p&gt;&lt;p&gt;랜덤하게 생성된 키값을 주고요.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이 키와 어떤 값(X)를 붙여서 해시 입력으로 넣었을 때 해시 결과가 아래와 같이 나오는 X를 찾으시오.&lt;/p&gt;&lt;p&gt;예를들면&amp;nbsp;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;SHA256 해시의 입력으로 아래 주어진 키에 X를 붙여서 넣었을 때 아래 주어진 해시를 출력하는 X를 찾으시오.&amp;nbsp;&lt;/p&gt;&lt;p&gt;키 : '0c62f876ef1dea830de9f32c2f4b46dd6d74d50d15896e09ef5a2fcd4ac7e1d7'&lt;/p&gt;&lt;p&gt;해시 :&amp;nbsp; '38744961f4eda323853183a6f6bc135434347285158efaaba7b9280fdb569a95'&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;라고 문제를 출제합니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;해시의 충돌은 발생할 수 밖에 없습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;즉 같은 해시를 만들어 낼 수 있는 입력은 아주 많이 존재한다는 거죠.&lt;/p&gt;&lt;p&gt;하지만 랜덤으로 선택된 키를 제공함으로서 내가 미리 계산해둔 해시 입력값은 의미가 없어집니다.&lt;/p&gt;&lt;p&gt;정답이 미리 계산해 둔 데이터베이스에 있을 수도 있지만, 역시 하늘에 별따기죠.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;문제의 난이도 조정은 어떻게 하지?&lt;/h2&gt;&lt;p&gt;그런데, 위에 예를 든 것처럼 문제를 출제하면 어떤 경우에는 평생 아무도 못 푸는 문제가 되고 맙니다.&lt;/p&gt;&lt;p&gt;해시의 특성 2에서 40조의 8 제곱에 관한 설명을 보셨죠?&lt;/p&gt;&lt;p&gt;문제의 난이도를 조정하는 법은 의외로 쉽습니다.&lt;/p&gt;&lt;p&gt;아래와 같이 하는 거죠.&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;256 bits 결과를 내는 SHA256 해시의 결과가 아래와 같은 입력값을 찾으시오.&lt;/p&gt;&lt;p&gt;단, X는 아무 값이나 들어가 일치하지 않아도 됩니다.&lt;/p&gt;&lt;p&gt;해시 :&amp;nbsp; 'XXXXXXXXXXeda323853183a6f6bc135434347285158efaaba7b9280fdb569a95'&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;해시 결과를 하나의 값으로 고정하는 것이 아니라 특정 그룹으로 묶어 문제를 출제하는 것입니다.&lt;/p&gt;&lt;p&gt;제일 쉬운 문제는 마지막 한 bit만 일치하면 되는 문제겠죠.&amp;nbsp;&lt;/p&gt;&lt;p&gt;확율적으로 2번만 시도하면 1번은 정답을 맞출 수 있습니다.&lt;/p&gt;&lt;p&gt;제일 어려운 문제는 당연히 256 bits가 모두 일치하는 문제고요.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;지금까지 블록체인에서 사용되는 해시함수의 특징에 대해서 간단히, 가능하면 쉽게 알아봤습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;포스트 순서입니다.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/6&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 1 - 해시함수란?&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(102, 102, 102); font-family: &amp;quot;Noto Sans&amp;quot;, sans-serif; font-size: 14px;&quot;&gt;&lt;a href=&quot;http://blog.10000lab.xyz/7&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 2 - 특성 1 - 충돌이 거의 발생하지 않는다.&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/8&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 3 - 특성 2 - 원본 내용을 알 수 없다&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/9&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 4 - 특성 3 - 퍼즐 게임을 만들 수 있다==코인 마이닝 문제 출제&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;</description>
      <category>블록체인</category>
      <category>SHA256</category>
      <category>블록체인</category>
      <category>암호화페</category>
      <category>해시함수</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/9</guid>
      <comments>https://sueng.tistory.com/9#entry9comment</comments>
      <pubDate>Sat, 31 Mar 2018 14:35:49 +0900</pubDate>
    </item>
    <item>
      <title>[블록체인] 해시함수 이해 3 - 특성 2 - 원본 내용을 알 수 없다</title>
      <link>https://sueng.tistory.com/8</link>
      <description>&lt;p&gt;블록체인에 사용되는 해시함수는 무엇이고 어떤 특성을 가지고 있는지 알아보고 있습니다.&lt;/p&gt;&lt;p&gt;그 세번째 글로 해시 함수의 특성 2 - 원본 내용을 알 수 없다입니다.&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;이전 글은 아래 링크에서 보실 수 있습니다.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/6&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인]해시함수 이해1 - 해시함수란?&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/7&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 2 - 특성 1 - 충돌이 거의 발생하지 않는다.&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;첫번째 글에서 해시함수란&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;어떤 길이의 데이터를 입력해도 정해진 길이의 결과를 주는 함수&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;라고 했습니다.&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9901AF4F5ABE5D3906&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9901AF4F5ABE5D3906&quot; width=&quot;820&quot; height=&quot;513&quot; filename=&quot;143.jpg&quot; filemime=&quot;image/jpeg&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.freepik.com/free-vector/concept-of-security-hand-with-key-opens-closes-the-lock_1215705.htm&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;Designed by Freepik&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이번 해시함수의 특징은 이 해시결과를 보고서는 원본 메시지가 무엇인지 알아내는 것이 거의 불가능하다는 것입니다.&lt;/p&gt;&lt;p&gt;바로 앞의 글에서 해시 함수는 입력 데이터가 다르면 해시 결과가 다르다라고 말했습니다.&lt;/p&gt;&lt;p&gt;같은 해시결과를 만드는 값은 반드시 존재하지만 실제로 그 값을 찾는 것은 불가능에 가깝다고 설명했습니다.&lt;/p&gt;&lt;p&gt;다시 말하면 해시 결과를 알려줘도 그 결과를 만드는 입력 데이터를 찾는 일은 불가능하다는 거죠.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;원본을 알아내는 것이 불가능할까? 동전 던지기 문제&lt;/h2&gt;&lt;p&gt;동전을 던저 앞(head), 뒤(tail)을 맞추는 게임을 생각해 보겠습니다.&lt;/p&gt;&lt;p&gt;A와 B가 미리 앞, 뒤를 선택해서 심판을 보기로한 C에게 제출합니다.&lt;/p&gt;&lt;p&gt;이때 그냥 제출하는 것이 아니라 SHA256 해시를 돌려서 결과를 제출합니다.&lt;/p&gt;&lt;p&gt;심판 C가 실제 동전을 던진 후에 A, B가 제출한 답과 비교를 하려고 합니다.&lt;/p&gt;&lt;p&gt;제출된 해시는 모두가 볼 수 있게 그냥 공개합니다. &lt;br /&gt;해시 원본을 알아내는 것은 불가능하니까 동전을 던지기 전이라도 본인이 선택한 결과의 해시를 공개해도 문제가 없겠죠?&lt;/p&gt;&lt;p&gt;정말 문제가 없을까요?&lt;/p&gt;&lt;p&gt;A가 제출한 해시는 아래와 같습니다.&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;'38744961f4eda323853183a6f6bc135434347285158efaaba7b9280fdb569a95'&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;B가 제출한 값입니다.&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;'38744961f4eda323853183a6f6bc135434347285158efaaba7b9280fdb569a95'&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;해시를 보면 무얼 적어냈는지 모르겠네요.&lt;/p&gt;&lt;p&gt;동전던지기에서 가능한 입력은 head와 tail뿐이니까 해시를 한번 구해볼까요?&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; a = b'tail'&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; b = b'head'&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; sha256(a).hexdigest()&lt;/p&gt;&lt;p&gt;'0c62f876ef1dea830de9f32c2f4b46dd6d74d50d15896e09ef5a2fcd4ac7e1d7'&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; sha256(b).hexdigest()&lt;/p&gt;&lt;p&gt;'9f2e6d33a3717ee826353a404ba4618d1aeeb6879ad7936bce8ed5f46814924d'&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;이런, 위의 내용을 보니 금방 알아보겠네요.&lt;/p&gt;&lt;p&gt;A가 제출한 해시는 tail의 해시이고 B는 head의 해시를 제출했군요.&lt;/p&gt;&lt;p&gt;그렇습니다.&amp;nbsp;&lt;/p&gt;&lt;p&gt;이렇게 입력 데이터가 한정된 경우(이번 예에서는 head나 tail)는 미리 입력에대한 해시를 구해보면 쉽게 제출된 해시가 어떤 값인지 분별이 가능합니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;동전 던지기 문제의 해결 방법은?&lt;/h2&gt;&lt;p&gt;이를 해결할 방법은 있는 걸까요?&lt;/p&gt;&lt;p&gt;256 bits의 랜덤한 데이터를 원본 데이터에 덪붙이면 어떨까요?&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/7&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;해시결과가 충돌되지 않는다&lt;/a&gt;는 글을 보시면 256 bits 데이터가 갖는 의미를 알 수 있을 겁니다.&lt;/p&gt;&lt;p&gt;이 랜덤값을 &lt;b&gt;키(Key)&lt;/b&gt;라고 부르겠습니다.&lt;/p&gt;&lt;p&gt;이 키를 추가해서 해시를 구해볼까요?&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; a = b'e6d85489f5082f21b2ecb993c799bb45e3ba7ca24618c553ff3b650b2b4e0c9b&lt;b&gt;tail&lt;/b&gt;'&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; b = b'96f77711bac6bb95014d94f3b19c604176412101054d6d439a9b142ed2642278&lt;b&gt;head&lt;/b&gt;'&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; sha256(a).hexdigest()&lt;/p&gt;&lt;p&gt;'6c8f20b2fea69cded0afe060ebb80b79a5d0e850f1c1f621c0aadb09454f49d0'&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; sha256(b).hexdigest()&lt;/p&gt;&lt;p&gt;'3401b7f3ab6d4f1555bf53dc0692611c900fb29fcb9679d5ac6b65880d7847d3'&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;A와 B가 선택한 값의 앞에 랜덤 키를 추가해서 해시를 구했습니다.&lt;/p&gt;&lt;p&gt;입력에 랜덤 키가 들어가서&amp;nbsp; 해시만 보고 원본이 무엇인지 알수가 없게 되었습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;그럼 심판 C는 어떻게 확인을 하죠?&lt;/h2&gt;&lt;p&gt;A와 B는 각각 랜덤하게 선택한 키를 가지고 있습니다. 그리고 실제로 자기가 선택한 값을 알고 있죠.&lt;/p&gt;&lt;p&gt;처음에는 해시값만 C에게 제출을 했지만 C가 동전을 던진 후 결과를 확인할 때는 키와 실제 본인이 선택한 값을 제출합니다.&lt;/p&gt;&lt;p&gt;C는 키와 선택한 값(head 또는 tail)을 붙인 후 해시를 실행해 보고 원래 제출한 해시값과 일치하는지 확인만 하면 됩니다.&lt;/p&gt;&lt;p&gt;그런데 만일 A가 동전 던진 결과를 보고 조작된 키와 선택한 값을 제출하면 어떻게 될까요?&lt;/p&gt;&lt;p&gt;가능은 하지만 그런 값을 찾는 것은 불가능에 가깝다고 앞의 글 &lt;a href=&quot;http://blog.10000lab.xyz/7&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;해시결과가 충돌되지 않는다&lt;/a&gt;에서 설명을 했습니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;이렇게 해서 해시의 두번째 특성까지 알아봤습니다.&lt;/p&gt;&lt;p&gt;다음 이어질 내용은 해시의 세번째 특성이면서 비트코인 마이닝과 관련된 내용입니다.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote class=&quot;tx-quote-tistory&quot;&gt;&lt;p&gt;포스트 순서입니다.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/6&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 1 - 해시함수란?&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: rgb(102, 102, 102); font-family: &amp;quot;Noto Sans&amp;quot;, sans-serif; font-size: 14px;&quot;&gt;&lt;a href=&quot;http://blog.10000lab.xyz/7&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 2 - 특성 1 - 충돌이 거의 발생하지 않는다.&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/8&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 3 - 특성 2 - 원본 내용을 알 수 없다&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blog.10000lab.xyz/9&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;[블록체인] 해시함수 이해 4 - 특성 3 - 퍼즐 게임을 만들 수 있다==코인 마이닝 문제 출제&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>블록체인</category>
      <category>SHA256</category>
      <category>블록체인</category>
      <category>암호화페</category>
      <category>해시함수</category>
      <author>엔디엘디(NdLd)</author>
      <guid isPermaLink="true">https://sueng.tistory.com/8</guid>
      <comments>https://sueng.tistory.com/8#entry8comment</comments>
      <pubDate>Sat, 31 Mar 2018 00:53:40 +0900</pubDate>
    </item>
  </channel>
</rss>