<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>맨동이</title>
    <link>https://gusehd66.tistory.com/</link>
    <description>IT, 웹개발, 프론트엔드 등 자기계발을 위한 블로그입니다.</description>
    <language>ko</language>
    <pubDate>Sun, 26 Jul 2026 04:16:00 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>맨동</managingEditor>
    <item>
      <title>[AI] openai.error.RateLimitError: You exceeded your current quota, please check your plan and billing details.</title>
      <link>https://gusehd66.tistory.com/entry/AI-openaierrorRateLimitError-You-exceeded-your-current-quota-please-check-your-plan-and-billing-details</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;유튜브 영상보면서 colab으로 실습좀 해보려했더니 ..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: start;&quot;&gt;Error Code 429 - You exceeded your current quota, please check your plan and billing details.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 에러가 떴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;냅다 복사해서 검색해보니 나같은 사람이 많았고, OpenAi Help Center 에서도 설명이 나와있었다.&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;결론부터 말하면 아래 openai 홈페이지에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;credit card를 등록한 사용자만 사용&lt;/b&gt;&lt;/span&gt;할 수있다는것.&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;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;credit card를 등록하기전 api key말고&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;카드 등록후 발급한 api key를 사용&lt;/b&gt;&lt;/span&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;&lt;a href=&quot;https://platform.openai.com/account/billing/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://platform.openai.com/account/billing/overview&lt;/a&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;609&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIVSNa/btsF12bX8hu/uT9L7nkAsuoqGCSejjFJk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIVSNa/btsF12bX8hu/uT9L7nkAsuoqGCSejjFJk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIVSNa/btsF12bX8hu/uT9L7nkAsuoqGCSejjFJk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIVSNa%2FbtsF12bX8hu%2FuT9L7nkAsuoqGCSejjFJk1%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;609&quot; height=&quot;277&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;277&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;&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;b&gt;카드 등록할때 5달러 내라고 하는데 실제로 청구되진 않는것 같다.. 일단 쓰자&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;743&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MzoMo/btsF1cTXyjS/Q6nYRQmMu32IawkIylEGwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MzoMo/btsF1cTXyjS/Q6nYRQmMu32IawkIylEGwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MzoMo/btsF1cTXyjS/Q6nYRQmMu32IawkIylEGwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMzoMo%2FbtsF1cTXyjS%2FQ6nYRQmMu32IawkIylEGwk%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;743&quot; height=&quot;337&quot; data-origin-width=&quot;743&quot; data-origin-height=&quot;337&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>AI</category>
      <category>AI</category>
      <category>ChatGPT</category>
      <category>Langchain</category>
      <category>openai</category>
      <category>openai.error.RateLimitError</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/86</guid>
      <comments>https://gusehd66.tistory.com/entry/AI-openaierrorRateLimitError-You-exceeded-your-current-quota-please-check-your-plan-and-billing-details#entry86comment</comments>
      <pubDate>Fri, 22 Mar 2024 21:51:14 +0900</pubDate>
    </item>
    <item>
      <title>[Angular] @ViewChild</title>
      <link>https://gusehd66.tistory.com/entry/Angular-ViewChild</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@ViewChild의&amp;nbsp;정의&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@ViewChild는&amp;nbsp;Angular의&amp;nbsp;코어&amp;nbsp;라이브러리에서&amp;nbsp;제공하는&amp;nbsp;데코레이터&amp;nbsp;중&amp;nbsp;하나로,&amp;nbsp;&lt;b&gt;자식&amp;nbsp;컴포넌트나&amp;nbsp;DOM&amp;nbsp;요소에&amp;nbsp;직접&amp;nbsp;접근할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;기능을&amp;nbsp;제공&lt;/b&gt;합니다.&amp;nbsp;이&amp;nbsp;데코레이터를&amp;nbsp;활용함으로써,&amp;nbsp;우리는&amp;nbsp;컴포넌트의&amp;nbsp;뷰에&amp;nbsp;위치한&amp;nbsp;자식&amp;nbsp;요소들에&amp;nbsp;대한&amp;nbsp;직접적인&amp;nbsp;제어를&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있게&amp;nbsp;되는데,&amp;nbsp;이는&amp;nbsp;웹&amp;nbsp;애플리케이션의&amp;nbsp;동적인&amp;nbsp;행동을&amp;nbsp;쉽게&amp;nbsp;구현하는&amp;nbsp;데&amp;nbsp;큰&amp;nbsp;도움이&amp;nbsp;됩니다.&amp;nbsp;&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;&lt;b&gt;@ViewChild의&amp;nbsp;사용&amp;nbsp;방법&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1706784069210&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// @ViewChild(탐색 대상 클래스명) 프로퍼티명: 탐색 대상 클래스명;

@ViewChild(Pane)
  set pane(v: Pane) {
    setTimeout(() =&amp;gt; {
      this.selectedPane = v.id;
    }, 0);
  }
  
  @Component({
    selector: 'test',
    template: `               
          &amp;lt;textbox class=&quot;input&quot; #AccountInput placeholder=&quot;'Input Value.'&quot; [(value)]=&quot;account&quot;&amp;gt;&amp;lt;/textbox&amp;gt;
	`,
    styleUrls: ['./login.component.scss'],
})
export class TESTComponent implements OnDestroy, AfterViewInit {
	...
    pubic inputText:string = '';
    @ViewChild('AccountInput')
    set accountTextBox(v: TextBox) {
      	this.inputText = v.value;
      }
  }
    ... 
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위의&amp;nbsp;코드는&amp;nbsp;ChildComponent라는&amp;nbsp;이름의&amp;nbsp;자식&amp;nbsp;컴포넌트에&amp;nbsp;child라는&amp;nbsp;참조&amp;nbsp;이름을&amp;nbsp;부여하는&amp;nbsp;것을&amp;nbsp;나타냅니다.&amp;nbsp;이로써&amp;nbsp;우리는&amp;nbsp;이&amp;nbsp;child라는&amp;nbsp;참조를&amp;nbsp;통해&amp;nbsp;ChildComponent의&amp;nbsp;메서드를&amp;nbsp;호출하거나,&amp;nbsp;프로퍼티를&amp;nbsp;변경하는&amp;nbsp;등의&amp;nbsp;작업을&amp;nbsp;수행할&amp;nbsp;수&amp;nbsp;있게&amp;nbsp;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Template에 있는 AccountInput라는 ID로 할당된 Template 레퍼런스를 매개변수로 받아 set을 통해 변수에 값을 할당하는 등 원하는 작업을 할 수 있습니다.&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;&lt;b&gt;@ViewChild의&amp;nbsp;생명주기&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@ViewChild는&amp;nbsp;Angular의&amp;nbsp;컴포넌트&amp;nbsp;생명주기에&amp;nbsp;따라&amp;nbsp;값이&amp;nbsp;설정됩니다.&amp;nbsp;일반적으로&amp;nbsp;ngOnInit&amp;nbsp;단계에서는&amp;nbsp;아직&amp;nbsp;@ViewChild가&amp;nbsp;설정되지&amp;nbsp;않았기&amp;nbsp;때문에&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;없습니다.&amp;nbsp;그러나&amp;nbsp;ngAfterViewInit&amp;nbsp;단계부터는&amp;nbsp;사용이&amp;nbsp;가능하며,&amp;nbsp;이&amp;nbsp;시점부터&amp;nbsp;자식&amp;nbsp;요소에&amp;nbsp;대한&amp;nbsp;조작이&amp;nbsp;가능해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;@ViewChild와&amp;nbsp;@ViewChildren의&amp;nbsp;차이점&lt;/b&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Angular에서는&amp;nbsp;@ViewChild&amp;nbsp;외에도&amp;nbsp;@ViewChildren이라는&amp;nbsp;데코레이터를&amp;nbsp;제공합니다.&amp;nbsp;@ViewChild는&amp;nbsp;첫번째&amp;nbsp;자식&amp;nbsp;요소만을&amp;nbsp;가져오는&amp;nbsp;반면,&amp;nbsp;@ViewChildren은&amp;nbsp;모든&amp;nbsp;자식&amp;nbsp;요소를&amp;nbsp;가져옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Web</category>
      <category>@viewchild</category>
      <category>angular</category>
      <category>viewchild</category>
      <category>앵귤러</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/85</guid>
      <comments>https://gusehd66.tistory.com/entry/Angular-ViewChild#entry85comment</comments>
      <pubDate>Thu, 1 Feb 2024 20:05:34 +0900</pubDate>
    </item>
    <item>
      <title>[Web] 웹 표준과 웹 접근성</title>
      <link>https://gusehd66.tistory.com/entry/Web-%EC%9B%B9-%ED%91%9C%EC%A4%80%EA%B3%BC-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;웹 표준&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹상에서 지켜야하는 표준 규칙.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;W3C에서 지정한 표준안을 지키는 사이트가 웹 표준을 잘 준수한 사이트입니다.&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;b&gt;예:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;문서 구조&lt;/span&gt;&lt;/b&gt;: 해당 페이지의 기본 정보를 포함하는 헤드와 본문을 포함하는 바디를 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;표준 엘리먼트 사용&lt;/b&gt;:&lt;/span&gt; 모든 요소는 시작 태그와 종료태그가 함께 있어야 하며, 모든 요소와 속성은 소문자여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;인코딩 선언&lt;/span&gt;&lt;/b&gt;: 모든 HTML&amp;nbsp; 문서는 기본 인코딩으로 'utf-8'을 사용한다.&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;웹 접근성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 접근성은 장애인과 비장애인 모두 웹사이트를 사용할 수 있도록 하는 방식을 가리킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;한국형 웹 컨텐츠 접근성 지침으로 2.0버전이 있으며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;웹 접근성 표준은 원칙, 지침, 검사 항목 3단계로 구성되어 있습니다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원칙은 웹 접근성 제고를 위한 4가지 원칙, 지침은 각 원칙을 준수하기 위한 13개 지침, 검사는 해당 지침의 준수 여부를 확인하느 22개의 검사 항목으로 구성되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 77px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 22.1705%; height: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;항목&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 44.4961%; height: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;내용&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 10px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;예제&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 22.1705%; height: 17px;&quot;&gt;인식의 용이성&lt;/td&gt;
&lt;td style=&quot;width: 44.4961%; height: 17px;&quot;&gt;텍스트가 아닌 콘텐츠는 그 의미나 용도를 이해할 수 있게 적절한 대체 텍스트를 제공해야 합니다.&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;img 태그의 alt 속성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 16px;&quot;&gt;
&lt;td style=&quot;width: 22.1705%; height: 16px;&quot;&gt;운용의 용이성&lt;/td&gt;
&lt;td style=&quot;width: 44.4961%; height: 16px;&quot;&gt;모든 기능은 키보드만으로도 사용 가능해야 합니다.&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 16px;&quot;&gt;a, button, input 등의 태그 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 22.1705%; height: 34px;&quot; rowspan=&quot;2&quot;&gt;이해의 용이성&lt;/td&gt;
&lt;td style=&quot;width: 44.4961%; height: 17px;&quot;&gt;입력 서식은 시각 장애인 등이 해당 서식을 이해할 수 있도록 레이블을 제공해야 합니다.&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;label 태그&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 44.4961%; height: 17px;&quot;&gt;레이블을 제공할 수 없는 입력 서식에는 title 을 제공합니다.&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;input의 title 속성&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;</description>
      <category>Web</category>
      <category>web</category>
      <category>웹</category>
      <category>웹접근성</category>
      <category>웹표준</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/84</guid>
      <comments>https://gusehd66.tistory.com/entry/Web-%EC%9B%B9-%ED%91%9C%EC%A4%80%EA%B3%BC-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1#entry84comment</comments>
      <pubDate>Mon, 18 Jul 2022 21:35:26 +0900</pubDate>
    </item>
    <item>
      <title>[Git] git reset과 git checkout의 차이점</title>
      <link>https://gusehd66.tistory.com/entry/Git-git-reset%EA%B3%BC-git-checkout%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
      <description>&lt;h2 id=&quot;1-수정사항-되돌리기&quot; data-ke-size=&quot;size26&quot;&gt;1. 수정사항 되돌리기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 작성하면서 여러 군데에 로그를 출력하는 코드를 삽입했다던가,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 환경에서만 작동하는 코드를 임시로 넣었을 때 그 내용을 되돌리는 경우에는&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; checkout&lt;/b&gt;&lt;/span&gt;을 사용합니다.&lt;br /&gt;기존 커밋과 비교해서 직접 수정해도 되지만, 수정한 내용이 많을 경우에 사용하면 편리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;새롭게 추가된 파일, 다시 말하자면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Untracked file&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;의 경우에는 checkout을 하더라도 삭제되지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;2-Unstaging&quot; data-ke-size=&quot;size26&quot;&gt;2. Unstaging&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;add&lt;span&gt;&amp;nbsp;&lt;/span&gt;명령어로 stage 상태로 만든 파일을 다시 unstage 상태로 만드는 방법은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;reset&lt;/b&gt; &lt;/span&gt;명령어로 unstage 상태로 만들수있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;3-Commit-되돌리기&quot; data-ke-size=&quot;size26&quot;&gt;3. Commit 되돌리기&lt;/h2&gt;
&lt;h3 id=&quot;3-1-reset&quot; data-ke-size=&quot;size23&quot;&gt;3.1. reset&lt;/h3&gt;
&lt;h4 id=&quot;3-1-1-mixed&quot; data-ke-size=&quot;size20&quot;&gt;3.1.1. mixed&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reset은 말그대로 커밋을 되돌리는 명령어입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 추가하고 커밋한 후,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reset&lt;span&gt;&amp;nbsp;&lt;/span&gt;명령어 뒤에 커밋 아이디를 입력하면 해당 커밋으로 되돌아갈 수 있습니다.&lt;br /&gt;git log를 보면 돌아온 커밋&lt;span&gt;&amp;nbsp;&lt;/span&gt;이후의 커밋들이 전부 사라진 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 추가한 파일들은 그대로 존재합니다.&lt;br /&gt;status를 보면 어떻게 된 상태인지를 파악할 수 있는데요,&lt;br /&gt;기본적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;reset을 사용하게 되면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;해당 커밋 이후의 내용은 현재 내가 수정한 것처럼 내용 자체는 남아있게 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reset을 사용할 때 아무 옵션을 주지 않으면&lt;span&gt;&amp;nbsp;&lt;/span&gt;--mixed&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션이 기본적으로 들어가게 되는데 그 동작이 위의 내용과 같습니다.&lt;/p&gt;
&lt;h4 id=&quot;3-1-2-soft&quot; data-ke-size=&quot;size20&quot;&gt;3.1.2. soft&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일들을 추가하고 커밋한 후 reset --soft로 soft 옵션을 걸게되면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;log상으로는 동일하게 커밋 내용이 사라지지만 리셋 이후의 수정한 내용 또한 동일하게 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 해당 내용들이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;staging area에 존재하게 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;h4 id=&quot;3-1-3-hard&quot; data-ke-size=&quot;size20&quot;&gt;3.1.3. hard&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 파일들을 추가하고 커밋한 상태에서 --hard 옵션으로 reset을 실행하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 커밋이 리셋되면서 &lt;b&gt;해당 커밋 이후의 내용을 모조리 날려버립니다.&lt;/b&gt;&lt;/p&gt;
&lt;h4 id=&quot;3-1-4-정리&quot; data-ke-size=&quot;size20&quot;&gt;3.1.4. 정리&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;reset은 두 가지 용도로 사용 가능합니다. unstaging이나 commit reset.&lt;/li&gt;
&lt;li&gt;commit reset의 경우 세 가지 옵션이 존재하며(mixed, soft, hard), default는 mixed입니다.&lt;br /&gt;공통적으로 리셋시킨 커밋 이후의 커밋은 사라지게 됩니다.&lt;/li&gt;
&lt;li&gt;mixed option : 리셋 이후의 커밋 내용들이 unstage 상태로 존재&lt;/li&gt;
&lt;li&gt;soft option : 리셋 이후의 커밋 내용들이 stage 상태로 존재&lt;/li&gt;
&lt;li&gt;hard option : 리셋 이후의 커밋 내용들이 전부 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;3-2-revert&quot; data-ke-size=&quot;size23&quot;&gt;3.2. revert&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 커밋만 되돌리고 싶은 경우에 사용하는 것이 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;revert&lt;/span&gt; &lt;/b&gt;명령어 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;origin&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;커밋을 기준으로 file1을 추가하고 커밋, file2를 추가하고 커밋했을 때&lt;br /&gt;이 상태에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;file1을 추가한 커밋&lt;/b&gt;만 되돌리고 싶다면&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;git revert [되돌릴 커밋] 을 입력하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 revert commit 창이 뜨고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;revert message&lt;/b&gt;를 입력합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그를 보면&lt;span&gt;&amp;nbsp;&lt;/span&gt;reset과는 다르게 커밋이 사라지지 않고, 방금 전에 입력한 메시지로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;새로운 커밋&lt;/b&gt;이 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 상태를 보면 file1이 사라진 것을 알 수 있습니다.&lt;br /&gt;즉,&lt;span&gt;&amp;nbsp;&lt;/span&gt;revert&lt;span&gt;&amp;nbsp;&lt;/span&gt;명령어는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;해당 커밋을 취소하는 커밋을 생성하는 것&lt;/b&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;이전 커밋을 취소하고 수정 후에 다시 반영하고 싶은 경우에는 -n 옵션을 사용하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-n&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션을 사용하게 되면 바로 커밋 메시지를 작성하는 창으로 전환되지 않고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;취소한 변경사항이 stage area에 존재&lt;/b&gt;하게 됩니다.&lt;br /&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;마지막으로 reset 과 checkout의 차이를 짚어보자면&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 60px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;reset&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;checkout&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;HEAD가 가리키던 브랜치가 다른 커밋을 가르키도록 한다.&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;HEAD 자체가 다른 커밋이나 브랜치를 가르키도록 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;HEAD도 결국 간접적으로 다른 커밋을 가르키게 되는 효과가 생긴다.&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;브랜치를 통하지 않고, 커밋을 직접적으로 가르키는 HEAD를 Detached HEAD라고 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Git</category>
      <category>Git</category>
      <category>git checkout</category>
      <category>git reset</category>
      <category>git revert</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/83</guid>
      <comments>https://gusehd66.tistory.com/entry/Git-git-reset%EA%B3%BC-git-checkout%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90#entry83comment</comments>
      <pubDate>Mon, 28 Mar 2022 22:55:29 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] this 간단 정리</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-this-%EA%B0%84%EB%8B%A8-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;자바스크립트 this&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체는 상태를 나타내는 프로퍼티와 동작을 나타내는 메서드를 하나의 논리적인 단위로 묶은 복합적인 자료구조이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;자바스크립트는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 특수한 식별자 this 를 제공한다.&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;b&gt;this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수이다.&lt;/b&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;this는 자바스크립트 엔진에 의해 암묵적으로 생성되며, 코드 어디서든 참조할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수를 호출하면 arguments 객체와 this가 암묵적으로 생성된다.&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;여기서 this가 가리키는 값, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;this 바인딩은 함수 호출 방식에 의해 동적으로 결정이 된다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;바인딩이란 식별자와 값을 연결하는 과정을 의미한다. 예를 들어, 변수 선언은 변수 이름과 확보된 메모리 공간의 주소를 바인딩하는 것이다. this 바인딩은 this와 this가 가리킬 객체를 바인딩하는 것이다.&lt;/b&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&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;b&gt;정리 :&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 100px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;함수 호출 방식&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;&amp;nbsp;this 바인딩&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;일반 함수 호출&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;전역 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;메서드 호출&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;메서드를 호출한 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;생성자 함수 호출&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;생성자 함수가 생성할 인스턴스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;apply/call/bind 메서드에 의한 간접 호출&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;메서드에 첫번째 인수로 전달한 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 함수 내부의 this는 strict 모드에서 &lt;u&gt;undefined가 바인딩된다.&lt;/u&gt; 일반 함수에서 this를 참조할 필요가 없기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;일반 함수로 호출된 모든 함수(중첩 함수, 콜백 함수 포함) 내부의 this에는 전역 객체가 바인딩된다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>this</category>
      <category>자바스크립트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/82</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-this-%EA%B0%84%EB%8B%A8-%EC%A0%95%EB%A6%AC#entry82comment</comments>
      <pubDate>Wed, 16 Mar 2022 20:33:56 +0900</pubDate>
    </item>
    <item>
      <title>[TypeScript] Property '...' does not exist on type 'DefaultRootState' - Redux type Error</title>
      <link>https://gusehd66.tistory.com/entry/TypeScript-Property-does-not-exist-on-type-DefaultRootState-Redux-type-Error</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;95&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uxbgj/btrvkGwKPKr/vAETHQPCLCrjzKjrhPzfjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uxbgj/btrvkGwKPKr/vAETHQPCLCrjzKjrhPzfjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uxbgj/btrvkGwKPKr/vAETHQPCLCrjzKjrhPzfjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuxbgj%2FbtrvkGwKPKr%2FvAETHQPCLCrjzKjrhPzfjK%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;459&quot; height=&quot;95&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;95&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Property 'nav' does not exist on type 'DefaultRootState'&lt;/span&gt;&lt;/b&gt;&lt;/h2&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;React + TS + redux 사용중&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DefaultRootState 값에 찾는 값이 없다는 에러를 발견했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결방법은&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;rootReducer가 있는 곳에 RootState 타입을 선언하고 state에게 알려주면 해결완료!&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;export type RootState = ReturnType&amp;lt;typeof rootReducer&amp;gt;&lt;/code&gt;&lt;/pre&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;452&quot; data-origin-height=&quot;42&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caUWlt/btrvhNXsUrR/1cOKBBzT8m2xMhxbr8k9F1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caUWlt/btrvhNXsUrR/1cOKBBzT8m2xMhxbr8k9F1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caUWlt/btrvhNXsUrR/1cOKBBzT8m2xMhxbr8k9F1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaUWlt%2FbtrvhNXsUrR%2F1cOKBBzT8m2xMhxbr8k9F1%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;452&quot; height=&quot;42&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;42&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;19&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQG4hJ/btru5cR1Brp/tKm898VqRNFqxwHCZ8gKb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQG4hJ/btru5cR1Brp/tKm898VqRNFqxwHCZ8gKb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQG4hJ/btru5cR1Brp/tKm898VqRNFqxwHCZ8gKb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQG4hJ%2Fbtru5cR1Brp%2FtKm898VqRNFqxwHCZ8gKb1%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;486&quot; height=&quot;19&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;19&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>TypeScript</category>
      <category>DefaultRootState</category>
      <category>Error</category>
      <category>redux type</category>
      <category>typescript</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/81</guid>
      <comments>https://gusehd66.tistory.com/entry/TypeScript-Property-does-not-exist-on-type-DefaultRootState-Redux-type-Error#entry81comment</comments>
      <pubDate>Sun, 6 Mar 2022 18:57:36 +0900</pubDate>
    </item>
    <item>
      <title>[Webpack] webpack5로 webpack-dev-server 사용하기</title>
      <link>https://gusehd66.tistory.com/entry/Webpack-webpack5%EB%A1%9C-webpack-dev-server-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;유데미 강의를 보며 typescript에 webpack을 적용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 강의는 webpack 4버전으로 녹화된 강의였고..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 webpack5로 설정을 하던중 다른 부분이 있어 기록으로 남길겸 글을 남기게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;webpack-dev-server ?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;빠른 실시간 리로드 기능을 갖춘 개발 서버로서&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;디스크에 저장되지 않는 메모리 컴파일을 사용하기 때문에 컴파일 속도가 빨라지고,&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;webpack.config.js파일에 devServer 옵션으로 커스터마이징도 가능하다.&lt;/b&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;22년 3월 기준 npm install 버전과 나의 프로젝트 구성 목록이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;262&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mjgBB/btruQkCLM4V/xXjPku2KWPg2S4ysPUKPPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mjgBB/btruQkCLM4V/xXjPku2KWPg2S4ysPUKPPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mjgBB/btruQkCLM4V/xXjPku2KWPg2S4ysPUKPPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmjgBB%2FbtruQkCLM4V%2FxXjPku2KWPg2S4ysPUKPPK%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;262&quot; height=&quot;136&quot; data-origin-width=&quot;262&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;291&quot; data-origin-height=&quot;383&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqYiVB/btruXaMaQY2/dXTNS4iURUpEqawYRHID01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqYiVB/btruXaMaQY2/dXTNS4iURUpEqawYRHID01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqYiVB/btruXaMaQY2/dXTNS4iURUpEqawYRHID01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqYiVB%2FbtruXaMaQY2%2FdXTNS4iURUpEqawYRHID01%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;291&quot; height=&quot;383&quot; data-origin-width=&quot;291&quot; data-origin-height=&quot;383&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;&lt;b&gt;npm start&lt;/b&gt;로 실행했을 시에는 webpack-dev-server가 실행되게 하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;build&lt;/b&gt;시에는 따로 build용 config 파일을 만들어 적용해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(webpack 4버전에서는 &quot;&lt;b&gt;webpack-dev-server&lt;/b&gt;&quot; 를 사용하여 실행하였지만, 5버전에서는 &quot;&lt;span&gt;&lt;b&gt;webpack server&lt;/b&gt;&quot; 명령어로 서버를 실행할 수 있다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;42&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2lOR2/btruRMZ9Y4g/qamaB6IUuJym6gfN5a81ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2lOR2/btruRMZ9Y4g/qamaB6IUuJym6gfN5a81ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2lOR2/btruRMZ9Y4g/qamaB6IUuJym6gfN5a81ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2lOR2%2FbtruRMZ9Y4g%2FqamaB6IUuJym6gfN5a81ak%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;407&quot; height=&quot;42&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;42&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;npm start시 실행되는 개발서버에 대한 config 파일을 살펴보면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRaDea/btruYSxuTNT/iw7NRESjbbDJmWAaOacc7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRaDea/btruYSxuTNT/iw7NRESjbbDJmWAaOacc7K/img.png&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;457&quot; data-is-animation=&quot;false&quot; style=&quot;width: 59.9492%; margin-right: 10px;&quot; data-widthpercent=&quot;60.65&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRaDea/btruYSxuTNT/iw7NRESjbbDJmWAaOacc7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRaDea%2FbtruYSxuTNT%2Fiw7NRESjbbDJmWAaOacc7K%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;357&quot; height=&quot;457&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HLMU8/btruZPnMIke/g2WBwdBCEM6pycrowDCml1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HLMU8/btruZPnMIke/g2WBwdBCEM6pycrowDCml1/img.png&quot; data-origin-width=&quot;376&quot; data-origin-height=&quot;742&quot; style=&quot;width: 38.888%;&quot; data-widthpercent=&quot;39.35&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HLMU8/btruZPnMIke/g2WBwdBCEM6pycrowDCml1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHLMU8%2FbtruZPnMIke%2Fg2WBwdBCEM6pycrowDCml1%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;376&quot; height=&quot;742&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;왼쪽은 webpack 4 오른쪽은&amp;nbsp; webpack 5&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4버전에서는 devServer에 대한 설정을 명시하지 않아도 자동으로 서버가 index.html&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 찾아 실행하였지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5버전에서는 &lt;span style=&quot;color: #ee2323;&quot;&gt;Cannot get/&lt;/span&gt; 에러가 발생하고 index.html 파일을 찾지 못하여서 따로 devServer 설정을 했다.&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;u&gt;&lt;b&gt;webpack-dev-server는 기본적으로 번들링 된 파일을 생성하지 않으므로 번들링된 결과물을 메모리에 저장하고, 메모리에 저장된 번들을 브라우저에 넘겨주는 방식이다.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;따로 output으로 dist 경로에 추출한 파일을 변경하여도, decServer에 변경사항이 적용되지 않는다.&lt;/b&gt;&lt;/u&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;하지만 pulicPath를 지정해서 기본적으로 메모리상에 있을 dist폴더를 만들고 참조가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 dist 폴더에 bundle.js라는 파일명으로 번들링시키고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;indexl.html 파일에서 bundle.js 파일을 참조하면된다.&lt;/p&gt;
&lt;pre id=&quot;code_1646233142029&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script type=&quot;module&quot; src=&quot;/dist/bundle.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 터미널에서 npm run start 명령어 실행후 localhost:8080 포트로 접속하면 내가 원하는대로 페이지가 뜬다.&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;production용 webpack config 파일은 약간 다르다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mlmSC/btruQlaBOfw/ureE5675l7gwQnNBZxV0g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mlmSC/btruQlaBOfw/ureE5675l7gwQnNBZxV0g1/img.png&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;512&quot; style=&quot;width: 52.7147%; margin-right: 10px;&quot; data-widthpercent=&quot;53.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mlmSC/btruQlaBOfw/ureE5675l7gwQnNBZxV0g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmlmSC%2FbtruQlaBOfw%2FureE5675l7gwQnNBZxV0g1%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;466&quot; height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wlru1/btruXZwHGg1/p8rLspIpdiQbe91GZVbkQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wlru1/btruXZwHGg1/p8rLspIpdiQbe91GZVbkQ0/img.png&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;437&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;46.67&quot; style=&quot;width: 46.1225%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wlru1/btruXZwHGg1/p8rLspIpdiQbe91GZVbkQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwlru1%2FbtruXZwHGg1%2Fp8rLspIpdiQbe91GZVbkQ0%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;348&quot; height=&quot;437&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;왼쪽은 webpack 4 오른쪽은&amp;nbsp; webpack 5&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4버전에서는 컴파일시 dist 폴더를 초기화 하기위해 따로 플러그인을 설정하였지만 5버전에서는 output에 바로 설정할 수 있었다.&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;config 설정을 저장하고 npm run build 를 실행하면&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;dist 폴더에 직접 bundle.js 파일이 생성되니 눈으로 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 루트폴더에 있는 index.html 을 라이브서버로 실행하면 페이지가 잘 출력된다.&lt;/p&gt;</description>
      <category>Bundler</category>
      <category>cannot get/</category>
      <category>webpack</category>
      <category>webpack-dev-server</category>
      <category>webpack5</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/80</guid>
      <comments>https://gusehd66.tistory.com/entry/Webpack-webpack5%EB%A1%9C-webpack-dev-server-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0#entry80comment</comments>
      <pubDate>Thu, 3 Mar 2022 00:17:09 +0900</pubDate>
    </item>
    <item>
      <title>[React] Component 외부 vs 내부 변수 선언</title>
      <link>https://gusehd66.tistory.com/entry/React-Component-%EC%99%B8%EB%B6%80-vs-%EB%82%B4%EB%B6%80-%EB%B3%80%EC%88%98-%EC%84%A0%EC%96%B8</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Component&amp;nbsp;외부&amp;nbsp;vs&amp;nbsp;내부&amp;nbsp;변수&amp;nbsp;선언&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React를 사용하다 문득 Component 외부에서 변수 나 함수를 선언하는 것과 내부에서 선언하는 것의 차이가 궁금해져서 구글링을 하게되었다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;a href=&quot;https://stackoverflow.com/questions/62848106/functional-component-write-functions-inside-or-outside-the-component&quot;&gt;https://stackoverflow.com/questions/62848106/functional-component-write-functions-inside-or-outside-the-component&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1645537926133&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Functional Component: Write functions inside or outside the component?&quot; data-og-description=&quot;I often wrote functional components following a 'Class architecture' where all my function that concern the component are written inside of it like a method in a class. For example, I have here a&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/62848106/functional-component-write-functions-inside-or-outside-the-component&quot; data-og-url=&quot;https://stackoverflow.com/questions/62848106/functional-component-write-functions-inside-or-outside-the-component&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bRG8Ar/hyNvg1E1ZL/BI7po2MWVMkZbOsR2Tx6x0/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/62848106/functional-component-write-functions-inside-or-outside-the-component&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/62848106/functional-component-write-functions-inside-or-outside-the-component&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bRG8Ar/hyNvg1E1ZL/BI7po2MWVMkZbOsR2Tx6x0/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Functional Component: Write functions inside or outside the component?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I often wrote functional components following a 'Class architecture' where all my function that concern the component are written inside of it like a method in a class. For example, I have here a&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컴포넌트 외부 let 사용 ?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 검색을 하다 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;컴포넌트 외부에서 let은 절대 사용하지 말아야 한다는 것&lt;/b&gt;&lt;/span&gt;을 알게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;s&gt;(당연하게 그러고 있었지만 이유는 딱 정의할 수 없었다.)&lt;/s&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;컴포넌트를 import 해서 사용할 때, return 영역에서 해당 컴포넌트의 hook function 만 반복 실행하는 거고, 컴포넌트 위에 선언한 변수들은 import 할 때 한번만 scan되기 때문에 호출한 컴포넌트 hook은 각각의 컨텍스트를 가지니까 hook 내부 변수는 그 hook에서만 유효한데 반해,&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컴포넌트 바깥에 선언한 변수는 해당 파일 내에서 전역 컨텍스트와 비슷하게 정의 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 각각의 hook 들에서 해당 변수명을 호출할 때, 내부에 호출한 변수가 없으면 전역 컨텍스트까지 스코프 체인 따라 올라간다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 let 키워드로 hook 외부에서 선언하면 동일한 변수를 참조해서 문제가 생길 수 있기 때문이다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>React</category>
      <category>component</category>
      <category>component 내부 변수</category>
      <category>component 외부 변수</category>
      <category>let</category>
      <category>react</category>
      <category>스코프 체인</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/79</guid>
      <comments>https://gusehd66.tistory.com/entry/React-Component-%EC%99%B8%EB%B6%80-vs-%EB%82%B4%EB%B6%80-%EB%B3%80%EC%88%98-%EC%84%A0%EC%96%B8#entry79comment</comments>
      <pubDate>Tue, 22 Feb 2022 23:00:10 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] constructor 와 non-constructor</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-constructor-%EC%99%80-non-constructor</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진은 함수 정의를 평가하여 함수 객체를 생성할 때 함수 정의 방식에 따라 함수를 constructor 와 non-constructor 로 구분한다.&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;constructor : 함수 선언문, 함수 표현식, 클래스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;non-constructor : 메서드(ES6 메서드 축약 표현), 화살표 함수&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1645439102120&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 일반함수 정의: 함수선언문, 함수표현식
