<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>tonirr</title>
    <link>https://soyeondev.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 9 Apr 2026 12:00:14 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>tonirr</managingEditor>
    <item>
      <title>[WEB] Window.postMessage()</title>
      <link>https://soyeondev.tistory.com/312</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--사각 점선 박스 시작--&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;WebRTC로 화상 기능을 개발하면서 기존 창과 새 창 사이 메세지를 주고 받아야 하는 상황에서&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;Window.postMessage()를 통해 기존 창의 값을 참조할 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;처음 postMessage를 사용하기로 하였을 때 창 간에 메세지를 주고 받는다는 것이 생소해서 서칭과정이 길었다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서 Window.postMessage()의 개념과 예제를 상기시키면서 정리하고 이후 포스팅에서&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;React Hook에서 Window.postMessage()를 사용하여 개발한 과정 및 발생 이슈들을 정리해보려고 한다.&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Window.postMessage()란?&lt;/h3&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;window.postMessage()&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메소드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Window&quot;&gt;Window&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;오브젝트 사이에서 안전하게 cross-origin 통신을 할 수 있게 합니다. 예시로, 페이지와 생성된 팝업 간의 통신이나, 페이지와 페이지 안의 iframe 간의 통신에 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;일반적으로, 다른 페이지 간의 스크립트는 각 페이지가 같은 프로토콜, 포트 번호와 호스트을 공유하고 있을 때에(&quot;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy&quot;&gt;동일 출처 정책&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&quot;으로도 불려 집니다.) 서로 접근할 수 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;window.postMessage()&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;는 이 제약 조건을 안전하게 우회하는 기능을 제공합니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;MDN에서는 이렇게 설명하고 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; 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: #1b1b1b;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;나는 기존 창과 새창 간에 통신할 때에 사용하였는데,&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #1b1b1b;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;이 경우 동일 근원 출처 정책으로 인해 기존 창과 새 창이 각각의 window를 가지고 있어 통신할 수 없는 것이 원칙이나 Window.postMessage를 사용하면 안전하게 기존 창과 새 창이 통신할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;문법&lt;/h3&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;아래 과정을 통해 하나의 window는 다른 window를 참조할 수 있다. 하나의 예시이고 참조 방식에 따라 방법은 달라진다.&lt;/p&gt;
&lt;pre id=&quot;code_1637307317775&quot; class=&quot;javascript&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;targetWindow = window.opener 	// 새 창을 만들고 그 새창을 참조할 경우&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;targetWindow를 만든 후 아래 과정처럼 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1637307313948&quot; class=&quot;javascript&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;targetWindow.postMessage(message, targetOrigin, [transfer]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;i&gt;targetWindow&lt;/i&gt;&lt;/span&gt;를 생성하는 방법은 아래와 같다. 필요한 상황을 골라서 사용하면 된다.&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://developer.mozilla.org/ko/docs/Web/API/Window/open&quot;&gt;Window.open&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(새 창을 만들고 새 창을 참조할 때),&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Window/opener&quot;&gt;Window.opener&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(새 창을 만든 window를 참조할 때),&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/contentWindow&quot;&gt;HTMLIFrameElement.contentWindow&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;(en-US)&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(부모 window에서 임베디드된&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTML/Element/iframe&quot;&gt;&amp;lt;iframe&amp;gt;&lt;/a&gt;을 참조할 때),&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/parent&quot;&gt;Window.parent&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;(en-US)&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(임베디드된&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTML/Element/iframe&quot;&gt;&amp;lt;iframe&amp;gt;&lt;/a&gt;에서 부모 window를 참조할 때),&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/frames&quot;&gt;Window.frames&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;(en-US)&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;+ an index value (named or numeric).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;i&gt;targetWindow&lt;/i&gt;&lt;/span&gt;를 생성한 후 다른 window에 보내질 데이터를 &lt;i&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;message&lt;/span&gt;&lt;/i&gt; 부분에 실어서 보낸다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;i&gt;targetOrigin &lt;/i&gt;&lt;/span&gt;에서는&amp;nbsp;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;i&gt;targetWindow &lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;의 origin을 지정하며 별도로 지정하지 않음(&quot;*&quot;)으로 지정하거나 URI를 작성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: center; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;디스페치 이벤트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 스크립트를 실행할 경우 메시지를 수신하는 window측에서 전달된 메시지를 받을 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1637308151776&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;window.addEventListener(&quot;message&quot;, receiveMessage, false);