function one() {}
const two = function() {};

// 프로퍼티 x의 값으로 할당된 것은 일반 함수로 정의된 함수와 같다. 메서드로 인정X
const test = {
 x: function() {}
};

new one(); // -&amp;gt; one {}
new two(); // -&amp;gt; two {}
new test.x(); // -&amp;gt; x {}

// 화살표 함수 정의
const arrow = ()=&amp;gt;{};

new arrow(); // TypeError: arrow is not a constructor

// 메서드 정의
const obj = {
 x() {}
};

new obj.x(); // TypeError: obj.x is not a constructor&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5MfBG/btrtYVPH76U/cWKET4mfA7btqSto00OIX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5MfBG/btrtYVPH76U/cWKET4mfA7btqSto00OIX1/img.png&quot; data-origin-width=&quot;194&quot; data-origin-height=&quot;225&quot; data-is-animation=&quot;false&quot; style=&quot;width: 35.2631%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5MfBG/btrtYVPH76U/cWKET4mfA7btqSto00OIX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5MfBG%2FbtrtYVPH76U%2FcWKET4mfA7btqSto00OIX1%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;194&quot; height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v3mo1/btrtZa0jXKD/8CkqHfbRY4iPVlxlDEkpA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v3mo1/btrtZa0jXKD/8CkqHfbRY4iPVlxlDEkpA1/img.png&quot; data-origin-width=&quot;314&quot; data-origin-height=&quot;202&quot; data-is-animation=&quot;false&quot; style=&quot;width: 63.5741%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v3mo1/btrtZa0jXKD/8CkqHfbRY4iPVlxlDEkpA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv3mo1%2FbtrtZa0jXKD%2F8CkqHfbRY4iPVlxlDEkpA1%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;314&quot; height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>constructor</category>
      <category>javascript</category>
      <category>non-constructor</category>
      <category>자바스크립트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/78</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-constructor-%EC%99%80-non-constructor#entry78comment</comments>
      <pubDate>Mon, 21 Feb 2022 20:07:56 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] 일급 객체</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-%EC%9D%BC%EA%B8%89-%EA%B0%9D%EC%B2%B4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;일급 객체&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일급 객체는 4가지 조건을 만족하는 객체를 말한다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 변수나 자료구조(객체,배열 등)에 저장할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 함수의 매개변수에 전달할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 함수의 반환값으로 사용할 수 있다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트의 함수는 &lt;span style=&quot;color: #ee2323;&quot;&gt;4가지 조건을 모두 만족하는 일급 객체&lt;/span&gt;이다.&lt;/p&gt;
&lt;pre id=&quot;code_1645363334133&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1. 함수는 무명의 리터럴로 생성 가능
const increase = function(num) {
 return ++num;
};

const decrease = function(num) {
 return --num;
};

// 2. 함수는 객체에 저장이 가능
const predicates = { increase, decrease };

// 3. 함수는 매개변수에 전달 가능
function Counter(predicate) {
 let num=0;
 
 // 4. 함수의 반환값으로 사용 가능
 return fuction () {
  num = predicate(num);
  return num;
 };
}
 
const increaser = Counter(predicates.increase);
console.log(increase()); // 1
console.log(increase()); // 2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수가 일급 객체라는 것은 함수를 객체와 동일하게 사용할 수 있다는 뜻이다.&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>일급 객체</category>
      <category>자바스크립트</category>
      <category>함수</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/77</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-%EC%9D%BC%EA%B8%89-%EA%B0%9D%EC%B2%B4#entry77comment</comments>
      <pubDate>Sun, 20 Feb 2022 22:29:11 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] 스코프 체인과 렉시컬 스코프</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B2%B4%EC%9D%B8%EA%B3%BC-%EB%A0%89%EC%8B%9C%EC%BB%AC-%EC%8A%A4%EC%BD%94%ED%94%84</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;스코프&amp;nbsp;체인과&amp;nbsp;렉시컬&amp;nbsp;스코프&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;스코프 체인&lt;/b&gt;&lt;/h2&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;b&gt; 함수의 중첩에 의해 계층적 구조를 갖는다는 것을 의미&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 함수의 지역 스코프를 중첩 함수의 상위 스코프라 한다.&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;239&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMTMa5/btrtLyUyE0z/9BMbXDrabrKA62XlWgAH60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMTMa5/btrtLyUyE0z/9BMbXDrabrKA62XlWgAH60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMTMa5/btrtLyUyE0z/9BMbXDrabrKA62XlWgAH60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMTMa5%2FbtrtLyUyE0z%2F9BMbXDrabrKA62XlWgAH60%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;239&quot; height=&quot;426&quot; data-origin-width=&quot;239&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;/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;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt; 스코프 체인&lt;/span&gt;&lt;/b&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;b&gt;변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색&lt;/b&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조할 수 있지만 &lt;b&gt;하위 스코프에서 유효한 변수를 상위 스코프에서 참조할 수 없음&lt;/b&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;pre id=&quot;code_1645191955985&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function func1() {
 console.log('global function func1');
}

function func2() {
 function func1() {
  console.log('local function func1');
 }

 func1(); // local function func1
}

func2();&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;결과&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;268&quot; data-origin-height=&quot;191&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lDxBq/btrtH1cA4Py/mce4XkIIKKwhmjQTPF1nBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lDxBq/btrtH1cA4Py/mce4XkIIKKwhmjQTPF1nBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lDxBq/btrtH1cA4Py/mce4XkIIKKwhmjQTPF1nBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlDxBq%2FbtrtH1cA4Py%2Fmce4XkIIKKwhmjQTPF1nBK%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;268&quot; height=&quot;191&quot; data-origin-width=&quot;268&quot; data-origin-height=&quot;191&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;/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;b&gt;식별자를 검색하는 규칙'&lt;/b&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;&lt;b&gt;함수 레벨 스코프&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지역은 &lt;b&gt;코드 블록이 아닌 함수에 의해서만 지역 스코프가 생성&lt;/b&gt;된다.&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;b&gt;블록 레벨 스코프&lt;/b&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;하지만 var 키워드로 선언된 변수는 오로지 함수의 코드 블록 만을 지역스코프로 인정한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 &lt;b&gt;함수 레벨 스코프&lt;/b&gt; 라고한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1645192508331&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var i = 10;

for (var i=0; i&amp;lt;5; i++){
 console.log(i); // 0 1 2 3 4
}

console.log(i); // 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 밖에서 var 키워드로 선언된 변수는 코드 블록 내에서 선언되었다 할지라도 모두 전역 변수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;for문에서 반복을 위해 선언된 변수 또한 var 키워드로 선언하면 전역 변수가 된다.&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;렉시컬 스코프&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645192683019&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = 1;

function func1() {
 var x = 10;
 func2();
}

function func2() {
 console.log(x);
}

func1(); // 1
func2(); // 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수를 어디서 호출했는지에 따라 함수의 상위 스코프를 결정하는 방식을 &lt;b&gt;동적 스코프&lt;/b&gt;라 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수를 어디서 정의했는지에 따라 함수의 상위 스코프를 결정하는 방식은 &lt;b&gt;정적 스코프&lt;/b&gt;라 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 &lt;span style=&quot;color: #ee2323;&quot;&gt;렉시컬 스코프(정적 스코프)&lt;/span&gt;를 따르므로 함수를 어디서 정의했는지에 따라 상위 스코프를 결정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;위 예제의 func2 함수는 전역에서 정의된 함수이므로, func1 함수 안에서 호출하였더라도 전역 스코프를 기억한다.&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>렉시컬 스코프</category>
      <category>블록 레벨 스코프</category>
      <category>스코프</category>
      <category>스코프 체인</category>
      <category>자바스크립트</category>
      <category>함수 레벨 스코프</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/76</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B2%B4%EC%9D%B8%EA%B3%BC-%EB%A0%89%EC%8B%9C%EC%BB%AC-%EC%8A%A4%EC%BD%94%ED%94%84#entry76comment</comments>
      <pubDate>Fri, 18 Feb 2022 23:05:58 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] 스코프 Scope</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84-Scope</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Scope&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스코프&lt;/b&gt;(&lt;b&gt;유효범위&lt;/b&gt;) 는 , 자바스크립트를 포함한 모든 프로그래밍 언어의 중요한 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1644821038835&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function add(x,y) {
 //매개변수는 함수 몸체 내부에서만 참조할 수 있다.
 //매개변수의 스코프는 함수 몸체 내부이다.
 console.log(x,y) //2 5
 return x + y;
}

add(2,5);

// 매개변수는 함수 내부에서만 참조할 수 있다.
console.log(x,y); // ReferenceError: x is not defined&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;모든 식별자는 자신이 &lt;u&gt;선언된 위치에 의해 자신이 유효한 볌위, 다른 코드가 자신을 참조할 수 있는 범위&lt;/u&gt;가 결정된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 유효 범위가 바로 &lt;b&gt;스코프&lt;/b&gt;이다. 즉 스코프는 &lt;b&gt;식별자가 유효한 범위&lt;/b&gt;를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1644821354328&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let x = 'global';

function check() {
 let x = 'local';
 console.log(x);
}

check();

console.log(x);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;check 함수의 바깥 영역과 내부 영역에 같은 이름을 같은 x변수를 선언 후,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x를 참조하면 자바스크립트 엔진이 둘 중 어느 변수를 참조할 것인지를 결정하는 &lt;b&gt;식별자 결정&lt;/b&gt;을 한다.&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;b&gt;자바스크립트 엔진이 식별자를 검색할 때 사용하는 규칙&lt;/b&gt;이라고도 할 수 있다.&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;style7&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JBiVt/btrs7qLNPBx/paku4BGtRMI3w6Feb5QpkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JBiVt/btrs7qLNPBx/paku4BGtRMI3w6Feb5QpkK/img.png&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;111&quot; data-is-animation=&quot;false&quot; style=&quot;width: 53.8636%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JBiVt/btrs7qLNPBx/paku4BGtRMI3w6Feb5QpkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJBiVt%2Fbtrs7qLNPBx%2Fpaku4BGtRMI3w6Feb5QpkK%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;358&quot; height=&quot;111&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/leCA5/btrs8PKRjie/zwXYSOrrmHHkjsqDfJQLRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/leCA5/btrs8PKRjie/zwXYSOrrmHHkjsqDfJQLRk/img.png&quot; data-origin-width=&quot;342&quot; data-origin-height=&quot;127&quot; data-is-animation=&quot;false&quot; style=&quot;width: 44.9736%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/leCA5/btrs8PKRjie/zwXYSOrrmHHkjsqDfJQLRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FleCA5%2Fbtrs8PKRjie%2FzwXYSOrrmHHkjsqDfJQLRk%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;342&quot; height=&quot;127&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 var 키워드로 선언된 변수는 같은 스코프 내에 중복 선언이 허용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;let 과 const는 같은 스코프 내에서 중복 선언을 허용하지 않으므로 부작용을 줄여준다.&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: #666666;&quot;&gt;( var는 재할당,재정의, 호이스팅, &lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;nbsp;for문 종료시에도 접근 가능, 전역 변수남발 등 문제가 많은 놈이다. 쓰지말자)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;스코프의 종류&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;스코프는 &lt;b&gt;전역 스코프&lt;/b&gt;와 &lt;b&gt;지역 스코프&lt;/b&gt;로 나눌 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;코드의 가장 바깥에서 선언한 변수는 전역 변수로 전역 스코프를 가지며 어디서든지 참조할 수 있게된다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;지역 변수는 함수 내부에서 지역 스코프를 가지며 자신의 지역 스코프와 하위 지역 스코프에서만 유효하다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>scope</category>
      <category>스코프</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/75</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84-Scope#entry75comment</comments>
      <pubDate>Mon, 14 Feb 2022 17:29:42 +0900</pubDate>
    </item>
    <item>
      <title>[React] Error: Cannot read properties of undefined (reading ~)</title>
      <link>https://gusehd66.tistory.com/entry/React-Error-Cannot-read-properties-of-undefined-reading</link>
      <description>&lt;h2 id=&quot;cannot-read-properties-of-undefined&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Cannot read properties of undefined&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Uncaught TypeError: Cannot read properties of undefined (reading 'length')&lt;/b&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E96aQ/btrs5Am5IPN/4emwLO5PiQml9KqTraYzK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E96aQ/btrs5Am5IPN/4emwLO5PiQml9KqTraYzK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E96aQ/btrs5Am5IPN/4emwLO5PiQml9KqTraYzK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE96aQ%2Fbtrs5Am5IPN%2F4emwLO5PiQml9KqTraYzK0%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;424&quot; height=&quot;33&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;33&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p id=&quot;cannot-read-properties-of-undefined&quot; data-ke-size=&quot;size18&quot;&gt;Cannot read properties of undefined 에러는 화면이 렌더가 되지 않을때 콘솔창을 키면 자주 볼 수 있는 오류 메시지다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;에러내용은 친절하게 설명해준대로 undefined 의 프로퍼티를 읽을 수 없다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(무엇을 읽을 수 없는지 어디서 에러가 발생했는지도 친절하게 알려준다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오탈자 문제가 아니라면 사용하는 state가 실제로 undefined란 얘긴데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;useState는 비동기로 작동하기 때문에 페이지가 그려지기 전까지 undefined를 가지고 있다가&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이지가 그려진 후 필요한 state를 넣어준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;해결 방법은 &lt;b&gt;조건문, &amp;amp;&amp;amp; 연산자, 옵셔널 체이닝( ?. )&lt;/b&gt;을 활용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&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;</description>
      <category>React</category>
      <category>Cannot read properties of undefined</category>
      <category>react</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/74</guid>
      <comments>https://gusehd66.tistory.com/entry/React-Error-Cannot-read-properties-of-undefined-reading#entry74comment</comments>
      <pubDate>Sun, 13 Feb 2022 14:40:37 +0900</pubDate>
    </item>
    <item>
      <title>[React] React-query 병렬 쿼리</title>
      <link>https://gusehd66.tistory.com/entry/React-React-query-%EB%B3%91%EB%A0%AC-%EC%BF%BC%EB%A6%AC</link>
      <description>&lt;div&gt;
&lt;div data-key=&quot;6e565fc975594baabb20585ef2dae378&quot;&gt;
&lt;div data-block-content=&quot;6e565fc975594baabb20585ef2dae378&quot;&gt;
&lt;h2 data-rnw-media-class=&quot;207__206&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;26c6a9008a234ae0bd720099bdb1dcf1&quot;&gt;&lt;span data-offset-key=&quot;26c6a9008a234ae0bd720099bdb1dcf1:0&quot;&gt;병렬 쿼리&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span data-key=&quot;6a9b4ad15cf8467a897c09c78876ddf2&quot;&gt;&lt;span data-offset-key=&quot;6a9b4ad15cf8467a897c09c78876ddf2:0&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;ff06f3ca84aa4a8d88f58fa1d4a785f7&quot;&gt;
&lt;div data-block-content=&quot;ff06f3ca84aa4a8d88f58fa1d4a785f7&quot;&gt;
&lt;h3 data-rnw-media-class=&quot;208__207&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;c163bec8b9024a9199ade80662d602fe&quot;&gt;&lt;span data-offset-key=&quot;c163bec8b9024a9199ade80662d602fe:0&quot;&gt;정적으로 병렬 쿼리 선언하기&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJoZWFkaW5nLTElMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQiVCMyU5MSVFQiVBMCVBQyUyMCVFQyVCRiVCQyVFQiVBNiVBQyUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmQxM2JmZmE3YTk2YzQwNTdiY2UzZWYzY2FlMDJkN2VjJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyODBlM2M1MDIzNjI0NDA1NzhjNWYwYzUwMDkwYTA4N2YlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQiVCMyU5MSVFQiVBMCVBQyUyMCVFQyVCRiVCQyVFQiVBNiVBQyVFQiU4QSU5NCUyMCVFQiU4RiU5OSVFQyU4QiU5QyVFQyU4NCVCMSVFQyU5RCU4NCUyMCVFQyVCNSU5QyVFQiU4QyU4MCVFRCU5OSU5NCVFRCU5NSU5OCVFQSVCOCVCMCUyMCVFQyU5QyU4NCVFRCU5NSVCNCUyMCVFQiVCMyU5MSVFQiVBMCVBQyVFQiVBMSU5QyUyMCVFQyU4QiVBNCVFRCU5NiU4OSUyMCVFQiU5MCU5OCVFQSVCMSVCMCVFQiU4MiU5OCUyMCVFQiU4RiU5OSVFQyU4QiU5QyVFQyU5NyU5MCUyMCVFQyU4QiVBNCVFRCU5NiU4OSVFQiU5MCU5OCVFQiU4QSU5NCUyMCVFQyVCRiVCQyVFQiVBNiVBQyVFQyU5RSU4NSVFQiU4QiU4OCVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI2YTliNGFkMTVjZjg0NjdhODk3YzA5Yzc4ODc2ZGRmMiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjc5YTc4NGIxYTc2OTQ4ZWNhMGQzODlhNzEwZmU3OTJmJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyaGVhZGluZy0yJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlQTAlOTUlRUMlQTAlODElRUMlOUMlQkMlRUIlQTElOUMlMjAlRUIlQjMlOTElRUIlQTAlQUMlMjAlRUMlQkYlQkMlRUIlQTYlQUMlMjAlRUMlODQlQTAlRUMlOTYlQjglRUQlOTUlOTglRUElQjglQjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJjMTYzYmVjOGI5MDI0YTkxOTlhZGU4MDY2MmQ2MDJmZSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmZmMDZmM2NhODRhYTRhOGQ4OGY1OGZhMWQ0YTc4NWY3JTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJ1c2VRdWVyeSUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCUyQyUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIydXNlSW5maW5pdGVRdWVyeSUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFQiVBNSVCQyUyMCVFQiU4MiU5OCVFQiU5RSU4MCVFRCU5RSU4OCUyMCVFQyU4NCVBMCVFQyU5NiVCOCVFRCU5NSU5OCVFQiVBOSVCNCUyMCVFQyU5RSU5MCVFQiU4RiU5OSVFQyU5QyVCQyVFQiVBMSU5QyUyMCVFQiVCMyU5MSVFQiVBMCVBQyUyMCVFQyVCRiVCQyVFQiVBNiVBQyVFQSVCMCU4MCUyMCVFQyU4QiVBNCVFRCU5NiU4OSVFQiU5MCVBOSVFQiU4QiU4OCVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIyODI3ZDg5MGRjMGY0OTY5OWRlMTBlNjhhZDIxM2Y5MSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjFmZDhlZGI4ZDEyNzQwMjI4YWFkMzEzMDZkYjFiZTgxJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNTI1YzY1NzNhNzY1NDAzNDhkODU2YmFiYzY1NGRhMDYlMjIlN0Q=&quot;&gt;
&lt;div data-key=&quot;1fd8edb8d12740228aad31306db1be81&quot;&gt;
&lt;div data-block-content=&quot;1fd8edb8d12740228aad31306db1be81&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;2827d890dc0f49699de10e68ad213f91&quot;&gt;useQuery&lt;span data-offset-key=&quot;2827d890dc0f49699de10e68ad213f91:1&quot;&gt; , &lt;/span&gt;useInfiniteQuery&lt;span data-offset-key=&quot;2827d890dc0f49699de10e68ad213f91:3&quot;&gt; 를 나란히 선언하면 자동으로 병렬 쿼리가 실행됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1644483592567&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; function App () {
   // 병렬 실행
   const usersQuery = useQuery('users', fetchUsers)
   const teamsQuery = useQuery('teams', fetchTeams)
   const projectsQuery = useQuery('projects', fetchProjects)
   ...
 }&lt;/code&gt;&lt;/pre&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;div data-block-content=&quot;fa8b0e6a95dd4ab2890274e288d8fc8a&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;6ec5deb64c27486abb7bc777e3293081&quot;&gt;&lt;span data-offset-key=&quot;6ec5deb64c27486abb7bc777e3293081:0&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-key=&quot;839f466c651743fc862967150363c772&quot;&gt;&lt;span data-offset-key=&quot;839f466c651743fc862967150363c772:0&quot;&gt;React의 &lt;b&gt;Suspense&lt;/b&gt;모드에서 리액트 쿼리를 사용할 때 첫번째 쿼리가 프로미스를 던지고 다른 쿼리가 실행되기 전에 &lt;/span&gt;&lt;b&gt;컴포넌트를 일시 중단하기 때문에 병렬 쿼리가 실행되지 않습니다. &lt;/b&gt;&lt;/span&gt;
&lt;div data-key=&quot;0f5bbccb14944a7eb3ea4244972c7c19&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmI2NTg2ZDk2NjMxZDQ1MjdiMzk0ODZiNGE2MDNkNDgzJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyaW5saW5lJTIyJTJDJTIydHlwZSUyMiUzQSUyMmxpbmslMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlMjJyZWYlMjIlM0ElN0IlMjJraW5kJTIyJTNBJTIydXJsJTIyJTJDJTIydXJsJTIyJTNBJTIyaHR0cHMlM0ElMkYlMkZyZWFjdGpzLm9yZyUyRmRvY3MlMkZyZWFjdC1hcGkuaHRtbCUyM3JlYWN0c3VzcGVuc2UlMjIlN0QlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMlN1c3BlbnNlJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNWFmYmY4ODMwNDZhNDJhN2I2ZTM1M2EzNmNlNzYyZDglMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJiYjE2MTJjYTMzZjE0MDMyOGQyOTNhMWQxYzZmMWQ1MiUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFQiVBQSVBOCVFQiU5MyU5QyVFQyU5NyU5MCVFQyU4NCU5QyUyMCVFQiVBNiVBQyVFQyU5NSVBMSVFRCU4QSVCOCUyMCVFQyVCRiVCQyVFQiVBNiVBQyVFQiVBNSVCQyUyMCVFQyU4MiVBQyVFQyU5QSVBOSVFRCU5NSVBMCUyMCVFQiU5NSU4QyUyMCVFQyVCMiVBQiVFQiVCMiU4OCVFQyVBNyVCOCUyMCVFQyVCRiVCQyVFQiVBNiVBQyVFQSVCMCU4MCUyMCVFRCU5NCU4NCVFQiVBMSU5QyVFQiVBRiVCOCVFQyU4QSVBNCVFQiVBNSVCQyUyMCVFQiU4RCU5OCVFQyVBNyU4MCVFQSVCMyVBMCUyMCVFQiU4QiVBNCVFQiVBNSVCOCUyMCVFQyVCRiVCQyVFQiVBNiVBQyVFQSVCMCU4MCUyMCVFQyU4QiVBNCVFRCU5NiU4OSVFQiU5MCU5OCVFQSVCOCVCMCUyMCVFQyVBMCU4NCVFQyU5NyU5MCUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVDJUJCJUI0JUVEJThGJUFDJUVCJTg0JThDJUVEJThBJUI4JUVCJUE1JUJDJTIwJUVDJTlEJUJDJUVDJThCJTlDJTIwJUVDJUE0JTkxJUVCJThCJUE4JUVEJTk1JTk4JUVBJUI4JUIwJTIwJUVCJTk1JThDJUVCJUFDJUI4JUVDJTk3JTkwJTIwJUVCJUIzJTkxJUVCJUEwJUFDJTIwJUVDJUJGJUJDJUVCJUE2JUFDJUVBJUIwJTgwJTIwJUVDJThCJUE0JUVEJTk2JTg5JUVCJTkwJTk4JUVDJUE3JTgwJTIwJUVDJTk1JThBJUVDJThBJUI1JUVCJThCJTg4JUVCJThCJUE0LiUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJib2xkJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI4MzlmNDY2YzY1MTc0M2ZjODYyOTY3MTUwMzYzYzc3MiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjMyOWMwY2ExZTkyNTQxMWNiZmQ3ZjI1YjU4MmQ0M2FlJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlOUQlQjQlMjAlRUIlOTUlOEMlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMnVzZVF1ZXJpZXMlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlRUIlQTUlQkMlMjAlRUMlODIlQUMlRUMlOUElQTklRUQlOTUlOTglRUElQjElQjAlRUIlODIlOTglMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMnVzZVF1ZXJ5JTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJTIwJUVDJTlEJUI4JUVDJThBJUE0JUVEJTg0JUI0JUVDJThBJUE0JUVDJTk3JTkwJTIwJUVCJThDJTgwJUVEJTk1JTlDJTIwJUVCJUIzJTg0JUVCJThGJTg0JTIwJUVBJUI1JUFDJUVDJTg0JUIxJUVDJTlEJTg0JTIwJUVEJTk1JUI0JUVDJTk1JUJDJUVEJTk1JUE5JUVCJThCJTg4JUVCJThCJUE0LiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjczOWY2YTMyZDUzNTRiNjFhMWQ5YzFiZTVmNWFlOTJiJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMGY1YmJjY2IxNDk0NGE3ZWIzZWE0MjQ0OTcyYzdjMTklMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhZDg0YjBlYTg1ZDM0Y2E5YThiN2JhMTkxMTAyMjFmYyUyMiU3RA==&quot;&gt;
&lt;div data-block-content=&quot;0f5bbccb14944a7eb3ea4244972c7c19&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;739f6a32d5354b61a1d9c1be5f5ae92b&quot;&gt;&lt;span data-offset-key=&quot;739f6a32d5354b61a1d9c1be5f5ae92b:0&quot;&gt;이 때, &lt;/span&gt;useQueries&lt;span data-offset-key=&quot;739f6a32d5354b61a1d9c1be5f5ae92b:2&quot;&gt; 를 사용하거나 &lt;/span&gt;useQuery&lt;span data-offset-key=&quot;739f6a32d5354b61a1d9c1be5f5ae92b:4&quot;&gt; 인스턴스에 대한 별도 구성을 해야합니다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;47ef44c6a1434af290f6900e56b4bd67&quot;&gt;
&lt;div data-block-content=&quot;47ef44c6a1434af290f6900e56b4bd67&quot;&gt;
&lt;h3 data-rnw-media-class=&quot;208__207&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;f432bc6a453d4500819b052137da9837&quot;&gt;&lt;span data-offset-key=&quot;f432bc6a453d4500819b052137da9837:0&quot;&gt;동적으로 병렬 쿼리 선언하기&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span data-key=&quot;3635c471d376412f9f5bfd30b78c6a0e&quot;&gt;&lt;span data-offset-key=&quot;3635c471d376412f9f5bfd30b78c6a0e:0&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;react hook에는 다음과 같은 규칙이 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후크는 JavaScript 함수이지만 두 가지 추가 규칙을 부과합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;최상위 수준에서&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Hooks만 호출 합니다&lt;span&gt;&amp;nbsp;&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;루프, 조건 또는 중첩 함수 내에서 Hooks를 호출하지 마십시오&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;React 함수 구성 요소&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;에서만 Hooks를 호출 합니다&lt;span&gt;&amp;nbsp;&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;일반 JavaScript 함수에서 Hooks를 호출하지 마십시오.&lt;span&gt;&amp;nbsp;&lt;/span&gt;(Hooks를 호출할 수 있는 다른 유효한 장소가 하나 있습니다. 사용자 정의 Hooks입니다. 잠시 후에 이에 대해 알아보겠습니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;d09fb7b5367a48afb398fea223c08637&quot;&gt;
&lt;div data-block-content=&quot;d09fb7b5367a48afb398fea223c08637&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;e46a01b119854163846034301f0bcb87&quot;&gt;&lt;span data-offset-key=&quot;e46a01b119854163846034301f0bcb87:0&quot;&gt;때문에 루프, 조건 또는 중첩 함수내에서는 정적(수동)으로 병렬 쿼리를 선언할 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJoZWFkaW5nLTIlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQiU4RiU5OSVFQyVBMCU4MSVFQyU5QyVCQyVFQiVBMSU5QyUyMCVFQiVCMyU5MSVFQiVBMCVBQyUyMCVFQyVCRiVCQyVFQiVBNiVBQyUyMCVFQyU4NCVBMCVFQyU5NiVCOCVFRCU5NSU5OCVFQSVCOCVCMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmNhMjY5NWRkMDc2MzRhNzVhY2YwMTk0ZjAwOWNmNzcyJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZDU2MzU1NDNiNTgxNDdiNmI1NzY1ZTk1YzUwYTg1ODElMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjhmYWFhNDJiZjkwZTQ3OTA5YTA4ZWY1Njk5ZDkzZWM3JTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyaW5saW5lJTIyJTJDJTIydHlwZSUyMiUzQSUyMmxpbmslMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlMjJyZWYlMjIlM0ElN0IlMjJraW5kJTIyJTNBJTIydXJsJTIyJTJDJTIydXJsJTIyJTNBJTIyaHR0cHMlM0ElMkYlMkZydS5yZWFjdC5qcy5vcmclMkZkb2NzJTJGaG9va3Mtb3ZlcnZpZXcuaHRtbCUyMyUyNUVGJTI1QjglMjU4Ri1ydWxlcy1vZi1ob29rcyUyMiU3RCU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIycmVhY3QtaG9va3MlMjAlRUMlOUQlOTglMjAlRUElQjclOUMlRUMlQjklOTklMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIyYTljMWU3MWRlZTY0YmRiYTIxZjhlMzQyYzU4YmJiZCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmY2OTdlMzg5N2YzZTQ2MWE5ZDVkMWUyYjMzYjdjZGIyJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJTIwJUVDJTk3JTkwJTIwJUVDJTlEJTk4JUVEJTk1JTk4JUVCJUE5JUI0JTIwJUVCJUIwJTk4JUVCJUIzJUI1JUVCJUFDJUI4JTJDJTIwJUVDJUExJUIwJUVBJUIxJUI0JUVCJUFDJUI4JTIwJUVCJTk4JTkwJUVCJThBJTk0JTIwJUVDJUE0JTkxJUVDJUIyJUE5JTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVCJTgyJUI0JUVDJTk3JTkwJUVDJTg0JTlDJTIwaG9vayUyMCVFQiVBNSVCQyUyMCVFQyU4NCVBMCVFQyU5NiVCOCVFRCU5NSVBMCUyMCVFQyU4OCU5OCUyMCVFQyU5NyU4NiVFQiU4QiVBNC4lMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIzNjM1YzQ3MWQzNzY0MTJmOWY1YmZkMzBiNzhjNmEwZSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjZlZTFmMmQ1MWJmZjQ0YzE5NmNmZjVjYzNkODUwOTViJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUIlOTUlOEMlRUIlQUMlQjglRUMlOTclOTAlMjAlRUMlOUQlQjQlMjAlRUElQjIlQkQlRUMlOUElQjAlRUMlOTclOTQlMjAlRUMlQTAlOTUlRUMlQTAlODEoJUVDJTg4JTk4JUVCJThGJTk5KSVFQyU5QyVCQyVFQiVBMSU5QyUyMCVFQiVCMyU5MSVFQiVBMCVBQyUyMCVFQyVCRiVCQyVFQiVBNiVBQyVFQiVBNSVCQyUyMCVFQyU4NCVBMCVFQyU5NiVCOCVFRCU5NSVBMCUyMCVFQyU4OCU5OCUyMCVFQyU5NyU4NiVFQiU4QiVBNC4lMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlNDZhMDFiMTE5ODU0MTYzODQ2MDM0MzAxZjBiY2I4NyUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmQwOWZiN2I1MzY3YTQ4YWZiMzk4ZmVhMjIzYzA4NjM3JTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlOUQlQjQlMjAlRUIlOTUlOEMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMnVzZVF1ZXJpZXMlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlRUIlOUQlQkMlRUIlOEElOTQlMjBob29rJTIwJUVDJTlEJTg0JTIwJUVDJUEwJTlDJUVBJUIzJUI1JUVEJTk1JUI0JUVDJTg0JTlDJTIwJUVCJThGJTk5JUVDJUEwJTgxJUVDJTlDJUJDJUVCJUExJTlDJTIwJUVCJUIzJTkxJUVCJUEwJUFDJTIwJUVDJUJGJUJDJUVCJUE2JUFDJUVCJUE1JUJDJTIwJUVBJUI1JUFDJUVDJTg0JUIxJUVEJTk1JTk4JUVDJTk3JUFDJTIwJUVDJThCJUE0JUVEJTk2JTg5JUVEJTk1JUEwJTIwJUVDJTg4JTk4JTIwJUVDJTlFJTg4JUVCJThCJUE0LiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjhiMTkxNGM5ZTU3YjRjN2Y4NjI3NDVlMTY3MDUxMWVlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZGNkZTM4ZDU4MTFkNDI4ZDgwNGUwYWZmMTFkNzE2YTYlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIxYzhjZDVlNTIxODI0ZjBkOTljZTA4MjM5Zjg5NmQ3OSUyMiU3RA==&quot;&gt;
&lt;div data-key=&quot;dcde38d5811d428d804e0aff11d716a6&quot;&gt;
&lt;div data-block-content=&quot;dcde38d5811d428d804e0aff11d716a6&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;8b1914c9e57b4c7f862745e1670511ee&quot;&gt;&lt;span data-offset-key=&quot;8b1914c9e57b4c7f862745e1670511ee:0&quot;&gt;이 때 &lt;/span&gt;useQueries&lt;span data-offset-key=&quot;8b1914c9e57b4c7f862745e1670511ee:2&quot;&gt; 라는 hook 을 제공해서 동적으로 병렬 쿼리를 구성하여 실행할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1644483623703&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function App({ users }) {
   const userQueries = useQueries(
     users.map(user =&amp;gt; {
       return {
         queryKey: ['user', user.id],
         queryFn: () =&amp;gt; fetchUserById(user.id),
       }
     })
   )
 }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;3627acce671f4e5db2ae9948f5d1de7d&quot;&gt;
&lt;div data-block-content=&quot;3627acce671f4e5db2ae9948f5d1de7d&quot;&gt;
&lt;h3 data-rnw-media-class=&quot;207__206&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;68aef0b0f3664353a050793513898f1b&quot;&gt;&lt;span data-offset-key=&quot;68aef0b0f3664353a050793513898f1b:0&quot;&gt;종속 쿼리&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;b6143ffc86734cde950aec4701551482&quot;&gt;
&lt;div data-block-content=&quot;b6143ffc86734cde950aec4701551482&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;d3fbdd455b8e49f1b533407a36504fcf&quot;&gt;&lt;span data-offset-key=&quot;d3fbdd455b8e49f1b533407a36504fcf:0&quot;&gt;종속 쿼리는 이전 쿼리의 실행이 마무리 되어야 실행 될 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJoZWFkaW5nLTElMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyVBMiU4NSVFQyU4NiU4RCUyMCVFQyVCRiVCQyUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjNmNmFkN2ZlMGUxZjRlMjM4NjkzZmY0YzI5NTFjODYwJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNzhiYWJmZmI1NDBiNGY5NmE5YjFiNGZhOTRjMTRhZWQlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyVBMiU4NSVFQyU4NiU4RCUyMChkZXBlbmRlbnQpJTIwJUVDJUJGJUJDJUVCJUE2JUFDJUVCJThBJTk0JTIwJUVDJTlEJUI0JUVDJUEwJTg0JTIwJUVDJUJGJUJDJUVCJUE2JUFDJUVDJTlEJTk4JTIwJUVDJThCJUE0JUVEJTk2JTg5JUVDJTlEJUI0JTIwJUVCJUE3JTg4JUVCJUFDJUI0JUVCJUE2JUFDJTIwJUVCJTkwJTk4JUVDJTk2JUI0JUVDJTk1JUJDJTIwJUVDJThCJUE0JUVEJTk2JTg5JTIwJUVCJTkwJUEwJTIwJUVDJTg4JTk4JTIwJUVDJTlFJTg4JUVDJThBJUI1JUVCJThCJTg4JUVCJThCJUE0LiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmQzZmJkZDQ1NWI4ZTQ5ZjFiNTMzNDA3YTM2NTA0ZmNmJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYjYxNDNmZmM4NjczNGNkZTk1MGFlYzQ3MDE1NTE0ODIlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU5RCVCNCUyMCVFQSVCMCU5OSVFQyU5RCU4MCUyMCVFQyVCMiU5OCVFQiVBNiVBQyVFQiVBNSVCQyUyMCVFRCU5NSU5OCVFQSVCOCVCMCUyMCVFQyU5QyU4NCVFRCU5NSVCNCVFQyU4NCVBMCUyMCVFQyU5NSU4NCVFQiU5RSU5OCVFQyU5OSU4MCUyMCVFQSVCMCU5OSVFQyU5RCVCNCUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyZW5hYmxlZCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFQyU5OCVCNSVFQyU4NSU5OCVFQyU5QyVCQyVFQiVBMSU5QyUyMCVFQyVCRiVCQyVFQiVBNiVBQyVFQSVCMCU4MCUyMCVFQyU4QiVBNCVFRCU5NiU4OSVFQiU5MCVBMCUyMCVFQyVBNCU4MCVFQiVCOSU4NCVFQSVCMCU4MCUyMCVFQiU5MCU5OCVFQyU5NyU4OCVFQyU5RCU4NCUyMCVFQiU5NSU4QyVFQiVBNSVCQyUyMCVFQyU5NSU4QyVFQiVBNiVBQyVFQiVBOSVCNCUyMCVFQiU5MCVBOSVFQiU4QiU4OCVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI0MjQzZTc5Y2FmNDM0ZDczYmZjOGVhNWMxZGFiNzlmZCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjIyNjUxM2RkZGJmOTQyY2FiYmZmZjI5NmVmNjc4OTZjJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMTllZjBjM2E0MGUxNGFjYmEwOTRkNDc1NmEyMDg2NzUlMjIlN0Q=&quot;&gt;
&lt;div data-key=&quot;226513dddbf942cabbfff296ef67896c&quot;&gt;
&lt;div data-block-content=&quot;226513dddbf942cabbfff296ef67896c&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;4243e79caf434d73bfc8ea5c1dab79fd&quot;&gt;&lt;span data-offset-key=&quot;4243e79caf434d73bfc8ea5c1dab79fd:0&quot;&gt;이 같은 처리를 하기 위해선 아래와 같이 &lt;/span&gt;enabled&lt;span data-offset-key=&quot;4243e79caf434d73bfc8ea5c1dab79fd:2&quot;&gt; 옵션으로 쿼리가 실행될 준비가 되었을 때를 알리면 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1644483640390&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; const { data: user } = useQuery(['user', email], getUserByEmail)
 
 const userId = user?.id
 
 const { isIdle, data: projects } = useQuery(
   ['projects', userId],
   getProjectsByUser,
   {
     // userId 가 존재할때 까지 쿼리를 실행하지 않습니다.
     enabled: !!userId,
   }
 )&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>react</category>
      <category>react-query</category>
      <category>병렬 쿼리</category>
      <category>종속 쿼리</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/73</guid>
      <comments>https://gusehd66.tistory.com/entry/React-React-query-%EB%B3%91%EB%A0%AC-%EC%BF%BC%EB%A6%AC#entry73comment</comments>
      <pubDate>Thu, 10 Feb 2022 18:17:29 +0900</pubDate>
    </item>
    <item>
      <title>[React] React-Quries 기본사항</title>
      <link>https://gusehd66.tistory.com/entry/React-React-Quries-%EA%B8%B0%EB%B3%B8%EC%82%AC%ED%95%AD</link>
      <description>&lt;div&gt;
&lt;div data-key=&quot;53436837d2a2412faffe1f62cbbee21a&quot;&gt;
&lt;div data-block-content=&quot;53436837d2a2412faffe1f62cbbee21a&quot;&gt;
&lt;h2 data-rnw-media-class=&quot;207__206&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span data-key=&quot;3664524bef144ad7896e125a2b1948b4&quot;&gt;&lt;span data-offset-key=&quot;3664524bef144ad7896e125a2b1948b4:0&quot;&gt;기본사항&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;fb63ea942194422d8ee7a2b0794e3c18&quot;&gt;
&lt;div data-block-content=&quot;fb63ea942194422d8ee7a2b0794e3c18&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;3060f746052e4f2d82c5eae3dbafe3ce&quot;&gt;&lt;span data-offset-key=&quot;3060f746052e4f2d82c5eae3dbafe3ce:0&quot;&gt;쿼리는 기본적으로 &lt;/span&gt;&lt;b&gt;유니크한 키&lt;/b&gt;&lt;span data-offset-key=&quot;3060f746052e4f2d82c5eae3dbafe3ce:2&quot;&gt;로 구분되며 프로미스(Promise) 기반 메서드 (GET, POST 등)로 서버에서 데이터를 가져올 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;span data-key=&quot;882046b2bbea4944a6f12e6323a35cda&quot;&gt;&lt;span data-offset-key=&quot;882046b2bbea4944a6f12e6323a35cda:2&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;3c86228a9b8547e7b5f8a092f72e0600&quot;&gt;
&lt;div data-block-content=&quot;3c86228a9b8547e7b5f8a092f72e0600&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;155d13e487d842debaf26a938b9a7a25&quot;&gt;&lt;span data-offset-key=&quot;155d13e487d842debaf26a938b9a7a25:0&quot;&gt;컴포넌트나 커스텀 훅에서 쿼리를 구독하려면 다음과 같이 &lt;/span&gt;useQuery&lt;span data-offset-key=&quot;155d13e487d842debaf26a938b9a7a25:2&quot;&gt; 를 호출한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;e57d48ab50f44ce59e04e085411428ee&quot;&gt;
&lt;div data-block-content=&quot;e57d48ab50f44ce59e04e085411428ee&quot;&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1644236152765&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; import { useQuery } from 'react-query'
 
 function App() {
   const info = useQuery('todos', fetchTodoList)
 }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;4488e4fa27f94d879a693af0bef0556a&quot;&gt;
&lt;div data-block-content=&quot;4488e4fa27f94d879a693af0bef0556a&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;a9c3a228ffa6449890046b945c8e6832&quot;&gt;&lt;span data-offset-key=&quot;a9c3a228ffa6449890046b945c8e6832:0&quot;&gt;여기서 &lt;/span&gt;&lt;b&gt;유니크한 키 &lt;/b&gt;&lt;span data-offset-key=&quot;a9c3a228ffa6449890046b945c8e6832:2&quot;&gt;는 Application 전체에서 쿼리를 다시 가져오고, 캐싱하고, 공유하기 위해 내부적으로 사용된다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;70c398afa686487a8bba22a701150bbe&quot;&gt;
&lt;div data-block-content=&quot;70c398afa686487a8bba22a701150bbe&quot;&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1644236166617&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const result = useQuery('todos', fetchTodoList);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;30e3eaaa8e374f388d9e53f3c1c894f6&quot;&gt;
&lt;div data-block-content=&quot;30e3eaaa8e374f388d9e53f3c1c894f6&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;1087296f371f47a3a5cecd38d0f413de&quot;&gt;&lt;span data-offset-key=&quot;1087296f371f47a3a5cecd38d0f413de:1&quot;&gt;쿼리의 상태는 4가지로 분류할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-key=&quot;2b1eedbe5f464c3c8dda64602ddbdcfc&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-key=&quot;bca468ccf13041a9afd75e800454b8b6&quot;&gt;
&lt;div data-block-content=&quot;bca468ccf13041a9afd75e800454b8b6&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;68084317e3dd491abc80cc5f39274868&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;2321f634ca89495d9336e773d716f651&quot;&gt;isLoading&lt;span data-offset-key=&quot;2321f634ca89495d9336e773d716f651:1&quot;&gt; , &lt;/span&gt;status === 'loading'&lt;span data-offset-key=&quot;2321f634ca89495d9336e773d716f651:3&quot;&gt; : 데이터 가져오는 중&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li data-key=&quot;c3bc1157fca84ad2984787ef2036b19c&quot;&gt;
&lt;div data-block-content=&quot;c3bc1157fca84ad2984787ef2036b19c&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;a9fd3cd97761471d8da5d02122317955&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;96668045176b439d93f268e6720f0130&quot;&gt;isError&lt;span data-offset-key=&quot;96668045176b439d93f268e6720f0130:1&quot;&gt;, &lt;/span&gt;status === 'error'&lt;span data-offset-key=&quot;96668045176b439d93f268e6720f0130:3&quot;&gt; : 에러 발생&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li data-key=&quot;f2168c6328b9488cb4bbe0e44981455e&quot;&gt;
&lt;div data-block-content=&quot;f2168c6328b9488cb4bbe0e44981455e&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;9f83bc21f4274333b03edcd2e5e90be2&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;1af2f5eb8b7546b2ada33550084118dc&quot;&gt;isSuccess&lt;span data-offset-key=&quot;1af2f5eb8b7546b2ada33550084118dc:1&quot;&gt; , &lt;/span&gt;status === 'success'&lt;span data-offset-key=&quot;1af2f5eb8b7546b2ada33550084118dc:3&quot;&gt; : 쿼링 성공&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li data-key=&quot;a6282a754df841c9a9d39895b150b7cd&quot;&gt;
&lt;div data-block-content=&quot;a6282a754df841c9a9d39895b150b7cd&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;6c535c9e5d3546ef81ca31f11f36d252&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;b0327aa11ec34070a0fccd5093358c5e&quot;&gt;isIdle&lt;span data-offset-key=&quot;b0327aa11ec34070a0fccd5093358c5e:1&quot;&gt;, &lt;/span&gt;status === 'idle'&lt;span data-offset-key=&quot;b0327aa11ec34070a0fccd5093358c5e:3&quot;&gt; : 쿼링 불가능&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;3100d39400f649748ee2e96fe4f1493a&quot;&gt;
&lt;div data-block-content=&quot;3100d39400f649748ee2e96fe4f1493a&quot;&gt;
&lt;h2 data-rnw-media-class=&quot;207__206&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span data-key=&quot;2573e15b73724e0da3c952d53bd38589&quot;&gt;&lt;span data-offset-key=&quot;2573e15b73724e0da3c952d53bd38589:0&quot;&gt;쿼리 키(Query Keys)&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;193228376e6d495a9282112f8c73a1c1&quot;&gt;
&lt;div data-block-content=&quot;193228376e6d495a9282112f8c73a1c1&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;94fb7692f97c4a6ea1cffeabb34ee389&quot;&gt;&lt;span data-offset-key=&quot;94fb7692f97c4a6ea1cffeabb34ee389:0&quot;&gt;react-query 는 쿼리의 &lt;/span&gt;&lt;b&gt;유니크한 키&lt;/b&gt;&lt;span data-offset-key=&quot;94fb7692f97c4a6ea1cffeabb34ee389:2&quot;&gt;&amp;nbsp;를 기반으로 쿼리 캐싱을 관리합니다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;9956aebfab0747b3a07cf7f4e667ca2b&quot;&gt;
&lt;div data-block-content=&quot;9956aebfab0747b3a07cf7f4e667ca2b&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;aaee2174f42247ebb9d3d7a6caabe5e3&quot;&gt;&lt;span data-offset-key=&quot;aaee2174f42247ebb9d3d7a6caabe5e3:0&quot;&gt;쿼리 키(Query Keys)는 문자열이 될 수도 있고 문자 배열이 될 수 도 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-key=&quot;5c5f3e5d1378445688d765e686e501af&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-key=&quot;536ec2b491c04f75abf3d505ec151aed&quot;&gt;
&lt;div data-block-content=&quot;536ec2b491c04f75abf3d505ec151aed&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;f62331af610d41e68e403de5288a229f&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;1d86f902d2a24f0a8979d54a96fe8706&quot;&gt;&lt;b&gt;문자열&lt;/b&gt;&lt;span data-offset-key=&quot;1d86f902d2a24f0a8979d54a96fe8706:1&quot;&gt; : 가장 단순한 형태의 쿼리 키는 문자열 입니다. 쿼리 키로 문자열이 전달되면 문자열을 사용하여 내부적으로 배열로 변환합니다.&lt;/span&gt;&lt;/span&gt;&lt;span data-key=&quot;a63f970b84e7404f82359abcb59e8bea&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot; data-offset-key=&quot;a63f970b84e7404f82359abcb59e8bea:9&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1644236185370&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; useQuery('todos', ...) // queryKey === ['todos']&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-key=&quot;cc11ff784c594a7fa5eccdef67057083&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-key=&quot;3b8acd8cdf884936962ed0b8abeb67c0&quot;&gt;
&lt;div data-block-content=&quot;3b8acd8cdf884936962ed0b8abeb67c0&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;ca7ea4baa3624c0c8a9da59d06b8306e&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;b78f2fcf982a4f929a3c052e86c56a1e&quot;&gt;&lt;span data-key=&quot;b78f2fcf982a4f929a3c052e86c56a1e&quot;&gt;&lt;b&gt;문자 배열&lt;/b&gt;&lt;span data-offset-key=&quot;b78f2fcf982a4f929a3c052e86c56a1e:1&quot;&gt; : 계층 구조의 데이터 / 파라미터가 있는 쿼리&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;pre id=&quot;code_1644236191664&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useQuery(['todo', 5], ...)
 // queryKey === ['todo', 5]
 
useQuery(['todo', 5, { preview: true }], ...)
 // queryKey === ['todo', 5, { preview: true }]
 
useQuery(['todos', { type: 'done' }], ...)
 // queryKey === ['todos', { type: 'done' }]&lt;/code&gt;&lt;/pre&gt;
&lt;span data-key=&quot;21775b7c3c6d439cadd5bead29fa3e74&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot; data-offset-key=&quot;21775b7c3c6d439cadd5bead29fa3e74:1&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>react</category>
      <category>react-query</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/72</guid>
      <comments>https://gusehd66.tistory.com/entry/React-React-Quries-%EA%B8%B0%EB%B3%B8%EC%82%AC%ED%95%AD#entry72comment</comments>
      <pubDate>Mon, 7 Feb 2022 21:22:59 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] hover 시 올라가는 버튼 만들기</title>
      <link>https://gusehd66.tistory.com/entry/CSS-hover-%EC%8B%9C-%EC%98%AC%EB%9D%BC%EA%B0%80%EB%8A%94-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;hover시 살짝 올라가는 버튼UI를 만들어보자.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2022-02-03 21;12;47.gif&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;245&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0FElA/btrstK23h9s/VMdWPGNi9KoXKhkzDPCrQ1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0FElA/btrstK23h9s/VMdWPGNi9KoXKhkzDPCrQ1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0FElA/btrstK23h9s/VMdWPGNi9KoXKhkzDPCrQ1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/0FElA/btrstK23h9s/VMdWPGNi9KoXKhkzDPCrQ1/img.gif&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;360&quot; height=&quot;245&quot; data-filename=&quot;2022-02-03 21;12;47.gif&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;245&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;pre id=&quot;code_1643889966427&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;body {
  background-color:lightgrey;
  display:flex;
  align-items:center;
  height:300px;
}

button {
  cursor: pointer;
  color: black;
  width: 300px;
  height: 30px;
  display: block;
  margin: 0 auto;
  border: solid 1px black;
  background-color: whitesmoke;
  border-radius: 5px;
  box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease 0s;
}

button:hover {
   background-color: #1b273f;
    box-shadow: 0px 15px 20px rgba(27, 39, 63, 0.4);
    color: whitesmoke;
    transform: translateY(-5px);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;codepen&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot; data-height=&quot;300&quot; data-default-tab=&quot;html,result&quot; data-slug-hash=&quot;xxPOWXK&quot; data-user=&quot;gusehd66&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/gusehd66/pen/xxPOWXK&quot;&gt; Untitled&lt;/a&gt; by 김현동 (&lt;a href=&quot;https://codepen.io/gusehd66&quot;&gt;@gusehd66&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;</description>
      <category>CSS</category>
      <category>CSS</category>
      <category>hover</category>
      <category>올라가는 버튼</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/71</guid>
      <comments>https://gusehd66.tistory.com/entry/CSS-hover-%EC%8B%9C-%EC%98%AC%EB%9D%BC%EA%B0%80%EB%8A%94-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0#entry71comment</comments>
      <pubDate>Thu, 3 Feb 2022 21:21:10 +0900</pubDate>
    </item>
    <item>
      <title>[React] React가 불변성을 지키는 이유</title>
      <link>https://gusehd66.tistory.com/entry/React-React%EA%B0%80-%EB%B6%88%EB%B3%80%EC%84%B1%EC%9D%84-%EC%A7%80%ED%82%A4%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;React가&amp;nbsp;불변성을&amp;nbsp;지키는&amp;nbsp;이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React가 불변성을 지키는 이유는 부모컴포넌트가 re-rendering 되거나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state,props가 변화될 때 렌더링이 일어나게 된다.&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;근데 렌더링을 할지 말지 판단하기 위해 state가 변화되는지를 판단한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 과정에서 state 객체 내의 모든 value를 다 깊은 비교하면 당연하게도 효율적이지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;state를 직접 변경하게 되면 value 값은 바뀌지만 참조 값은 바뀌지 않으므로 렌더링이 일어나지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mutable한 상태를 사용하게 되면 리액트 돔이 제대로 된 추적을 할 수 없을 것이고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예기치 않은 사이드 이펙트를 발생시킬 수 있다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;어떻게 불변성을 지킬까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;스프레드 문법, map, filter, slice, reduce 와 같은 새로운 배열을 반환하는 메소드들을 활용한다.&lt;/span&gt;&lt;span&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&gt;setState를 이용할 때 원시타입 경우에는 값을 바로 넣어주어도 되지만&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;참조타입인 경우에는 새로운 객체나 배열을 생성한 후 값을 넣어주어야 한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1643274514422&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 원시타입
const [number, setNumber] = useState(0)
setState(7)

// 참조타입
const [cellPhone, setCellPhone] = useState({ type: 'iphone', series : &quot;12pro&quot; })
setState({...cellPhone, series: '13'})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>react</category>
      <category>react 불변성</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/70</guid>
      <comments>https://gusehd66.tistory.com/entry/React-React%EA%B0%80-%EB%B6%88%EB%B3%80%EC%84%B1%EC%9D%84-%EC%A7%80%ED%82%A4%EB%8A%94-%EC%9D%B4%EC%9C%A0#entry70comment</comments>
      <pubDate>Thu, 27 Jan 2022 18:14:15 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] Reduce 메서드란 ?</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-Reduce-%EB%A9%94%EC%84%9C%EB%93%9C%EB%9E%80</link>
      <description>&lt;div&gt;
&lt;div&gt;&lt;b&gt;Reduce 메서드란?&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서 함수를 실행하고, 하나의 결과값을 반환한다.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;map과 forEach 와는 조금 다른 &lt;span style=&quot;color: #ee2323;&quot;&gt;누산값&lt;/span&gt;을 곁들인 메서드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문법&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1643113294960&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// reduce
const array1 = [10, 20, 30, 40];

array1.reduce((누산값, 현재요소값, 현재요소의index, 현재배열) =&amp;gt; {
  return 다음누산값;
}, 초기누산값);&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;212&quot; data-origin-height=&quot;199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zHLDm/btrrKx4Bj05/wyu1IRk1QTDvQLk940FCKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zHLDm/btrrKx4Bj05/wyu1IRk1QTDvQLk940FCKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zHLDm/btrrKx4Bj05/wyu1IRk1QTDvQLk940FCKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzHLDm%2FbtrrKx4Bj05%2Fwyu1IRk1QTDvQLk940FCKk%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;212&quot; height=&quot;199&quot; data-origin-width=&quot;212&quot; data-origin-height=&quot;199&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
reduce 메서드 자체의 반환값은 100이 된다.&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 콜백 함수&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백 함수의 첫 번째 파라미터는 reduce 메서드에서 이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;콜백 함수가 동작할 때 &lt;u&gt;return 하는 값이 다음 콜백 함수의 첫 번째 파라미터&lt;/u&gt;로 전달&lt;/b&gt;&lt;/span&gt;되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;배열의 요소를 다 돌고&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;마지막 콜백 함수가 동작한 이후의 return 값이 reduce 메서드의 return 값&lt;/span&gt;&lt;/b&gt;이 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백 함수의&lt;span&gt;&amp;nbsp;&lt;/span&gt;파라미터 생략은, 3,4번째 파라미터만 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 초기누산 값&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 파라미터인 초기누산값을 주지 않으면 &lt;span style=&quot;color: #ee2323;&quot;&gt;배열의 인덱스 0 값&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;b&gt;응용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1643113294962&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const hangul = ['가', '나', '다', '가', '나',
   '다', '라', '가', '나', '마'];

const result = hangul.reduce((acc, el, i) =&amp;gt; {
  console.log(`${i}번째`)
  console.log(`acc:`, acc);
  console.log(`현재 값:`, el);

  acc[el] = (acc[el] || 0) + 1;

  return acc;
}, {});

console.log(&quot;결과: &quot;,result);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드처럼 초기값을 빈 객체로 두고, 배열을 돌면서 중복된 요소를 카운트하는 데에도 충분히 활용할 수가 있다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;324&quot; data-origin-height=&quot;659&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dj6fOg/btrrIXbQSt5/GXqeTkfNuvOCud1BTboYj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dj6fOg/btrrIXbQSt5/GXqeTkfNuvOCud1BTboYj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dj6fOg/btrrIXbQSt5/GXqeTkfNuvOCud1BTboYj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdj6fOg%2FbtrrIXbQSt5%2FGXqeTkfNuvOCud1BTboYj1%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;324&quot; height=&quot;659&quot; data-origin-width=&quot;324&quot; data-origin-height=&quot;659&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 파라미터를 생략 했을 때의 결과&lt;/p&gt;
&lt;pre id=&quot;code_1643113294964&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const numbers = [1, 2, 3];

const sum = numbers.reduce((acc, el, i) =&amp;gt; {
  console.log(`${i}번째 콜백함수`)
  console.log(`acc: ${acc}`);
  console.log(`현재값: ${el}`);

  return el + acc;
});

console.log(`결과: ${sum}`);&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;122&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y7SrN/btrrF7syTTR/XKy2pePBvyLlXBOrZwKYo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y7SrN/btrrF7syTTR/XKy2pePBvyLlXBOrZwKYo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y7SrN/btrrF7syTTR/XKy2pePBvyLlXBOrZwKYo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy7SrN%2FbtrrF7syTTR%2FXKy2pePBvyLlXBOrZwKYo0%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;122&quot; height=&quot;148&quot; data-origin-width=&quot;122&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;배열의 index 0이 초기값이 되기 때문에,&amp;nbsp; 0번째 콜백 함수는 동작하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콜백 함수의 동작 횟수에 따라 결과에 차이가 있을법한 경우라면 오류로 이어질 수&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;있기 때문에, 생략은 가능하지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;생략하지 않는 것이 권장&lt;/span&gt;&lt;/b&gt;된다.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>reduce</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/69</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-Reduce-%EB%A9%94%EC%84%9C%EB%93%9C%EB%9E%80#entry69comment</comments>
      <pubDate>Tue, 25 Jan 2022 22:24:20 +0900</pubDate>
    </item>
    <item>
      <title>[React] 배열의 key값으로 index를 사용하지 말자</title>
      <link>https://gusehd66.tistory.com/entry/React-%EB%B0%B0%EC%97%B4%EC%9D%98-key%EA%B0%92%EC%9C%BC%EB%A1%9C-index%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EB%A7%90%EC%9E%90</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #212529;&quot;&gt;Each child in an array should have a unique &amp;ldquo;key&amp;rdquo; prop.&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열을 사용하는데 key 값을 까먹고 넣지 않으면&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;Each child in an array should have a unique &amp;ldquo;key&amp;rdquo; prop.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔창에서 위와 같은 문구를 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 유니크한 key 값이 필요하다는 것!&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;Key값이 왜 필요한가 ?&lt;/h3&gt;
&lt;pre id=&quot;code_1642133751114&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ul&amp;gt;
  &amp;lt;li&amp;gt;첫번째&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;두번째&amp;lt;/li&amp;gt;  
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1642133756328&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ul&amp;gt;
  &amp;lt;li&amp;gt;첫번째&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;두번째&amp;lt;/li&amp;gt;  
  &amp;lt;li&amp;gt;세번째&amp;lt;/li&amp;gt;  
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스트의 엘리먼트를 하나 더 추가하면 두 트리의 변경은 잘 작동하지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;key 값이 없기 때문에 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;변경되지 않은 엘리먼트 또한 재평가&lt;/b&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;이런 문제를 해결하기 위해 key값을 &lt;s&gt;넣어주는것이 좋다.&lt;/s&gt; &lt;span style=&quot;background-color: #dddddd; color: #006dd7;&quot;&gt;넣어주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;key 값을 넣어주게 되면 key값으로 판단하여 변경된 부분만 추가할 수 있게되기 때문인데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;key 값을 index로 사용하게 되면 배열을 추가하거나 삭제할때 바뀐부분을 찾지 못할 수 있게된다.&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;list가 변경되었을 때 list 가 다시 재평가가 되며 index가 다시 부여 되기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 key값에 index를 넣는것은 지양해야 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 정적이고 변경되지 않을 배열에는 사용해도 무방하다.&lt;/p&gt;</description>
      <category>React</category>
      <category>index</category>
      <category>unique key</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/68</guid>
      <comments>https://gusehd66.tistory.com/entry/React-%EB%B0%B0%EC%97%B4%EC%9D%98-key%EA%B0%92%EC%9C%BC%EB%A1%9C-index%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EB%A7%90%EC%9E%90#entry68comment</comments>
      <pubDate>Fri, 14 Jan 2022 13:32:43 +0900</pubDate>
    </item>
    <item>
      <title>[React] CRA 디폴트 파일인 reportWebVitals</title>
      <link>https://gusehd66.tistory.com/entry/React-CRA-%EB%94%94%ED%8F%B4%ED%8A%B8-%ED%8C%8C%EC%9D%BC%EC%9D%B8-reportWebVitals</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDGVov/btroTc45L93/F2JK4V6en6eQ2zcmb8ZlmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDGVov/btroTc45L93/F2JK4V6en6eQ2zcmb8ZlmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDGVov/btroTc45L93/F2JK4V6en6eQ2zcmb8ZlmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDGVov%2FbtroTc45L93%2FF2JK4V6en6eQ2zcmb8ZlmK%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;641&quot; height=&quot;366&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CRA로 리액트 프로젝트를 생성하고 index.js 를 보면 맨 밑에 reportWebVitals() 라는 함수를 실행하고 있는 부분이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이부분은 같은 폴더의 reportWebVitals 파일에서 가져온 함수를 실행하고 있는 것인데&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;주석 처리된 예 처럼 함수에 console.log를 넣어주면 개발창으로 앱의 퍼포먼스시간들을 분석하여 객체 형태로 보여준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;541&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfFVZS/btro37HUELk/TJN47r5y7C0RwmC8UKKd01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfFVZS/btro37HUELk/TJN47r5y7C0RwmC8UKKd01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfFVZS/btro37HUELk/TJN47r5y7C0RwmC8UKKd01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfFVZS%2Fbtro37HUELk%2FTJN47r5y7C0RwmC8UKKd01%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;541&quot; height=&quot;424&quot; data-origin-width=&quot;541&quot; data-origin-height=&quot;424&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;&lt;br /&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&amp;nbsp;&amp;nbsp;//&amp;nbsp;metric(측정도구)&amp;nbsp;이름&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;name:&amp;nbsp;'CLS'&amp;nbsp;|&amp;nbsp;'FCP'&amp;nbsp;|&amp;nbsp;'FID'&amp;nbsp;|&amp;nbsp;'LCP'&amp;nbsp;|&amp;nbsp;'TTFB';&lt;/b&gt; &lt;br /&gt;&amp;nbsp;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&amp;nbsp;//&amp;nbsp;측정된&amp;nbsp;현재값&amp;nbsp;(값이&amp;nbsp;작을수록&amp;nbsp;빠른성능을&amp;nbsp;뜻합니다)&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;value:&amp;nbsp;number;&lt;/b&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;//&amp;nbsp;&amp;nbsp;현재&amp;nbsp;측정값(current&amp;nbsp;value)과&amp;nbsp;최신&amp;nbsp;측정값(last-reported&amp;nbsp;value)&amp;nbsp;차이&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&amp;nbsp;//&amp;nbsp;&amp;nbsp;첫번째&amp;nbsp;리포트에서&amp;nbsp;위&amp;nbsp;둘값은&amp;nbsp;항상&amp;nbsp;같습니다.&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;delta:&amp;nbsp;number;&lt;/b&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;//&amp;nbsp;특정&amp;nbsp;측정도구를&amp;nbsp;나타대는&amp;nbsp;유니크한&amp;nbsp;ID&amp;nbsp;값으로&amp;nbsp;중복되는&amp;nbsp;값들을&amp;nbsp;관리할&amp;nbsp;때&amp;nbsp;사용된다.&lt;/span&gt; &lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;id:&amp;nbsp;string;&lt;/b&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;//&amp;nbsp;계산된&amp;nbsp;측정값들의&amp;nbsp;내용들이&amp;nbsp;배열로&amp;nbsp;나열&amp;nbsp;된다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&amp;nbsp;&amp;nbsp;//&amp;nbsp;ex)&amp;nbsp;PerformanceNavigationTiming,&amp;nbsp;LargestContentfulPaint&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;entries:&amp;nbsp;(PerformanceEntry&amp;nbsp;|&amp;nbsp;FirstInputPolyfillEntry&amp;nbsp;|&amp;nbsp;NavigationTimingPolyfillEntry)[];&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Ref&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/GoogleChrome/web-vitals/#types&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/GoogleChrome/web-vitals/#types&lt;/a&gt;&lt;/p&gt;</description>
      <category>React</category>
      <category>CRA</category>
      <category>react</category>
      <category>reportWebVitals</category>
      <category>webvital</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/67</guid>
      <comments>https://gusehd66.tistory.com/entry/React-CRA-%EB%94%94%ED%8F%B4%ED%8A%B8-%ED%8C%8C%EC%9D%BC%EC%9D%B8-reportWebVitals#entry67comment</comments>
      <pubDate>Mon, 27 Dec 2021 20:38:37 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] 자바스크립트의 표준화</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-%ED%91%9C%EC%A4%80%ED%99%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;넷스케이프 커뮤니케이션즈와 마이크로소프트가 자사 브라우저의 시장 점유율을 높이기 위해 자사 브라우저에서만 동작하는 기능을 추가하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로 인해 브라우저에 따라 웹페이지가 정상적으로 동작하지 않는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;크로스 브라우징 이슈&lt;/u&gt;&lt;/span&gt;가 발생하기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제점을 방지하기 위해 자바스크립트의 표준화가 필요했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 69.5349%; height: 220px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; text-align: center; height: 20px;&quot;&gt;버전&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; text-align: center; height: 20px;&quot;&gt;출시 연도&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; text-align: center; height: 20px;&quot;&gt;특징&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; text-align: center; height: 20px;&quot;&gt;ES1&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;1997&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; text-align: center; height: 20px;&quot;&gt;초판&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #efefef;&quot;&gt;ES2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;1998&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;ISO/IEC 16262 국제표준과 동일한 규격 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;ES3&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;1999&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;정규 표현식, try...catch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;ES5&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;2009&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;(HTML5와 함께 출현한 표준안)&lt;br /&gt;JSON, strict mode, 접근자 프로퍼티,&amp;nbsp;&lt;br /&gt;forEach, map, filter, reduce, some, every&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;ES6&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;2015&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;let/const, 클래스, 화살표 함수, 템플릿 리터럴, 디스트럭처링 할당, 스프레드 문법, rest 파라미터, 심벌, 프로미스, 이터러블, for...of, 모듈 import/export&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;ES7&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;2016&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;지수 연산자, Array.prototype.includes, String.prototype.includes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;ES8&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;2017&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;async/await, Object&amp;nbsp; 정적 메서드(Object.values, Object.entries, Object.getOwnPropertyDescriptors)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;ES9&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;2018&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;Object rest/spread 프로퍼티, Promise.prototype.finally, for await..of&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;ES10&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;2019&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;Object.fromEntries, &lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;Array.prototype.flat, Array.prototype.flatMap&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 19.9554%; height: 20px; text-align: center;&quot;&gt;ES11&lt;/td&gt;