function receiveMessage(event)
{
  if (event.origin !== &quot;http://example.org:8080&quot;)
    return;

  // ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: center; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;예제&lt;/h3&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;새 창을 만들고 새 창을 참조하는 경우(Window.open)를 통해 이해해보자&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1637309621133&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
 * &amp;lt;http://example.com:8080&amp;gt;에 있는 윈도우 A의 스크립트:
 */

// 새 창을 참조하는 객체 popup을 만든다.
var popup = window.open(...popup details...);

// https://secure.example.net 도메인에 아래와 같은 메세지를 보낸다.
popup.postMessage(&quot;The user is 'bob' and the password is 'secret'&quot;,
                  &quot;https://secure.example.net&quot;);

// http://example.com 도메인에 아래와 같은 메세지를 보낸다.
popup.postMessage(&quot;hello there!&quot;, &quot;http://example.com&quot;);

// &amp;lt;http://example.com:8080&amp;gt;에서 메세지를 받는 함수
function receiveMessage(event)
{
  // origin 체크를 통해 message를 신뢰할 것인지 확인한다.
  if (event.origin !== &quot;http://example.com&quot;)
    return;

  // event.source is popup
  // event.data 가 &quot;hi there yourself!  the secret response is: rheeeeet!&quot;
}
// &amp;lt;http://example.com:8080&amp;gt;에 이벤트 등록 한다.
window.addEventListener(&quot;message&quot;, receiveMessage, false);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1637310313536&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
 * In the popup's scripts, running on &amp;lt;http://example.com&amp;gt;:
 */
function receiveMessage(event)
{
  //  origin 체크를 통해 message를 신뢰할 것인지 확인한다.
  if (event.origin !== &quot;http://example.com:8080&quot;)
    return;

  // event.source가 window.opener라면 event.data는 &quot;hello there!&quot;이 될 것이다.

  // event.origin은 &amp;lt;http://example.com&amp;gt; 즉 새창을 띄운 origin 창을 말하며 
  // origin 창에 아래 메세지를 보낸다. 
  event.source.postMessage(&quot;hi there yourself!  the secret response &quot; +
                           &quot;is: rheeeeet!&quot;,
                           event.origin);
}

// &amp;lt;http://example.com&amp;gt;에 이벤트 등록을 한다.
window.addEventListener(&quot;message&quot;, receiveMessage, false);&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3aOkg/btrlDdlo954/bcKoHEPMUErjik8xFH9TK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3aOkg/btrlDdlo954/bcKoHEPMUErjik8xFH9TK1/img.png&quot; data-alt=&quot;서로 도메인이 다른 Controller Window와 Receiver Window가 message를 주고 받을 수 있다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3aOkg/btrlDdlo954/bcKoHEPMUErjik8xFH9TK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3aOkg%2FbtrlDdlo954%2FbcKoHEPMUErjik8xFH9TK1%2Fimg.png&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;536&quot; height=&quot;381&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;381&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서로 도메인이 다른 Controller Window와 Receiver Window가 message를 주고 받을 수 있다&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;다음 포스팅에서 React Hook 프로젝트에서 window.postMessage()를 사용하는 과정에서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 등록이 안되면서 메세지를 불러오지 못하거나 컴포넌트 이동중에 여러번 이벤트 등록되어 window message를 주고받는 과정에서 이슈가 발생하는 등의 시행착오를 하나씩 정리해보려고 한다.&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;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/Window/postMessage&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage&lt;/a&gt;&lt;/p&gt;</description>
      <category>web</category>
      <category>window.postMessage()</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/312</guid>
      <comments>https://soyeondev.tistory.com/312#entry312comment</comments>
      <pubDate>Fri, 19 Nov 2021 20:00:40 +0900</pubDate>
    </item>
    <item>
      <title>[javascript] Promise개념과 활용</title>
      <link>https://soyeondev.tistory.com/311</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--사각 점선 박스 시작--&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--서브 문단 마지막 사용 끝--&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--헤드라인 끝--&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Promise 란&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise는 javascript안에 내장되어 있는 객체이며 비동기 적인 것을 수행할 때 콜백함수 대신 유용하게 사용할 수 있는 객체이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;804&quot; data-filename=&quot;스크린샷 2021-11-08 오후 7.50.44.png&quot; width=&quot;617&quot; height=&quot;434&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ncuJT/btrkaPzYIOB/RKYRhcoikwShJfifhApKr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ncuJT/btrkaPzYIOB/RKYRhcoikwShJfifhApKr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ncuJT/btrkaPzYIOB/RKYRhcoikwShJfifhApKr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FncuJT%2FbtrkaPzYIOB%2FRKYRhcoikwShJfifhApKr1%2Fimg.png&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;804&quot; data-filename=&quot;스크린샷 2021-11-08 오후 7.50.44.png&quot; width=&quot;617&quot; height=&quot;434&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Promise의 state&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise는 다음 중 하나의 상태를 가진다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대기(pending): 연산을 수행중이거나 거부되지 않은 초기 상태&lt;/li&gt;
&lt;li&gt;이행(fulfilled): 연산이 성공적으로 완료됨&lt;/li&gt;
&lt;li&gt;거부(rejected): 연산이 실패함&lt;/li&gt;
&lt;/ul&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 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Producer vs Consumer&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise는 원하는 기능을 수행해서 해당 데이터를 만들어내는 Producer와 데이터를 소비하는 Consumer로 나뉘어진다.&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;Producer&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1636362490162&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const promise = new Promise(() =&amp;gt; {
	setTimeout(() =&amp;gt; {
    	// resolve('user id is ...')
        // reject(new Error('no network'));
    }, 2000);
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise 객체를 생성하여 Promise에서 실행 되어야 하는 코드를 정의한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise 객체를 만드는 순간 executor 함수가 바로 실행되는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성과 동시에 Promise 내에 정의한 setTimeout가 실행되고 setTimeout이 정상적으로 작동한다면 resolve함수가 반환되며 에러가 발생할 경우 reject함수가 반환된다.&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;Consumer&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1636363031658&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;promise
	.then(value =&amp;gt; {
		console.log(value);
	}).catch(error =&amp;gt; {
    		console.log(error);
   	 }).finally(() =&amp;gt; {
    		console.log('finally');
    	});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;consumer 프로세스는 then, catch, finally로 나누어 설명할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;promise 객체가 성공적으로 실행될 경우 then에서 resolve의 return 값을 반환받고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;promise 객체가 에러를 발생시킬 경우 catch에서 reject의 return값을 반환받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 promise의 resolve와 reject에 관계없이 finally가 실행되면서 promise의 consumer&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Promise Chaning&lt;/h3&gt;
&lt;pre id=&quot;code_1636364802174&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 3. Promise chaining
const fetchNumber = new Promise((resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; resolve(1), 1000);
});

fetchNumber
// 여기에서 num은 resolve에 파라미터로 전달된 값을 의미
.then(num =&amp;gt; num * 2)
.then(num =&amp;gt; num * 3)
.then(num =&amp;gt; {
    return new Promise((resolve, reject) =&amp;gt; {
        setTimeout(() =&amp;gt; resolve(num - 1), 1000);
    });
})
.then(num =&amp;gt; console.log(num));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;promise는 then에서 resolve를 통해 반환받은 값을 전달받아 계속적으로 처리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째 then에서 resolve에서 반환한 1을 num으로 전달받고 곱하기 2를 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 then에서 첫번째 then에서 반환한 결과값 2를 num으로 전달받아 곱하기 3을 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세번째 then에서 두번째 then에서 반환한 결과값 6을 num으로 전달받아 새로운 Promise 생성자의 resolve에 값을 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 Promise 생성자의 resolve에서 num에 1을 빼주고 있으므로 최종적으로 반환되는 값은 5이다.&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: center; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Promise를 사용한 Error Handling&lt;/h3&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;Promise를 한꺼번에 여러개를 사용하다보면 어느 Promise객체에서 Error가 발생했는지 알 수 없는 경우가 있다.&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 경우를 대비해 하나의 Promise 객체 then마다 catch 함수를 바로 붙여서 에러가 발생하면 이렇게 처리해줘라는 과정을 덧붙이면 어디에서 에러가 발생했는지 직관적으로 알 수 있다.&lt;/p&gt;
&lt;p style=&quot;float: none; text-align: left; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1636365898912&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const getHen = () =&amp;gt;
    new Promise((resolve, reject) =&amp;gt; {
        setTimeout(() =&amp;gt; resolve('hen'), 1000);
    });
const getEgg = hen =&amp;gt; 
    new Promise((resolve, reject) =&amp;gt; {
        //setTimeout(() =&amp;gt; resolve(`${hen} =&amp;gt; egg`), 1000);
        setTimeout(() =&amp;gt; reject(new Error(`error! ${hen} =&amp;gt; egg`), 1000));
    });
const cook = egg =&amp;gt; 
    new Promise((resolve, reject) =&amp;gt; {
        setTimeout(() =&amp;gt; resolve(`${egg} =&amp;gt; fri`), 1000);
    });

getHen()
    .then(getEgg)
    .catch(error =&amp;gt; {
        return 'bread';
    })
    .then(cook)
    .then(console.log)
    .catch(console.log)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드는 getHen, getEgg, cook 함수를 통해 각각 hen, egg, fri를 반환받는 Producer과정을 정의한 후&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;세 개의 함수를 then으로 묶어서 Consumer과정을 거친다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;만약 Consumer과정에서 적어도 하나의 함수에서 에러가 발생한다면 프로그램이 끝까지 실행되지 않고 에러를 발생시키고 종료될 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 각각의 Promise의 then에 catch로 에러가 발생할 경우 이런 것을 실행해줘라는 명령을 덧붙인다면 단순히 에러를 발생시키고 프로그램이 종료되지 않고 에러가 발생된 함수에 대해서만 명령한대로 처리를 할 것이며 프로그램은 끝까지 실행될 것이다.&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Promise.all&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드에서 a와 b모두 Promise로 정의된 비동기일 때 Promise.all 메소드에 인자로 넣어주면 인자로 넣어준 모든 비동기(promise)가 실행완료된 시점에 callback을 실행하도록 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1636367181051&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let a = Promise.resolve(10);
let b = Promise.resolve(20);
Promise.all([a, b]).then(function([resA, resB]) {
	console.log(resA + resB);	// 30
});&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;사용자가 화면에 진입했을 때 여러개의 api를 통해 데이터를 받아와서 모든 api 통신과 처리가 완료된 후 완성된 화면을 사용자에게 노출하여야 하는 상황에서 Promise.all을 사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처리중일 경우 로딩바를 화면에 노출시키고 Promise.all이 완료되었을 때 사용자에게 화면을 노출하는 방식으로 구현하였다.&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;Promise.all을 찾다가 Promise를 정확하게 다시 공부해야 겠다는 생각이 들어 포스팅을 작성하게 되었는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async와 await의 개념에 대해서도 더 깊게 공부해야겠다는 생각이 들었다.&lt;/p&gt;</description>
      <category>javascript</category>
      <category>catch</category>
      <category>Error Handling</category>
      <category>Promise</category>
      <category>then</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/311</guid>
      <comments>https://soyeondev.tistory.com/311#entry311comment</comments>
      <pubDate>Mon, 8 Nov 2021 19:37:57 +0900</pubDate>
    </item>
    <item>
      <title>[WEB] window, DOM, BOM</title>
      <link>https://soyeondev.tistory.com/310</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--사각 점선 박스 시작--&gt;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;window&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--부제목-그레이 끝--&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;window 객체는 웹 브라우저의 창을 나타내는 객체로 대부분의 웹 브라우저에서 지원하고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;javascript의 모든 객체, 전역 함수, 전역 변수들은 자동으로 window 객체의 프로퍼티가 된다. window 객체의 메소드는 전역 함수이고 window 객체의 프로퍼티는 전역 변수가 된다. 문서 객체 모델(DOM)의 요소들도 모두 window 객체의 프로퍼티가 된다.&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;window의 구조&lt;/h3&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;window객체는 2가지 역할을 한다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;첫번째는 javascript의 전역 객체로 동작하는 역할이며 두번째는 브라우저 창(browser window)을 대변하고 이를 제어할 수 있는 메서드를 제공하는 역할이다.&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;616&quot; data-filename=&quot;스크린샷 2021-11-02 오후 10.00.13.png&quot; width=&quot;402&quot; height=&quot;321&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc49JG/btrjErF466U/Bn9udIezMksLcxLkst8P71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc49JG/btrjErF466U/Bn9udIezMksLcxLkst8P71/img.png&quot; data-alt=&quot;window 객체의 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc49JG/btrjErF466U/Bn9udIezMksLcxLkst8P71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc49JG%2FbtrjErF466U%2FBn9udIezMksLcxLkst8P71%2Fimg.png&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;616&quot; data-filename=&quot;스크린샷 2021-11-02 오후 10.00.13.png&quot; width=&quot;402&quot; height=&quot;321&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;window 객체의 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size20&quot;&gt;window 객체를 전역 객체로 사용&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1635858639379&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function sayHi() {
  alert(&quot;안녕하세요.&quot;);
}

// 전역 함수는 전역 객체(window)의 메서드임
window.sayHi();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size20&quot;&gt;브라우저 창을 대변하는 역할&lt;!--사각 점선 박스 시작--&gt;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1635858586884&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;alert(window.innerHeight); // 창 내부(inner window) 높이&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;문서 객체 모델(DOM)&lt;/h3&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;문서 객체 모델(Document Object Model, DOM)은 웹페이지 내의 모든 콘텐츠를 객체로 나타내준다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;document&lt;span style=&quot;background-color: #ffffff;&quot;&gt; 객체는 페이지의 기본 진입점 역할을 하며 document 객체를 이용해서 페이지 내에 있는 것들은 무엇이든지 변경할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1635858828855&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 배경을 붉은색으로 변경하기
document.body.style.background = &quot;red&quot;;

// 1초 후 원상태로 복구하기
setTimeout(() =&amp;gt; document.body.style.background = &quot;&quot;, 1000);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;브라우저 객체 모델(BOM)&lt;/h3&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;브라우저 객체 모델(Browser Object Model, BOM)은 문서 이외의 모든 것을 제어하기 위해 브라우저가 제공하는 추가 객체를 나타낸다.&lt;/p&gt;
&lt;pre id=&quot;code_1635859122147&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;alert(location.href); // 현재 URL을 보여줌
if (confirm(&quot;위키피디아 페이지로 가시겠습니까?&quot;)) {
  location.href = &quot;https://wikipedia.org&quot;; // 새로운 페이지로 넘어감
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;window 객체에서 제공하는 BOM은 MDN 속성을 보면 된다.&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 navigator 객체는 브라우저와 운영체제에 대한 정보를 제공하는 것으로 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;navigator.userAgent&amp;nbsp;&lt;span style=&quot;background-color: #ffffff;&quot;&gt; 는 브라우저가 실행 중인 운영체제(Windows, Linux, Mac 등)정보를 알려준다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;location 객체는 현재 URL을 읽을 수 있게 해주며 새로운 URL로 변경할 수 있게 한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;참고문서&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Window&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/Window&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://sushmithavootukuri.medium.com/difference-between-window-document-and-screen-in-javascript-757a65b25e9a&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://sushmithavootukuri.medium.com/difference-between-window-document-and-screen-in-javascript-757a65b25e9a&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ko.javascript.info/browser-environment&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ko.javascript.info/browser-environment&lt;/a&gt;&lt;/p&gt;</description>
      <category>web</category>
      <category>boM</category>
      <category>DoM</category>
      <category>web</category>
      <category>window</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/310</guid>
      <comments>https://soyeondev.tistory.com/310#entry310comment</comments>
      <pubDate>Tue, 2 Nov 2021 22:24:29 +0900</pubDate>
    </item>
    <item>
      <title>[javascript] Intersection Observer API</title>
      <link>https://soyeondev.tistory.com/309</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--사각 점선 박스 시작--&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rhzuJ/btrmpvYEZ6h/M4oe0hriGjPxwtwZ5EtKd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rhzuJ/btrmpvYEZ6h/M4oe0hriGjPxwtwZ5EtKd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rhzuJ/btrmpvYEZ6h/M4oe0hriGjPxwtwZ5EtKd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrhzuJ%2FbtrmpvYEZ6h%2FM4oe0hriGjPxwtwZ5EtKd0%2Fimg.png&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;460&quot; height=&quot;460&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Intersection Observer란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Intersection Observer란 브라우저 뷰포트(Viewport)와 선택된 요소(Element)의 교차점을 관찰하는 API이다. 쉽게 말하면 선택된 요소가 사용자 화면에 현재 보이는지 보이지 않는지를 구별하는 기능을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Intersection Observer의 생성과 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new IntersectionObserver()를 통해 인스턴스(io)를 생성, 관찰자(Observer)를 초기화, 관찰할 대상(Element)을 지정하여 사용할 수 있다. 생성자는 2개의 인수(callback, options)를 가진다.&lt;/p&gt;
&lt;pre id=&quot;code_1634467337743&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const io = new IntersectionObserver(callback, options) // 관찰자 초기화
io.observe(element)	// 관찰할 대상(요소) 등록&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;callback&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관찰할 대상이 등록되거나 가시성에 변화가 발생하면 관찰자는 콜백을 실행하며 콜백은 2개의 인수(entries, observer)를 가지고 있다.&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;entries, observer&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;entries는 IntersectionObserverEntry 인스턴스의 배열이며 IntersectionObserverEntry는 읽기 전용(Read only)의 다음 속성들을 포함하고 있다.&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;boundingClientRect: 관찰 대상의 사각형 정보(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly&quot;&gt;DOMRectReadOnly&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;intersectionRect: 관찰 대상의 교차한 영역 정보(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly&quot;&gt;DOMRectReadOnly&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;intersectionRatio: 관찰 대상의 교차한 영역 백분율(intersectionRect&lt;span&gt;&amp;nbsp;&lt;/span&gt;영역에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;boundingClientRect&lt;span&gt;&amp;nbsp;&lt;/span&gt;영역까지 비율, Number)&lt;/li&gt;
&lt;li&gt;isIntersecting: 관찰 대상의 교차 상태(Boolean)&lt;/li&gt;
&lt;li&gt;rootBounds: 지정한 루트 요소의 사각형 정보(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly&quot;&gt;DOMRectReadOnly&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;target: 관찰 대상 요소(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Element&quot;&gt;Element&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;time: 변경이 발생한 시간 정보(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp&quot;&gt;DOMHighResTimeStamp&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;observer는 콜백이 실행되는 해당 인스턴스를 참조한다.&lt;/p&gt;
&lt;pre id=&quot;code_1634468266258&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const io = new IntersectionObserver((entries, observer) =&amp;gt; {
  console.log(observer)
}, options)

io.observe(element)&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;options&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;root, rootMargin, threshold&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;root는 타겟의 가시성을 검사하기 위해 뷰포트 대신 사용할 요소 객체(루트 요소)를 지정한다. 타겟의 조상 요소여야 하며 지정하지 않거나 null의 경우 브라우저의 뷰포트가 기본적으로 사용된다.&lt;/p&gt;
&lt;pre id=&quot;code_1634468449009&quot; class=&quot;javascript&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const io = new IntersectionObserver(callback, {
  root: document.getElementById('my-viewport')
})&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;rootMargin은 바깥 여백(margin)을 이용해 root범위를 확장 또는 축소할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본값은 0px 0px 0px 0px이며 단위를 꼭 입력하여야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1634468547350&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const io = new IntersectionObserver(callback, {
  rootMargin: '200px 0px'
})&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;threshold는 옵저버가 실행되기 위해 타겟의 가시성이 얼마나 필요한지 백분율로 표시하는 것으로 기본값은 Array타입의 [0]이지만 Number 타입의 단일 값으로도 작성할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0: 타겟의 가장자리 픽셀이 Root 범위를 교차하는 순간(타겟의 가시성이 0%일 때) 옵저버가 실행&lt;/li&gt;
&lt;li&gt;0.3: 타겟의 가시성 30%일 때 옵저버가 실행&lt;/li&gt;
&lt;li&gt;[0, 0.3, 1]: 타겟의 가시성이 0%, 30%, 100%일 때 모두 옵저버가 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1634468662197&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const io = new IntersectionObserver(callback, {
  threshold: 0.3 // or `threshold: [0.3]`
})&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;h2 data-ke-size=&quot;size26&quot;&gt;Methods&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;observe(), unobserve()&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;observe()는 대상 요소의 관찰을 시작하는 메소드이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1634468836532&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const io = new IntersectionObserver(callback, options)

const div = document.querySelector('div')

io.observe(div) // DIV 요소 관찰&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;unobserve()는 대상 요소의 관찰을 중지하는 메소드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관찰을 중지할 하나의 대상 요소를 인수로 지정해야 하며 해당 인스턴스가 관찰하고 있지 않은 대상 요소가 인수로 지정된 경우 아무 동작도 하지 않는다.&lt;/p&gt;
&lt;pre id=&quot;code_1634469025064&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const io1 = new IntersectionObserver(callback, options)
const io2 = new IntersectionObserver(callback, options)

// ...

io1.observe(div)
io2.observe(li)
io2.observe(h2)

io1.unobserve(h2) // nothing..
io2.unobserve(h2) // H2 요소 관찰 중지&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--헤드라인 끝--&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;box-sizing: border-box; border-width: 0px 0px 2px 10px; word-spacing: 3px; border-bottom-style: solid; border-bottom-color: #cccccc; padding: 3px 5px; border-left-style: solid; border-left-color: #55555b; margin: 5px 0px; letter-spacing: 1px; line-height: 1.5; border-image: initial;&quot; data-ke-size=&quot;size23&quot;&gt;Intersection Observer 적용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 Intersection Observer를 무한 스크롤 기능을 구현하는데 사용하였다.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 API통신을 해서 가져온 데이터를 원하는 만큼만 지정하여 Intersection Observer를 사용하여 관찰 요소로 등록하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;callback에서 이미 보여진 이미지들은 unobserve()를 통해 관찰 중지시켰다.&lt;/p&gt;
&lt;pre id=&quot;code_1634469208832&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const options = {threshold: 0};
// 관찰 대상이 등록되거나 가시성에 변화가 생길 경우 callback을 실행
const callback = (entreis, observer) =&amp;gt; {
    entreis.forEach((entry) =&amp;gt; {
        if(entry.isIntersecting) {  // 관찰 대상이 보일 경우
            observer.unobserve(entry.target);   // 관찰 대상을 관찰 중지함
            entry.target.src = entry.target.dataset.src;    // entry의 data-src를 img 태그 src에 저장                     
        }
    })
};
const io = new IntersectionObserver(callback, options);
// lazy 클래스를 가지고 있는 element를 모두 가져옴
const lazyImages = Array.from(document.getElementsByClassName(&quot;lazy&quot;));
console.log(&quot;lazyImages: &quot;, lazyImages);        
lazyImages.forEach((image) =&amp;gt; {
    io.observe(image); // 각각의 element를 관찰
})&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;관찰 대상 업데이트&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무한스크롤 기능의 경우 스크롤이 화면 하단에 닿은 경우 다음 데이터셋이 기존 데이터셋에 이어져서 사용자에게 보여져야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 Intersection Observer 인스턴스에 새로운 데이터셋을 관찰 등록해 주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;float: none; clear: none;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;!--헤드라인 끝--&gt;&lt;/p&gt;</description>
      <category>javascript</category>
      <category>Intersection Observer</category>
      <category>javascript</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/309</guid>
      <comments>https://soyeondev.tistory.com/309#entry309comment</comments>
      <pubDate>Sun, 17 Oct 2021 20:28:18 +0900</pubDate>
    </item>
    <item>
      <title>[javascript]  Uncaught TypeError: Cannot read properties of undefined (reading 'appendChild')</title>
      <link>https://soyeondev.tistory.com/307</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dYm1XT/btrmiEJlrX9/dnDXUNm2rFtfi7hXJC2Ff0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dYm1XT/btrmiEJlrX9/dnDXUNm2rFtfi7hXJC2Ff0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dYm1XT/btrmiEJlrX9/dnDXUNm2rFtfi7hXJC2Ff0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdYm1XT%2FbtrmiEJlrX9%2FdnDXUNm2rFtfi7hXJC2Ff0%2Fimg.png&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;484&quot; height=&quot;484&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&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;Vanilla JS로 컴포넌트 방식을 사용하여 웹페이지를 만들던 중&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;appendChild를 통해 부모 컴포넌트에 자식 컴포넌트를 append 하는 과정에서 아래와 같은 에러가 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 글에서 칭하는 컴포넌트는 javascript class를 말한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Uncaught TypeError: Cannot read properties of undefined (reading 'appendChild')&lt;/blockquote&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;해당 에러때문에 부모 컴포넌트에 자식 컴포넌트가 append 되지 않았다.&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드에 적은 대로 $target이 아닌 ${target}으로 넘겨 주어야 했다.&lt;/p&gt;
&lt;pre id=&quot;code_1633928249396&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default class App {
    constructor($target){        
        const searchSection = new SearchSection($target); 
        // $target(x), ${target}(o)
    }
}&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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;$target으로 넘겨주면 안되는 것이 아니라&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;자식컴포넌트에서 받는 방법에 따라 넘겨주는 방법이 달라진다는 것이다.&lt;/span&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;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;부모 컴포넌트에서 ${target}으로 넘겨주면 자식 컴포넌트에서도 ${target}으로 받아야 하며&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;부모 컴포넌트에서 $target으로 넘겨주면 자식 컴포넌트에서도 $target으로 받아주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1633929284762&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 부모 컴포넌트
export default class App {
    constructor($target){
    	// 자식 컴포넌트 생성
        const searchSection = new SearchSection({$target}); // {$target}으로 넘겨줌
    }
}

// 자식 컴포넌트
export default class SearchSection {
	// 자식 컴포넌트 생성자
    constructor({$target}) {  // {$target}으로 받음
        this.section = document.createElement(&quot;section&quot;);
        $target.appendChild(this.section);
        this.render();
    }
    
    render() {
      const wrapper = document.createElement(&quot;div&quot;);
      this.section.appendChild(wrapper);
    }
}&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;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;결론은 일관성있게 적으면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>javascript</category>
      <category>VanillaJS</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/307</guid>
      <comments>https://soyeondev.tistory.com/307#entry307comment</comments>
      <pubDate>Mon, 11 Oct 2021 14:15:55 +0900</pubDate>
    </item>
    <item>
      <title>[javascript] setTimeout과 setInterval의 차이</title>
      <link>https://soyeondev.tistory.com/306</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb5lpT/btrmhJRSV6A/A7BdEdG1Z14luqWFxoOnK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb5lpT/btrmhJRSV6A/A7BdEdG1Z14luqWFxoOnK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb5lpT/btrmhJRSV6A/A7BdEdG1Z14luqWFxoOnK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb5lpT%2FbtrmhJRSV6A%2FA7BdEdG1Z14luqWFxoOnK1%2Fimg.png&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;500&quot; height=&quot;500&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;setTimeout&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동작이 한번 일어남&lt;/li&gt;
&lt;li&gt;실행중 다른 setTimeout으로 인해 함수가 호출되어도 기존에 실행되는 함수에 영향을 주지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631823945993&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let timer = setTimeout(function(){}, time); // 사용 
clearTimeout(timer); // 종료&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;setInterval&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본 동작이 반복적으로 일어남&lt;/li&gt;
&lt;li&gt;실행중 다른 setInterval으로 인해 함수가 호출되면 기존에 실행되는 함수는 종료됨&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1631823990290&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let timer = setInterval(function(){}, time); // 사용
clearTimeout(timer); // 종료&lt;/code&gt;&lt;/pre&gt;</description>
      <category>javascript</category>
      <category>javascript</category>
      <category>setInterval</category>
      <category>setTimeout</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/306</guid>
      <comments>https://soyeondev.tistory.com/306#entry306comment</comments>
      <pubDate>Fri, 17 Sep 2021 06:27:15 +0900</pubDate>
    </item>
    <item>
      <title>[React] useEffect 사용법과 작동방식</title>
      <link>https://soyeondev.tistory.com/305</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bx8WjO/btrmidLYWzc/eJTGeIVgu3G4c6BKMG9kg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bx8WjO/btrmidLYWzc/eJTGeIVgu3G4c6BKMG9kg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bx8WjO/btrmidLYWzc/eJTGeIVgu3G4c6BKMG9kg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbx8WjO%2FbtrmidLYWzc%2FeJTGeIVgu3G4c6BKMG9kg0%2Fimg.png&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;1200&quot; height=&quot;675&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;useEffect(() =&amp;gt; {}, []);&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1631822678003&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; { 
	console.log(&quot;컴포넌트 나타남&quot;); 
    return () =&amp;gt; { console.log(&quot;컴포넌트 사라짐&quot;); }; 
}, []);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트 처음 로드 시&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;31&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IVnUu/btrfgZHcz3E/t7IzSGR0psizJnF6cSwmz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IVnUu/btrfgZHcz3E/t7IzSGR0psizJnF6cSwmz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IVnUu/btrfgZHcz3E/t7IzSGR0psizJnF6cSwmz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIVnUu%2FbtrfgZHcz3E%2Ft7IzSGR0psizJnF6cSwmz0%2Fimg.png&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;741&quot; height=&quot;31&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;31&quot;/&gt;&lt;/span&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;&lt;b&gt;useEffect(() &amp;rArr; {}, [value]);&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1631822740392&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    console.log(&quot;value 컴포넌트 나타남&quot;);
    return () =&amp;gt; {
      console.log(&quot;value 컴포넌트 사라짐&quot;);
    };
  }, [value]);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트 처음 로드 시&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (1).png&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;35&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpeplz/btrflukXdTW/GNks0cAf4aRMsaS0nJrmF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpeplz/btrflukXdTW/GNks0cAf4aRMsaS0nJrmF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpeplz/btrflukXdTW/GNks0cAf4aRMsaS0nJrmF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdpeplz%2FbtrflukXdTW%2FGNks0cAf4aRMsaS0nJrmF0%2Fimg.png&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;656&quot; height=&quot;35&quot; data-filename=&quot;Untitled (1).png&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;35&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트 로드 후 title 수정 시&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (2).png&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;55&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9tCnf/btrficr1o6J/UnwMNtn6KjzIkisAnXOCNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9tCnf/btrficr1o6J/UnwMNtn6KjzIkisAnXOCNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9tCnf/btrficr1o6J/UnwMNtn6KjzIkisAnXOCNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9tCnf%2Fbtrficr1o6J%2FUnwMNtn6KjzIkisAnXOCNk%2Fimg.png&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;653&quot; height=&quot;55&quot; data-filename=&quot;Untitled (2).png&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;55&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>React</category>
      <category>react hook</category>
      <category>useEffect</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/305</guid>
      <comments>https://soyeondev.tistory.com/305#entry305comment</comments>
      <pubDate>Fri, 17 Sep 2021 06:00:58 +0900</pubDate>
    </item>
    <item>
      <title>Server-Side Rendering과 Client-Side Rendering에 대한 개념 이해</title>
      <link>https://soyeondev.tistory.com/303</link>
      <description>&lt;article id=&quot;0fe9ca32-bcda-440f-ba27-8ac03135a20f&quot; class=&quot;page sans Notion_P&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/article&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;pngkit_realistic-spider-web-png_1049388.png&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOeEWs/btrmrud74YC/TOa3EOSckxG7xZzWWhYWz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOeEWs/btrmrud74YC/TOa3EOSckxG7xZzWWhYWz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOeEWs/btrmrud74YC/TOa3EOSckxG7xZzWWhYWz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOeEWs%2Fbtrmrud74YC%2FTOa3EOSckxG7xZzWWhYWz0%2Fimg.png&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;402&quot; height=&quot;402&quot; data-filename=&quot;pngkit_realistic-spider-web-png_1049388.png&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;h2 id=&quot;ead3f962-db71-4ae1-9c3b-40aa0ea8b8f0&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Server-Side Rendering(SSR)이란?&lt;/b&gt;&lt;/h2&gt;
&lt;ul id=&quot;c792921a-9fc9-46f6-957d-3abbbdbe018e&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버에서 사용자에게 보여줄 페이지를 모두 구성해서 사용자에게 페이지를 보여주는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;5c9fb966-a5d7-4f18-b5f8-e554c70d972b&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JSP/Servlet 아키텍처에서 이 방법을 사용하였음&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;a1410ed5-7e39-4a1f-9073-450f3516e747&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;9f6d73d2-45cd-4edf-b626-f7270816df4b&quot; data-ke-size=&quot;size16&quot;&gt;  장점&lt;/p&gt;
&lt;div&gt;
&lt;ul id=&quot;566cd140-af1e-479e-9697-52ff7cd69dc2&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 처음으로 컨텐츠를 볼 수 있는 시점을 앞당길 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;0fba9015-47de-4452-b61e-31b7d7957eed&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;검색엔진최적화 SEO(search engine optimization) 적용이 용이&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;138ba70f-db77-4c64-b5dc-d3d8a703488e&quot; data-ke-size=&quot;size16&quot;&gt;  단점&lt;/p&gt;
&lt;div&gt;
&lt;ul id=&quot;528fef0f-8002-4cbe-b532-8ff8a462de25&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 요청에 관해서 필요한 부분만 수정하는 것이 아니라 완전히 새페이지를 로딩하고 보여줌&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;86048344-f045-4e4c-a60c-7d5627a0472b&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매 요청하다 전체를 로딩해서 CSR보다 비교적 느림&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;26bc3e57-528d-438c-b1f5-f9fcfec2beba&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대역폭(bandwidth) 을 많이 사용함  대역폭(bandwidth) 이란?&lt;/li&gt;
&lt;li&gt;어떤 네트워크 유형에서 최대 데이터 전송 비율(시간당 전송량)을 말하며, 보통 초당 비트수(bps)로 이야기함&lt;/li&gt;
&lt;li id=&quot;bd8d30c0-dce9-4fd5-a897-d83c8a0945d3&quot; data-ke-size=&quot;size16&quot;&gt;많이 사용되는 대역폭의 뜻은 네트워크를 통해 전송되는 데이터의 양&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;e70dd1c3-43af-44c9-9a48-e7b0e44b1fa4&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 경험 좋지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;e57158f4-4fb9-489f-afeb-63708958a369&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;42f15943-fd87-4e54-b138-dc43b82c5265&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Client-Side Rendering(CSR)이란?&lt;/b&gt;&lt;/h2&gt;
&lt;ul id=&quot;86b47d60-9725-4300-8ba3-bac1d972f768&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버가 json파일만 보내주고 html을 그리는 것은 클라이언트 측에서 js가 수행하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;883e0535-8963-4a89-9f7e-92aa19331df1&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버에서 빈 html 문서를 받고 js를 다운로드 받고 js를 작동해서 api로부터 데이터를 가져오고(fetch) 콘텐츠를 보는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;628e3e3c-51b4-4625-a275-bc4bcda1f0af&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;점점 더 복잡해지는 웹페이지를 구현하기 위해 전통적인 방식인 SSR보다는 CSR로 웹을 구현하는 경우가 많아짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;d999af3c-6ffb-4578-9730-383a64aa065e&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;bf9963b4-0b4b-4e57-8cea-bbd234431456&quot; data-ke-size=&quot;size16&quot;&gt;  장점&lt;/p&gt;
&lt;div&gt;
&lt;ul id=&quot;b3c0dc6a-b0e5-40d1-b7cf-7059dd047022&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CSR은 사용자의 행동에 따라 필요한 부분만 다시 읽어들여 SSR보다 조금 더 빠른 렌더링이 가능함&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;2e314e2e-256c-4914-87bb-848492750308&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;page 전체를 요청하지 않고 페이지에 필요한 부분만 변경하기 때문에 모바일 네트워크에서도 빠른 속도로 렌더링 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id=&quot;bf2f5ad5-c489-46e0-848d-86d109f7d709&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;lazy loading 지원  lazy loading 이란?&lt;/li&gt;
&lt;li&gt;페이지 로딩 시 중요하지 않은 리소스의 로딩을 늦추는 기술&lt;/li&gt;
&lt;li id=&quot;b011491f-f50b-47f6-8813-2e1c2c8cd0d4&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;00cfb897-dd9f-45b2-a132-1b51d7bbb117&quot; data-ke-size=&quot;size16&quot;&gt;  단점&lt;/p&gt;
&lt;div&gt;
&lt;ul id=&quot;63f31952-418f-4d17-a947-d8935098bf0a&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Googlebot과 Search console에 검색 노출이 되지 않음 &amp;rarr; 브라우저가 없으므로 html만 가져와서 검색에는 노출되지 않음&lt;/li&gt;
&lt;li&gt;페이지를 읽고 javascript를 읽은 후 화면을 그리는 시간까지 모두 마쳐야 콘텐츠가 사용자에게 보여지기 때문에 초기 구동 속도가 느림&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p id=&quot;be978da7-181b-4dfe-bd37-0358dcd58389&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;letter-spacing: 0px;&quot; href=&quot;https://boltlessengineer.github.io/Notion2Tistory&quot;&gt;Uploaded by Notion2Tistory v1.1.0&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</description>
      <category>web</category>
      <category>client side rendering</category>
      <category>CSR</category>
      <category>server side rendering</category>
      <category>SSR</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/303</guid>
      <comments>https://soyeondev.tistory.com/303#entry303comment</comments>
      <pubDate>Mon, 30 Aug 2021 22:56:16 +0900</pubDate>
    </item>
    <item>
      <title>[React] Create React App 프로젝트 구조</title>
      <link>https://soyeondev.tistory.com/300</link>
      <description>&lt;article id=&quot;2a855fa5-60eb-4e9b-8952-732668d96e44&quot; class=&quot;page sans Notion_P&quot;&gt;
&lt;div class=&quot;page-body&quot;&gt;
&lt;div class=&quot;n2t_comment&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/article&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rF1fD/btrmoqC10f4/cVOnfGBvXjpckOwLqRuLfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rF1fD/btrmoqC10f4/cVOnfGBvXjpckOwLqRuLfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rF1fD/btrmoqC10f4/cVOnfGBvXjpckOwLqRuLfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrF1fD%2FbtrmoqC10f4%2FcVOnfGBvXjpckOwLqRuLfK%2Fimg.png&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;1200&quot; height=&quot;675&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&quot;create-react-app-프로젝트의-구조&quot; data-renderer-start-pos=&quot;1&quot; data-ke-size=&quot;size23&quot;&gt;create-react-app 프로젝트의 구조&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-renderer-start-pos=&quot;28&quot; data-ke-size=&quot;size16&quot;&gt;React 개발환경 설치에서 생성한 create-react-app 프로젝트의 기본 구조에 대해 알아보겠습니다.&lt;/p&gt;
&lt;div data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;145653808&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;471&quot; data-height=&quot;331&quot; data-id=&quot;af0acfce-fb56-4dfa-8c36-60798d6db70c&quot; data-collection=&quot;contentId-145653808&quot; data-file-name=&quot;project-struecture2.PNG&quot; data-file-size=&quot;28070&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;project-struecture2.PNG&quot; data-test-progress=&quot;1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;785&quot; data-origin-height=&quot;551&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MjyC1/btrmjbAcKh7/QHUiWOqkcbgaAUX0yFNAd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MjyC1/btrmjbAcKh7/QHUiWOqkcbgaAUX0yFNAd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MjyC1/btrmjbAcKh7/QHUiWOqkcbgaAUX0yFNAd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMjyC1%2FbtrmjbAcKh7%2FQHUiWOqkcbgaAUX0yFNAd0%2Fimg.png&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;785&quot; height=&quot;551&quot; data-origin-width=&quot;785&quot; data-origin-height=&quot;551&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;create-react-app으로 프로젝트를 생성하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;기본적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #4c9aff;&quot; data-renderer-mark=&quot;true&quot;&gt;node_modules&lt;/span&gt;&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #4c9aff;&quot; data-renderer-mark=&quot;true&quot;&gt;public&lt;/span&gt;&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #4c9aff;&quot; data-renderer-mark=&quot;true&quot;&gt;src&lt;/span&gt;&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #4c9aff;&quot; data-renderer-mark=&quot;true&quot;&gt;.gitignore&lt;/span&gt;&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #4c9aff;&quot; data-renderer-mark=&quot;true&quot;&gt;package-lock.json&lt;/span&gt;&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #4c9aff;&quot; data-renderer-mark=&quot;true&quot;&gt;package.json&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;파일이 생성됩니다.&lt;br /&gt;위부터 차례대로 살펴보겠습니다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;232&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;234&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-emoji-id=&quot;1f4c1&quot; data-emoji-short-name=&quot;:file_folder:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;node_modules&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;설치된 외부 라이브러리가 포함되어 있으며 라이브러리 구조를 파악할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div data-context-id=&quot;145653808&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;197&quot; data-height=&quot;525&quot; data-id=&quot;bd410bf2-5692-4755-9370-163439e896c3&quot; data-collection=&quot;contentId-145653808&quot; data-file-name=&quot;nodemodules.PNG&quot; data-file-size=&quot;39668&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;nodemodules.PNG&quot; data-test-progress=&quot;1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;875&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRYePM/btrmisaNThA/WNYKci6KuBfyrKz9Z4KItk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRYePM/btrmisaNThA/WNYKci6KuBfyrKz9Z4KItk/img.png&quot; data-alt=&quot;node_modules&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRYePM/btrmisaNThA/WNYKci6KuBfyrKz9Z4KItk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRYePM%2FbtrmisaNThA%2FWNYKci6KuBfyrKz9Z4KItk%2Fimg.png&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;329&quot; height=&quot;875&quot; data-origin-width=&quot;329&quot; data-origin-height=&quot;875&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;node_modules&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-emoji-id=&quot;1f4a1&quot; data-emoji-short-name=&quot;:bulb:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; create-react-app을 생성하면 node_modules 폴더에 기본 라이브러리가 추가되어 있습니다. &lt;br /&gt;추가적으로 라이브러리가 필요할 경우 npm install 명령어를 통해 설치할 수 있습니다.&lt;/p&gt;
&lt;div data-level=&quot;1&quot;&gt;
&lt;p data-renderer-start-pos=&quot;440&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;npm package 추가 방법&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div data-level=&quot;1&quot;&gt;
&lt;p data-renderer-start-pos=&quot;462&quot; data-ke-size=&quot;size16&quot;&gt;vs code 사용 시 새 터미널을 열고 아래 명령어를 입력합니다.&lt;br /&gt;터미널 열기 &amp;rarr; vscode 메뉴 - 터미널 - 새 터미널&lt;/p&gt;
&lt;pre id=&quot;code_1638097786353&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install --save 'package name'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div data-level=&quot;1&quot;&gt;
&lt;p data-renderer-start-pos=&quot;570&quot; data-ke-size=&quot;size16&quot;&gt;npm install 명령어 관련 문서 &amp;rarr; &lt;span data-inline-card=&quot;true&quot; data-card-url=&quot;https://docs.npmjs.com/cli/v7/commands/npm-install&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-inline-card=&quot;true&quot; data-card-url=&quot;https://docs.npmjs.com/cli/v7/commands/npm-install&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://docs.npmjs.com/cli/v7/commands/npm-install&quot; data-testid=&quot;inline-card-resolved-view&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;npm-install | npm Docs&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div data-level=&quot;1&quot;&gt;
&lt;p data-renderer-start-pos=&quot;598&quot; data-ke-size=&quot;size16&quot;&gt;위 명령어를 통해 node_modules에 라이브러리를 설치할 수 있습니다 &lt;span data-emoji-id=&quot;1f600&quot; data-emoji-short-name=&quot;:grinning:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-renderer-start-pos=&quot;644&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;646&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-emoji-id=&quot;1f4c1&quot; data-emoji-short-name=&quot;:file_folder:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; public&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자에게 배포할 때 외부적으로 보여지는 대표적인 파일들이 포함되어 있어요.&lt;br /&gt;index.html, logo.png, robots.txt, favicon.ico등 정적 요소들이 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-renderer-start-pos=&quot;766&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-emoji-id=&quot;1f4c1&quot; data-emoji-short-name=&quot;:file_folder:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; src&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;직접 프로그래밍 하는 소스 코드가 포함되어 있습니다.&lt;br /&gt;index.js, App.js, index.css, App.css등 동적 요소들이 포함&lt;br /&gt;대부분 소스 코드 작성은 src 폴더에서 진행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-renderer-start-pos=&quot;891&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;.gitignore&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;git에 추가하고 싶지 않은 파일을 해당 파일에 기재합니다.&lt;br /&gt;일반적으로 node_modules(외부 라이브러리 모음 폴더) .env(설정 파일) 등이 포함됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;145653808&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;766&quot; data-height=&quot;485&quot; data-id=&quot;609cb5ae-55dc-4619-8323-2b9bbdeb2c76&quot; data-collection=&quot;contentId-145653808&quot; data-file-name=&quot;gitignore.PNG&quot; data-file-size=&quot;47279&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;gitignore.PNG&quot; data-test-progress=&quot;1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1276&quot; data-origin-height=&quot;809&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eec31s/btrmifiNQQ0/05DU4O8WCUsBKmM6S2lzM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eec31s/btrmifiNQQ0/05DU4O8WCUsBKmM6S2lzM1/img.png&quot; data-alt=&quot;.gitignore&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eec31s/btrmifiNQQ0/05DU4O8WCUsBKmM6S2lzM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feec31s%2FbtrmifiNQQ0%2F05DU4O8WCUsBKmM6S2lzM1%2Fimg.png&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;1276&quot; height=&quot;809&quot; data-origin-width=&quot;1276&quot; data-origin-height=&quot;809&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;.gitignore&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-media-caption=&quot;true&quot; data-testid=&quot;media-caption&quot; data-renderer-start-pos=&quot;1007&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-renderer-start-pos=&quot;1020&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1022&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-emoji-id=&quot;1f4c4&quot; data-emoji-short-name=&quot;:page_facing_up:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; package.json&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;npm에서 버전을 관리할 때 프로젝트에서 외부적으로 쓰이고 있는 라이브러리 버전 등이 명시되어 있습니다.&lt;/li&gt;
&lt;li&gt;npm install 명령어를 통해 라이브러리를 추가하고 버전을 업데이트 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-layout=&quot;center&quot; data-node-type=&quot;mediaSingle&quot;&gt;
&lt;div&gt;
&lt;div data-context-id=&quot;145653808&quot; data-type=&quot;file&quot; data-node-type=&quot;media&quot; data-width=&quot;747&quot; data-height=&quot;767&quot; data-id=&quot;d8bbd0e5-089d-4a44-a4f0-85fbc306b750&quot; data-collection=&quot;contentId-145653808&quot; data-file-name=&quot;package.PNG&quot; data-file-size=&quot;100432&quot; data-file-mime-type=&quot;image/png&quot; data-alt=&quot;&quot;&gt;
&lt;div data-testid=&quot;media-card-view&quot;&gt;
&lt;div data-testid=&quot;media-file-card-view&quot; data-test-status=&quot;complete&quot; data-test-media-name=&quot;package.PNG&quot; data-test-progress=&quot;1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1245&quot; data-origin-height=&quot;1278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NUc6m/btrmlX2uV3w/HEYD1UQUWr2HB8O03XbBK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NUc6m/btrmlX2uV3w/HEYD1UQUWr2HB8O03XbBK0/img.png&quot; data-alt=&quot;package.json&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NUc6m/btrmlX2uV3w/HEYD1UQUWr2HB8O03XbBK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNUc6m%2FbtrmlX2uV3w%2FHEYD1UQUWr2HB8O03XbBK0%2Fimg.png&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;1245&quot; height=&quot;1278&quot; data-origin-width=&quot;1245&quot; data-origin-height=&quot;1278&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;package.json&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-media-caption=&quot;true&quot; data-testid=&quot;media-caption&quot; data-renderer-start-pos=&quot;1153&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;dependencies (line:5)
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트에 설치된 외부 라이브러리 명세서&lt;br /&gt;&amp;ldquo;@testing-library/jest-dom&amp;rdquo;: &amp;ldquo;^5.14.1&amp;rdquo; 에서 &lt;br /&gt;&amp;ldquo;@testing-library/jest-dom&amp;rdquo;는 패키지명을 의미하며 &amp;ldquo;^5.14.1&amp;rdquo;는 설치된 버전을 의미 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;scripts (line:15)
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;2&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트에서 사용하고 있는 명령어가 포함되어 있음&lt;br /&gt;&amp;ldquo;start&amp;rdquo; : &amp;ldquo;react-scripts start&amp;rdquo;&lt;br /&gt;npm start로 실행할 경우 react-scripts 라이브러리의 start.js가 실행됩니다. &lt;br /&gt;start.js는 src/index.js를 엔트리로 하는 소스 파일을 번들링하고 browser에 띄웁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-renderer-start-pos=&quot;1559&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1561&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-emoji-id=&quot;1f4c4&quot; data-emoji-short-name=&quot;:page_facing_up:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; package-lock.json&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;npm을 사용해서 node_modules 트리나 package.json 파일 수정 시 자동 생성되는 파일&lt;br /&gt;파일이 생성되는 시점의 의존성 트리에 대한 정보를 가지고 있어 외부 라이브러리 버전 충돌 시 &lt;br /&gt;정상작동하였던 시점의 버전이 설치되어 이슈를 방지할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-renderer-start-pos=&quot;1740&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-emoji-id=&quot;1f4cc&quot; data-emoji-short-name=&quot;:pushpin:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 오류 방지를 위해 package.json과 함께 저장소에 해당 파일을 포함해서 커밋해야 합니다.&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1803&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1805&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-emoji-id=&quot;1f4c4&quot; data-emoji-short-name=&quot;:page_facing_up:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;a href=&quot;http://readme.md/&quot; data-renderer-mark=&quot;true&quot;&gt;README.md&lt;/a&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트에 대해 설명하는 내용이 포함되어 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-renderer-start-pos=&quot;1849&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>create react app</category>
      <category>react</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/300</guid>
      <comments>https://soyeondev.tistory.com/300#entry300comment</comments>
      <pubDate>Fri, 13 Aug 2021 03:37:29 +0900</pubDate>
    </item>
    <item>
      <title>[React] Class vs Function component</title>
      <link>https://soyeondev.tistory.com/299</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React는 컴포넌트들로 이루어져 있습니다.&lt;br /&gt;컴포넌트를 만드는 방법은 대표적으로 Class를 사용하는 방법과 Function을 사용하는 방법이 있습니다. &lt;br /&gt;각각의 특징에 대해 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Class 컴포넌트 - React에서 제공하는 컴포넌트를 extends하여 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;385&quot; data-filename=&quot;class_component.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pUEyh/btra10v5HOt/2WMtOvUvo7yCwtZ7G1c1k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pUEyh/btra10v5HOt/2WMtOvUvo7yCwtZ7G1c1k0/img.png&quot; data-alt=&quot;Class component&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pUEyh/btra10v5HOt/2WMtOvUvo7yCwtZ7G1c1k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpUEyh%2Fbtra10v5HOt%2F2WMtOvUvo7yCwtZ7G1c1k0%2Fimg.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;385&quot; data-filename=&quot;class_component.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;Class component&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;4&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Class에 포함되는 데이터가 저장되는 객체입니다.&lt;/li&gt;
&lt;li&gt;state가 변경되면 render()가 호출되면서 컴포넌트를 다시 그립니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;render()&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;4&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;render()는 클래스 컴포넌트에서 반드시&amp;nbsp;정의해야 하는 메서드입니다.&lt;/li&gt;
&lt;li&gt;React에서 정의한 컴포넌트, 여러개의 엘리먼트를 묶어 표시할 수 있는 Fragment등이 render()에 포함됩니다.&lt;/li&gt;
&lt;li&gt;브라우저와 직접적인 상호작용을 하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lifecycle methods&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;lifecycle methods란 컴포넌트가 사용자에게 보여지거나 없어질 때, 업데이트 되었을 때, DOM tree에 올라갔을 때 등의 특정 시점에 따라 코드가 실행되도록 하는 메소드 입니다.&lt;/li&gt;
&lt;/ul&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;자주 사용되는 lifecycle method&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1. 마운트&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트의 인스턴스가 생성되어 DOM 상에 삽입되는 시점&lt;/li&gt;
&lt;li&gt;render()&lt;/li&gt;
&lt;li&gt;componentDidMount()
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트가 마운트된 직후, 즉 트리에 삽입된 직후에 호출됩니다.&lt;/li&gt;
&lt;li&gt;DOM 노드가 있어야 하는 초기화 작업은 이 메서드에서 이루어지면 됩니다. 외부에서 데이터를 불러와야 한다면, 네트워크 요청을 보내기 적절한 위치입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2. 업데이트&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;props 또는 state가 변경되는 시점&lt;/li&gt;
&lt;li&gt;render()&lt;/li&gt;
&lt;li&gt;componentDidUpdate()
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 메소드는 컴포넌트 업데이트가 일어난 직후에 호출됩니다.&lt;/li&gt;
&lt;li&gt;이 메서드는 최초 렌더링에서는 호출되지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3. 마운트 해제&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트가 DOM상에서 제거되는 시점&lt;/li&gt;
&lt;li&gt;componentWillUnmount()
&lt;ul style=&quot;list-style-type: disc;&quot; data-indent-level=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 메소드는 컴포넌트가 마운트 해제되어 DOM에서 제거되기 직전에 호출됩니다.&lt;/li&gt;
&lt;li&gt;메서드 내에서 타이머 제거, 네트워크 요청 취소 요청 등을 수행할 수 있습니다.&lt;span data-emoji-id=&quot;1f4cc&quot; data-emoji-short-name=&quot;:pushpin:&quot; data-emoji-text=&quot; &quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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: #000000;&quot;&gt;  Class 컴포넌트는 언제 사용할까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;컴포넌트가 데이터를 소유하고 있고 주기적으로 업데이트 되어야 한다면 Class를 사용하는 것이 좋습니다.&lt;/span&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;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;Function-컴포넌트&quot; data-renderer-start-pos=&quot;1224&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Function 컴포넌트 - 함수로 컴포넌트를 구현&lt;/b&gt;&lt;/p&gt;
&lt;p data-renderer-start-pos=&quot;1224&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;146&quot; data-filename=&quot;function_component.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/olQcI/btraXW13zSb/yptloh8H3CCxCcVEHDxXS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/olQcI/btraXW13zSb/yptloh8H3CCxCcVEHDxXS0/img.png&quot; data-alt=&quot;Function component&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/olQcI/btraXW13zSb/yptloh8H3CCxCcVEHDxXS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FolQcI%2FbtraXW13zSb%2Fyptloh8H3CCxCcVEHDxXS0%2Fimg.png&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;146&quot; data-filename=&quot;function_component.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;Function component&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fucntion 컴포넌트에는 state와 lifecycle methods가 존재하지 않습니다.&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;&lt;span style=&quot;color: #000000;&quot;&gt;  state와 lifecycle methods가 왜 존재하지 않을까?&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;함수는 한 가지의 기능(업무)을 수행하는 단위이기 때문에 state객체나 method가 존재하지 않습니다.&lt;/span&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;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;그러나,&lt;/span&gt;&lt;br /&gt;&lt;b&gt;React 16.8 version&lt;/b&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;부터 Hook이 도입되면서 Function 컴포넌트에서도 state와 lifecycle method를&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;사용할 수 있게 되었습니다! 이로 인해 Class 컴포넌트에서만 사용할 수 있던 state와 lifecycle method&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;뿐만 아니라 여러 기능들을 사용할 수 있게 되었습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;현재에는 Function 컴포넌트 방식에서는 대부분 Hook을 함께 사용하고 있습니다.&lt;/span&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;&lt;span style=&quot;color: #f89009;&quot;&gt;  &lt;span style=&quot;color: #000000;&quot;&gt;Hook은 왜 도입 되었을까?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;&amp;nbsp;기존 Class 컴포넌트에서 가능한 기능들을 가능할 수 있도록 해줍니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;&amp;nbsp;Class는 Function 컴포넌트보다 어렵습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;&amp;nbsp;class의 경우 this가 필요하여 데이터 바인딩 이슈가 발생할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;&amp;nbsp;Functional programming이 트렌드화 되면서 React에서도 적용을 시도하였습니다.&lt;/span&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;&lt;span style=&quot;color: #f89009;&quot;&gt;  &lt;span style=&quot;color: #000000;&quot;&gt;Class 컴포넌트 대신 Hook만 배워도 될까?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;&amp;nbsp;Hook이 많은 장점을 가지고 있지만 이미 시장에 나와있는 상품들 중에는 Class로 작성된 것들이 많기 때문에&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;&amp;nbsp;Class형도 숙지하는 것이 좋습니다.&lt;/span&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;&lt;span style=&quot;background-color: #fcfcfc; color: #f89009;&quot;&gt; &lt;span style=&quot;color: #000000;&quot;&gt; Function 컴포넌트는 언제 사용하나요?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666;&quot;&gt;컴포넌트에 state가 없고 항상 정적으로 데이터가 표기된다면 간단하게 Function방식을 사용하는 것이 좋습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>React</category>
      <category>Class compoment</category>
      <category>component</category>
      <category>Function component</category>
      <category>react</category>
      <author>tonirr</author>
      <guid isPermaLink="true">https://soyeondev.tistory.com/299</guid>
      <comments>https://soyeondev.tistory.com/299#entry299comment</comments>
      <pubDate>Mon, 2 Aug 2021 21:26:32 +0900</pubDate>
    </item>
  </channel>
</rss>