&lt;td style=&quot;width: 19.7881%; height: 20px; text-align: center;&quot;&gt;2020&lt;/td&gt;
&lt;td style=&quot;width: 60.2564%; height: 20px; text-align: center;&quot;&gt;String.prototype.matchAll, BigInt, globalThis, null 병합 연산자, 옵셔널 체이닝 연산자&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>자바스크립트</category>
      <category>표준화</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/66</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-%ED%91%9C%EC%A4%80%ED%99%94#entry66comment</comments>
      <pubDate>Mon, 15 Nov 2021 16:22:08 +0900</pubDate>
    </item>
    <item>
      <title>[React] npm install EEXIST: file already exists 해결하기</title>
      <link>https://gusehd66.tistory.com/entry/React-npm-install-EEXIST-file-already-exists-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;EEXIST:&amp;nbsp;file&amp;nbsp;already&amp;nbsp;exists&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;npm i react-router-dom을 하는데 오류가 떴습니다.&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;160&quot; data-origin-height=&quot;27&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RQgRx/btripEGP8sq/JbGQFnaevEZ2zR7R8ARkSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RQgRx/btripEGP8sq/JbGQFnaevEZ2zR7R8ARkSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RQgRx/btripEGP8sq/JbGQFnaevEZ2zR7R8ARkSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRQgRx%2FbtripEGP8sq%2FJbGQFnaevEZ2zR7R8ARkSk%2Fimg.png&quot; data-origin-width=&quot;160&quot; data-origin-height=&quot;27&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;size18&quot;&gt;react-router-dom 뿐만아니라 npm install 시 이런 오류가 날 수 있는데요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오류는 이미 사용중이다 존재한다 라고 해서&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;권한 문제일까 싶어&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;cmd 창을 관리자 권한으로 실행해서 npm install 을 해도 마찬가지였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결책&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-ke-size=&quot;size18&quot;&gt;node_modules 폴더 삭제&lt;/li&gt;
&lt;li data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;npm install&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;npm audit fix&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그리고 실행했더니 성공하였습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>code EEXIST</category>
      <category>npm error</category>
      <category>react</category>
      <category>react-router-dom error</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/65</guid>
      <comments>https://gusehd66.tistory.com/entry/React-npm-install-EEXIST-file-already-exists-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0#entry65comment</comments>
      <pubDate>Thu, 21 Oct 2021 22:19:11 +0900</pubDate>
    </item>
    <item>
      <title>[React] Warning: Invalid DOM property `for`. Did you mean `htmlFor`?</title>
      <link>https://gusehd66.tistory.com/entry/React-Warning-Invalid-DOM-property-for-Did-you-mean-htmlFor</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;JSX에서 for 오류&lt;/u&gt;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Waring 코드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Warning: Invalid DOM property `for`. Did you mean `htmlFor`?&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-origin-width=&quot;583&quot; data-origin-height=&quot;188&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lQekO/btrhVZ4D8LE/MiYpTjvKHcrPciFf8eaKjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lQekO/btrhVZ4D8LE/MiYpTjvKHcrPciFf8eaKjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lQekO/btrhVZ4D8LE/MiYpTjvKHcrPciFf8eaKjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlQekO%2FbtrhVZ4D8LE%2FMiYpTjvKHcrPciFf8eaKjK%2Fimg.png&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;188&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;h4 data-ke-size=&quot;size20&quot;&gt;이유&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX는 javaScrit이기 때문에 for은 반복의 의미를 가지고 있어서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 상에서는 htmlFor을 써줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결방법&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;for대신&lt;span&gt;&amp;nbsp;&lt;/span&gt;htmlFor을 써야한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1634374769600&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// warning
&amp;lt;label for=&quot;attach-file&quot; className=&quot;factoryInput__label&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1634374784929&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;label htmlFor=&quot;attach-file&quot; className=&quot;factoryInput__label&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>React</category>
      <category>jsx</category>
      <category>react</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/64</guid>
      <comments>https://gusehd66.tistory.com/entry/React-Warning-Invalid-DOM-property-for-Did-you-mean-htmlFor#entry64comment</comments>
      <pubDate>Sat, 16 Oct 2021 18:00:35 +0900</pubDate>
    </item>
    <item>
      <title>[React]  Warning: React does not recognize the `computedMatch` prop on a DOM element</title>
      <link>https://gusehd66.tistory.com/entry/React-Warning-React-does-not-recognize-the-computedMatch-prop-on-a-DOM-element</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Warning 코드&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Warning: React does not recognize the&lt;span&gt;&amp;nbsp;&lt;/span&gt;computedMatch&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase&lt;span&gt;&amp;nbsp;&lt;/span&gt;computedmatch&lt;span&gt;&amp;nbsp;&lt;/span&gt;instead. If you accidentally passed it from a parent component, remove it from the DOM element.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;449&quot; data-origin-height=&quot;246&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dgEUw3/btrhUX0xTur/BJEJfMDMJz6HEoWGXn2Wm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dgEUw3/btrhUX0xTur/BJEJfMDMJz6HEoWGXn2Wm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dgEUw3/btrhUX0xTur/BJEJfMDMJz6HEoWGXn2Wm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdgEUw3%2FbtrhUX0xTur%2FBJEJfMDMJz6HEoWGXn2Wm1%2Fimg.png&quot; data-origin-width=&quot;449&quot; data-origin-height=&quot;246&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;p data-ke-size=&quot;size16&quot;&gt;react-router-dom을 사용할 때 위와 같은 오류가 뜰 때가 있었다.&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;/p&gt;
&lt;pre id=&quot;code_1634373234679&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Switch&amp;gt;
                &amp;lt;&amp;gt;
                {isLoggedIn ? (
                &amp;lt;div
                    style={{
                        maxWidth: 890,
                        width: &quot;100%&quot;,
                        margin: &quot;0 auto&quot;,
                        marginTop: 80,
                        display: &quot;flex&quot;,
                        justifyContent: &quot;center&quot;,
                    }}
                &amp;gt;
                    &amp;lt;Route exact path=&quot;/&quot;&amp;gt;
                        &amp;lt;Home userObj={userObj} /&amp;gt;
                    &amp;lt;/Route&amp;gt;
                    &amp;lt;Route exact path=&quot;/profile&quot;&amp;gt;
                        &amp;lt;Profile userObj={userObj} refreshUser={refreshUser}/&amp;gt;
                    &amp;lt;/Route&amp;gt;
                &amp;lt;/div&amp;gt;
                ): (&amp;lt;Route exact Path=&quot;/&quot;&amp;gt;
                    &amp;lt;Auth/&amp;gt;
                &amp;lt;/Route&amp;gt;
                )}
                &amp;lt;/&amp;gt;
            &amp;lt;/Switch&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Switch 태그안에 Fragment 태그(&amp;lt;&amp;gt; &amp;lt;/&amp;gt;)를 사용하면된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;리액트 공식문서 발췌&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The unknown-prop warning will fire if you attempt to render a DOM element with a prop that is not recognized by React as a legal DOM attribute/property. You should ensure that your DOM elements do not have spurious props floating around.&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에서 합법적 인 DOM 속성 / 속성으로 인식되지 않는 소품으로 DOM 요소를 렌더링하려고하면 unknown-prop 경고가 발생합니다. DOM 요소에 허위 소품이 떠 다니지 않도록해야합니다.&lt;/p&gt;</description>
      <category>React</category>
      <category>computedMatch</category>
      <category>react</category>
      <category>react warning</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/63</guid>
      <comments>https://gusehd66.tistory.com/entry/React-Warning-React-does-not-recognize-the-computedMatch-prop-on-a-DOM-element#entry63comment</comments>
      <pubDate>Sat, 16 Oct 2021 17:37:32 +0900</pubDate>
    </item>
    <item>
      <title>[Git] error: GH007: Your push would publish a private email address</title>
      <link>https://gusehd66.tistory.com/entry/Git-error-GH007-Your-push-would-publish-a-private-email-address</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;개인 프로젝트를 여느 날과 똑같이 작업을 하고 커밋&amp;amp;푸시를 했는데 rejected 메시지가 뜨면서 푸시가 되질 않았다..&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;push 도중 만난&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-origin-width=&quot;573&quot; data-origin-height=&quot;153&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHDDks/btrgqxnR0OI/LKin9q1YSNGQ08VLInXXk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHDDks/btrgqxnR0OI/LKin9q1YSNGQ08VLInXXk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHDDks/btrgqxnR0OI/LKin9q1YSNGQ08VLInXXk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHDDks%2FbtrgqxnR0OI%2FLKin9q1YSNGQ08VLInXXk1%2Fimg.png&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;153&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;라는 에러 메시지였다.&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;/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-origin-width=&quot;771&quot; data-origin-height=&quot;81&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHSYGw/btrgjy2Ryp7/hX491aCPSyDYeLfNrApvy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHSYGw/btrgjy2Ryp7/hX491aCPSyDYeLfNrApvy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHSYGw/btrgjy2Ryp7/hX491aCPSyDYeLfNrApvy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHSYGw%2Fbtrgjy2Ryp7%2FhX491aCPSyDYeLfNrApvy1%2Fimg.png&quot; data-origin-width=&quot;771&quot; data-origin-height=&quot;81&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;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YVknI/btqHLfnz5yM/zDh7o2jHeRDNkmCOcTsMX0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;구글의 자동번역&quot;&gt;위의 설정이 체크되어 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YVknI/btqHLfnz5yM/zDh7o2jHeRDNkmCOcTsMX0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;구글의 자동번역&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 data-url=&quot;https://blog.kakaocdn.net/dn/YVknI/btqHLfnz5yM/zDh7o2jHeRDNkmCOcTsMX0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;구글의 자동번역&quot;&gt;내용은 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YVknI/btqHLfnz5yM/zDh7o2jHeRDNkmCOcTsMX0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;구글의 자동번역&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;내이메일을 노출하는 명령줄 푸시 차단&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;(작성자 이메일로 비공개 이메일을 사용하는 커밋을 푸시하면 푸시를 차단하고 비공개 이메일 노출에 대해 경고합니다.)&lt;/b&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Git</category>
      <category>GH007</category>
      <category>Git</category>
      <category>git error</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/62</guid>
      <comments>https://gusehd66.tistory.com/entry/Git-error-GH007-Your-push-would-publish-a-private-email-address#entry62comment</comments>
      <pubDate>Thu, 30 Sep 2021 13:24:50 +0900</pubDate>
    </item>
    <item>
      <title>[React] 리액트 렌더링이 두 번 발생하는 이유</title>
      <link>https://gusehd66.tistory.com/entry/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%B4-%EB%91%90-%EB%B2%88-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;렌더링이 두 번 발생하는 이유는&amp;nbsp;&lt;/span&gt;&lt;b&gt;React.StrictMode&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;u&gt;npx create-react-app 으로 생성하면 자동 설정이 되있습니다.&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;따라서 &lt;b&gt;index.js&lt;/b&gt; 에서 이 Wrapper를 제거해주면 컴포넌트가 두번씩 호출되지 않습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1631509161413&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ReactDOM.render(
    &amp;lt;App /&amp;gt;,
  document.getElementById('root')
);&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;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;StrictMode는 애플리케이션 내의 잠재적인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;문제를 알아내기 위한 도구&lt;/b&gt;입니다.&lt;br /&gt;Fragment와 같이 UI를 렌더링하지 않으며, 자손들에 대한 부가적인 검사와 경고를 활성화합니다.&lt;br /&gt;Strict 모드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;개발 모드에서만 활성화&lt;/b&gt;되기 때문에, 프로덕션 빌드에는 영향을 끼치지 않습니다.&lt;br /&gt;&lt;a href=&quot;https://ko.reactjs.org/docs/strict-mode.html#gatsby-focus-wrapper&quot;&gt;리액트 공식문서&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;StrictMode는 아래와 같은 부분에서 도움이 됩니다.&lt;/p&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;레거시 문자열 ref 사용에 대한 경고&lt;/li&gt;
&lt;li&gt;권장되지 않는 findDOMNode 사용에 대한 경고&lt;/li&gt;
&lt;li&gt;예상치 못한 부작용 검사&lt;/li&gt;
&lt;li&gt;레거시 context API 검사&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>React</category>
      <category>react</category>
      <category>렌더링</category>
      <category>리액트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/61</guid>
      <comments>https://gusehd66.tistory.com/entry/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%B4-%EB%91%90-%EB%B2%88-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0#entry61comment</comments>
      <pubDate>Mon, 13 Sep 2021 14:00:52 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] Storage(localStorage, sessionStorage)</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-StoragelocalStorage-sessionStorage</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;자바스크립트로 웹 개발을 할 때, 데이터를 저장하고 싶은데 저장해야할 데이터가 별로 중요하지 않거나, 유실되도 무방할 데이터라면 서버 단에 데이터를 저장하는 것이 낭비일 수가 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;로컬-스토리지-vs-세션-스토리지&quot; data-ke-size=&quot;size26&quot;&gt;로컬 스토리지 vs. 세션 스토리지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;하지만 이러한 로컬 스토리지의 데이터 영속성(persistence) 어디까지나 계속해서 동일한 컴퓨터에서 동일한 브라우저를 사용할 때만 해당합니다.&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가 완전히 동일한 형태입니다. 따라서, 본 포스팅에서는 로컬 스토리지 기준으로만 예시를 드리려고 합니다. 세션 스토리지를 사용하실 때는 예제 코드의&lt;span&gt;&amp;nbsp;&lt;/span&gt;localStorage&lt;span&gt;&amp;nbsp;&lt;/span&gt;부분을&lt;span&gt;&amp;nbsp;&lt;/span&gt;sessionStorage로 대체하시기만 하면 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;기본-api&quot; data-ke-size=&quot;size26&quot;&gt;기본 API&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 스토리지는 기본적으로 키(key)와 값(value)으로 이루어진 데이터를 저장할 수 있습니다. 개념적으로 해시 테이블 자료 구조를 생각하시면 이해가 쉬우실 것 같습니다. 자바스크립트 API의 기본적인 사용 방법은 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630655174396&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 키에 데이터 쓰기
localStorage.setItem(&quot;key&quot;, value);

// 키로 부터 데이터 읽기
localStorage.getItem(&quot;key&quot;);

// 키의 데이터 삭제
localStorage.removeItem(&quot;key&quot;);

// 모든 키의 데이터 삭제
localStorage.clear();

// 저장된 키/값 쌍의 개수
localStorage.length;&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&gt;&amp;nbsp;&lt;/span&gt;window.localStorage를 사용해야하지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;window&lt;span&gt;&amp;nbsp;&lt;/span&gt;객체의 대부분의 속성이 그러하듯, 줄여서&lt;span&gt;&amp;nbsp;&lt;/span&gt;localStorage로 로컬 스토리지 객체에 접근할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저의 콘솔 창을 열고 다음과 같이 테스트를 해보시면 대강 어떻게 사용하는지 금방 감이 잡히실 겁니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630655188951&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; localStorage.getItem('name')
null
&amp;gt; localStorage.getItem('email')
null
&amp;gt; localStorage.setItem('email', 'test@user.com')
undefined
&amp;gt; localStorage.getItem('email')
&quot;test@user.com&quot;
&amp;gt; localStorage.setItem('email', 'test@admin.com')
undefined
&amp;gt; localStorage.getItem('email')
&quot;test@admin.com&quot;
&amp;gt; localStorage.removeItem('email')
undefined
&amp;gt; localStorage.getItem('email')
null&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;주의-사항&quot; data-ke-size=&quot;size26&quot;&gt;주의 사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 스토리지를 사용할 때 주의해야 할 부분이 하나 있는데요. 오직 문자형(string) 데이터 타입만 지원한다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 숫자형 데이터를 로컬 스토리지에 쓰고 다시 다시 읽어보면 다음과 같이 본래 숫자가 아닌 문자가 나오는 것을 알 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630655228303&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; localStorage.setItem('num', 1)
undefined
&amp;gt; localStorage.getItem('num') === 1
false
&amp;gt; localStorage.getItem('num')
&quot;1&quot;
&amp;gt; typeof localStorage.getItem('num')
&quot;string&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 웹 스토리지의 성질 때문에 객체형 데이터를 저장할 때 다음과 같이 큰 낭패를 보게 될 수도 있습니다.&amp;nbsp;&lt;span style=&quot;color: #7ec699;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1630655238576&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; localStorage.setItem('obj', {a: 1, b: 2})
undefined
&amp;gt; localStorage.getItem('obj')
&quot;[object Object]&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제가 발생하는 이유는 웹 스토리지는 문자열 데이터 밖에 저장할 수 없기 때문에, 다른 타입의 데이터를 저장하려고 할 때 문자형으로 변환을 하기 때문입니다.&lt;span style=&quot;color: #7ec699;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1630655263365&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; String(1)
&quot;1&quot;
&amp;gt; String({a: 1, b: 2})
&quot;[object Object]&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;해결-방법&quot; data-ke-size=&quot;size26&quot;&gt;해결 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 스토리지를 사용할 때 위와 같은 문제를 피하기 위해서 많이 사용하는 방법이 JSON 형태로 데이터를 읽고 쓰는 것입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630655314105&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; localStorage.setItem('json', JSON.stringify({a: 1, b: 2}))
undefined
&amp;gt; JSON.parse(localStorage.getItem('json'))
{a: 1, b: 2}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 로컬 스토리지에 쓸 데이터를 JSON 형태로 직렬화(serialization)하고, 읽은 데이터를 JSON 형태로 역직렬화(deserialization)해주면 원본의 데이터를 그대로 얻을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열형 데이터를 로컬 스토리지에 저장할 때도 동일한 방법을 문제를 예방할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630655320339&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; localStorage.setItem('nums', JSON.stringify([1, 2, 3]))
undefined
&amp;gt; JSON.parse(localStorage.getItem('nums'))
[1, 2, 3]&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;데이터-청소&quot; data-ke-size=&quot;size26&quot;&gt;데이터 청소&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 스토리지에 저장된 데이터는 웹페이지를 닫는다고 해서 사라지지 않으므로 불필요한 데이터가 남지 않도록 직접 청소해주는 것이 좋겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630655327934&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; localStorage.length
5
&amp;gt; localStorage.key(0)
&quot;email&quot;
&amp;gt; localStorage.removeItem('obj')
undefined
&amp;gt; localStorage.length
4
&amp;gt; localStorage.clear()
undefined
&amp;gt; localStorage.length
0&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;참고로 브라우저의 개발자 도구를 통해서 웹 스토리지에 어떤 데이터가 저장되어 있는지를 쉽게 확인하고 삭제할 수 있습니다. 예를 들어, 크롬의 경우 Application 탭에 들어가면 왼편에 Storage 영역이 보일 것입니다.&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;웹 스토리지에 대한 좀 더 자세한 내용은 아래 MDN 문서를 참고바랍니다.&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/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>LocalStorage</category>
      <category>sessionStorage</category>
      <category>storage</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/60</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-StoragelocalStorage-sessionStorage#entry60comment</comments>
      <pubDate>Fri, 3 Sep 2021 16:49:42 +0900</pubDate>
    </item>
    <item>
      <title>[Javascript] ES11 (ECMAScript 2020)</title>
      <link>https://gusehd66.tistory.com/entry/Javascript-ES11-ECMAScript-2020</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;ES11 에서 추가된 기능들에 대해서 알아보겠습니다.&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;optional-chaining&quot; data-ke-size=&quot;size26&quot;&gt;1. Optional Chaining(?.)&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. globalThis&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Nullish coalescing Operator(??)&lt;/h2&gt;
&lt;h2 id=&quot;globalthis&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;dynamic-import&quot; data-ke-size=&quot;size26&quot;&gt;4. Dynamic import&lt;/h2&gt;
&lt;h2 id=&quot;bigint&quot; data-ke-size=&quot;size26&quot;&gt;5. BigInt&lt;/h2&gt;
&lt;h2 id=&quot;stringprototypematchall&quot; data-ke-size=&quot;size26&quot;&gt;6. String.prototype.matchAll&lt;/h2&gt;
&lt;h2 id=&quot;promiseallsettled&quot; data-ke-size=&quot;size26&quot;&gt;7. Promise.allSettled&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;optional-chaining&quot; data-ke-size=&quot;size26&quot;&gt;1. Optional Chaining (?.)&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;옵셔널 체이닝(optional chaining)&amp;nbsp;?.을 사용하면 프로퍼티가 없는 중첩 객체를 에러 없이 안전하게 접근할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;?.은 ?.'앞&amp;rsquo;의 평가 대상이 undefined나 null이면 평가를 멈추고 undefined를 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1630553909522&quot; class=&quot;javascript&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; color: #666666; font-size: 14px; 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; background-color: #ffffff;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const data = {
  user: {
    name: 'foo',
    getName() {
      return this.name
    }
  }
}

const user1 = data?.user // {...}
// 위와 동일한 동작을 함
const user2 = data !== undefined &amp;amp;&amp;amp; data !== null ? data.user : undefined // {...}

const userName = data?.user.getName?.() // foo
const firstFriend = data?.user.friends?.[0] // undefined&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;?.은 읽기나 삭제하기에는 사용할 수 있지만 쓰기에는 사용할 수 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;?.은 할당 연산자 왼쪽에서 사용할 수 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f2f0; color: #708090;&quot;&gt;// user가 존재할 경우 user.name에 값을 쓰려는 의도로 아래와 같이 코드를 작성해 보았습니다.&lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0;&quot;&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f2f0;&quot;&gt;user&lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0; color: #a67f59;&quot;&gt;?.&lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0;&quot;&gt;name &lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0; color: #a67f59;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0; color: #669900;&quot;&gt;&quot;Violet&quot;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0; color: #999999;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0;&quot;&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f5f2f0; color: #708090;&quot;&gt;// SyntaxError: Invalid left-hand side in assignment&lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #f5f2f0; color: #708090;&quot;&gt;// 에러가 발생하는 이유는 undefined = &quot;Violet&quot;이 되기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&quot;globalthis&quot; data-ke-size=&quot;size26&quot;&gt;2. globalThis&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전역 객체는 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다 먼저 실행되는 특수한 객체입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 js 실행환경에 따라서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 클라이언트 사이드 환경(브라우져) 에서는 window, self, frames, this, global 을 사용해서 접근했고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 서버 사이드 환경(노드환경) 에서는 global 을 통해서 접근했습니다.&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&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;globalThis&lt;/b&gt;를 이용하면 손쉽게 접근 가능하다는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1630553909523&quot; class=&quot;javascript&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; color: #666666; font-size: 14px; 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; background-color: #ffffff;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 브라우저 실행 환경 기준

globalThis === window // true

// 브라우져 기준으로 아래 3개는 동일하다.
console.log(globalThis);
console.log(window);
console.log(this);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Nullish coalescing Operator (??)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Null 병합 연산자입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;??는 왼쪽 피연산자 값이 null이나 undefined일 경우 오른쪽 피연산자를 반환하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지 않으면 왼쪽 피연산자를 return하는 연산자입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b1b1b;&quot;&gt;왼쪽 피연산자가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;null&lt;span style=&quot;color: #1b1b1b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;undefined&lt;span style=&quot;color: #1b1b1b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;뿐만 아니라&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;falsy&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #1b1b1b;&quot;&gt;값에 해당할 경우 오른쪽 피연산자를 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;논리 연산자 OR (||)&lt;span style=&quot;color: #1b1b1b;&quot;&gt;와는 다르게&lt;/span&gt; ??를 사용하면 null or undefined인 경우에만 기본 값을 할당해주어 좀 더 안전한 코드를 작성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1630554269242&quot; class=&quot;javascript&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; color: #666666; font-size: 14px; 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; background-color: #ffffff;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const data = {
  title: 'foo',
  desc: ''
}

const description1 = data.desc ?? 'default value' // ''
// 위와 동일한 동작을 함
const description2 =
  data.desc !== undefined &amp;amp;&amp;amp; data.desc !== null ? data.desc : 'default value' // ''

const description3 = data.desc || 'default value' // 'default value'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;dynamic-import&quot; data-ke-size=&quot;size26&quot;&gt;4. Dynamic import&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;import(module)&lt;span&gt;&amp;nbsp;&lt;/span&gt;표현식은 모듈을 읽고 이 모듈이 내보내는 것들을 모두 포함하는 객체를 담은 이행된 프라미스를 반환합니다. 호출은 어디서나 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 내 어디에서 동적으로 사용할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async/await이나 then/catch를 사용해서 비동기 처리할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630553909523&quot; class=&quot;javascript&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; color: #666666; font-size: 14px; 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; background-color: #ffffff;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let modulePath = prompt(&quot;어떤 모듈을 불러오고 싶으세요?&quot;);

import(modulePath)
  .then(obj =&amp;gt; &amp;lt;모듈 객체&amp;gt;)
  .catch(err =&amp;gt; &amp;lt;로딩 에러, e.g. 해당하는 모듈이 없는 경우&amp;gt;)

// async/await 사용
;(async () =&amp;gt; {
    try {
      const module = await import(&quot;./myModule.js&quot;);
    } catch(error) {
      ...
    }
})()&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1630555043360&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let {hi, bye} = await import('./say.js');

hi();
bye();&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;bigint&quot; data-ke-size=&quot;size26&quot;&gt;5. BigInt&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BigInt는 Number원시값의 표현 최대치인 2^53-1 보다 큰 값을 표현하고 싶을때 사용가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BigInt를 사용하려면 정수값 뒤에 n을 붙이거나, BigInt(args)로 인자값을 넣어서 사용합니다.&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;단점은 Match 메서드와 함께 사용할 수 없으며, Number 타입의 원시값과 같이 연산 할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1630553909524&quot; class=&quot;javascript&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; color: #666666; font-size: 14px; 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; background-color: #ffffff;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 정수 리터럴 방식
const bigInt1 = 9007199254740999n
// 생성자 함수 방식
const bigInt2 = BigInt(9007199254740998)

console.log(bigInt1 &amp;gt; bigInt2) // true
console.log(bigInt1 &amp;gt; bigInt2 + 2n) // false
console.log(bigInt2 + 2) // error&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;stringprototypematchall&quot; data-ke-size=&quot;size26&quot;&gt;6. String.prototype.matchAll&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;String.protorype.exec 메서드와 유사하게 동작하며,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;lastIndex&lt;/b&gt;로 부터 시작해서 정규표현식과 첫번째로 일치하는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하위 문자열의 정보를 반환하는 String.prototype.exec와 달리 일치하는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모든 하위 문자열의 정보를 포함하고 있는 이터레이터를 return 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1630553909524&quot; class=&quot;javascript&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; color: #666666; font-size: 14px; 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; background-color: #ffffff;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const regexp = /t(e)(st(\d?))/g
const str = 'test1test2'
const array = [...str.matchAll(regexp)]

console.log(array[0]) // [&quot;test1&quot;, &quot;e&quot;, &quot;st1&quot;, &quot;1&quot;]
console.log(array[1]) // [&quot;test2&quot;, &quot;e&quot;, &quot;st2&quot;, &quot;2&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;promiseallsettled&quot; data-ke-size=&quot;size26&quot;&gt;7. Promise.allSettled&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Promise.allSettled&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드는 인자로 받은 배열이나&lt;span&gt;&amp;nbsp;&lt;/span&gt;iterable&lt;span&gt;&amp;nbsp;&lt;/span&gt;객체를 통해 열거된&lt;span&gt;&amp;nbsp;&lt;/span&gt;Promise&lt;span&gt;&amp;nbsp;&lt;/span&gt;객체들이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모두 실행됐을 때&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;resolve하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Promise&lt;span&gt;&amp;nbsp;&lt;/span&gt;객체를 반환&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise.allSettled&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Promise.all&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드와 유사하지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Promise.all&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;열거된&lt;span&gt;&amp;nbsp;&lt;/span&gt;Promise&lt;span&gt;&amp;nbsp;&lt;/span&gt;객체들 중 하나라도&lt;span&gt;&amp;nbsp;&lt;/span&gt;reject되면 자신도&lt;span&gt;&amp;nbsp;&lt;/span&gt;reject&lt;/b&gt;하지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Promise.allSettled&amp;nbsp;메서드는 이행 여부와 상관없이 전부 다 실행되면&amp;nbsp;resolve합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1630553909525&quot; class=&quot;javascript&quot; style=&quot;overflow: auto; margin: 0px; padding: 0px; color: #666666; font-size: 14px; 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; background-color: #ffffff;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 정수 리터럴 방식
const promise1 = Promise.resolve(10)
const promise2 = new Promise((_, reject) =&amp;gt; setTimeout(reject, 100, 'foo'))
const promises = [promise1, promise2]

Promise.allSettled(promises).then(
  results =&amp;gt; results.forEach(result =&amp;gt; console.log(result.status)) 
  // &quot;fulfilled&quot;, &quot;rejected&quot;
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>ECMAScript 2020</category>
      <category>ES11</category>
      <category>javascript</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/59</guid>
      <comments>https://gusehd66.tistory.com/entry/Javascript-ES11-ECMAScript-2020#entry59comment</comments>
      <pubDate>Thu, 2 Sep 2021 13:01:05 +0900</pubDate>
    </item>
    <item>
      <title>[Bundler] 번들러</title>
      <link>https://gusehd66.tistory.com/entry/Bundler-%EB%B2%88%EB%93%A4%EB%9F%AC</link>
      <description>&lt;h2 id=&quot;2-번들러의-개념&quot; data-ke-size=&quot;size26&quot;&gt;1. 번들러의 개념&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹사이트에서는 HTML, CSS, JavaScript가 동작을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React, SCSS, TypeScript 등의 여러 라이브러리나 프레임워크를 사용하여 코딩을 진행하고 프로젝트를 제작합니다. 그리고 번들러를 통해 변환하는 과정을 거쳐 HTMl, CSS, JavaScript로 웹에서 동작시킬 수 있도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, 번들러가 직접적으로 변환시키는 것은 아닙니다. 예를 들어, SCSS 문법을 CSS로 변환시킬 때 parcel-bundler가 Sass라는 외부 패키지를 설치하여 이로부터 도움을 받아 완료한 것입니다.&lt;/p&gt;
&lt;h2 id=&quot;3-parcel-vs-webpack&quot; data-ke-size=&quot;size26&quot;&gt;3. parcel VS webpack&lt;/h2&gt;
&lt;h3 id=&quot;31-parcel&quot; data-ke-size=&quot;size23&quot;&gt;3.1 parcel&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parcel 번들러는 별도의 구성이 없는 단순 자동 번들링을 제공해줍니다. 매우 편리한 번들러이지만 webpack 번들러에 비해 구성이 꼼꼼하지 않습니다. 그러므로 프로젝트의 규모가 커질수록 parcel 번들러의 아쉬움을 발견하는 경우가 있습니다. 이러한 이유로 parcel 번들러는 소/중형 프로젝트에 적합하다고 할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;32-webpack&quot; data-ke-size=&quot;size23&quot;&gt;3.2 webpack&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;webpack 번들러는 꼼꼼하고 자세하게 번들링할 수 있는 구성 옵션을 설정해줄 수 있습니다. 그러한 구성 옵션을 통해 개발자의 입맛에 맞게 정리를 할 수 있습니다. 그러므로 당연하게도 중/대형 프로젝트에 유용하게 사용 가능합니다. 그러나 아무래도 이러한 이유로 확인해야할 사항이 많다는 단점이 있습니다.&lt;/p&gt;</description>
      <category>bundler</category>
      <category>parcel</category>
      <category>webpack</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/58</guid>
      <comments>https://gusehd66.tistory.com/entry/Bundler-%EB%B2%88%EB%93%A4%EB%9F%AC#entry58comment</comments>
      <pubDate>Thu, 12 Aug 2021 19:50:19 +0900</pubDate>
    </item>
    <item>
      <title>[React] ESLint</title>
      <link>https://gusehd66.tistory.com/entry/React-ESLint</link>
      <description>&lt;h1 id=&quot;eslint&quot;&gt;ESLint&lt;/h1&gt;
&lt;h2 id=&quot;1-eslint&quot; data-ke-size=&quot;size26&quot;&gt;1. ESLint&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발을 진행하면서 코딩 스타일을 공통적으로 맞추어 진행할 수 있어야 서로 쉽게 이해를 하며 업무를 할 수 있습니다. 이를 도와주는 도구가 바로 ESLint입니다. ESLint 혹은 Lint라 불립니다.&lt;/p&gt;
&lt;h3 id=&quot;11-패키지-설치&quot; data-ke-size=&quot;size23&quot;&gt;1.1 패키지 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm 명령어로 프로젝트를 시작하고 ESLint 패키지를 설치해보도록 하겠습니다. 개발용 의존성 패키지로 설치하겠습니다. 이는 아시다시피 개발하는 상황에만 필요하며, 웹브라우저에서 동작할 시에는 필요하지 않음을 의미하는 옵션입니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ mkdir eslint-test&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ cd eslint-test&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ npm init -y&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ npm i eslint -D // 패키지 설치&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&quot;12-패키지-초기화&quot; data-ke-size=&quot;size23&quot;&gt;1.2 패키지 초기화&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ npx eslint --init&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;172&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnSfFa/btrbocXOxkP/NIOLf87PZg8789bq7wdRL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnSfFa/btrbocXOxkP/NIOLf87PZg8789bq7wdRL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnSfFa/btrbocXOxkP/NIOLf87PZg8789bq7wdRL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnSfFa%2FbtrbocXOxkP%2FNIOLf87PZg8789bq7wdRL0%2Fimg.png&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;172&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;해당 명령어를 입력하면 ESLint가 초기화됩니다. 그리고 초기화의 결과로 위와 같은 화면을 보여주며 선택하는 옵션에 따라 config 파일이 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하늘색으로 표시된 옵션이 default 값이며, 이를 선택하도록 하겠습니다.&lt;/p&gt;
&lt;h3 id=&quot;13-eslintrcjs&quot; data-ke-size=&quot;size23&quot;&gt;1.3 eslintrc.js&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실제로 VScode로 프로젝트를 열어 설치된&lt;span&gt;&amp;nbsp;&lt;/span&gt;.eslintrc.js&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일을 열어주도록 하겠습니다. 파일 내에는 옵션 내용이 명시되어 있으며,&lt;span&gt;&amp;nbsp;&lt;/span&gt;rules에 본인 혹은 팀의 규칙에 맞추어 설정해주시면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1628391724683&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: &quot;eslint:recommended&quot;,
  parserOptions: {
    ecmaVersion: 12,
  },
  rules: {
    semi: [&quot;error&quot;, &quot;always&quot;],
  },
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의&lt;span&gt;&amp;nbsp;&lt;/span&gt;semi&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션은 문장 뒤에 세미콜론을 붙이지 않으면 항상 에러로 간주하겠다는 것을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ESLint의 홈페이지에서 이외에도 여러 옵션을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>eslint</category>
      <category>react</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/57</guid>
      <comments>https://gusehd66.tistory.com/entry/React-ESLint#entry57comment</comments>
      <pubDate>Sun, 8 Aug 2021 12:02:49 +0900</pubDate>
    </item>
    <item>
      <title>[React] React Life Cycle - 2</title>
      <link>https://gusehd66.tistory.com/entry/React-React-Life-Cycle-2</link>
      <description>&lt;h1 id=&quot;component-lifecycle&quot;&gt;Component Lifecycle&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 &lt;b&gt;&lt;u&gt;16.3 버전&lt;/u&gt;&lt;/b&gt; 이상의 변경된 내용에 대해 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;라이프사이클-변경-사항v163-이상&quot; data-ke-size=&quot;size26&quot;&gt;라이프사이클 변경 사항(v16.3 이상)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;constructor&lt;/li&gt;
&lt;li&gt;&lt;s&gt;componentWillMount&lt;/s&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;=&amp;gt; getDerivedStateFromProps&lt;/li&gt;
&lt;li&gt;&lt;b&gt;render&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;componentDidMount&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;componentWillReceiveProps&lt;/s&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;=&amp;gt; getDerivedStateFromProps&lt;/li&gt;
&lt;li&gt;shouldComponentUpdate&lt;/li&gt;
&lt;li&gt;&lt;b&gt;render&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;s&gt;componentWillUpdate&lt;/s&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;=&amp;gt; getSnapshotBeforeUpdate&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DOM에 적용&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;componentDidUpdate&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;componentWillUnmount&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;1-getderivedstatefromprops&quot; data-ke-size=&quot;size23&quot;&gt;1. getDerivedStateFromProps&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getDerivedStateFromProps는 최초 마운트 시와 갱신 시 모두에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;render&lt;span&gt;&amp;nbsp;&lt;/span&gt;메소드를 호출하기 직전에 호출됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state를 갱신하기 위한 객체를 반환하거나,&lt;span&gt;&amp;nbsp;&lt;/span&gt;null을 반환하여 아무 것도 갱신하지 않을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메소드는 시간이 흐름에 따라 변하는 props에 state가 의존하는 아무 드문 사용례를 위하여 존재합니다. 예를 들어, 무엇을 움직이도록 만들지 결정하기 위하여 이전과 현재의 자식 엘리먼트를 비교하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Transition&amp;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;1.1 코드 예시&lt;/p&gt;
&lt;pre id=&quot;code_1627909552889&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static getDerivedStateFromProps(nextProps, prevState) {
  console.log(&quot;getDerivedStateFromProps&quot;, nextProps, prevState);

  return {
    age: 390,
  }
}

ReactDOM.render(&amp;lt;App name=&quot;Orosy&quot; /&amp;gt;, document.querySelector(&quot;#root&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-getsnapshotbeforeupdate&quot; data-ke-size=&quot;size23&quot;&gt;2. getSnapshotBeforeUpdate&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getSnapshotBeforeUpdate는 가장 마지막으로 렌더링된 결과가 DOM 등에 반영되었을 때에 호출됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메소드를 사용하면 컴포넌트가 DOM으로부터 스크롤 위치 등과 같은 정보를 이후 변경되기 전에 얻을 수 있습니다. 이 라이프사이클 메소드가 반환하는 값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;componentDidUpdate에 인자로 전달됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메소드에 대한 사용례는 흔하지 않지만, 채팅 화면처럼 스크롤 위치를 따로 처리하는 작업이 필요한 UI 등을 생각해볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스냅샷 값을 반환하거나&lt;span&gt;&amp;nbsp;&lt;/span&gt;null을 반환합니다.&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;2.1 코드 예시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드는 위에서 언급했던 것처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;getSnapshotBeforeUpdate를 이용하여 데이터가 업데이트하게 되면 스크롤 위치가 자동으로 변하게 되는 로직을 구현한 코드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 코드는 이해하기 쉽지 않기 때문에 이러한 방식으로 해당 라이프사이클을 활용하는 것이라고 알아주시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1627909564031&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let i = 0;

class App extends React.Component {
  state = { list: [] };

  render() {
    return (
      &amp;lt;div id=&quot;list&quot; style={{ height: 100, overflow: &quot;scroll&quot; }}&amp;gt;
        {this.state.list.map((i) =&amp;gt; {
          return &amp;lt;div&amp;gt;{i}&amp;lt;/div&amp;gt;;
        })}
      &amp;lt;/div&amp;gt;
    );
  }

  componentDidMount() {
    setInterval(() =&amp;gt; {
      this.setState((state) =&amp;gt; ({
        list: [...state.list, i++],
      }));
    }, 1000);
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    if (prevState.list.length === this.state.list.length) return null;
    const list = document.querySelector(&quot;#list&quot;);
    return list.scrollHeight - list.scrollTop;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log(snapshot);
    if (snapshot === null) return;
    const list = document.querySelector(&quot;#list&quot;);
    list.scrollTop = list.scrollHeight - snapshot;
  }
}

ReactDOM.render(&amp;lt;App name=&quot;Orosy&quot; /&amp;gt;, document.querySelector(&quot;#root&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-componentdidcatch&quot; data-ke-size=&quot;size23&quot;&gt;3. componentDidCatch&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;componentDidCatch는 이름에서 알 수 있다시피 자손 컴포넌트에서 오류가 발생했을 때에 호출되는 메소드입니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 해당 라이프사이클의 단점은 자손 컴포넌트가 아닌 자기 자신에게 오류가 발생하게 되면, 오류를 캐치할 수 없게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에&lt;span&gt;&amp;nbsp;&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;3.1 코드 예시&lt;/p&gt;
&lt;pre id=&quot;code_1627909574473&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class App extends React.Component {
  state = {
    hasError: false,
  };
  render() {
    if (this.state.hasError) {
      return &amp;lt;div&amp;gt;에러 발생!!&amp;lt;/div&amp;gt;;
    }
    return &amp;lt;WebService /&amp;gt;;
  }
  componentDidCatch(error, info) {
    this.setState({ hasError: true });
  }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>React</category>
      <category>Component Lifecycle</category>
      <category>lifecycle</category>
      <category>react</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/56</guid>
      <comments>https://gusehd66.tistory.com/entry/React-React-Life-Cycle-2#entry56comment</comments>
      <pubDate>Mon, 2 Aug 2021 22:12:08 +0900</pubDate>
    </item>
    <item>
      <title>[React] React Life Cycle - 1</title>
      <link>https://gusehd66.tistory.com/entry/React-React-Life-Cycle-1</link>
      <description>&lt;h1 id=&quot;component-lifecycle&quot;&gt;Component Lifecycle&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 내용은 16.3 버전 이전의 내용을 다루고 있습니다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;라이프사이클-v163-이전&quot; data-ke-size=&quot;size26&quot;&gt;라이프사이클 (v16.3 이전)&lt;/h2&gt;
&lt;h3 id=&quot;1-component-생성-및-마운트&quot; data-ke-size=&quot;size23&quot;&gt;1. Component 생성 및 마운트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;constructor&lt;/li&gt;
&lt;li&gt;componentWillMount&lt;/li&gt;
&lt;li&gt;&lt;b&gt;render(최초 렌더)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;componentDidMount&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.1 코드 예시&lt;/p&gt;
&lt;pre id=&quot;code_1626672190813&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class App extends React.Component {
  state = {
    age: 25,
  };
  constructor(props) {
    super(props);

    console.log(&quot;constructor&quot;, props);
  }
  render() {
    console.log(&quot;render&quot;);
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;h2&amp;gt;
          Hello {this.props.name} - {this.state.age}
        &amp;lt;/h2&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }

  componentWillMount() {
  console.log(&quot;componentWillMount&quot;);
  }

  componentDidMount() {
  console.log(&quot;componentDidMount&quot;);
  }
}

ReactDOM.render(&amp;lt;App name=&quot;Dongit&quot; /&amp;gt;, document.querySelector(&quot;#root&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드로 Component 생성과 마운트에 대해 알아볼 수 있습니다. &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;constructor라는 생성자가 콘솔창에 출력이 되고 이후 렌더 메소드에 있는render라는 내용이 출력이 되는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&lt;span&gt;&amp;nbsp;&lt;/span&gt;render&lt;span&gt;&amp;nbsp;&lt;/span&gt;전에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;componentWillMount&lt;span&gt;&amp;nbsp;&lt;/span&gt;그리고 이후에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;componentDidMount&lt;span&gt;&amp;nbsp;&lt;/span&gt;라이프사이클이 콘솔창에 출력되는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;2-component-propsstate-변경&quot; data-ke-size=&quot;size23&quot;&gt;2. Component props,state 변경&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;componentWillReceiveProps (state 변경 시, 실행되지 않음)&lt;/li&gt;
&lt;li&gt;shouldComponentUpdate&lt;/li&gt;
&lt;li&gt;componentWillUpdate&lt;/li&gt;
&lt;li&gt;&lt;b&gt;render(최초 렌더)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;componentDidUpdate&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.1 코드 예시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 클래스 컴포넌트로 이벤트 핸들러를 만든 코드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1626672229741&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;componentWillReceiveProps(nextProps) {
  console.log(&quot;componentWillReceiveProps&quot;, nextProps);
}

shouldComponentUpdate(nextProps, nextState)  {
  console.log(&quot;shouldComponentUpdate&quot;, nextProps, nextState);

  return false;
}

componentWillUpdate(nextProps, nextState) {
  console.log(&quot;componentWillUpdate&quot;, nextProps, nextState);
}

componentDidUpdate(prevProps, prevState) {
  console.log(&quot;componentDidUpdate&quot;, prevProps, prevState);
}

ReactDOM.render(&amp;lt;Component /&amp;gt;, document.querySelector(&quot;#root&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shouldComponentUpdate는 다른 라이프사이클과는 달리&lt;span&gt;&amp;nbsp;&lt;/span&gt;shouldComponentUpdate는 불린 데이터인 true와 false를 갖게 됩니다. 여기서 값을 false로 지정하게 되면, 이후의 라이프사이클은 실행되지 않습니다. 결국,&lt;span&gt;&amp;nbsp;&lt;/span&gt;componentWillUpdate부터 실행되지 않으며, 쉽게 말해 업데이트가 실행되지 않음을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로 인해 render의 실행 여부를 결정할 수 있는 중요한 라이프사이클입니다.&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;2.2 componenetWillReceiveProps&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 라이프사이클은 props를 새로 지정했을 때 바로 호출되며, state의 변경에 반응하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 라이프사이클에서 props에 따라 state를 변경해야 한다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;setState를 이용하여 state를 변경합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;그러면 다음 이벤트로 각각 가는 것이 아니라 한번에 변경됩니다.&lt;/b&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;2.3 shouldComponentUpdate&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 라이프사이클은 props, state 하나만 변경되거나 둘 다 변경되어도 실행이 됩니다. newProps와 newState를 인자로 하여 호출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 언급했던 것처럼,&lt;span&gt;&amp;nbsp;&lt;/span&gt;return type이 불린 데이터입니다. 해당 함수를 구현하지 않으면 디폴트 값은 true이며, false일 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;render가 호출되지 않습니다.&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;2.4 componentWillUpdate&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 재렌더링 되기 직전에 불리며, 여기선&lt;span&gt;&amp;nbsp;&lt;/span&gt;setState와 같은 메소드는 사용해선 안됩니다.&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;2.5 componentDidUpdate&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 재렌더링을 마치면 불리는 라이프사이클입니다.&lt;/p&gt;
&lt;h3 id=&quot;3-component-언마운트&quot; data-ke-size=&quot;size23&quot;&gt;3. Component 언마운트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.1 componentWillUnmount&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 컴포넌트가&lt;span&gt;&amp;nbsp;&lt;/span&gt;unmount되고 난 후에는 처리할 수 없습니다. 그렇기 때문에 해당 라이프사이클만 활용이 가능합니다.&lt;/p&gt;</description>
      <category>React</category>
      <category>Component Lifecycle</category>
      <category>life cycle</category>
      <category>react</category>
      <category>shouldComponentUpdate</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/55</guid>
      <comments>https://gusehd66.tistory.com/entry/React-React-Life-Cycle-1#entry55comment</comments>
      <pubDate>Mon, 19 Jul 2021 14:34:32 +0900</pubDate>
    </item>
    <item>
      <title>[React] React Router</title>
      <link>https://gusehd66.tistory.com/entry/React-React-Router</link>
      <description>&lt;h1&gt;React Router로 라우팅 하기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA는&lt;span&gt;&amp;nbsp;&lt;/span&gt;index.html&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일에&lt;span&gt;&amp;nbsp;&lt;/span&gt;div&lt;span&gt;&amp;nbsp;&lt;/span&gt;엘리먼트만 하나 두고, 자바스크립트로 모든 부분을 동적으로 랜더링하는 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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로 간단하게 라우팅을 구현할 수 있습니다. 예를 들어, 다음 코드 처럼 현재 어떤 컴포넌트가 랜더링되야 하는지 상태로 관리할 수 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;header&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;내의 특정 메뉴 버튼을 클릭하면 상응하는 컴포넌트로&lt;span&gt;&amp;nbsp;&lt;/span&gt;comp&lt;span&gt;&amp;nbsp;&lt;/span&gt;상태가 바뀌기 때문에 화면에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;main&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;부분이 갱신되게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1626425162924&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
import Home from &quot;./Home&quot;;
import About from &quot;./About&quot;;
import NotFound from &quot;./NotFound&quot;;

function App() {
  const [comp, setComp] = useState(Home);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;header&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; setComp(Home)}&amp;gt;Home&amp;lt;/button&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; setComp(About)}&amp;gt;About&amp;lt;/button&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; setComp(NotFound)}&amp;gt;Users&amp;lt;/button&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;hr /&amp;gt;
      &amp;lt;main children={comp} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이런 방식으로 라우팅을 구현하게 되면 사용자 입장에서 다음과 같은 문제가 발생합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 페이지에 대한 즐겨찾기 등록이 불가합니다. 컴포넌트가 전환되더라도 브라우저 주소창의 URL은 고정되어 있기 때문입니다.&lt;/li&gt;
&lt;li&gt;뒤로 가기 버튼을 누르면 해당 앱내에서 이전 페이지로 이동하는 것이 아니라 그 전에 서핑하던 다른 웹사이트로 이동해버립니다.&lt;/li&gt;
&lt;li&gt;새로 고침 버튼을 누르면 사용 중이던 컴포넌트가 아닌 무조건 최초에 렌더링되었던&lt;span&gt;&amp;nbsp;&lt;/span&gt;Home&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트로 이동합니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;SEO(검색 엔진 최적화) 측면에서도 일반 웹사이트들과 차이가 있어서 검색 엔진에 의해 원치않는 방식으로 색인이 될 수도 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;react-router란&quot; data-ke-size=&quot;size26&quot;&gt;React Router란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;React Router는 위에서 살펴본 SPA의 라우팅 문제를 해결하기 위해서 거의 표준처럼 사용되고 있는 네비게이션 라이브러리입니다. React Router를 사용하면 앱에서 발생하는 라우팅이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;location&lt;span style=&quot;color: #1b2e46;&quot;&gt;나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;history&lt;span style=&quot;color: #1b2e46;&quot;&gt;와 같은 브라우저 내장 API와 완벽하게 연동이 됩니다. 따라서 SPA에서 제공하는 다이나믹한 사용자 경험을 그대로 살리면서도 기존 웹사이트에서 가능하던 브라우저 상의 매끈한 라우팅을 제공할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;react-router-설치&quot; data-ke-size=&quot;size26&quot;&gt;React Router 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;React Router는 Web 용과 Native 용이 존재합니다. 아래와 같이 Web 용&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;react-router-dom&lt;span style=&quot;color: #1b2e46;&quot;&gt;을 React 애플리케이션 프로젝트에 설치해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ &lt;span style=&quot;color: #f08d49;&quot;&gt;npm&lt;/span&gt; i react-router-dom&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;react-router-핵심-컴포넌트&quot; data-ke-size=&quot;size26&quot;&gt;React Router 핵심 컴포넌트&lt;/h2&gt;
&lt;h3 id=&quot;link-컴포넌트&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;Link 컴포넌트&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;HTML의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;a&amp;gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그와 유사한 기능을 하는 컴포넌트라고 생각하시면 이해가 쉽습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;a&amp;gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;href&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성을 통해 이동할 경로를 지정하는 반면에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;Link&amp;gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;to&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop을 통해서 이동할 경로를 지정해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;lt;&lt;/span&gt;Link to&lt;span style=&quot;color: #67cdcc;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #7ec699;&quot;&gt;&quot;/about&quot;&lt;/span&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;About&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;/&lt;/span&gt;Link&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;예를 들어, 위의 코드는 브라우저에서 클릭이 가능한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;About&lt;span style=&quot;color: #1b2e46;&quot;&gt;으로 랜더링되고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;About&lt;span style=&quot;color: #1b2e46;&quot;&gt;를 클릭하면 주소창의 경로가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;도메인 네임&amp;gt;/about&lt;span style=&quot;color: #1b2e46;&quot;&gt;으로 갱신됩니다. 일반적으로 화면 상단이나 좌측에 위치한 네비게이션 바를 구현할 때 주로 사용하게되는 컴포넌트입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;route-컴포넌트&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;Route 컴포넌트&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;Route&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 현재 주소창의 경로와 매치될 경우 보여줄 컴포넌트를 지정하는데 사용됩니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;path&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop을 통해서 매치시킬 경로를 지정하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;component&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop을 통해서 매치되었을 때 보여줄 컴포넌트를 할당합니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;lt;&lt;/span&gt;Route path&lt;span style=&quot;color: #67cdcc;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #7ec699;&quot;&gt;&quot;/about&quot;&lt;/span&gt; component&lt;span style=&quot;color: #67cdcc;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;{&lt;/span&gt;About&lt;span style=&quot;color: #cccccc;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #67cdcc;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;예를 들어, 위의 코드는 현재 주소창의 경로가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;/about&lt;span style=&quot;color: #1b2e46;&quot;&gt;일 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;About&lt;span style=&quot;color: #1b2e46;&quot;&gt;라는 컴포넌트를 보여줍니다. 일반적으로 현재 주소창의 URL 경로에 따라 특정 컨텐트를 보여주거나 숨기기 위해서 사용될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;router-컴포넌트&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;Router 컴포넌트&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;Router&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 위에 나온&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Route&amp;gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Link&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트가 함께 유기적으로 동작하도록 묶어주는데 사용합니다. 다시 말해,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Route&amp;gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Link&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 DOM 트리 상에서 항상&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Router&amp;gt;를 공통 상위 컴포넌트로 가져야합니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;lt;&lt;/span&gt;Router&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;nbsp; ...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;Link &lt;span style=&quot;color: #67cdcc;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;Link &lt;span style=&quot;color: #67cdcc;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;nbsp; ...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;Router &lt;span style=&quot;color: #67cdcc;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;Router &lt;span style=&quot;color: #67cdcc;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;nbsp; ...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #67cdcc;&quot;&gt;/&lt;/span&gt;Router&lt;span style=&quot;color: #67cdcc;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;즉, 전체적으로 React Router를 사용하는 어플리케이션은 이와 같은 구조를 가지게 됩니다. 실제 프로젝트에서는 위 컴포넌트들이 여러 파일에 걸쳐서 흩어져 있을 수도 있겠지만, 이 큰 그림을 염두해두고 코드를 읽다보면 어렵지 않게 라우팅 흐름을 파악하실 수 있으실 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;react-router로-라우팅-구현&quot; data-ke-size=&quot;size26&quot;&gt;React Router로 라우팅 구현&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;자 그럼, 처음에 직접 구현했던 라우팅을 React Router를 이용해서 재구현 해보겠습니다. 먼저 설치한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;react-router-dom&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;패키지로 부터 3가지 핵심 컴포넌트를 임포트해야합니다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #cc99cd;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #cccccc;&quot;&gt;{&lt;/span&gt; Link&lt;span style=&quot;color: #cccccc;&quot;&gt;,&lt;/span&gt; Route&lt;span style=&quot;color: #cccccc;&quot;&gt;,&lt;/span&gt; BrowserRouter &lt;span style=&quot;color: #cc99cd;&quot;&gt;as&lt;/span&gt; Router &lt;span style=&quot;color: #cccccc;&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #cc99cd;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #7ec699;&quot;&gt;&quot;react-router-dom&quot;&lt;/span&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&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 Router가 제공하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Router&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트가 여러 종류가 있는데, 여기서는 대게 일반적은 라우팅을 위해 사용되는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;BrowserRouter&amp;gt;를 사용하였습니다. 다른 라우터들은 추후 기회가 되면 다른 포스트를 통해서 다루도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 헤더 부분을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Link&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트를 사용해서 리팩토링 합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;to&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop에 해당 메뉴 클릭 시 이동해야할 경로를 지정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1626425462314&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;header&amp;gt;
  &amp;lt;Link to=&quot;/&quot;&amp;gt;
    &amp;lt;button&amp;gt;Home&amp;lt;/button&amp;gt;
  &amp;lt;/Link&amp;gt;
  &amp;lt;Link to=&quot;/about&quot;&amp;gt;
    &amp;lt;button&amp;gt;About&amp;lt;/button&amp;gt;
  &amp;lt;/Link&amp;gt;
  &amp;lt;Link to=&quot;/users&quot;&amp;gt;
    &amp;lt;button&amp;gt;Users&amp;lt;/button&amp;gt;
  &amp;lt;/Link&amp;gt;
&amp;lt;/header&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음, 메인 부분을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Route&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트를 사용해서 리팩토링 합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;path&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop에 매치 시 비교될 경로를 지정하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;component&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop에 매치 시 보여줄 컴포넌트를 할당합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;경로를 사용하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Route&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트에만&lt;span&gt;&amp;nbsp;&lt;/span&gt;exact&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop이 사용된 이유는, React Router의 디폴트 매칭 규칙 때문입니다. React Router는&lt;span&gt;&amp;nbsp;&lt;/span&gt;path&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop의 경로와 현재 브라우저의 주소창의 URL 경로 (location.pathname)와 비교를 하는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 URL 경로 값이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Route&amp;gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;path&lt;span&gt;&amp;nbsp;&lt;/span&gt;porp 값과 전체가 아닌 앞부분만 일치해도 매치되는 것으로 간주합니다. 따라서&lt;span&gt;&amp;nbsp;&lt;/span&gt;path가&lt;span&gt;&amp;nbsp;&lt;/span&gt;/일 경우,&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;뿐만 아니라&lt;span&gt;&amp;nbsp;&lt;/span&gt;/로 시작하는 모든 URL 경로, 사실 상 가능한 모든 경우의 수의 경로와 매치가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에,&lt;span&gt;&amp;nbsp;&lt;/span&gt;exact&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop이 없으면, 의도치 않게&lt;span&gt;&amp;nbsp;&lt;/span&gt;Home&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트가 URL 경로와 상관없이 항상 보여지게 됩니다. 하지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;exact&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop을 붙여주면 URL 경로 값이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Route&amp;gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;path&lt;span&gt;&amp;nbsp;&lt;/span&gt;값과 완벽히 전체가 일치해야 매치되는 것으로 처리를 해줍니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1626425492794&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;main&amp;gt;
  &amp;lt;Route exact path=&quot;/&quot; component={Home} /&amp;gt;
  &amp;lt;Route path=&quot;/about&quot; component={About} /&amp;gt;
  &amp;lt;Route path=&quot;/users&quot; component={NotFound} /&amp;gt;
&amp;lt;/main&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;마지막으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;Router&amp;gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트로 위에서 작성한 모든&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;Link&amp;gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;Route&amp;gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트를 함께 감싸주기만 하면 끝입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1626425501683&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import { Link, Route, BrowserRouter as Router } from &quot;react-router-dom&quot;;
import Home from &quot;./Home&quot;;
import About from &quot;./About&quot;;
import NotFound from &quot;./NotFound&quot;;

function App() {
  return (
    &amp;lt;Router&amp;gt;
      &amp;lt;header&amp;gt;
        &amp;lt;Link to=&quot;/&quot;&amp;gt;
          &amp;lt;button&amp;gt;Home&amp;lt;/button&amp;gt;
        &amp;lt;/Link&amp;gt;
        &amp;lt;Link to=&quot;/about&quot;&amp;gt;
          &amp;lt;button&amp;gt;About&amp;lt;/button&amp;gt;
        &amp;lt;/Link&amp;gt;
        &amp;lt;Link to=&quot;/users&quot;&amp;gt;
          &amp;lt;button&amp;gt;Users&amp;lt;/button&amp;gt;
        &amp;lt;/Link&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;hr /&amp;gt;
      &amp;lt;main&amp;gt;
        &amp;lt;Route exact path=&quot;/&quot; component={Home} /&amp;gt;
        &amp;lt;Route path=&quot;/about&quot; component={About} /&amp;gt;
        &amp;lt;Route path=&quot;/users&quot; component={NotFound} /&amp;gt;
      &amp;lt;/main&amp;gt;
    &amp;lt;/Router&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b2e46;&quot;&gt;이제 브라우저에서 네이게이션 메뉴를 클릭해보면 브라우저의 주소가 현재 페이지에 맞게 갱신이 되는 것을 확인하실 수 있을 겁니다. 뿐만 아니라, 뒤로 가기, 앞으로 가기, 새로 고침 버튼들도 일반 웹사이트를 서핑하듯이 작동하는 것을 확인하실 수 있을 겁니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>React</category>
      <category>react</category>
      <category>React Router</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/54</guid>
      <comments>https://gusehd66.tistory.com/entry/React-React-Router#entry54comment</comments>
      <pubDate>Fri, 16 Jul 2021 17:54:08 +0900</pubDate>
    </item>
    <item>
      <title>[React] JSX</title>
      <link>https://gusehd66.tistory.com/entry/React-JSX</link>
      <description>&lt;h2 id=&quot;jsx란&quot; data-ke-size=&quot;size26&quot;&gt;JSX란?&lt;/h2&gt;
&lt;h3 id=&quot;1-특징&quot; data-ke-size=&quot;size23&quot;&gt;1. 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX는 JavaScript의 XML입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript 문법의 확장판으로 리액트에서 요소를 제공합니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴파일에 최적화&lt;/li&gt;
&lt;li&gt;확장자는 jsx 또는 js&lt;/li&gt;
&lt;li&gt;컴파일 과정이 필요하므로 변환 과정에서 오류가 있다면 빌드 시 오류 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-사용-이유&quot; data-ke-size=&quot;size23&quot;&gt;2. 사용 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. React.createElement와&lt;span&gt;&amp;nbsp;&lt;/span&gt;JSX를 비교하였을 때,&lt;span&gt;&amp;nbsp;&lt;/span&gt;JSX의 가독성이 훨씬 뛰어납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;Babel과 같은 컴파일 과정에서 문법적인 오류를 인지하기 쉽습니다.&lt;/p&gt;
&lt;h3 id=&quot;3-변환-과정&quot; data-ke-size=&quot;size23&quot;&gt;3. 변환 과정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX의 문법으로 작성된 코드는 순수한 JavaScript로 컴파일하여 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 가능하도록 하는 것이 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;Babel입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RXDoM/btq9ymHhlJW/teBHIPKq25MujUDCIAMQDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RXDoM/btq9ymHhlJW/teBHIPKq25MujUDCIAMQDK/img.png&quot; data-origin-width=&quot;244&quot; data-origin-height=&quot;123&quot; style=&quot;width: 42.3892%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RXDoM/btq9ymHhlJW/teBHIPKq25MujUDCIAMQDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRXDoM%2Fbtq9ymHhlJW%2FteBHIPKq25MujUDCIAMQDK%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;244&quot; height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rDwcm/btq9yM6QyAR/cGCZ0yZrD1wERhXInnk8d0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rDwcm/btq9yM6QyAR/cGCZ0yZrD1wERhXInnk8d0/img.png&quot; data-origin-width=&quot;317&quot; data-origin-height=&quot;120&quot; style=&quot;width: 56.448%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rDwcm/btq9yM6QyAR/cGCZ0yZrD1wERhXInnk8d0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrDwcm%2Fbtq9yM6QyAR%2FcGCZ0yZrD1wERhXInnk8d0%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;317&quot; height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 id=&quot;4-사용-방법&quot; data-ke-size=&quot;size23&quot;&gt;4. 사용 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.1 CDN&lt;/p&gt;
&lt;pre id=&quot;code_1626234676664&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script src=&quot;https://unpkg.com/@babel/standalone/babel.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDN을 통해, 별도의 설치 없이&lt;span&gt;&amp;nbsp;&lt;/span&gt;Babel&lt;span&gt;&amp;nbsp;&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;4.2 작성법&lt;/p&gt;
&lt;pre id=&quot;code_1626234689629&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script type=&quot;text/babel&quot;&amp;gt; // 아래에 JSX 문법 작성
  ReactDOM.render(
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;주제&amp;lt;/h1&amp;gt;
        &amp;lt;ul&amp;gt;
          &amp;lt;li&amp;gt;React&amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;Vue&amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;,
    document.querySelector('#root')
  );
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX&lt;span&gt;&amp;nbsp;&lt;/span&gt;문법으로 코드를 작성하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;Babel이 자동으로 JavaScript 문법으로 컴파일을 진행하게 됩니다.&lt;/p&gt;
&lt;h3 id=&quot;5-jsx-문법&quot; data-ke-size=&quot;size23&quot;&gt;5. JSX 문법&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최상위 요소가 하나여야만 합니다.&lt;/li&gt;
&lt;li&gt;최상위 요소를 return하는 경우,&lt;span&gt;&amp;nbsp;&lt;/span&gt;()로 감싸야합니다.&lt;/li&gt;
&lt;li&gt;자식 요소를 바로 렌더링하고 싶다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;&amp;gt;자식 요소&amp;lt;/&amp;gt;를 사용합니다. 이를 Fragment라 부릅니다.&lt;/li&gt;
&lt;li&gt;자바스크립트 표현식을 사용하려면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;{표현식}을 이용합니다.&lt;/li&gt;
&lt;li&gt;if 문은 사용할 수 없습니다. 삼항 연산자 혹은 &amp;amp;&amp;amp;을 사용합니다.&lt;/li&gt;
&lt;li&gt;style을 이용하여 인라인 스타일링이 가능합니다.&lt;/li&gt;
&lt;li&gt;class 대신 className을 사용해 class를 적용할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>React</category>
      <category>jsx</category>
      <category>react</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/53</guid>
      <comments>https://gusehd66.tistory.com/entry/React-JSX#entry53comment</comments>
      <pubDate>Wed, 14 Jul 2021 13:01:12 +0900</pubDate>
    </item>
    <item>
      <title>[React] Props와 State</title>
      <link>https://gusehd66.tistory.com/entry/React-Props%EC%99%80-State</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Props, State&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;Props&lt;/span&gt;는 컴포넌트 외부에서 컴포넌트에게 주는 데이터이고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;State&lt;/span&gt;는 컴포넌트 내부에서 변경할 수 있는 데이터입니다.&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;span style=&quot;color: #ef5369;&quot;&gt;render&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Props와&lt;span&gt;&amp;nbsp;&lt;/span&gt;State를 바탕으로 컴포넌트를 그립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&lt;span&gt;&amp;nbsp;&lt;/span&gt;Props와&lt;span&gt;&amp;nbsp;&lt;/span&gt;State가 변경이 되면, 컴포넌트를 다시 그리게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 그리는 방법을 기술하는 함수가 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;render&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수입니다.&lt;/p&gt;
&lt;h3 id=&quot;2-props&quot; data-ke-size=&quot;size23&quot;&gt;2. Props&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.1 Props 사용 예제 (1)&lt;/p&gt;
&lt;pre id=&quot;code_1626155464705&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// {message: 'Hello!!!'}
function Component(props) {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;{props.message}&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

ReactDOM.render(
  &amp;lt;Component message='Hello' /&amp;gt;,
  document.querySelector('#root')
);&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;함수로 컴포넌트를 만들고 props 를 매개변수로 받고 있습니다.&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;2.2 Props 사용 예제 (2)&lt;/p&gt;
&lt;pre id=&quot;code_1626155500394&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Component extends React.Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;{this.props.message}&amp;lt;/h1&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}

ReactDOM.render(
  &amp;lt;Component message='Hello' /&amp;gt;,
  document.querySelector('#root')
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스로 컴포넌트를 만들고 this 를 사용하여 props에 접근할 수 있습니다.&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;2.3 기본값 사용 예제&lt;/p&gt;
&lt;pre id=&quot;code_1626155515558&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Component(props) {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;{props.message}&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

Component.defaultProps = {
  message: 'default값'
}

ReactDOM.render(
  &amp;lt;Component /&amp;gt;,
  document.querySelector('#root')
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 값을 지정하지 않고,&amp;nbsp;default&amp;nbsp;값을 설정하여 화면에 출력해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1626155528304&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Component extends React.Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;{this.props.message}&amp;lt;/h1&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
  static defaultProps = {
    message: '기본값!',
  }
}

ReactDOM.render(
  &amp;lt;Component /&amp;gt;,
  document.querySelector('#root')
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;Component mesaage='Not default' /&amp;gt;으로 직접 값을 지정한다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Not default 라는&lt;span&gt;&amp;nbsp;메세지가&lt;/span&gt;&amp;nbsp;출력됩니다.&lt;/p&gt;
&lt;h3 id=&quot;3-state&quot; data-ke-size=&quot;size23&quot;&gt;3. State&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;State는 현재 클래스 컴포넌트에서만 사용할 수 있는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Hooks을 사용하면, 함수에도 사용이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1626155537762&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Component extends React.Component {
  state = {
    count: 0,
  }
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;{this.props.message}&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;{this.state.count}&amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }

  // 라이프사이클: 화면에 올리자마자 바로 실행되는 함수
  componentDidMount() {
    setTimeout(() =&amp;gt; {
    // this.state.count = this.state.count + 1
    this.setState({
      count: this.state.count + 1,
    })
  }, 3000)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0으로 시작한&lt;span&gt;&amp;nbsp;&lt;/span&gt;state&lt;span&gt;&amp;nbsp;&lt;/span&gt;값이 3초 뒤 1로 변하게 되는 코드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state는&lt;span&gt; &lt;/span&gt;객체 데이터 형태로 제공이 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 방법으로는&lt;span&gt;&amp;nbsp;&lt;/span&gt;constructor,&lt;span&gt;&amp;nbsp;&lt;/span&gt;super를 키워드를 사용하여 클래스의 확장 기능을 이용하여 작성하는 방법도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1626155546124&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// state = {
//   count: 0,
// }
constructor(props) {
  super(props);

  //
  this.state = { count: 0 };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tate&lt;span&gt;&amp;nbsp;&lt;/span&gt;값을 변하게 만들 때에는 아래의 코드처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;setState를 호출하여 값이 바뀐 상태로&lt;span&gt;&amp;nbsp;&lt;/span&gt;render&lt;span&gt;&amp;nbsp;&lt;/span&gt;메소드가 자동으로 호출되고, 화면이 다시 그려집니다.&lt;/p&gt;
&lt;pre id=&quot;code_1626155553255&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// this.state.count = this.state.count + 1
this.setState({
  count: this.state.count + 1,
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 전달하는 방법 외에 함수를 전달하는 방법도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항상&lt;span&gt;&amp;nbsp;&lt;/span&gt;setState가 가장 최신의&lt;span&gt;&amp;nbsp;&lt;/span&gt;state&lt;span&gt;&amp;nbsp;&lt;/span&gt;값을 사용하도록 보장하도록 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 전달하면 0에서 1이 추가되고 끝나지만, 함수를 사용하게 되면 0에서 1, 1에서 2, 2에서 3 이런 식으로 업데이트가 반영되도록 해줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1626155559363&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;this.setState((previousState)=&amp;gt;{
  const newState = { count: previousState.count + 1 }
  return newState
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이&lt;span&gt;&amp;nbsp;&lt;/span&gt;setState에 전달하는 함수를&lt;span&gt;&amp;nbsp;&lt;/span&gt;updater라 부르며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 이전&lt;span&gt;&amp;nbsp;&lt;/span&gt;state&lt;span&gt;&amp;nbsp;&lt;/span&gt;값에 접근할 수 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setState&lt;span&gt;&amp;nbsp;&lt;/span&gt;호출은 일괄적으로 처리되기 때문에 여러 업데이트 사항이 충돌 없이 차례대로 반영되도록 합니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>props</category>
      <category>react</category>
      <category>State</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/52</guid>
      <comments>https://gusehd66.tistory.com/entry/React-Props%EC%99%80-State#entry52comment</comments>
      <pubDate>Tue, 13 Jul 2021 15:04:55 +0900</pubDate>
    </item>
    <item>
      <title>[Web] SPA (Single Page Application)</title>
      <link>https://gusehd66.tistory.com/entry/Web-SPA-Single-Page-Application</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;과거의 웹 사이트&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;SPA란 ?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제를 해결하기 위해 등장한 것이 SPA(Single Page Application)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 웹 사이트의 전체 페이지를 하나의 페이지에 담아 동적으로 화면을 바꿔가며 표현하는 것이 SPA입니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;장점&quot; data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 친화적(빠른 반응성, 화면 전환 애니메이션)입니다.&lt;/li&gt;
&lt;li&gt;화면에 필요한 부분의 데이터만 받아서 렌더링 하기 때문에 처리과정이 효율적입니다.&lt;/li&gt;
&lt;li&gt;서버 요청이 적습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;단점&quot; data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음 화면을 로딩할 때, 모든 화면이 미리 준비되어 있어야 하기 때문에 로딩에 시간이 걸립니다.&lt;/li&gt;
&lt;li&gt;검색엔진 최적화(SEO): SPA의 소스코드는 최초에 앱을 실행하기 위한 script, link 태그나 데이터가 비어 있는 뷰 껍데기 정도로 구성되어 있을 뿐이라 웹 크롤러가 데이터를 수집할 수 없습니다. (극복 가능)&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>Web</category>
      <category>SPA</category>
      <category>web</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/51</guid>
      <comments>https://gusehd66.tistory.com/entry/Web-SPA-Single-Page-Application#entry51comment</comments>
      <pubDate>Wed, 7 Jul 2021 14:06:19 +0900</pubDate>
    </item>
    <item>
      <title>[javascript] async 와 await</title>
      <link>https://gusehd66.tistory.com/entry/javascript-async-%EC%99%80-await</link>
      <description>&lt;h2 id=&quot;async--await는-뭔가요&quot; data-ke-size=&quot;size26&quot;&gt;async &amp;amp; await란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #313130;&quot;&gt;async와 await는 자바스크립트의 비동기 처리 패턴 중 가장 최근에 나온 문법입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #313130;&quot;&gt;기존의 비동기 처리 방식인 콜백 함수와 프로미스의 단점을 보완하고 개발자가 읽기 좋은 코드를 작성할 수 있게 도와줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;async--await-기본-문법&quot; data-ke-size=&quot;size26&quot;&gt;async &amp;amp; await 기본 문법&lt;/h2&gt;
&lt;pre id=&quot;code_1625474063641&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function 함수명() {
  await 비동기_처리_메서드_명();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수의 앞에&lt;span&gt;&amp;nbsp;&lt;/span&gt;async&lt;span&gt;&amp;nbsp;&lt;/span&gt;라는 예약어를 붙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러고 나서 함수의 내부 로직 중 HTTP 통신을 하는 비동기 처리 코드 앞에&lt;span&gt;&amp;nbsp;&lt;/span&gt;await를 붙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주의하셔야 할 점은 비동기 처리 메서드가 꼭 프로미스 객체를 반환해야&lt;span&gt;&amp;nbsp;&lt;/span&gt;await가 의도한 대로 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;await의 대상이 되는 비동기 처리 코드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Axios&lt;span&gt;&amp;nbsp;&lt;/span&gt;등 프로미스를 반환하는 API 호출 함수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;async--await-간단한-예제&quot; data-ke-size=&quot;size26&quot;&gt;async &amp;amp; await 간단한 예제&lt;/h2&gt;
&lt;pre id=&quot;code_1625474114219&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function fetchItems() {
  return new Promise(function(resolve, reject) {
    var items = [1,2,3];
    resolve(items)
  });
}

async function logItems() {
  var resultItems = await fetchItems();
  console.log(resultItems); // [1,2,3]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&lt;span&gt;&amp;nbsp;&lt;/span&gt;fetchItems()&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수는 프로미스 객체를 반환하는 함수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로미스는 &amp;ldquo;자바스크립트 비동기 처리를 위한 객체&amp;ldquo;입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fetchItems()&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 실행하면 프로미스가 이행(Resolved)되며 결과 값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;items&lt;span&gt;&amp;nbsp;&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&gt;&amp;nbsp;&lt;/span&gt;logItems()&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 보겠습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;logItems()&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 실행하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;fetchItems()&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수의 결과 값인&lt;span&gt;&amp;nbsp;&lt;/span&gt;items&lt;span&gt;&amp;nbsp;&lt;/span&gt;배열이&lt;span&gt;&amp;nbsp;&lt;/span&gt;resultItems&lt;span&gt;&amp;nbsp;&lt;/span&gt;변수에 담깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;await를 사용하지 않았다면 데이터를 받아온 시점에 콘솔을 출력할 수 있게 콜백 함수나&lt;span&gt;&amp;nbsp;&lt;/span&gt;.then()등을 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 async await 문법 덕택에 비동기에 대한 사고를 하지 않아도 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;async--await-실용-예제&quot; data-ke-size=&quot;size26&quot;&gt;async &amp;amp; await 실용 예제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #313130;&quot;&gt;async &amp;amp; await 문법이 가장 빛을 발하는 순간은 여러 개의 비동기 처리 코드를 다룰 때입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #313130;&quot;&gt;아래와 같이 각각&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;사용자&lt;span style=&quot;color: #313130;&quot;&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;할 일 목록&lt;span style=&quot;color: #313130;&quot;&gt;을 받아오는 HTTP 통신 코드가 있다고 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1625474254637&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function fetchUser() {
  var url = 'https://jsonplaceholder.typicode.com/users/1'
  return fetch(url).then(function(response) {
    return response.json();
  });
}

function fetchTodo() {
  var url = 'https://jsonplaceholder.typicode.com/todos/1';
  return fetch(url).then(function(response) {
    return response.json();
  });
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 함수들을 실행하면 각각 사용자 정보와 할 일 정보가 담긴 프로미스 객체가 반환됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 이제 이 두 함수를 이용하여 할 일 제목을 출력해보겠습니다. 살펴볼 예제 코드의 로직은 아래와 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fetchUser()를 이용하여 사용자 정보 호출&lt;/li&gt;
&lt;li&gt;받아온 사용자 아이디가&lt;span&gt;&amp;nbsp;&lt;/span&gt;1이면 할 일 정보 호출&lt;/li&gt;
&lt;li&gt;받아온 할 일 정보의 제목을 콘솔에 출력&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 코드를 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625474286976&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function logTodoTitle() {
  var user = await fetchUser();
  if (user.id === 1) {
    var todo = await fetchTodo();
    console.log(todo.title); // delectus aut autem
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;logTodoTitle()&lt;span style=&quot;color: #313130;&quot;&gt;를 실행하면 콘솔에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;delectus aut autem&lt;span style=&quot;color: #313130;&quot;&gt;가 출력될 것입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #313130;&quot;&gt;위 비동기 처리 코드를 만약 콜백이나 프로미스로 했다면 훨씬 더 코드가 길어졌을 것이고 인덴팅 뿐만 아니라 가독성도 좋지 않았을 겁니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #313130;&quot;&gt;이처럼 async await 문법을 이용하면 기존의 비동기 처리 코드 방식으로 사고하지 않아도 되는 장점이 생깁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;async--await-예외-처리&quot; data-ke-size=&quot;size26&quot;&gt;async &amp;amp; await 예외 처리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async &amp;amp; await에서 예외를 처리하는 방법은 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;try catch 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로미스에서 에러 처리를 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;.catch()를 사용했던 것처럼 async에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;catch {}&lt;span&gt;&amp;nbsp;&lt;/span&gt;를 사용하시면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 전 코드에 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;try catch&lt;span&gt;&amp;nbsp;&lt;/span&gt;문법을 적용해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625474357951&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function logTodoTitle() {
  try {
    var user = await fetchUser();
    if (user.id === 1) {
      var todo = await fetchTodo();
      console.log(todo.title); // delectus aut autem
    }
  } catch (error) {
    console.log(error);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #313130;&quot;&gt;위의 코드를 실행하다가 발생한 네트워크 통신 오류뿐만 아니라 간단한 타입 오류 등의 일반적인 오류까지도&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;catch&lt;span style=&quot;color: #313130;&quot;&gt;로 잡아낼 수 있습니다. 발견된 에러는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;error&lt;span style=&quot;color: #313130;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&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;color: #9d9d9d;&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>Async</category>
      <category>await</category>
      <category>javascript</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/49</guid>
      <comments>https://gusehd66.tistory.com/entry/javascript-async-%EC%99%80-await#entry49comment</comments>
      <pubDate>Mon, 5 Jul 2021 17:39:44 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] Promise</title>
      <link>https://gusehd66.tistory.com/entry/JavaScript-Promise</link>
      <description>&lt;h2 id=&quot;promise가-뭔가요&quot; data-ke-size=&quot;size26&quot;&gt;Promise란?&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로미스는 &lt;u&gt;자바스크립트 비동기 처리&lt;/u&gt;에 사용되는 객체입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트의 비동기 처리란 &amp;lsquo;특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성&amp;rsquo;을 의미합니다.&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;promise가-왜-필요한가요&quot; data-ke-size=&quot;size26&quot;&gt;Promise의 필요성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로미스는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용합니다. 일반적으로 웹 애플리케이션을 구현할 때 서버에서 데이터를 요청하고 받아오기 위해&amp;nbsp; API를 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API가 실행되면 서버에다가 데이터를 보내달라는 요청을 보냅니다.&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;/p&gt;
&lt;h2 id=&quot;프로미스-코드---기초&quot; data-ke-size=&quot;size26&quot;&gt;프로미스 코드 - 기초&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 프로미스가 어떻게 동작하는지 이해하기 위해 예제 코드를 살펴보겠습니다. 먼저 아래 코드는 간단한 ajax 통신 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288488840&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getData(callbackFunc) {
  $.get('url 주소/products/1', function(response) {
    callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
  });
}

getData(function(tableData) {
  console.log(tableData); // $.get()의 response 값이 tableData에 전달됨
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;;&lt;/span&gt;위 코드는 제이쿼리의&lt;span&gt;&amp;nbsp;&lt;/span&gt;ajax 통신 API를 이용하여 지정된 url에서 1번 상품 데이터를 받아오는 코드입니다.&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;/p&gt;
&lt;pre id=&quot;code_1625288561505&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getData(callback) {
  // new Promise() 추가
  return new Promise(function(resolve, reject) {
    $.get('url 주소/products/1', function(response) {
      // 데이터를 받으면 resolve() 호출
      resolve(response);
    });
  });
}

// getData()의 실행이 끝나면 호출되는 then()
getData().then(function(tableData) {
  // resolve()의 결과 값이 여기로 전달됨
  console.log(tableData); // $.get()의 reponse 값이 tableData에 전달됨
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백 함수로 처리하던 구조에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;new Promise(),&lt;span&gt;&amp;nbsp;&lt;/span&gt;resolve(),&lt;span&gt;&amp;nbsp;&lt;/span&gt;then()와 같은 프로미스 API를 사용한 구조로 바뀌었습니다.&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;프로미스의-3가지-상태states&quot; data-ke-size=&quot;size26&quot;&gt;프로미스의 3가지 상태(states)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로미스의 상태(states)란 프로미스의 처리 과정을 의미합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖습니다.&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;&lt;b&gt;Pending(대기)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new Promise()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드를 호출하면 대기(Pending) 상태가 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288579730&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Promise();&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;new Promise()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수의 인자는&lt;span&gt;&amp;nbsp;&lt;/span&gt;resolve,&lt;span&gt;&amp;nbsp;&lt;/span&gt;reject입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288589148&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Promise(function(resolve, reject) {
  // ...
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff;&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;b&gt;Fulfilled(이행)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백 함수의 인자&lt;span&gt;&amp;nbsp;&lt;/span&gt;resolve를 아래와 같이 실행하면 이행(Fulfilled) 상태가 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288594065&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Promise(function(resolve, reject) {
  resolve();
});&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&gt;&amp;nbsp;&lt;/span&gt;then()을 이용하여 처리 결과 값을 받을 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288607981&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getData() {
  return new Promise(function(resolve, reject) {
    var data = 100;
    resolve(data);
  });
}

// resolve()의 결과 값 data를 resolvedData로 받음
getData().then(function(resolvedData) {
  console.log(resolvedData); // 100
});&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;&lt;b&gt;Rejected(실패)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reject를 아래와 같이 호출하면 실패(Rejected) 상태가 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288651225&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Promise(function(resolve, reject) {
  reject();
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고, 실패 상태가 되면 실패한 이유(실패 처리의 결과 값)를&lt;span&gt;&amp;nbsp;&lt;/span&gt;catch()로 받을 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288670275&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getData() {
  return new Promise(function(resolve, reject) {
    reject(new Error(&quot;Request is failed&quot;));
  });
}

// reject()의 결과 값 Error를 err에 받음
getData().then().catch(function(err) {
  console.log(err); // Error: Request is failed
});&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 id=&quot;프로미스-코드---쉬운-예제&quot; data-ke-size=&quot;size26&quot;&gt;프로미스 코드 - 쉬운 예제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 프로미스 코드를 만들어보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이해하기 쉽게 앞에서 살펴본 ajax 통신 예제 코드에 프로미스를 적용해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288690230&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getData() {
  return new Promise(function(resolve, reject) {
    $.get('url 주소/products/1', function(response) {
      if (response) {
        resolve(response);
      }
      reject(new Error(&quot;Request is failed&quot;));
    });
  });
}

// 위 $.get() 호출 결과에 따라 'response' 또는 'Error' 출력
getData().then(function(data) {
  console.log(data); // response 값 출력
}).catch(function(err) {
  console.error(err); // Error 출력
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 서버에서 제대로 응답을 받아오면&lt;span&gt;&amp;nbsp;&lt;/span&gt;resolve()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드를 호출하고, 응답이 없으면&lt;span&gt;&amp;nbsp;&lt;/span&gt;reject()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드를 호출하는 예제입니다. 호출된 메서드에 따라&lt;span&gt;&amp;nbsp;&lt;/span&gt;then()이나&lt;span&gt;&amp;nbsp;&lt;/span&gt;catch()로 분기하여 응답 결과 또는 오류를 출력합니다.&lt;/p&gt;
&lt;h2 id=&quot;여러-개의-프로미스-연결하기-promise-chaining&quot; data-ke-size=&quot;size26&quot;&gt;여러 개의 프로미스 연결하기 (Promise Chaining)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로미스의 또 다른 특징은 여러 개의 프로미스를 연결하여 사용할 수 있다는 점입니다. 앞 예제에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;then()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드를 호출하고 나면 새로운 프로미스 객체가 반환됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1625288701744&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getData() {
  return new Promise({
    // ...
  });
}

// then() 으로 여러 개의 프로미스를 연결한 형식
getData()
  .then(function(data) {
    // ...
  })
  .then(function() {
    // ...
  })
  .then(function() {
    // ...
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 위의 형식을 참고하여 실제로 돌려볼 수 있는 예제를 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 처리 예제에서 가장 흔하게 사용되는&lt;span&gt;&amp;nbsp;&lt;/span&gt;setTimeout() API를 사용하였습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288708093&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Promise(function(resolve, reject){
  setTimeout(function() {
    resolve(1);
  }, 1000);
})
.then(function(result) {
  console.log(result); // 1
  return result + 10;
})
.then(function(result) {
  console.log(result); // 11
  return result + 20;
})
.then(function(result) {
  console.log(result); // 31
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로미스 객체를 하나 생성하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;setTimeout()을 이용해 1초 후에&lt;span&gt;&amp;nbsp;&lt;/span&gt;resolve()를 호출하는 예제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;resolve()가 호출되면 프로미스가 대기 상태에서 이행 상태로 넘어가기 때문에 첫 번째&lt;span&gt;&amp;nbsp;&lt;/span&gt;.then()의 로직으로 넘어갑니다. 첫 번째&lt;span&gt;&amp;nbsp;&lt;/span&gt;.then()에서는 이행된 결과 값 1을 받아서 10을 더한 후 그다음&lt;span&gt;&amp;nbsp;&lt;/span&gt;.then()&lt;span&gt;&amp;nbsp;&lt;/span&gt;으로 넘겨줍니다. 두 번째&lt;span&gt;&amp;nbsp;&lt;/span&gt;.then()에서도 마찬가지로 바로 이전 프로미스의 결과 값 11을 받아서 20을 더하고 다음&lt;span&gt;&amp;nbsp;&lt;/span&gt;.then()으로 넘겨줍니다. 마지막&lt;span&gt;&amp;nbsp;&lt;/span&gt;.then()에서 최종 결과 값 31을 출력합니다.&lt;/p&gt;
&lt;h2 id=&quot;실무에서-있을-법한-프로미스-연결-사례&quot; data-ke-size=&quot;size26&quot;&gt;실무에서 있을 법한 프로미스 연결 사례&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 웹 서비스에서 있을 법한 사용자 로그인 인증 로직에 프로미스를 여러 개 연결해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288718690&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;getData(userInfo)
  .then(parseValue)
  .then(auth)
  .then(diaplay);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 페이지에 입력된 사용자 정보를 받아와 파싱, 인증 등의 작업을 거치는 코드를 나타내었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서&lt;span&gt;&amp;nbsp;&lt;/span&gt;userInfo는 사용자 정보가 담긴 객체를 의미하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;parseValue,&lt;span&gt;&amp;nbsp;&lt;/span&gt;auth,&lt;span&gt;&amp;nbsp;&lt;/span&gt;display는 각각 프로미스를 반환해주는 함수라고 가정했습니다. 아래와 같이 말이죠.&lt;/p&gt;
&lt;pre id=&quot;code_1625288728337&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var userInfo = {
  id: 'test@abc.com',
  pw: '****'
};

function parseValue() {
  return new Promise({
    // ...
  });
}
function auth() {
  return new Promise({
    // ...
  });
}
function display() {
  return new Promise({
    // ...
  });
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 여러 개의 프로미스를&lt;span&gt;&amp;nbsp;&lt;/span&gt;.then()으로 연결하여 처리할 수 있습니다.&lt;/p&gt;
&lt;h2 id=&quot;프로미스의-에러-처리-방법&quot; data-ke-size=&quot;size26&quot;&gt;프로미스의 에러 처리 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 살펴본 프로미스 예제는 코드가 항상 정상적으로 동작한다고 가정하고 구현한 예제입니다. 실제 서비스를 구현하다 보면 네트워크 연결, 서버 문제 등으로 인해 오류가 발생할 수 있습니다. 따라서, 프로미스의 에러 처리 방법에 대해서도 알고 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러 처리 방법에는 다음과 같이 2가지 방법이 있습니다.&lt;br /&gt;&lt;br /&gt;1.then()의 두 번째 인자로 에러를 처리하는 방법&lt;/p&gt;
&lt;pre id=&quot;code_1625288735033&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;getData().then(
  handleSuccess,
  handleError
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.catch()를 이용하는 방법&lt;/p&gt;
&lt;pre id=&quot;code_1625288740771&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;getData().then().catch();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 2가지 방법 모두 프로미스의&lt;span&gt;&amp;nbsp;&lt;/span&gt;reject()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드가 호출되어 실패 상태가 된 경우에 실행됩니다. 간단하게 말해서 프로미스의 로직이 정상적으로 돌아가지 않는 경우 호출되는 거죠. 아래와 같이 말입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288745843&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getData() {
  return new Promise(function(resolve, reject) {
    reject('failed');
  });
}

// 1. then()의 두 번째 인자로 에러를 처리하는 코드
getData().then(function() {
  // ...
}, function(err) {
  console.log(err);
});

// 2. catch()로 에러를 처리하는 코드
getData().then().catch(function(err) {
  console.log(err);
});&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;프로미스-에러-처리는-가급적-catch를-사용&quot; data-ke-size=&quot;size26&quot;&gt;프로미스 에러 처리는 가급적 catch()를 사용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 프로미스 에러 처리 방법 2가지를 살펴봤습니다. 개개인의 코딩 스타일에 따라서&lt;span&gt;&amp;nbsp;&lt;/span&gt;then()의 두 번째 인자로 처리할 수도 있고&lt;span&gt;&amp;nbsp;&lt;/span&gt;catch()로 처리할 수도 있겠지만 가급적&lt;span&gt;&amp;nbsp;&lt;/span&gt;catch()로 에러를 처리하는 게 더 효율적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 아래의 코드를 보시면 알 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288758759&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// then()의 두 번째 인자로는 감지하지 못하는 오류
function getData() {
  return new Promise(function(resolve, reject) {
    resolve('hi');
  });
}

getData().then(function(result) {
  console.log(result);
  throw new Error(&quot;Error in then()&quot;); // Uncaught (in promise) Error: Error in then()
}, function(err) {
  console.log('then error : ', err);
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getData()&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수의 프로미스에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;resolve()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메서드를 호출하여 정상적으로 로직을 처리했지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;then()의 첫 번째 콜백 함수 내부에서 오류가 나는 경우 오류를 제대로 잡아내지 못합니다. 따라서 코드를 실행하면 아래와 같은 오류가 납니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;110&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zFYeA/btq8KRNLwlq/FbbaZsKvMd60jcHfE0vLZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zFYeA/btq8KRNLwlq/FbbaZsKvMd60jcHfE0vLZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zFYeA/btq8KRNLwlq/FbbaZsKvMd60jcHfE0vLZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzFYeA%2Fbtq8KRNLwlq%2FFbbaZsKvMd60jcHfE0vLZ0%2Fimg.png&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;110&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;'에러를 잡지 못했습니다(Uncaught Error)' 로그&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 똑같은 오류를&lt;span&gt;&amp;nbsp;&lt;/span&gt;catch()로 처리하면 다른 결과가 나옵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625288767052&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// catch()로 오류를 감지하는 코드
function getData() {
  return new Promise(function(resolve, reject) {
    resolve('hi');
  });
}

getData().then(function(result) {
  console.log(result); // hi
  throw new Error(&quot;Error in then()&quot;);
}).catch(function(err) {
  console.log('then error : ', err); // then error :  Error: Error in then()
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 처리 결과는 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;642&quot; data-origin-height=&quot;112&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nYeB9/btq8GDcSdw3/tgCcsb0O5AzOj3fqCLKQKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nYeB9/btq8GDcSdw3/tgCcsb0O5AzOj3fqCLKQKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nYeB9/btq8GDcSdw3/tgCcsb0O5AzOj3fqCLKQKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnYeB9%2Fbtq8GDcSdw3%2FtgCcsb0O5AzOj3fqCLKQKK%2Fimg.png&quot; data-origin-width=&quot;642&quot; data-origin-height=&quot;112&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;발생한 에러를 성공적으로 콘솔에 출력한 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;따라서, 더 많은 예외 처리 상황을 위해 프로미스의 끝에 가급적 catch()를 붙이시기 바랍니다.&lt;/b&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;/p&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>Promise</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/48</guid>
      <comments>https://gusehd66.tistory.com/entry/JavaScript-Promise#entry48comment</comments>
      <pubDate>Sat, 3 Jul 2021 14:17:32 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 컴포지션 API - props, context</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EC%A7%80%EC%85%98-API-props-context</link>
      <description>&lt;h1 id=&quot;컴포지션-api---props-context&quot;&gt;컴포지션 API - props, context&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 전달인자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setup&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;펑션은 2가지 전달인자를 가집니다&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;props&lt;/li&gt;
&lt;li&gt;context&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;props&quot; data-ke-size=&quot;size23&quot;&gt;1.1 Props&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setup&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;펑션의 첫번째 전달인자는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;props&lt;span style=&quot;color: #2c3e50;&quot;&gt;입니다. 표준 컴포넌트에서 예상하는 것처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;setup&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;내부의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;props&lt;span style=&quot;color: #2c3e50;&quot;&gt;는 반응성이 있고, 새로운 props가 전달되면 업데이트됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;context&quot; data-ke-size=&quot;size23&quot;&gt;1.2 Context&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setup&lt;span style=&quot;color: #2c3e50;&quot;&gt;펑션의 두번째 전달인자는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;context&lt;span style=&quot;color: #2c3e50;&quot;&gt;입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;context&lt;span style=&quot;color: #2c3e50;&quot;&gt;는 3가지 컴포넌트 프로퍼티를 가지는 일반 JavaScript 객체입니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;컴포넌트-속성에-접근하기&quot; data-ke-size=&quot;size26&quot;&gt;2. 컴포넌트 속성에 접근하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setup&lt;span style=&quot;color: #2c3e50;&quot;&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;props&lt;/li&gt;
&lt;li&gt;attrs&lt;/li&gt;
&lt;li&gt;slots&lt;/li&gt;
&lt;li&gt;emit&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 다음 컴포넌트 옵션에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;접근할 수 없습니다&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;data&lt;/li&gt;
&lt;li&gt;computed&lt;/li&gt;
&lt;li&gt;methods&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;1-컴포지션-api-비교-예시&quot; data-ke-size=&quot;size26&quot;&gt;3. 컴포지션 API 비교 예시&lt;/h2&gt;
&lt;h3 id=&quot;11-컴포지션-api-사용-전-코드-예시&quot; data-ke-size=&quot;size23&quot;&gt;3.1 컴포지션 API 사용 전 코드 예시&lt;/h3&gt;
&lt;pre id=&quot;code_1625115032814&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;template&amp;gt;
  &amp;lt;MyBtn
    class=&quot;orosy&quot;
    style=&quot;color: red;&quot;
    color=&quot;#ff0000&quot;
    @hello=&quot;log&quot;&amp;gt;
    Apple
  &amp;lt;/mybtn&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
import MyBtn from '~/components/MyBtn'

export default {
  components: {
    MyBtn
  },
  methods: {
    log() {
      console.log('Hello world!')
    }
  }
}
&amp;lt;/script&amp;gt;

//MyBtn.vue
&amp;lt;template&amp;gt;
  &amp;lt;div
    v-bind=&quot;$attrs&quot;
    class=&quot;btn&quot;
    @click=&quot;hello&quot;&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  inheritAttrs: false,
  props: {
    color: {
      type: String,
      default: 'gray'
    }
  },
  emits: ['hello'],
  mounted() {
    console.log(this.color)
    console.log(this.$attrs)
  },
  methods: {
    hello() {
      this.$emit('hello')
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;12-컴포지션-api-사용-후-코드-예시&quot; data-ke-size=&quot;size23&quot;&gt;3.2 컴포지션 API 사용 후 코드 예시&lt;/h3&gt;
&lt;pre id=&quot;code_1625115055456&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MyBtn.vue
&amp;lt;template&amp;gt;
  &amp;lt;div
    v-bind=&quot;$attrs&quot;
    class=&quot;btn&quot;
    @click=&quot;hello&quot;&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
import { onMounted } from 'vue'
export default {
  inheritAttrs: false,
  props: {
    color: {
      type: String,
      default: 'gray'
    }
  },
  emits: ['hello'],
  setup(props, context) {
    function hello() {
      context.emit('hello')
    }
    onMounted(() =&amp;gt; {
      console.log(props.color)
      console.log(context.attrs)
    })

    return {
      hello
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;this-사용법&quot; data-ke-size=&quot;size26&quot;&gt;4. this&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;setup()&lt;span&gt;&amp;nbsp;&lt;/span&gt;내부의&lt;span&gt;&amp;nbsp;&lt;/span&gt;this는 현재 활성화된 인스턴스에 대한 참조가 아닙니다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다른 컴포넌트 옵션들이 resolved가 되기 전에&lt;span&gt;&amp;nbsp;&lt;/span&gt;setup()이 호출되었기 때문에,&lt;span&gt;&amp;nbsp;&lt;/span&gt;setup()&lt;span&gt;&amp;nbsp;&lt;/span&gt;내부의&lt;span&gt;&amp;nbsp;&lt;/span&gt;this는 다른 옵션 내부의&lt;span&gt;&amp;nbsp;&lt;/span&gt;this와 다르게 동작합니다. 이로인해 다른 Options API와 함께&lt;span&gt;&amp;nbsp;&lt;/span&gt;setup()를 사용할 때 혼동이 발생할 수 있습니다.&lt;/p&gt;</description>
      <category>Vue</category>
      <category>context</category>
      <category>props</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>컴포넌트 API</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/47</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EC%A7%80%EC%85%98-API-props-context#entry47comment</comments>
      <pubDate>Thu, 1 Jul 2021 13:56:15 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 컴포지션 API</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EC%A7%80%EC%85%98-API</link>
      <description>&lt;h3 id=&quot;12-컴포지션-api의-필요성&quot; data-ke-size=&quot;size23&quot;&gt;1. 컴포지션 API의 필요성&lt;/h3&gt;
&lt;pre id=&quot;code_1625111423575&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;template&amp;gt;
  &amp;lt;h1 @click=&quot;increase&quot;&amp;gt;
    {{ count }} / {{ doubleCount }}
  &amp;lt;/h1&amp;gt;
  &amp;lt;h1&amp;gt;
    {{ message }} / {{ reversedMessage }}
  &amp;lt;/h1&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      message: 'Hello world!',
      count: 0
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    },
    reversedMessage() {
      return this.message.split('').reverse().join('')
    }
  },
  methods: {
    increase() {
      this.count += 1
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;message와 관련된 코드, 그리고 count와 관련된 코드가 나뉘어 작성을 하게 되며 코드가 동작하는 로직을 이해하기 위해서 관련 코드의 옵션 블록을 지속적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;점프&lt;/b&gt;해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 이해하기 위해 관련 옵션들을 위, 아래로 이동(스크롤)하여 코드를 보는 행동을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;점프&lt;/b&gt;라고 표현합니다. 논리적인 관점 단위로 개발을 하려고 해도 이 옵션의 규칙을 지켜야하고 더 많은 논리 주제가 추가될 수록 코드의 양이 많아져 가독성이 떨어지고 유지보수성이 낮아집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 동일한 논리적 관심사와 관련있는 코드를 함께 배치할 수 있다면 더 좋을 것입니다. 이것이 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Composition API&lt;/b&gt;가 할 수 있는 일입니다.&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1 id=&quot;컴포지션-api---반응형-데이터&quot;&gt;컴포지션 API - 반응형 데이터&lt;/h1&gt;
&lt;h2 id=&quot;1-반응형-데이터반응성&quot; data-ke-size=&quot;size26&quot;&gt;2. 반응형 데이터(반응성)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js의 중요한 개념인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;반응성&lt;/b&gt;에 대해 살펴본 적이 있습니다. 이를 컴포지션 API로 코드를 수정하여 사용할 수 있으며 이에 대해 살펴봅시다.&lt;/p&gt;
&lt;h3 id=&quot;11-코드-예시&quot; data-ke-size=&quot;size23&quot;&gt;2.1 코드 예시&lt;/h3&gt;
&lt;pre id=&quot;code_1625111213121&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;h1 @click=&quot;increase&quot;&amp;gt;
  {{ count }}
&amp;lt;/h1&amp;gt;
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increase() {
      this.count += 1
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클릭 이벤트를 통해&amp;nbsp;0인&lt;span&gt;&amp;nbsp;&lt;/span&gt;count가 1씩 증가하는 코드로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;반응성&lt;/b&gt;이 적용되어 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;12-컴포지션-api-사용-예시중간형&quot; data-ke-size=&quot;size23&quot;&gt;2.2 컴포지션 API 사용 예시(중간형)&lt;/h3&gt;
&lt;pre id=&quot;code_1625111222035&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;App.vue
&amp;lt;h1 @click=&quot;increase&quot;&amp;gt;
  {{ count }}
&amp;lt;/h1&amp;gt;
export default {
  setup() {
    let count = 0 // 
    function increase() {
      count += 1
    }

    return {
      count,
      increase
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드와 똑같이 구현을 했지만, 실제로 이벤트가 동작하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 데이터인&lt;span&gt;&amp;nbsp;&lt;/span&gt;count가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;반응성&lt;/b&gt;을 갖고 있지 않기 때문입니다.&lt;br /&gt;이처럼 컴포지션 API를 활용할 때에는 특정한 데이터가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;반응성&lt;/b&gt;을 가지도록 Vue 에서 제공하는 ref라는 기능을 사용해야 합니다.&lt;/p&gt;
&lt;h3 id=&quot;13-컴포지션-api-사용-예시완성형&quot; data-ke-size=&quot;size23&quot;&gt;2.3 컴포지션 API 사용 예시(완성형)&lt;/h3&gt;
&lt;pre id=&quot;code_1625111229487&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;App.vue
&amp;lt;h1 @click=&quot;increase&quot;&amp;gt;
  {{ count }}
&amp;lt;/h1&amp;gt;
import { ref } from 'vue' // vue 패키지에서 ref 기능 가져오기

export default {
  setup() {
    let count = ref(0) // ref 함수의 인수로 초기값 0 입력
    function increase() {
      count.value += 1 // count는 객체 데이터로 반환되므로 value 속성 명시
    }

    return {
      count,
      increase
    }
  }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Vue</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>반응형 데이터</category>
      <category>컴포지션 API</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/46</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EC%A7%80%EC%85%98-API#entry46comment</comments>
      <pubDate>Thu, 1 Jul 2021 12:51:03 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 컴포넌트 - Refs</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Refs</link>
      <description>&lt;h1 id=&quot;컴포넌트---refs&quot;&gt;컴포넌트 - Refs&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;11-개념&quot; data-ke-size=&quot;size23&quot;&gt;1.1 개념&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;비록 props와 이벤트가 존재하지만, 가끔은 자식 요소에 JavaScript를 이용해 직접 접근해야 하는 경우가 있습니다. 이 경우,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ref&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성을 이용해 레퍼런스 ID를 자식 컴포넌트나 HTML 요소에 부여함으로써 직접 접근할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1625050328020&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mounted() {
    const h1El = document.querySelector('#hello')
    console.log(h1El.textContent)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;원래의 경우라면 위처럼 DOM API를 사용하게 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;하지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;참조&lt;/b&gt;&lt;span style=&quot;color: #222426;&quot;&gt;하겠다는 의미의 &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ref &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #222426;&quot;&gt;라는 속성을 사용하면 해당 기능을 간단하게 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;12-refs-사용-예시&quot; data-ke-size=&quot;size23&quot;&gt;1.2 Refs 사용 예시&lt;/h3&gt;
&lt;pre id=&quot;code_1625050355675&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;h1 ref=&quot;hello&quot;&amp;gt;Hello world!&amp;lt;/h1&amp;gt;
export default {
  mounted() {
    console.log(this.$refs.hello.textContent)
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue에서 제공하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;ref라는 속성을 통해 해당 요소를 참조할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 참조된 내용은 Vue의&lt;span&gt;&amp;nbsp;&lt;/span&gt;$refs라는 객체에 해당하는 hello라는 이름으로 들어가서 저장이 되는 구조를 갖고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, HTML과 연결된 직후만 사용이 가능하므로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;created()라는 라이프사이클에서는 사용이 불가합니다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;13-컴포넌트에서-refs-사용-예시&quot; data-ke-size=&quot;size23&quot;&gt;1.3 컴포넌트에서 Refs 사용 예시&lt;/h3&gt;
&lt;pre id=&quot;code_1625050454453&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
&amp;lt;Hello ref=&quot;hello&quot; /&amp;gt;
import Hello from '~/components/Hello'

export default {
  components: {
    Hello
  },
  mounted() {
    console.log(this.$refs.hello.$el)
  }
}
&amp;lt;/script&amp;gt;

//Hello.vue(자식 컴포넌트)
&amp;lt;h1&amp;gt;Hello~&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 ref라는 속성으로 어떠한 이름(hello)으로 참조를 할 경우에는 참조된 이름 뒤쪽에&lt;span&gt;&amp;nbsp;&lt;/span&gt;$el을 명시해줘야만 해당하는 내용을 참조할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 여기서도 컴포넌트의 최상위 요소가 2개 이상이면&lt;span&gt;&amp;nbsp;&lt;/span&gt;$el&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성으로 어떤 요소를 바라봐야하는지 알 수 없게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1625050839973&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
export default {
  components: {
    Hello
  },
  mounted() {
    console.log(this.$refs.hello.$refs.good)
  }
}

//Hello.vue(자식 컴포넌트)
&amp;lt;h1&amp;gt;Hello~&amp;lt;/h1&amp;gt;
&amp;lt;h1 ref=&quot;good&quot;&amp;gt;Good?&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 경우에는 자식 컴포넌트에&lt;span&gt;&amp;nbsp;&lt;/span&gt;ref라는 속성에 이름을 명시하고 부모 컴포넌트에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;$el&lt;span&gt;&amp;nbsp;&lt;/span&gt;이 아닌&lt;span&gt;&amp;nbsp;&lt;/span&gt;$refs의 속성에 자식 컴포넌트에 명시한 이름을 코딩해주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Vue</category>
      <category>refs</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>컴포넌트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/45</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Refs#entry45comment</comments>
      <pubDate>Wed, 30 Jun 2021 20:02:58 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 컴포넌트 - Provide, Inject</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Provide-Inject</link>
      <description>&lt;h2 id=&quot;1-provide--inject&quot; data-ke-size=&quot;size26&quot;&gt;1. Provide &amp;amp; Inject&lt;/h2&gt;
&lt;h3 id=&quot;11-개념&quot; data-ke-size=&quot;size23&quot;&gt;1.1 개념&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 데이터를 부모에서 자식 컴포넌트로 전달해야할 때&lt;span&gt;&amp;nbsp;&lt;/span&gt;props를 사용합니다. 특정한 두 컴포넌트 사이에 깊이 중첩된 컴포넌트가 있는 구조의 경우 하위 컴포넌트에서 상위 컴포넌트의 무언가가 필요한 경우를 상상해보십시오. 이 경우에 두 컴포넌트 사이의 모든 컴포넌트에&lt;span&gt;&amp;nbsp;&lt;/span&gt;prop를 전달해야하므로 굉장히 번거로울 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide와&lt;span&gt;&amp;nbsp;&lt;/span&gt;inject&lt;span&gt;&amp;nbsp;&lt;/span&gt;쌍을 사용할 수 있습니다. 부모 컴포넌트는 컴포넌트 계층 구조의 깊이와 상관없이 모든 자식에 대한 종속성 제공자 역할을 할 수 있습니다. 이 기능은 2개의 부분으로 구성됩니다: 부모 컴포넌트는 데이터 제공을 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션을 사용하며, 자식 요소는 데이터 사용을 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;inject&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션을 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625049498142&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(조상[상위] 컴포넌트)
&amp;lt;Parent :msg=&quot;message&quot; /&amp;gt;
import Parent from '~/components/Parent'
export default {
  components: {
    Parent
  },
  data() {
    return {
      message: 'Hello world!'
    }
  }
}
//Parent.vue(부모 컴포넌트)
&amp;lt;Child :msg=&quot;msg&quot; /&amp;gt;
import Child from '~/components/Child'
export default {
  components: {
    Child
  },
  props: {
    msg: {
      type: String,
      default: ''
    }
  }
}
//Child.vue(자식 컴포넌트)
&amp;lt;div&amp;gt;  {{ msg }}  &amp;lt;/div&amp;gt;
export default {
  props: {
    msg: {
      type: String,
      default: ''
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;손자 컴포넌트인&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg를 루트 컴포넌트에 전달하려고 하면 두 단계를 거쳐야만 하고, 중간에 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Parent.vue&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일의&lt;span&gt;&amp;nbsp;&lt;/span&gt;props는 사용하지도 않지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg라는 데이터를&lt;span&gt;&amp;nbsp;&lt;/span&gt;Child.vue에 전달하는 역할말고는 전혀 사용을 하고 있지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 부분을 해결하기 위한 것이&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide와&lt;span&gt;&amp;nbsp;&lt;/span&gt;inject&lt;span&gt;&amp;nbsp;&lt;/span&gt;키워드입니다.&lt;/p&gt;
&lt;h3 id=&quot;12-provide-inject-사용-예시&quot; data-ke-size=&quot;size23&quot;&gt;1.2 Provide, Inject 사용 예시&lt;/h3&gt;
&lt;pre id=&quot;code_1625049524031&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(조상[상위] 컴포넌트)
&amp;lt;Parent /&amp;gt;
import Parent from '~/components/Parent'
export default {
  components: {
    Parent
  },
  data() {
    return {
      message: 'Hello world!'
    }
  },
  provide() {
    return {
      msg: this.message // data()의 message 사용할게!
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;data()의&lt;span&gt;&amp;nbsp;&lt;/span&gt;message&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션 부분을&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide의&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg라는 이름으로 사용하겠다는 코드를 작성하면 Parent.vue를 중간 매개체로 사용하지 않아도 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 html 부분에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;Parent /&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;코드만 작성해주시면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625049564067&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Parent.vue(부모 컴포넌트)
&amp;lt;Child /&amp;gt; // :msg=&quot;msg&quot; 부분 삭제
import Child from '~/components/Child'
export default {
  components: {
    Child
  }
}

//Child.vue(자식 컴포넌트)
&amp;lt;div&amp;gt;  {{ msg }}  &amp;lt;/div&amp;gt;
export default {
  inject: ['msg'] 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 받을&lt;span&gt;&amp;nbsp;&lt;/span&gt;Child.vue에&lt;span&gt;&amp;nbsp;&lt;/span&gt;inject라는 키워드를 사용하여 배열 데이터 안에&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide라는 옵션을 통해서 지정한 이름인&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg를 명시해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg가 하나의 데이터로 취급이 되어&lt;span&gt;&amp;nbsp;&lt;/span&gt;{{ msg }}&lt;span&gt;&amp;nbsp;&lt;/span&gt;이 부분에서 데이터가 출력되게 만들어줄 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;13-주의사항&quot; data-ke-size=&quot;size23&quot;&gt;1.3 주의사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide,&lt;span&gt;&amp;nbsp;&lt;/span&gt;inject라는 키워드를 사용하면 중간 과정 없이 바로 데이터를 전달해줄 수 있습니다. 그러나 여기서 주의사항이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그것은 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide&lt;span&gt;&amp;nbsp;&lt;/span&gt;키워드는 기본적으로 반응성을 제공할 수 없다는 것입니다. 그렇기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide는 데이터를 전달해서 출력하는 용도로만 사용하거나 혹은 추가 작업이 필요합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625049584628&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(조상[상위] 컴포넌트)
&amp;lt;button @click=&quot;message = 'Good?'&quot;&amp;gt;
  Click!
&amp;lt;/button&amp;gt;
&amp;lt;h1&amp;gt;App: {{ message }}&amp;lt;/h1&amp;gt;
&amp;lt;Parent /&amp;gt;
import Parent from '~/components/Parent'
import { computed } from 'vue' // computed 가져오기
export default {
  components: {
    Parent
  },
  data() {
    return {
      message: 'Hello world!'
    }
  },
  provide() {
    return {
      msg: computed(() =&amp;gt; {
        return this.message // 콜백 함수 형태로 return
      }) // msg: computed(() =&amp;gt; this.message) // 중괄호, return 생략 가능
    }
  }
}

//Child.vue(자식 컴포넌트)
&amp;lt;div&amp;gt;  {{ msg.value }}  &amp;lt;/div&amp;gt; // msg라는 데이터의 value 속성 값
export default {
  inject: ['msg'] 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg라는&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide에서 넘어온 데이터는 계산된 하나의 객체 데이터이며, 그 객체 데이터에서 내가 원하는 데이터를 출력하기 위해서는 그 안의 value라는 속성을 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게&lt;span&gt;&amp;nbsp;&lt;/span&gt;provide&lt;span&gt;&amp;nbsp;&lt;/span&gt;키워드를 사용하여 반응성을 유지하는 데이터를 만들기 위해서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;computed라는 함수를 실행해서 그 내부에서 반응성을 갖고 싶은 데이터를 반환해주면 되는 것입니다.&lt;/p&gt;</description>
      <category>Vue</category>
      <category>inject</category>
      <category>provide</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>컴포넌트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/44</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Provide-Inject#entry44comment</comments>
      <pubDate>Wed, 30 Jun 2021 19:51:09 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 컴포넌트 - Slot</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Slot</link>
      <description>&lt;h1&gt;컴포넌트 - Slot&lt;/h1&gt;
&lt;h2 id=&quot;1-slot&quot; data-ke-size=&quot;size26&quot;&gt;1. Slot&lt;/h2&gt;
&lt;h3 id=&quot;11-fallback-contents&quot; data-ke-size=&quot;size23&quot;&gt;1.1 Fallback Contents&lt;/h3&gt;
&lt;pre id=&quot;code_1625048951603&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
&amp;lt;MyBtn&amp;gt;Cherry&amp;lt;/MyBtn&amp;gt;
export default {
  components: {
    MyBtn
  }
}

//MyBtn.vue(자식 컴포넌트)
&amp;lt;div class=&quot;btn&quot;&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;slot의 태그로 부모 컴포넌트에서 받을 데이터의 자리를 표시하면&lt;span&gt; Cherry&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #222426;&quot;&gt;라는 텍스트를 화면에 출력할 수 있었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;하지만 여기서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;slot&lt;span style=&quot;color: #222426;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그 내에 내용을 입력할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1625049072523&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
&amp;lt;MyBtn&amp;gt;&amp;lt;/MyBtn&amp;gt;

//MyBtn.vue(자식 컴포넌트)
&amp;lt;div class=&quot;btn&quot;&amp;gt;
    &amp;lt;slot&amp;gt;Apple&amp;lt;/slot&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;slot&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그 내에 텍스트를 입력하면, 그 내용이 출력됩니다.&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;span&gt;&amp;nbsp;&lt;/span&gt;slot&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그 내에 입력한 컨텐츠를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Fallback Contents&lt;/b&gt;라 부르고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;대체 컨텐츠&lt;/b&gt;라는 의미입니다.&lt;/p&gt;
&lt;h3 id=&quot;12-named-slots&quot; data-ke-size=&quot;size23&quot;&gt;1.2 Named Slots&lt;/h3&gt;
&lt;pre id=&quot;code_1625049181047&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
&amp;lt;MyBtn&amp;gt;
    &amp;lt;span&amp;gt;Cherry&amp;lt;/span&amp;gt; // text
    &amp;lt;span&amp;gt;(B)&amp;lt;/span&amp;gt;    // icon
&amp;lt;/MyBtn&amp;gt;

//MyBtn.vue(자식 컴포넌트)
&amp;lt;div class=&quot;btn&quot;&amp;gt;
    &amp;lt;slot&amp;gt;Apple&amp;lt;/slot&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;slot&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그 안에 컨텐츠를 두 개 이상 입력할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이처럼 입력하게 되면 입력한 순서대로인 텍스트인&lt;span&gt; Cherry&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다음 아이콘&lt;span&gt;&amp;nbsp;&lt;/span&gt;(B)가 출력됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 순서를 정확히 지켜서 동작하게 하고 싶다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Named Slots(이름을 갖는 슬롯)&lt;/b&gt;을 적용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625049261153&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
&amp;lt;MyBtn&amp;gt;
  &amp;lt;template v-slot:icon&amp;gt;
    &amp;lt;span&amp;gt;(B)&amp;lt;/span&amp;gt;
  &amp;lt;/template&amp;gt;
  &amp;lt;template #text&amp;gt; // #: v-slot의 약어 
    &amp;lt;span&amp;gt;Cherry&amp;lt;/span&amp;gt;
  &amp;lt;/template&amp;gt;
&amp;lt;/MyBtn&amp;gt;

//MyBtn.vue(자식 컴포넌트)
&amp;lt;div class=&quot;btn&quot;&amp;gt;
  &amp;lt;slot name=&quot;icon&quot;&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;slot name=&quot;text&quot;&amp;gt;&amp;lt;/slot&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 자식 컴포넌트에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;slot&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그에 간단하게&lt;span&gt;&amp;nbsp;&lt;/span&gt;name이라는 속성을 추가해서 각각의 값을 명시해주고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트에는 컨텐츠를&lt;span&gt;&amp;nbsp;&lt;/span&gt;template라는 태그로 감싸줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그 태그에&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-slot이라는 속성을 추가해서 자식 컴포넌트에서 정의한&lt;span&gt;&amp;nbsp;&lt;/span&gt;slot&lt;span&gt;&amp;nbsp;&lt;/span&gt;이름을 명시해줍니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-slot은 약어로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;#&lt;/span&gt;을 사용하며, 약어를 주로 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서를 보장하면 부모 컴포넌트에서 순서가 뒤바뀐다 하더라도 보장한 순서대로 출력이 됩니다.&lt;/p&gt;</description>
      <category>Vue</category>
      <category>SLoT</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>컴포넌트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/43</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Slot#entry43comment</comments>
      <pubDate>Wed, 30 Jun 2021 19:36:13 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 컴포넌트 - Emit</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Emit</link>
      <description>&lt;h1 id=&quot;컴포넌트---emit&quot;&gt;컴포넌트 - Emit&lt;/h1&gt;
&lt;h2 id=&quot;1-이벤트-상속&quot; data-ke-size=&quot;size26&quot;&gt;1. 이벤트 상속&lt;/h2&gt;
&lt;pre id=&quot;code_1625048333972&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
&amp;lt;MyBtn @click=&quot;log&quot;&amp;gt;Banana&amp;lt;/MyBtn&amp;gt;
export default {
  components: {
    MyBtn
  },
  methods: {
    log() {
      console.log('Click!!')
    }
  }
}

//MyBtn.vue(자식 컴포넌트)
&amp;lt;div class=&quot;btn&quot;&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
&amp;lt;/div&amp;gt;
export default {
  inheritAttrs: false
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MyBtn 태그에 클릭 이벤트 발생시에 실행할 method를 연결하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나&lt;span&gt;&amp;nbsp;&lt;/span&gt;@click이라는 속성으로 연결을 하였기 때문에 자식 컴포넌트에&lt;span&gt;&amp;nbsp;&lt;/span&gt;inheritAttrs: false&lt;span&gt;&amp;nbsp;&lt;/span&gt;값으로 인해 클릭을 하여도 method가 실행되지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 컴포넌트에 최상위 요소가 2개 이상이고 inheritAttrs&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션을 사용해야하는 경우라면 이벤트를 적용할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이벤트도 $attrs와 비슷하게 필요한 경우에만 개별로 적용할 수 있습니다.&lt;/p&gt;
&lt;h2 id=&quot;2-emit&quot; data-ke-size=&quot;size26&quot;&gt;2. Emit&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 이벤트 속성을 가능하게 만드는 것이 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;emit입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625048354415&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MyBtn.vue(자식 컴포넌트)
&amp;lt;script&amp;gt;
export default {
  emits: [
    'click'
  ]
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이&lt;span&gt;&amp;nbsp;&lt;/span&gt;emits&lt;span&gt;&amp;nbsp;&lt;/span&gt;라는 옵션을 추가하여 배열 데이터로 부모 컴포넌트에서 추가한 옵션인 클릭 이벤트를 사용하겠다고 명시하시면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625048366212&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MyBtn.vue(자식 컴포넌트)
&amp;lt;template&amp;gt;
  &amp;lt;h1 @click=&quot;$emit('click')&quot;&amp;gt;ABC&amp;lt;/h1&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 template 태그에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;h1 @click=&quot;$emit('click')&quot;&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;click 옵션에&lt;span&gt;&amp;nbsp;&lt;/span&gt;$emit이라는 메소드에&lt;span&gt;&amp;nbsp;&lt;/span&gt;emits&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션에 정의한&lt;span&gt;&amp;nbsp;&lt;/span&gt;'click'을 입력해주시면 됩니다. 그러면 부모 컴포넌트(App.vue)에 정의한&lt;span&gt;&amp;nbsp;&lt;/span&gt;log()&lt;span&gt;&amp;nbsp;&lt;/span&gt;메소드가 실행되는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;h2 id=&quot;3-추가-코드-예시&quot; data-ke-size=&quot;size26&quot;&gt;3. 추가 코드 예시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게&lt;span&gt;&amp;nbsp;&lt;/span&gt;emit이라는 키워드를 통해 원하는 이름의 이벤트를 자유롭게 만들어 사용할 수 있습니다. 그리고 이를 활용하여 부모 컴포넌트와 자식 컴포넌트 간의 이벤트와 데이터를 주고 받을 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625048374965&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
&amp;lt;template&amp;gt;
  &amp;lt;MyBtn
    @dongit=&quot;log&quot;
    @change-msg=&quot;logMsg&quot;&amp;gt;
    Banana
  &amp;lt;/MyBtn&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
import MyBtn from '~/components/MyBtn'

export default {
  components: {
    MyBtn
  },
  methods: {
    log(event) {
      console.log('Click!!')
      console.log(event)
    },
    logMsg(msg) {
      console.log(msg)
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1625048384915&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MyBtn.vue(자식 컴포넌트)
&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;btn&quot;&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;h1 @dblclick=&quot;$emit('dongit', $event)&quot;&amp;gt;
    ABC
  &amp;lt;/h1&amp;gt;
  &amp;lt;input
    type=&quot;text&quot;
    v-model=&quot;msg&quot; /&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  emits: [
    'dongit',
    'changeMsg'
  ],
  data() {
    return {
      msg: ''
    }
  },
  watch: {
    msg() {
      this.$emit('changeMsg', this.msg)
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Vue</category>
      <category>emit</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>컴포넌트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/42</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Emit#entry42comment</comments>
      <pubDate>Wed, 30 Jun 2021 19:27:14 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js]  컴포넌트 - 속성 상속</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%86%8D%EC%84%B1-%EC%83%81%EC%86%8D</link>
      <description>&lt;h1 id=&quot;컴포넌트---속성-상속&quot;&gt;컴포넌트 - 속성 상속&lt;/h1&gt;
&lt;h2 id=&quot;1-속성-상속&quot; data-ke-size=&quot;size26&quot;&gt;1. 속성 상속&lt;/h2&gt;
&lt;h3 id=&quot;11-클래스-상속&quot; data-ke-size=&quot;size23&quot;&gt;1.1 클래스 상속&lt;/h3&gt;
&lt;pre id=&quot;code_1625046388959&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
&amp;lt;MyBtn class=&quot;fruit&quot;&amp;gt;Banana&amp;lt;/MyBtn&amp;gt;

//MyBtn.vue(자식 컴포넌트)
&amp;lt;template&amp;gt;
  &amp;lt;!-- &amp;lt;div class =&quot;btn orosy&quot;&amp;gt; --&amp;gt;
  &amp;lt;div class=&quot;btn&quot;&amp;gt; // 최상위 요소(Root Element)
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트의 html 요소에&lt;span&gt;&amp;nbsp;&lt;/span&gt;class&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성으로 값을 입력한 경우, 자식 컴포넌트의&lt;span&gt;&amp;nbsp;&lt;/span&gt;btn이라는 클래스에 상속이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 개념을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;속성 상속&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625046405225&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MyBtn.vue(자식 컴포넌트)
&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;btn&quot;&amp;gt; // 최상위 요소(Root Element)
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div&amp;gt;&amp;lt;/div&amp;gt; // 최상위 요소(Root Element)
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 자식 컴포넌트에&lt;span&gt;&amp;nbsp;&lt;/span&gt;template&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그 안에 있는 최상위 요소가 2개 이상일 경우에는 부모 컴포넌트에 입력한 속성 값이 어느 부분에 상속이 되어야하는지 판단할 수 없기 때문에 두 요소 모두 상속이 되지 않습니다.&lt;/p&gt;
&lt;h3 id=&quot;12-스타일-상속&quot; data-ke-size=&quot;size23&quot;&gt;1.2 스타일 상속&lt;/h3&gt;
&lt;pre id=&quot;code_1625046413963&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue(부모 컴포넌트)
 &amp;lt;MyBtn class=&quot;fruit&quot; style=&quot;color: red;&quot;&amp;gt;Banana&amp;lt;/MyBtn&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 내용처럼 속성 값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;class,&lt;span&gt;&amp;nbsp;&lt;/span&gt;style&lt;span&gt;&amp;nbsp;&lt;/span&gt;등 여러 개를 입력할 수 있습니다. 이러한 경우에도 속성 상속은 원활히 이루어집니다.&lt;/p&gt;
&lt;h2 id=&quot;2-속성-상속-제거&quot; data-ke-size=&quot;size26&quot;&gt;2. 속성 상속 제거&lt;/h2&gt;
&lt;h3 id=&quot;21-inheritattrs&quot; data-ke-size=&quot;size23&quot;&gt;2.1 inheritAttrs&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최상위 요소가 1개라면, 속성 상속이 이루어집니다. 그러나 이러한 기능을 없앨 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625046423729&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;MyBtn.vue(자식 컴포넌트)
&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;btn&quot;&amp;gt; // 최상위 요소(Root Element) 1개
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  inheritAttrs: false // 속성 상속 제거
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;inheritAttrs(inherit Attributes)의 값을 false로 입력해준다면, 속성 상속의 옵션을 사용하지 않을 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;22-attrsclass&quot; data-ke-size=&quot;size23&quot;&gt;2.2 $attrs.class&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속성 상속의 옵션을 사용하지 않겠다고 명시한 경우, 필요하다면 개별적으로 속성 상속을 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625046434498&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;template&amp;gt;
  &amp;lt;MyBtn class=&quot;fruit&quot; style=&quot;color: red;&quot;&amp;gt;
    Banana
  &amp;lt;/MyBtn&amp;gt;
&amp;lt;/template&amp;gt;

//MyBtn.vue
&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;btn&quot;&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;h1 :class=&quot;$attrs.class&quot;&amp;gt;&amp;lt;/h1&amp;gt; // 속성 상속
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$attrs.class라는 값을 class라는 키워드에 할당해주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트에 입력한 style 속성도 아래와 마찬가지로 상속이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625046443612&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MyBtn.vue
&amp;lt;h1
    :class=&quot;$attrs.class&quot;
    :style=&quot;$attrs.style&quot;&amp;gt;
&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 경우 모든 속성을 입력해주어야 한다는 번거로움이 발생하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트의 모든 속성을 상속하는 방법도 있으며, 이는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;h1 v-bind=&quot;$attrs&quot;&amp;gt;처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-bind로 약어를 사용하지 않고 그 값에&lt;span&gt;&amp;nbsp;&lt;/span&gt;$attrs를 할당해주면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625046454188&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;MyBtn.vue
&amp;lt;h1 v-bind=&quot;$attrs&quot;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;37&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q18JW/btq8xLNMJ8q/Kn5Z2kaOjHYd2ctwkKJx71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q18JW/btq8xLNMJ8q/Kn5Z2kaOjHYd2ctwkKJx71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q18JW/btq8xLNMJ8q/Kn5Z2kaOjHYd2ctwkKJx71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq18JW%2Fbtq8xLNMJ8q%2FKn5Z2kaOjHYd2ctwkKJx71%2Fimg.png&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;37&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;이처럼 class와 style의 속성인&lt;span&gt;&amp;nbsp;&lt;/span&gt;color까지 상속을 통해 모두 적용된 것을 확인할 수 있습니다.&lt;/p&gt;</description>
      <category>Vue</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>속성 상속</category>
      <category>컴포넌트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/41</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%86%8D%EC%84%B1-%EC%83%81%EC%86%8D#entry41comment</comments>
      <pubDate>Wed, 30 Jun 2021 18:56:11 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 컴포넌트 - 기초</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EA%B8%B0%EC%B4%88</link>
      <description>&lt;h1 id=&quot;컴포넌트-기초&quot;&gt;컴포넌트 기초&lt;/h1&gt;
&lt;h2 id=&quot;1-컴포넌트-기본-구성&quot; data-ke-size=&quot;size26&quot;&gt;1. 컴포넌트 기본 구성&lt;/h2&gt;
&lt;h3 id=&quot;11-appvue&quot; data-ke-size=&quot;size23&quot;&gt;1.1 App.vue&lt;/h3&gt;
&lt;pre id=&quot;code_1625041816290&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;MyBtn /&amp;gt; // 컴포넌트 렌더링
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
import MyBtn from '~/components/MyBtn' // MyBtn.vue 파일 가져오기

export default {
  components: {
    MyBtn // 가져온 컴포넌트 내부에서 사용할 수 있도록 내보내기
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;12-mybtnvue&quot; data-ke-size=&quot;size23&quot;&gt;1.2 MyBtn.vue&lt;/h3&gt;
&lt;pre id=&quot;code_1625041832305&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;btn&quot;&amp;gt;
    Apple
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;style scoped&amp;gt;
  .btn {
    display: inline-block;
    margin: 4px;
    padding: 6px 12px;
    border-radius: 4px;
    background-color: gray;
    color: white;
    cursor: pointer;
  }
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;2-컴포넌트의-특징&quot; data-ke-size=&quot;size26&quot;&gt;2. 컴포넌트의 특징&lt;/h2&gt;
&lt;h3 id=&quot;21-재활용&quot; data-ke-size=&quot;size23&quot;&gt;2.1 재활용&lt;/h3&gt;
&lt;pre id=&quot;code_1625041846073&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;MyBtn /&amp;gt;
  &amp;lt;MyBtn /&amp;gt;
  &amp;lt;MyBtn /&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트의 장점이라고 한다면, 컴포넌트는 얼마든지 반복해서 재사용할 수 있다는 것입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;App.vue&lt;span&gt;&amp;nbsp;&lt;/span&gt;파일에 위와 같이 작성한다면 버튼을 재활용하여 여러 개를 화면에 출력할 수 있기 때문입니다.&lt;/p&gt;
&lt;h3 id=&quot;22-props&quot; data-ke-size=&quot;size23&quot;&gt;2.2 Props&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 재활용을 하면서&lt;span&gt;&amp;nbsp;&lt;/span&gt;props라는 개념을 이용하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;App.vue라는 부모 컴포넌트에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;MyBtn.vue라는 자식 컴포넌트로 데이터를 전달할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 이유로&lt;span&gt;&amp;nbsp;&lt;/span&gt;props를 통해 구현한 이 기능을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;부모 컴포넌트와 자식 컴포넌트 간의 데이터 통신 방법&lt;/b&gt;이라고도 이야기합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;pre id=&quot;code_1625041957400&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;MyBtn color=&quot;royalblue&quot; /&amp;gt;

//MyBtn.vue
&amp;lt;div :style=&quot;{ backgroundColor: color }&quot; class=&quot;btn&quot;&amp;gt; // 데이터 바인딩
    Apple
&amp;lt;/div&amp;gt;
export default {
  props: {
    color: { // 외부에서 color 값을 지정할 때 받을 수 있게 함
      type: String,
      default: 'gray' // 기본값 지정
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;23-props로-클래스-추가&quot; data-ke-size=&quot;size23&quot;&gt;2.3 Props로 클래스 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;props를 이용해 클래스를 추가해보도록 합시다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;pre id=&quot;code_1625041974133&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;!-- &amp;lt;div class =&quot;large btn&quot;&amp;gt; --&amp;gt;
&amp;lt;MyBtn large /&amp;gt;
&amp;lt;!-- &amp;lt;div class =&quot;btn&quot;&amp;gt; --&amp;gt;
&amp;lt;MyBtn large /&amp;gt;
부모 컴포넌트에는 large라는 속성을 별도의 값이 없도록 추가해줍니다.

//MyBtn.vue
&amp;lt;div :class=&quot;{ large }&quot; class=&quot;btn&quot;&amp;gt; Apple &amp;lt;/div&amp;gt;
export default {
  props: {
    large: {
      type: Boolean,
      default: false
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이&lt;span&gt;&amp;nbsp;&lt;/span&gt;props에 속성&lt;span&gt;&amp;nbsp;&lt;/span&gt;large&lt;span&gt;&amp;nbsp;&lt;/span&gt;객체 리터럴 안으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;type으로 불린 데이터를 지정하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;default&lt;span&gt;&amp;nbsp;&lt;/span&gt;값으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;large라는 속성이 없도록&lt;span&gt;&amp;nbsp;&lt;/span&gt;false를 지정해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;344&quot; data-origin-height=&quot;68&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rN3iY/btq8xfnRNeU/WKwqD5plkXdqMweo0dKetK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rN3iY/btq8xfnRNeU/WKwqD5plkXdqMweo0dKetK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rN3iY/btq8xfnRNeU/WKwqD5plkXdqMweo0dKetK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrN3iY%2Fbtq8xfnRNeU%2FWKwqD5plkXdqMweo0dKetK%2Fimg.png&quot; data-origin-width=&quot;344&quot; data-origin-height=&quot;68&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;그러면 위처럼 클래스에&lt;span&gt;&amp;nbsp;&lt;/span&gt;large가 추가되어있고, 그렇지 않은 버튼은 포함되어 있지 않은 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;24-props로-text-입력&quot; data-ke-size=&quot;size23&quot;&gt;2.4 Props로 text 입력&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props를 이용하면 text의 내용 또한 입력이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625041889957&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;MyBtn text=&quot;Banana&quot; /&amp;gt;
&amp;lt;MyBtn :color=&quot;color&quot; /&amp;gt;
&amp;lt;MyBtn large color=&quot;royalblue&quot; /&amp;gt;
&amp;lt;MyBtn /&amp;gt;

//MyBtn.vue
&amp;lt;div class=&quot;btn&quot;&amp;gt; {{ text }} &amp;lt;/div&amp;gt;
export default {
  props: {
    text: {
      type: String,
      default: '' // 기본값은 공백
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 MyBtn의&lt;span&gt;&amp;nbsp;&lt;/span&gt;text&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성에 추가한 값이 버튼 안의 내용으로 입력되게 됩니다. 하지만 이를 화면에 출력하게 되면, 문제점을 발견하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;142&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bshGOV/btq8vfo77id/V6YKFUKoiphWs95VBpvBD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bshGOV/btq8vfo77id/V6YKFUKoiphWs95VBpvBD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bshGOV/btq8vfo77id/V6YKFUKoiphWs95VBpvBD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbshGOV%2Fbtq8vfo77id%2FV6YKFUKoiphWs95VBpvBD1%2Fimg.png&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;142&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;바로 위와 같이&lt;span&gt;&amp;nbsp;&lt;/span&gt;text&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성을 추가하지 않은 개체는 컨텐츠 내용이 출력되지 않게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;slot이라는 개념을 배워야 합니다.&lt;/p&gt;
&lt;h2 id=&quot;3-slot&quot; data-ke-size=&quot;size26&quot;&gt;3. Slot&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;text를 속성으로 넣게 되면, 위와 같은 문제가 발생하였습니다. 그렇다면 이를 해결하기 위해 html에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;button&amp;gt;text&amp;lt;button&amp;gt;처럼 컨텐츠 내용으로 직접 텍스트를 입력하는 방법을 활용해보도록 합시다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;pre id=&quot;code_1625042007660&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;MyBtn&amp;gt;Banana&amp;lt;/MyBtn&amp;gt;
&amp;lt;MyBtn :color=&quot;color&quot;&amp;gt;Apple&amp;lt;/MyBtn&amp;gt;
&amp;lt;MyBtn large color=&quot;royalblue&quot;&amp;gt;Cherry&amp;lt;/MyBtn&amp;gt;
&amp;lt;MyBtn&amp;gt;Orange&amp;lt;/MyBtn&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 부모 컴포넌트에 빈 태그가 아닌 열리고 닫히는 태그의 형태로 표시해줍니다. 그리고 그 안에는 컨텐츠로 들어가는 내용을 입력해줍니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;pre id=&quot;code_1625042017196&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MyBtn.vue
&amp;lt;div class=&quot;btn&quot;&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt; // 컨텐츠 자리 표시
&amp;lt;/div&amp;gt;
// 내용 삭제
// export default {
//   props: {
//    text: {
//      type: String,
//      default: ''
//    }
//  }
// }&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 버튼 안에 입력할 컨텐츠의 자리를 표시를 할 때&lt;span&gt;&amp;nbsp;&lt;/span&gt;slot&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그를 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 위처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;props에 입력했던&lt;span&gt;&amp;nbsp;&lt;/span&gt;text&lt;span&gt;&amp;nbsp;&lt;/span&gt;내용은 필요가 없으니 삭제합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;pre id=&quot;code_1625042027051&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.vue
&amp;lt;MyBtn :color=&quot;color&quot;&amp;gt;
  &amp;lt;span style=&quot;color: red&quot;&amp;gt;Banana&amp;lt;/span&amp;gt;
&amp;lt;/MyBtn&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;덧붙여,&lt;span&gt;&amp;nbsp;&lt;/span&gt;slot&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그에는 단순히 text만 입력하는 것이 아니라 자식 컴포넌트가 실행되는 부분에서 열리고 닫히는 태그 사이에 있는 모든 내용을&lt;span&gt;&amp;nbsp;&lt;/span&gt;slot이라는 태그 부분으로 대체하여 넣어준다는 개념입니다. 이를 통해 위처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;span&lt;span&gt;&amp;nbsp;&lt;/span&gt;태그 안에 text를 입력하고, 스타일까지 적용을 할 수가 있는 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;261&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfg8KT/btq8vg2CYKN/RvCk4ZZK1o4sCPN7Il6bOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfg8KT/btq8vg2CYKN/RvCk4ZZK1o4sCPN7Il6bOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfg8KT/btq8vg2CYKN/RvCk4ZZK1o4sCPN7Il6bOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcfg8KT%2Fbtq8vg2CYKN%2FRvCk4ZZK1o4sCPN7Il6bOK%2Fimg.png&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;261&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;</description>
      <category>Vue</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>컴포넌트</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/40</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EA%B8%B0%EC%B4%88#entry40comment</comments>
      <pubDate>Wed, 30 Jun 2021 17:36:57 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 폼입력 바인딩</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%ED%8F%BC%EC%9E%85%EB%A0%A5-%EB%B0%94%EC%9D%B8%EB%94%A9</link>
      <description>&lt;h1 id=&quot;폼-입력-바인딩&quot;&gt;폼 입력 바인딩&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;폼 입력 바인딩은 &lt;/b&gt;&lt;/b&gt;&lt;u&gt;&lt;b&gt;v-model&lt;/b&gt;&lt;/u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이라는 디렉티브를 사용하여 양방향 데이터 바인딩을 생성합니다.&lt;/p&gt;
&lt;h2 id=&quot;1-단방향-데이터-바인딩&quot; data-ke-size=&quot;size26&quot;&gt;1. 단방향 데이터 바인딩&lt;/h2&gt;
&lt;pre id=&quot;code_1625040376688&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;{{ msg }}&amp;lt;/h1&amp;gt;
&amp;lt;input type=&quot;text&quot; :value=&quot;msg&quot; /&amp;gt;
export default {
  data() {
    return {
      msg: 'Hello world!'
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 데이터를 스크립트 태그로 연결하여 Vue에서 활용할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 데이터를 출력하는 방법을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;단방향 데이터 바인딩&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터에서 html 쪽으로 한 방향으로만 흐르기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;단방향 데이터 바인딩&lt;/b&gt;이라 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단방향 데이터 바인딩으로 인하여 input 요소를 수정한다하더라도 수정된 내용이&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg&lt;span&gt;&amp;nbsp;&lt;/span&gt;데이터를 갱신하지 않습니다.&lt;/p&gt;
&lt;h2 id=&quot;2-양방향-데이터-바인딩&quot; data-ke-size=&quot;size26&quot;&gt;2. 양방향 데이터 바인딩&lt;/h2&gt;
&lt;pre id=&quot;code_1625040458107&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;{{ msg }}&amp;lt;/h1&amp;gt;
&amp;lt;input type=&quot;text&quot; :value=&quot;msg&quot; @input=&quot;msg = $event.target.value&quot;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 input 요소에 이벤트를 청취하도록 합니다. 그리고&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg의 데이터에&lt;span&gt;&amp;nbsp;&lt;/span&gt;$event.target.value를 할당합니다. 이를 통해,&lt;span&gt;&amp;nbsp;&lt;/span&gt;msg의 기본값인 'Hello world!'에 수정을 하면 반응성이 이루어져&lt;span&gt;&amp;nbsp;&lt;/span&gt;$event.target.value&lt;span&gt;&amp;nbsp;&lt;/span&gt;값으로 다시 할당이 되는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 개념이 바로 데이터가 양쪽으로 흐르는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;양방향 데이터 바인딩&lt;/b&gt;이라는 것입니다.&lt;/p&gt;
&lt;h2 id=&quot;3-v-model&quot; data-ke-size=&quot;size26&quot;&gt;3. v-model&lt;/h2&gt;
&lt;h3 id=&quot;31-사용법&quot; data-ke-size=&quot;size23&quot;&gt;3.1 사용법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 양방향 데이터 바인딩을 인라인 요소로 html에 입력하였습니다. 하지만, 이를 더 간단하게 표현할 수 있는 방법이 있으며 그것이 바로&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-model입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625040485947&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;{{ msg }}&amp;lt;/h1&amp;gt;
&amp;lt;input type=&quot;text&quot; v-model=&quot;msg&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;32-유의사항&quot; data-ke-size=&quot;size23&quot;&gt;3.2 유의사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-model의 경우 input 요소에 영어가 아닌 한글을 입력하게 되면, 하나의 글자가 완성되지 않으면 연결되지 않습니다. 한 박자 느리게 동작을 하게 되는거죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 한글이 자음과 모음으로 되어 있어 하나의 문자가 완성되기 전까지는 동작이 지연되기 때문입니다. 이러한 이유로 한글 입력 시에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-model이 아닌&lt;span&gt;&amp;nbsp;&lt;/span&gt;$ event.target.value를 사용하셔야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625040512720&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;{{ msg }}&amp;lt;/h1&amp;gt;
&amp;lt;input type=&quot;text&quot; :value=&quot;msg&quot; @input=&quot;msg = $event.target.value&quot;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;수식어&quot; data-ke-size=&quot;size26&quot;&gt;4.수식어&lt;/h2&gt;
&lt;h3 id=&quot;lazy&quot; data-ke-size=&quot;size23&quot;&gt;.lazy&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로,&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-model은 각&lt;span&gt;&amp;nbsp;&lt;/span&gt;input&lt;span&gt;&amp;nbsp;&lt;/span&gt;이벤트 후 입력과 데이터를 동기화 합니다. (단,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://v3.ko.vuejs.org/guide/forms.html#vmodel-ime-tip&quot;&gt;앞에서 설명&lt;/a&gt;한 IME 구성은 제외됩니다.).&lt;span&gt;&amp;nbsp;&lt;/span&gt;lazy&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어를 추가하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;change이벤트 이후에 동기화 할 수 있습니다.:&lt;/p&gt;
&lt;pre id=&quot;code_1625040755703&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- &quot;input&quot; 대신 &quot;change&quot; 이후에 동기화 됩니다. --&amp;gt; 
&amp;lt;input v-model.lazy=&quot;msg&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;number&quot; data-ke-size=&quot;size23&quot;&gt;.number&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 입력이 자동으로 숫자로 형변환 되기를 원하면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-model이 관리하는 input에&lt;span&gt;&amp;nbsp;&lt;/span&gt;number&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어를 추가하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625040851339&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;input v-model.number=&quot;age&quot; type=&quot;number&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type=&quot;number&quot;를 사용하는 경우에 HTML 입력 요소의 값은 항상 문자열을 반영하기 때문에 종종 유용합니다. 만약, 값이&lt;span&gt;&amp;nbsp;&lt;/span&gt;parseFloat()에 의해서 분석할 수 없는 경우, 원래의 값이 리턴됩니다.&lt;/p&gt;
&lt;h3 id=&quot;trim&quot; data-ke-size=&quot;size23&quot;&gt;.trim&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 입력한 내용에서 자동으로 앞뒤 공백을 제거하는 트림처리가 되길 바란다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-model이 관리하는 input에&lt;span&gt;&amp;nbsp;&lt;/span&gt;trim&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어를 추가하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625040856895&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;input v-model.trim=&quot;msg&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Vue</category>
      <category>v-model</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>폼 입력 바인디</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/39</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%ED%8F%BC%EC%9E%85%EB%A0%A5-%EB%B0%94%EC%9D%B8%EB%94%A9#entry39comment</comments>
      <pubDate>Wed, 30 Jun 2021 17:15:50 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 이벤트 수식어 와 키 수식어</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%88%98%EC%8B%9D%EC%96%B4-%EC%99%80-%ED%82%A4-%EC%88%98%EC%8B%9D%EC%96%B4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;이벤트 수식어&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 핸들러 내부에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;event.preventDefault()&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;event.stopPropagation()를 호출하는 것은 매우 보편적인 일입니다. 메소드 내에서 쉽게 이 작업을 할 수 있지만, DOM 이벤트 세부 사항을 처리하는 대신 데이터 로직에 대한 메소드만 사용할 수 있으면 더 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위하여, Vue는&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-on이벤트에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;이벤트 수식어&lt;/b&gt;를 제공합니다. 수식어는 점으로 된 접미사 입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;.stop&lt;/li&gt;
&lt;li&gt;.prevent&lt;/li&gt;
&lt;li&gt;.capture&lt;/li&gt;
&lt;li&gt;.self&lt;/li&gt;
&lt;li&gt;.once&lt;/li&gt;
&lt;li&gt;.passive&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1625039259799&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 클릭 이벤트 전파가 중단되었습니다. --&amp;gt;
&amp;lt;a @click.stop=&quot;doThis&quot;&amp;gt;&amp;lt;/a&amp;gt;

&amp;lt;!-- 제출 이벤트가 페이지를 다시 로드하지 않습니다. --&amp;gt;
&amp;lt;form @submit.prevent=&quot;onSubmit&quot;&amp;gt;&amp;lt;/form&amp;gt;

&amp;lt;!-- 수정자는 체이닝이 가능합니다. --&amp;gt;
&amp;lt;a @click.stop.prevent=&quot;doThat&quot;&amp;gt;&amp;lt;/a&amp;gt;

&amp;lt;!-- 단순히 수식어만 사용이 가능합니다. --&amp;gt;
&amp;lt;form @submit.prevent&amp;gt;&amp;lt;/form&amp;gt;

&amp;lt;!-- 캡처 모드를 사용할 때 이벤트 리스너를 사용 가능합니다.--&amp;gt;
&amp;lt;!--즉, 내부 엘리먼트를 대상으로 하는 이벤트가 해당 엘리먼트에서 처리되기 전에 여기서 처리합니다. --&amp;gt;
&amp;lt;div @click.capture=&quot;doThis&quot;&amp;gt;...&amp;lt;/div&amp;gt;

&amp;lt;!-- event.target이 엘리먼트 자체인 경우에만 트리거를 처리합니다.--&amp;gt;
&amp;lt;!-- 자식 엘리먼트에서는 처리되지 않습니다.--&amp;gt;
&amp;lt;div @click.self=&quot;doThat&quot;&amp;gt;...&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;관련 코드가 동일한 순서로 생성되므로 수식어를 사용할 때 순서를 지정하세요. 다시 말하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;v-on:click.prevent.self&lt;span style=&quot;color: #2c3e50;&quot;&gt;를 사용하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;모든 클릭&lt;/b&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;을 막을 수 있으며&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;v-on:click.self.prevent&lt;span style=&quot;color: #2c3e50;&quot;&gt;는 엘리먼트 자체에 대한 클릭만 방지합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1625039271851&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 클릭 이벤트는 최대한 한번에 트리거 됩니다.--&amp;gt;
&amp;lt;a @click.once=&quot;doThis&quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이티브 DOM이벤트에 독점적인 다른 수식어들과 달리,&lt;span&gt;&amp;nbsp;&lt;/span&gt;.once&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어는&lt;span&gt;&amp;nbsp;&lt;/span&gt;component events에서도 사용될 수 있습니다. 아직 컴포넌트에 대해서 읽지 않았더라도 걱정하시마십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 Vue는&lt;span&gt;&amp;nbsp;&lt;/span&gt;addEventListener의&lt;span&gt;&amp;nbsp;&lt;/span&gt;passive&lt;span&gt;&amp;nbsp;&lt;/span&gt;option&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;(opens new window)&lt;/span&gt;&lt;/span&gt;에 해당하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;.passive&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어도 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1625039304622&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 스크롤의 기본 이벤트를 취소할 수 없습니다. --&amp;gt;
&amp;lt;!-- 바로, `onScroll`완료되는 것을 기다리는 것을 대신합니다.  --&amp;gt;
&amp;lt;!-- 이 경우에`event.preventDefault()`를 포함하고 있습니다. --&amp;gt;
&amp;lt;div @scroll.passive=&quot;onScroll&quot;&amp;gt;...&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히&lt;span&gt;&amp;nbsp;&lt;/span&gt;.passive&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어는 모바일 환경에서 성능향상에 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.prevent&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어는 무시되고 브라우저에서 오류를 발생시키기 때문에,&lt;span&gt;&amp;nbsp;&lt;/span&gt;.passive&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어와&lt;span&gt;&amp;nbsp;&lt;/span&gt;.prevent&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어를 함께 사용하지 마십시오.&lt;span&gt;&amp;nbsp;&lt;/span&gt;.passive&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어는 당신이 이벤트의 기본 행동을 무시하지&lt;span&gt;&amp;nbsp;&lt;/span&gt;않기를&lt;span&gt;&amp;nbsp;&lt;/span&gt;원하는 브라우저와 상호작용한다는 사실을 기억하십시오.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;키-수식어&quot; data-ke-size=&quot;size26&quot;&gt;키 수식어&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;키보드 이벤트를 청취할 때, 종종 공동 키 코드를 확인해야 합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;Vue에서 키 이벤트를 청취할 때 키 수식어로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;v-on&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;@&lt;span style=&quot;color: #2c3e50;&quot;&gt;를 더할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1625039327685&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 키가 'Enter'일때만 `vm.submit()`을 호출할 수 있습니다.--&amp;gt;
&amp;lt;input @keyup.enter=&quot;submit&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KeyboardEvent.key&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;를 통해 노출된 유효 키 이름을 케밥 케이스로 변환하여 수식어로 사용할 수 있습니다.&lt;/span&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1625039345403&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;input @keyup.page-down=&quot;onPageDown&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;위의 예제에서, 핸들러는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;$event.key&lt;span style=&quot;color: #2c3e50;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;===&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;PageDown&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #2c3e50;&quot;&gt;일 때만 호출됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;키-명령어&quot; data-ke-size=&quot;size23&quot;&gt;키 명령어&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue는 가장흔히 사용되는 키에서 명령어를 제공합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;.enter&lt;/li&gt;
&lt;li&gt;.tab&lt;/li&gt;
&lt;li&gt;.delete&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&amp;ldquo;Delete&amp;rdquo; 와 &amp;ldquo;Backspace&amp;rdquo; 키 모두를 캡처합니다)&lt;/li&gt;
&lt;li&gt;.esc&lt;/li&gt;
&lt;li&gt;.space&lt;/li&gt;
&lt;li&gt;.up&lt;/li&gt;
&lt;li&gt;.down&lt;/li&gt;
&lt;li&gt;.left&lt;/li&gt;
&lt;li&gt;.right&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;시스템-수식어-키목록&quot; data-ke-size=&quot;size26&quot;&gt;시스템 수식어 키목록&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 수식어를 사용해 해당 수식어 키가 눌러진 경우에만 마우스 또는 키보드 이벤트 리스너를 트리거 할 수 있습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;.ctrl&lt;/li&gt;
&lt;li&gt;.alt&lt;/li&gt;
&lt;li&gt;.shift&lt;/li&gt;
&lt;li&gt;.meta&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1625039461909&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 알트 + 엔터 --&amp;gt;
&amp;lt;input @keyup.alt.enter=&quot;clear&quot; /&amp;gt;

&amp;lt;!-- 컨트롤 + 클릭 --&amp;gt;
&amp;lt;div @click.ctrl=&quot;doSomething&quot;&amp;gt;Do something&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #222222;&quot;&gt;수식어 키는 일반 키와 다르며&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;keyup&lt;span style=&quot;background-color: #f8f8f8; color: #222222;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이벤트와 함께 사용되면 이벤트가 발생할 때 수식어 키가 눌려있어야 합니다. 즉,&lt;/span&gt;keyup.ctrl&lt;span style=&quot;background-color: #f8f8f8; color: #222222;&quot;&gt;은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ctrl&lt;span style=&quot;background-color: #f8f8f8; color: #222222;&quot;&gt;을 누른 상태에서 키를 놓으면 트리거됩니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ctrl&lt;span style=&quot;background-color: #f8f8f8; color: #222222;&quot;&gt;키만 놓으면 트리거되지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;exact수식어&quot; data-ke-size=&quot;size23&quot;&gt;.exact수식어&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.exact&lt;span&gt;&amp;nbsp;&lt;/span&gt;수식어는 다른 시스템 수식어와 조합해 그 핸들러가 실행되기 위해 정확한 조합이 눌러야하는 것을 요구합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625039504974&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 아래코드는 Alt 또는 Shift와 함께 눌렀을 때도 실행됩니다.--&amp;gt;
&amp;lt;button @click.ctrl=&quot;onClick&quot;&amp;gt;A&amp;lt;/button&amp;gt;

&amp;lt;!-- 아래코드는 Cntl키만 눌려져 있을 때 실행됩니다.--&amp;gt;
&amp;lt;button @click.ctrl.exact=&quot;onCtrlClick&quot;&amp;gt;A&amp;lt;/button&amp;gt;

&amp;lt;!-- 아래 코드는 시스템 키가 눌리지 않은 상태인 경우에만 작동합니다.--&amp;gt;
&amp;lt;button @click.exact=&quot;onClick&quot;&amp;gt;A&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;마우스-버튼-수식어&quot; data-ke-size=&quot;size23&quot;&gt;마우스 버튼 수식어&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;.left&lt;/li&gt;
&lt;li&gt;.right&lt;/li&gt;
&lt;li&gt;.middle&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 수식어는 특정 마우스 버튼에 의해 트리거 된 이벤트로 핸들러를 제한합니다.&lt;/p&gt;</description>
      <category>Vue</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>이벤트 수식어</category>
      <category>키 수식어</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/38</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%88%98%EC%8B%9D%EC%96%B4-%EC%99%80-%ED%82%A4-%EC%88%98%EC%8B%9D%EC%96%B4#entry38comment</comments>
      <pubDate>Wed, 30 Jun 2021 16:52:14 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 이벤트 핸들링</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%ED%95%B8%EB%93%A4%EB%A7%81</link>
      <description>&lt;h1 id=&quot;이벤트-핸들링&quot;&gt;이벤트 핸들링&lt;/h1&gt;
&lt;h2 id=&quot;1-이벤트-청취&quot; data-ke-size=&quot;size26&quot;&gt;1. 이벤트 청취&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-on&lt;span&gt;&amp;nbsp;&lt;/span&gt;디렉티브는&lt;span&gt;&amp;nbsp;&lt;/span&gt;@기호로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM 이벤트를 듣고 트리거될 때와 JavaScript를 실행할 때 사용합니다.&lt;br /&gt;v-on:click=&quot;methodName&quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;혹은 줄여서&lt;span&gt;&amp;nbsp;&lt;/span&gt;@click=&quot;methodName&quot;으로 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625026528603&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;basic-event&quot;&amp;gt;
  &amp;lt;button @click=&quot;counter += 1&quot;&amp;gt;Add 1&amp;lt;/button&amp;gt;
  &amp;lt;p&amp;gt;The button above has been clicked {{ counter }} times.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
Vue.createApp({
  data() {
    return {
      counter: 1
    }
  }
}).mount('#basic-event')&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;2-메소드-이벤트-핸들러&quot; data-ke-size=&quot;size26&quot;&gt;2. 메소드 이벤트 핸들러&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드와 같이 간단한 코드의 경우에는 문제가 없지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 이벤트 핸들러의 로직은 더 복잡하기 때문에 위와 같은 방법은 지양하는 것이 좋습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625026640020&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;event-with-method&quot;&amp;gt;
  &amp;lt;button @click=&quot;greet&quot;&amp;gt;Greet&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
Vue.createApp({
  data() {
    return {
      name: 'Vue.js'
    }
  },
  methods: {
    greet(event) {
      // 메소드 안에서 사용하는 `this` 는 Vue 인스턴스를 가리킵니다.
      alert('Hello ' + this.name + '!')
      // `event` 는 네이티브 DOM 이벤트입니다
      if (event) {
        alert(event.target.tagName)
      }
    }
  }
}).mount('#event-with-method')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;methods라는 옵션을 추가한 뒤&lt;span&gt;&amp;nbsp;&lt;/span&gt;greet&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수를 만들어 그 안에 복잡한 로직을 코딩하여 클릭하면 실행할&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;이벤트 핸들러&lt;/b&gt;로써 메소드의 이름을 작성하시면 됩니다.&lt;/p&gt;
&lt;h2 id=&quot;3-인라인-메소드-핸들러&quot; data-ke-size=&quot;size26&quot;&gt;3. 인라인 메소드 핸들러&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메소드 이름을 직접 바인딩 하는 대신에, 인라인 JavaScript 구문에 메소드를 사용할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625026717785&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;inline-handler&quot;&amp;gt;
  &amp;lt;button @click=&quot;say('hi')&quot;&amp;gt;Say hi&amp;lt;/button&amp;gt;
  &amp;lt;button @click=&quot;say('what')&quot;&amp;gt;Say what&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1625026726374&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Vue.createApp({
  methods: {
    say(message) {
      alert(message)
    }
  }
}).mount('#inline-handler')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때로 인라인 명령문 핸들러에서 원본 DOM 이벤트에 액세스 해야할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특별한&lt;span&gt;&amp;nbsp;&lt;/span&gt;$event를 사용해 메소드에 전달할 수 있습니다.&lt;span style=&quot;color: #63a35c;&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1625026734747&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;button @click=&quot;warn('Form cannot be submitted yet.', $event)&quot;&amp;gt;
  Submit
&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;복합-이벤트-핸들러&quot; data-ke-size=&quot;size26&quot;&gt;복합 이벤트 핸들러&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 핸들러 안에서 복합 메소드를 지정할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 방식을 통해 하나의 이벤트에 여러 개의 메소드를 동시에 연결하여 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625026749975&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;button @click=&quot;handlerA(), handlerB()&quot;&amp;gt;
    Click me!
  &amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  methods: {
    handlerA() {
      console.log('A')
    },
    handlerB() {
      console.log('B')
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 유의해야할 점은 복합 메소드를 작성할 때에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;,로 구분하고 각각의 메소드들에 호출하겠다는&lt;span&gt;&amp;nbsp;&lt;/span&gt;()를 뒤에 붙여줘야 한다는 점입니다.&lt;/p&gt;</description>
      <category>Vue</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>이벤트 핸들러</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/37</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%ED%95%B8%EB%93%A4%EB%A7%81#entry37comment</comments>
      <pubDate>Wed, 30 Jun 2021 13:21:29 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 리스트 렌더링</title>
      <link>https://gusehd66.tistory.com/entry/Vuejs-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EB%A0%8C%EB%8D%94%EB%A7%81</link>
      <description>&lt;h1 id=&quot;리스트-렌더링&quot;&gt;리스트 렌더링&lt;/h1&gt;
&lt;h2 id=&quot;1-v-if&quot; data-ke-size=&quot;size26&quot;&gt;1. v-for&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-for&lt;span&gt;&amp;nbsp;&lt;/span&gt;디렉티브를 사용하여 배열을 기반으로 리스트를 렌더링 할 수 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-for&lt;span&gt;&amp;nbsp;&lt;/span&gt;디렉티브는&lt;span&gt;&amp;nbsp;&lt;/span&gt;fruit in fruits&lt;span&gt;&amp;nbsp;&lt;/span&gt;형태로 특별한 문법이 필요합니다. 여기서&lt;span&gt;&amp;nbsp;&lt;/span&gt;fruits는 원본 데이터 배열이고&lt;span&gt;&amp;nbsp;&lt;/span&gt;fruit은 반복되는 배열 엘리먼트의 별칭입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625025607059&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li
      v-for=&quot;fruit in fruits&quot;
      :key=&quot;fruit&quot;&amp;gt;
      {{ fruit }}
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;12-코드-예시&quot; data-ke-size=&quot;size23&quot;&gt;1.1 코드&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-for&lt;span&gt;&amp;nbsp;&lt;/span&gt;블록 안에는 부모 범위 속성에 대한 모든 권한이 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-for는 또한 현재 항목의 인덱스에 대한 두 번째 전달인자 옵션을 제공합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625025679466&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li
      v-for=&quot;(fruit, index) in fruits&quot;
      :key=&quot;fruit&quot;&amp;gt;
      {{ fruit }}-{{ index }}
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      fruits: ['Apple', 'Banana', 'Cherry']
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 id=&quot;2-필터링된-결과-표시&quot; data-ke-size=&quot;size26&quot;&gt;2. 필터링된 결과 표시&lt;/h2&gt;
&lt;h3 id=&quot;21-computed-속성&quot; data-ke-size=&quot;size23&quot;&gt;2.1 computed 속성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 데이터를 실제로 변경하거나 재설정하지 않고, 배열의 필터링되거나 정렬된 버전을 표시할 수도 있습니다. 이 경우 필터링되거나 정렬된 배열을 반환하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;computed&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성을 만들 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625025692408&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li
      v-for=&quot;fruit in newFruits&quot;
      :key=&quot;fruit.id&quot;&amp;gt;
      {{ fruit.name }}
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      fruits: ['Apple', 'Banana', 'Cherry']
    }
  },
  computed: {
    newFruits() {
      return this.fruits.map((fruit, index) =&amp;gt; {
        return {
          id: index,
          name: fruit
        }
      })
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 프로젝트를 진행하게 되면, 위와 같이 fruits와 같은 단순한 배열 구조가 아닌 newFruits()와 마찬가지로 배열 데이터 안에 객체 데이터가 있고, 그 객체 데이터 안에는 복잡한 구조로 여러가지 속성들로 데이터가 구분되어 있는 형태로 제공되는 데이터를 활용하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러한 데이터들을 화면에 반복적으로 출력하기 위해서는 위와 같은 방법으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-for&lt;span&gt;&amp;nbsp;&lt;/span&gt;디렉티브를 작성하셔야 합니다. 특히,&lt;span&gt;&amp;nbsp;&lt;/span&gt;v-for&lt;span&gt;&amp;nbsp;&lt;/span&gt;디렉티브를 사용하게 되면 반드시&lt;span&gt;&amp;nbsp;&lt;/span&gt;:key&lt;span&gt;&amp;nbsp;&lt;/span&gt;값으로 배열의 아이템들을 고유하게 구분해줄 수 있는 특정한 속성이 존재해야 하며 이를 통해 화면에 출력되는 내용을 최적화할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;22-shortid-패키지&quot; data-ke-size=&quot;size23&quot;&gt;2.2 shortid 패키지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 설명에 덧붙여&lt;span&gt;&amp;nbsp;&lt;/span&gt;:key&lt;span&gt;&amp;nbsp;&lt;/span&gt;값에 들어갈 id값을 고유하게 구분해줄 수 있도록 하는 shortid라는 패키지가 있으며, 이를 설치하여 사용해보도록 합시다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ npm i -D shortid&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1625025751044&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
import shortid from 'shortid' // 설치한 패키지 가져오기
export default {
  data() {
    return {
      fruits: ['Apple', 'Banana', 'Cherry']
    }
  },
  computed: {
    newFruits() {
      return this.fruits.map(fruit =&amp;gt; ({
          id: shortid.generate(), // shortid를 생성하는 generate() 메소드 실행
          name: fruit
        }))
    }
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;449&quot; data-origin-height=&quot;137&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/moww5/btq8sqjLohv/9598NkWONpTWAleUjM0kFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/moww5/btq8sqjLohv/9598NkWONpTWAleUjM0kFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/moww5/btq8sqjLohv/9598NkWONpTWAleUjM0kFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmoww5%2Fbtq8sqjLohv%2F9598NkWONpTWAleUjM0kFk%2Fimg.png&quot; data-origin-width=&quot;449&quot; data-origin-height=&quot;137&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;이러한 패키지를 통해 고유한 값이 필요한 곳에서 손쉽게 만들어낼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;id 값은 새로고침이 될 때마다 랜덤한 고유의 값으로 바뀝니다.&lt;/p&gt;
&lt;h2 id=&quot;3-배열-변경-감지&quot; data-ke-size=&quot;size26&quot;&gt;3. 배열 변경 감지&lt;/h2&gt;
&lt;h3 id=&quot;31-변이-메소드&quot; data-ke-size=&quot;size23&quot;&gt;3.1 변이 메소드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue는 감시 중인 변이 메소드를 래핑하면(배열의 데이터를 변경하면) 화면에 출력이 갱신되는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;반응성&lt;/b&gt;을 갖고 있습니다. 래핑된 메소드는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;push()&lt;/li&gt;
&lt;li&gt;pop()&lt;/li&gt;
&lt;li&gt;shift()&lt;/li&gt;
&lt;li&gt;unshift()&lt;/li&gt;
&lt;li&gt;splice()&lt;/li&gt;
&lt;li&gt;sort()&lt;/li&gt;
&lt;li&gt;reverse()&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;32-배열-교체&quot; data-ke-size=&quot;size23&quot;&gt;3.2 배열 교체&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름에서 알 수 있듯이 변이 메소드는 호출된 원래 배열을 변경합니다. 이에 비해&lt;span&gt;&amp;nbsp;&lt;/span&gt;filter(),&lt;span&gt;&amp;nbsp;&lt;/span&gt;concat()&lt;span&gt;&amp;nbsp;&lt;/span&gt;그리고&lt;span&gt;&amp;nbsp;&lt;/span&gt;slice()와 같은 원래 배열을 변경하지는 않지만 항상 새 배열을 반환하는 비-변이 메소드도 있습니다. 비-변이 메소드로 작업할 때 이전 배열을 새 배열로 바꿀 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1625025796520&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;example1.items = example1.items.filter(item =&amp;gt; item.message.match(/Foo/))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로 인해 Vue가 기존 DOM을 버리고 전체 목록을 다시 렌더링할 것이라고 생각할 수 있습니다. 다행히도 그렇지 않습니다. Vue는 DOM 요소 재사용을 최대화하기 위해 몇 가지 smart heuristics(스마트 휴리스틱, 과학적인 조건보다는 경험이나 직관에 의해 똑똑하게 의사결정을 하는 방식)을 구현하므로, 배열을 겹치는 객체를 포함하는 다른 배열로 교체하는 것은 매우 효율적인 작업입니다.&lt;/p&gt;</description>
      <category>Vue</category>
      <category>VUE</category>
      <category>vue.js</category>
      <category>리스트 렌더링</category>
      <author>맨동</author>
      <guid isPermaLink="true">https://gusehd66.tistory.com/36</guid>
      <comments>https://gusehd66.tistory.com/entry/Vuejs-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EB%A0%8C%EB%8D%94%EB%A7%81#entry36comment</comments>
      <pubDate>Wed, 30 Jun 2021 13:03:45 +0900</pubDate>
    </item>
  </channel>
</rss>