<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Pewww</title>
    <link>https://pewww.tistory.com/</link>
    <description>웹 프론트엔드 개발에 대한 정보를 담은 블로그입니다.
자료구조와 알고리즘을 비롯한 전반적인 개발 지식을 담는 것이 목표입니다!
https://github.com/Pewww</description>
    <language>ko</language>
    <pubDate>Wed, 26 Aug 2026 12:25:27 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Pewww</managingEditor>
    <image>
      <title>Pewww</title>
      <url>https://tistory1.daumcdn.net/tistory/2897008/attach/63bf9f1e3beb47b48260a0d5cc47741b</url>
      <link>https://pewww.tistory.com</link>
    </image>
    <item>
      <title>블로그 주소 이전</title>
      <link>https://pewww.tistory.com/33</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;블로그 주소가 이전되었습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/@yunjae.jung&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://medium.com/@yunjae.jung&lt;/a&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>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/33</guid>
      <comments>https://pewww.tistory.com/33#entry33comment</comments>
      <pubDate>Fri, 2 Sep 2022 10:55:48 +0900</pubDate>
    </item>
    <item>
      <title>JIRA 위키에서 티켓의 시간 추적 되돌리기</title>
      <link>https://pewww.tistory.com/32</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;위키에서는 티켓에 대한 예상, 남은 시간, 기록된 시간에 대한 정보를 제공하는 &lt;b&gt;시간 추적&lt;/b&gt; 기능을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;티켓 페이지.png&quot; data-origin-width=&quot;2010&quot; data-origin-height=&quot;828&quot; width=&quot;860&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6WnHs/btqUEAAEmem/sjR0GNxgtfi8Xgmlmnrfu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6WnHs/btqUEAAEmem/sjR0GNxgtfi8Xgmlmnrfu0/img.png&quot; data-alt=&quot;티켓 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6WnHs/btqUEAAEmem/sjR0GNxgtfi8Xgmlmnrfu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6WnHs%2FbtqUEAAEmem%2FsjR0GNxgtfi8Xgmlmnrfu0%2Fimg.png&quot; data-filename=&quot;티켓 페이지.png&quot; data-origin-width=&quot;2010&quot; data-origin-height=&quot;828&quot; width=&quot;860&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;티켓 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;프로젝트를 진행하며 작업 시간(= 기록된 시간)을 실수로 3시간이 아닌 33시간으로 등록했다면 어떻게 이전 상태로 되돌릴 수 있을까요?&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;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;위키의 티켓 페이지에는 활동이라는 카테고리가 존재하며,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&amp;nbsp; &amp;nbsp; 1. 모두&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&amp;nbsp; &amp;nbsp; 2. 댓글&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&amp;nbsp; &amp;nbsp; 3. 작업 기록&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&amp;nbsp; &amp;nbsp; 4. 이력&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&amp;nbsp; &amp;nbsp; 5. 활동&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;위와 같이 총 5가지의 탭으로 나뉩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;티켓과 관련된 작업 내용들은 모두 &lt;b&gt;히스토리&lt;/b&gt;로 남게 되며, 우리는 이를 &lt;b&gt;이력&lt;/b&gt; 탭에서 확인할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;이력.png&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;380&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwRwbA/btqUBwFjZjV/KHiJukMomMNs4tiMmDXH10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwRwbA/btqUBwFjZjV/KHiJukMomMNs4tiMmDXH10/img.png&quot; data-alt=&quot;이력 탭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwRwbA/btqUBwFjZjV/KHiJukMomMNs4tiMmDXH10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwRwbA%2FbtqUBwFjZjV%2FKHiJukMomMNs4tiMmDXH10%2Fimg.png&quot; data-filename=&quot;이력.png&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;380&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이력 탭&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;말 그대로 모든 작업 이력들에 대한 정보를 확인할 수 있지만, 해당 탭에서는 각 이력에 대한 수정이 불가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;따라서, 실제 수정이 목적이라면 이력이 아닌 &lt;b&gt;작업 기록&lt;/b&gt;이라는 탭으로 이동해야합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;작업기록.png&quot; data-origin-width=&quot;1318&quot; data-origin-height=&quot;271&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cV72tC/btqURvxyeBa/xdbQdjZxdn5646PUYswrQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cV72tC/btqURvxyeBa/xdbQdjZxdn5646PUYswrQk/img.png&quot; data-alt=&quot;작업 기록 탭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cV72tC/btqURvxyeBa/xdbQdjZxdn5646PUYswrQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcV72tC%2FbtqURvxyeBa%2FxdbQdjZxdn5646PUYswrQk%2Fimg.png&quot; data-filename=&quot;작업기록.png&quot; data-origin-width=&quot;1318&quot; data-origin-height=&quot;271&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;작업 기록 탭&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;얼추 보면 이력 탭에서 보던 리스트의 형태와 비슷해 보이지만, 위에서 작업 시간을 기록한 것과 같이 유저가 실제로 &lt;b&gt;작업에 대한&amp;nbsp;액션&lt;/b&gt;을 취한 기록들만을 노출합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;그렇기에, 상태를 '할 일'에서 '진행 중'으로 변경하거나 댓글을 남기는 등의 행위는 모두 작업 기록이 아닌 이력 탭에 남게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;작업 기록 탭에서는 수정이나 삭제, 공유 기능을 제공하기 때문에 사용자는 이를 이용하여 작업 시간을 이전 상태로 되돌리거나 커스텀하게 수정하는 것이 가능해집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;삭제 버튼 클릭 시 아래 사진과 같이 남은 예상 시간을 설정할 수 있는 팝업이 노출되며,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;391&quot; data-filename=&quot;삭제 팝업.png&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be2XTz/btqULCqXN5b/WwLeEaltJiS6W8FNkgiEz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be2XTz/btqULCqXN5b/WwLeEaltJiS6W8FNkgiEz1/img.png&quot; data-alt=&quot;삭제 팝업&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be2XTz/btqULCqXN5b/WwLeEaltJiS6W8FNkgiEz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe2XTz%2FbtqULCqXN5b%2FWwLeEaltJiS6W8FNkgiEz1%2Fimg.png&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;391&quot; data-filename=&quot;삭제 팝업.png&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;삭제 팝업&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;삭제가 완료됐을 때, 입력한 예상 시간 정보를 기반으로 시간 추적 정보가 원래대로 돌아온 것을 확인할 수 있게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;첫 상태로 돌아옴.png&quot; data-origin-width=&quot;1961&quot; data-origin-height=&quot;732&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdrHjY/btqUOBx68mi/EYNVkVfmAkmXQah4xwWgFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdrHjY/btqUOBx68mi/EYNVkVfmAkmXQah4xwWgFK/img.png&quot; data-alt=&quot;원본 상태로 돌아온 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdrHjY/btqUOBx68mi/EYNVkVfmAkmXQah4xwWgFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdrHjY%2FbtqUOBx68mi%2FEYNVkVfmAkmXQah4xwWgFK%2Fimg.png&quot; data-filename=&quot;첫 상태로 돌아옴.png&quot; data-origin-width=&quot;1961&quot; data-origin-height=&quot;732&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원본 상태로 돌아온 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>ETC Tech</category>
      <category>되돌리기</category>
      <category>위키</category>
      <category>작업 기록</category>
      <category>지라</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/32</guid>
      <comments>https://pewww.tistory.com/32#entry32comment</comments>
      <pubDate>Tue, 26 Jan 2021 13:55:13 +0900</pubDate>
    </item>
    <item>
      <title>크롬 퍼포먼스 탭과 debugger 키워드로 효율적인 디버깅하기</title>
      <link>https://pewww.tistory.com/31</link>
      <description>&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;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://medium.com/mesh-korea-fe-team-blog/%ED%81%AC%EB%A1%AC-%ED%8D%BC%ED%8F%AC%EB%A8%BC%EC%8A%A4-%ED%83%AD%EA%B3%BC-debugger-%ED%82%A4%EC%9B%8C%EB%93%9C%EB%A1%9C-%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-%EB%94%94%EB%B2%84%EA%B9%85%ED%95%98%EA%B8%B0-7dce9a8c0352&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://medium.com/mesh-korea-fe-team-blog/effective-debugging&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 이야기</category>
      <category>debugger</category>
      <category>js debugger</category>
      <category>디버깅</category>
      <category>크롬 퍼포먼스 탭</category>
      <category>효율적인 디버깅</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/31</guid>
      <comments>https://pewww.tistory.com/31#entry31comment</comments>
      <pubDate>Tue, 24 Nov 2020 19:49:28 +0900</pubDate>
    </item>
    <item>
      <title>ES2020 Optional Chaining과 void operator</title>
      <link>https://pewww.tistory.com/27</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;이번 ES2020에서 새로 추가된 Optional Chaining은 &quot;?.&quot;를 사용하여 객체의 속성 값에 대해 접근할 수 있게 해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;이미 타입스크립트 3.7 버전에서 구현된 기능이기 때문에, 기존에 타입스크립트를 사용하시던 개발자분들은 그리 낯설지 않은 문법일 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;참조하는 대상이 null이나 undefined가 아니라면(= &lt;b&gt;nullish&lt;/b&gt; 하지 않다면) 속성에 대한 접근이 가능하며, 만약 nullish 할 경우 undefined를 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587040035234&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getProp(obj) {
  return obj?.a;
}

// A
const obj = {
  a: 1
};

getProp(obj); // 1

// B
const obj2 = null;

getProp(obj2); // undefined&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;일반적인 객체 형식이 아닌 함수의 호출에도 역시 사용이 가능하며, 방법은 동일합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587192834573&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) {
  return x + y;
}

const num = add?.(2, 3);

console.log(num); // 5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;함수가 존재한다면 실행하고 아니면 undefined를 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;자바스크립트에서는 런타임시에 프로퍼티를 체크하기 때문에&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587193306800&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const user = {
  name: 'Pewww',
  gender: 'male'
};

// A와 B 모두 Uncaught TypeError: Cannot read property 'zonecode' of undefined 발생

// A
const {
  address: {
    zonecode
  }
} = user;

// B
const zonecode = user.address.zonecode;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;color: #202020; font-family: 'Noto Sans Light';&quot;&gt;와 같이 user의 address가 존재하지 않는 상황에서 zonecode에 접근할 경우 에러를 출력하며, 이를 방지하기 위해&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587199314508&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const {address} = user;
const {zonecode} = address || {};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;나&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587194140278&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const zonecode = user.address &amp;amp;&amp;amp; user.address.zonecode;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;와 같은 코드를 작성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;접근해야 할 대상이 많지 않을 땐 크게 신경쓰지 않아도 되지만, 객체의 중첩이 아래와 같이 깊어질 경우 구문은 지저분해질 수 밖에 없고 곧 가독성에 타격을 줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587193986805&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = {
  a: {
    b: {
      c: {
        d: {
          e: 'Hello'
        }
      }
    }
  }
};

// Before
const e = obj.a &amp;amp;&amp;amp; obj.a.b &amp;amp;&amp;amp; obj.a.b.c &amp;amp;&amp;amp; obj.a.b.c.d &amp;amp;&amp;amp; obj.a.b.c.d.e;

// After
const e = obj?.a?.b?.c?.d?.e;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;다소 뜬금 없을 수도 있지만, Optional Chaining이 적용된 코드가 Babel을 통해 transpiling을 거쳤을 때 어떻게 변화하는지 확인하고 싶어 테스트를 해봤습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587194718560&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = {
  a: 1
};

const a = obj?.a;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;다음과 같은 코드가 &lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587194766508&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = {
  a: 1
};

const a = obj == null ? void 0 : obj.a;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #202020; font-family: 'Noto Sans Light';&quot;&gt;의 형태로 변화하는 것을 보고 문득 void 0은 무엇이고 어떤식으로 동작을 하는지, undefined 대신 사용된 이유가 무엇일지 궁금해졌습니다.&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;p&gt;&lt;span style=&quot;color: #202020; font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;void&lt;/b&gt;는 연산자로써 뒤에 나타내는 표현식을 실행하고 undefined를 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #202020; font-family: 'Noto Sans Light';&quot;&gt;보통 구문은 아래와 같이 &lt;b&gt;void expression&lt;/b&gt;의 형태를 띄고,&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587199737806&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void console.log(5); // 콘솔에 5 출력 후 undefined 반환
void 120 + 110; // 120 + 110 계산 후 undefined 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;괄호의 유무의 따라 주어진 식의 평과 과정이 달라질 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587200623078&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// undefined == '10'과 같음, 따라서 false 반환
void 10 == '10';

// void true와 같음, 따라서 undefined 반환
void (10 == '10');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;&amp;nbsp;&lt;b&gt;IIFE&lt;/b&gt;를 사용할 때 void를 사용하면, function 키워드를 선언문이 아닌 표현식 처럼 간주하도록 강제하는 것 역시 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587199707312&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void function ceilNum(num) {
  const result = Math.ceil(num);
  console.log(result);
}(5.3);

// 콘솔에 6 출력
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;a 태그에 링크 기능을 제거하기 위해 사용하기도 하지만,&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587199681967&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;a href=&quot;javascript:void(0)&quot;&amp;gt;
  https://pewww.tistory.com
&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;Mozila에서 이벤트 처리기와 같은 대체제를 사용하라는 것으로 봐선 &lt;b&gt;javascript:&lt;/b&gt; 의사 프로토콜의 사용을 그리 권장하진 않는 듯 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;그렇다면 왜 Babel은 undefined가 아닌 void 0을 사용한 것일까요?&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;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;&lt;b&gt;undefined&lt;/b&gt;는 전역 객체의 속성이며, 초기 값은 undefined 그 자체의 원시 값입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;최신 브라우저에서 undefined는 ECMAScript 5 명세에 따라 설정과 쓰기가 불가능한 속성이지만, 오래된 브라우저에서는 전역에서의 값의 할당이 가능했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;물론 현재도 undefined는 &lt;b&gt;예약어&lt;/b&gt;(&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;u&gt;&lt;span style=&quot;background-color: #e6f5ff;&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0593d3;&quot; href=&quot;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Lexical_grammar#%ED%82%A4%EC%9B%8C%EB%93%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Lexical_grammar#키워드&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;) 가 아니기 때문에 지역 변수로써 선언될 수는 있지만, 역시 좋은 방법은 아니며 반드시 피해야 하는 구문이라고 MDN은 설명하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1587198844453&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function compareUndefined() {
  const undefined = 5;
  const num = 5;

  return num === undefined;
}

const result = compareUndefined();

console.log(result); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;이러한 특징들을 봤을 때, babel이 void 연산자를 사용한 이유는 아마 이 점이 아닐까 싶습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;&quot;&lt;b&gt;Undefined 그 자체로서의 의미를 보장하기 위해.&lt;/b&gt;&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;즉, 의미에 대한 불변성의 유지를 위한 것이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;상황에 따라 나타내는 값이 달라질 수 있는 undefined 대신 void 0을 사용함으로써, 데이터 (= transpile된 결과물) 의 정확성을 보장하고 혹시 모를 예외나 변수들을 미리 차단하는 것으로 보입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&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;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;어쨌든 이번 ES2020에 꽤나 흥미로운 문법들이 많이 추가되었던데, 잘 적응해서 실제 코드에 활용해봐야겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #202020;&quot;&gt;글 읽어주셔서 감사합니다 :D&lt;/span&gt;&lt;/p&gt;</description>
      <category>Javascript</category>
      <category>ES2020</category>
      <category>javascript</category>
      <category>Optional Chaining</category>
      <category>void 0</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/27</guid>
      <comments>https://pewww.tistory.com/27#entry27comment</comments>
      <pubDate>Sat, 18 Apr 2020 18:45:44 +0900</pubDate>
    </item>
    <item>
      <title>RTL로 HOC with React-Hooks 테스트 하기</title>
      <link>https://pewww.tistory.com/25</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이번 포스팅에서는 React-Testing-Library (줄여서 RTL) 를 활용한 HOC 테스트에 대해 정리해보려 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;리액트 컴포넌트 테스트를 위해 보통 Enzyme나 RTL을 사용하는데,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Enzyme가 Implementation Driven Test 방법론을 따르며 어플리케이션이 어떻게 동작하는지에 대해 초점이 맞춰진 반면,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;RTL은 Behavior Driven Test (행위 주도 테스트) 방법론을 기반으로 어플리케이션을 사용하는 사용자의 행동에 초점을 맞추고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;어쨌든, 예시로 들어볼 코드는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1584279628617&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// loginRequired.tsx

import * as React from 'react';
import {useSelector} from 'react-redux';
import Page401 from '../components/errors/Page401';

const loginRequired = (Target: React.ComponentType) =&amp;gt; {
  const LoginRequired = (props) =&amp;gt; {
    const {access} = useSelector(({session: {access}}) =&amp;gt; ({
      access
    }));

    return !access ? (
      &amp;lt;Page401/&amp;gt;
    ) : (
      &amp;lt;Target {...props}/&amp;gt;
    );
  };

  LoginRequired.displayName = 'LoginRequired';
  LoginRequired.getInitialProps = Target.getInitialProps;

  return LoginRequired;
};

export default loginRequired;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;loginRequired 로그인이 필요한 페이지들에서 사용되는 HOC 이며, 비로그인 상태의 유저가 페이지에 접근할 시 401 에러 페이지를 보여주는 역할을 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;해당 코드에서 저희가 테스트에 중점을 둬야 할 부분은 딱 2가지라고 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;useSelector hooks를 통해 access를 받아오는지&lt;/li&gt;
&lt;li&gt;받아온 access에 따라 각각 다른 페이지/컴포넌트를 보여주는지&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 두 부분에 중점을 둬서 테스트 코드를 작성해보면, 아래와 같이 나타낼 수 있을 것 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1584279738779&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// loginRequired.test.tsx // A

import * as React from 'react';
import {useSelector} from 'react-redux';
import {renderHook} from '@testing-library/react-hooks';
import loginRequired from '../loginRequired';
import {render} from '@testing-library/react';

const AccessedComp = () =&amp;gt; ( // B
  &amp;lt;div&amp;gt;로그인 된 상태입니다.&amp;lt;/div&amp;gt;
);

jest.mock('react-redux', () =&amp;gt; ({ // C
  useSelector: jest.fn()
}));

jest.mock('next/router', () =&amp;gt; ({ // D
  useRouter: () =&amp;gt; ({
    pathname: '/test',
    asPath: '/test?message=hello'
  })
}));

const mockUseSelector = useSelector as jest.Mock; // C

describe('loginRequired 테스트', () =&amp;gt; {
  it('access가 null일 때 Page401 반환', () =&amp;gt; {
    mockUseSelector.mockImplementation(callback =&amp;gt; callback({ // E
      session: {
      	access: null
      } 
    }));

    const {
      result: {
        current: {
          access
        }
      }
    } = renderHook( // F
      () =&amp;gt; useSelector(({session: {access}}) =&amp;gt; ({
        access
      }))
    );

    expect(access).toBeNull();

    const Comp = loginRequired(AccessedComp);
    const wrapper = render(&amp;lt;Comp/&amp;gt;); // G

    expect(wrapper.getByText('로그인 후 이용 가능한 서비스입니다.')).toBeInTheDocument(); // H
  });

  it('access가 null이 아닐 경우(= 로그인 된 상태일 때) 받은 컴포넌트 그대로 출력', () =&amp;gt; {
    mockUseSelector.mockImplementation(callback =&amp;gt; callback({
      session: {
        access: 'Access Token'
      }
    }));

    const {
      result: {
        current: {
          access
        }
      }
    } = renderHook(
      () =&amp;gt; useSelector(({session: {access}}) =&amp;gt; ({
        access
      }))
    );

    expect(access).not.toBeNull();

    const Comp = loginRequired(AccessedComp);
    const wrapper = render(&amp;lt;Comp/&amp;gt;);
    
    expect(wrapper.getByText('로그인 된 상태입니다.')).toBeInTheDocument();
  });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이제 주석 처리한 부분들에 대해 차근차근 설명해보겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;A&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;테스트를 위한 컴포넌트도 해당 파일 내에 같이 존재하기 때문에 확장자를 .ts가 아닌 .tsx로 설정하였습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;B&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;로그인 된 상태일 때 보여지는 임시 컴포넌트입니다.&lt;/p&gt;
&lt;p&gt;해당 테스트의 목적은 access의 상태에 따라 다른 페이지/컴포넌트를 보여주는 것이기 때문에, 컴포넌트의 props나 state, 복잡한 정도 등은 고려할 필요가 없다고 판단하여 위와 같이 간단히 작성하였습니다 :D&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;C&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Mocking은 유닛 테스트를 작성할 때, 해당 코드가 의존하는 부분을 가짜로 대체하는 기법을 말합니다.&lt;/p&gt;
&lt;p&gt;보통 테스트하려는 코드가 의존하는 부분을 사용자가 직접 생성하기 부담스러운 경우 (Database, API...) 많이 사용하는데, useSelector에도 충분히 활용될 수 있을 것 같아 Mocking 작업을 진행하였습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;D&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;아래와 같이 next.js의 useRouter hooks를 사용하는 구성 요소를 테스트 하고자 할 때,&lt;/p&gt;
&lt;pre id=&quot;code_1584280497198&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const Comp = () =&amp;gt; {
  const {asPath} = useRouter();
  .
  .
  .
};&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1584280508685&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;TypeError: Cannot destructure property 'asPath' of 'undefined' or 'null'.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;의 에러를 반환하는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;useRouter는 React.useContext를 사용하여 《next server / dist / lib / router-context》 에서 컨텍스트를 사용하기 때문에, 이를 해결하려면&lt;/p&gt;
&lt;pre id=&quot;code_1584280532151&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import {RouterContext} from 'next-server/dist/lib/router-context';

const wrapper = render(
  &amp;lt;RouterContenxt.Provider value={router}
    &amp;lt;Comp/&amp;gt;
  &amp;lt;/RouterContext.Provider&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;처럼 Wrapping 하는 것이 중요합니다.&lt;/p&gt;
&lt;p&gt;다만, jest.mock 함수를 이용하여 useRouter 자체를 Mocking 하는 작업 역시 가능하기 때문에, 해당 방법을 사용하여 테스트 코드를 작성하였습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;E&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://jestjs.io/docs/en/mock-function-api#mockfnmockimplementationfn&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://jestjs.io/docs/en/mock-function-api#mockfnmockimplementationfn&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1584280654151&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Jest &amp;middot;   Delightful JavaScript Testing&quot; data-og-description=&quot;  Delightful JavaScript Testing&quot; data-og-host=&quot;jestjs.io&quot; data-og-source-url=&quot;https://jestjs.io/docs/en/mock-function-api#mockfnmockimplementationfn&quot; data-og-url=&quot;https://jestjs.io/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/RQfS7/hyFhJdJTap/xBHKElFTil2nVOFIVmlUR1/img.png?width=796&amp;amp;height=416&amp;amp;face=0_0_796_416,https://scrap.kakaocdn.net/dn/oLG7j/hyFhTm7mp7/Rx3QoV2X3zONJEKFeuXUu1/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600,https://scrap.kakaocdn.net/dn/Cgwtq/hyFhNtF7nB/uisUDkbBY5IVvCAYyOb3ck/img.png?width=1844&amp;amp;height=1246&amp;amp;face=0_0_1844_1246&quot;&gt;&lt;a href=&quot;https://jestjs.io/docs/en/mock-function-api#mockfnmockimplementationfn&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jestjs.io/docs/en/mock-function-api#mockfnmockimplementationfn&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/RQfS7/hyFhJdJTap/xBHKElFTil2nVOFIVmlUR1/img.png?width=796&amp;amp;height=416&amp;amp;face=0_0_796_416,https://scrap.kakaocdn.net/dn/oLG7j/hyFhTm7mp7/Rx3QoV2X3zONJEKFeuXUu1/img.png?width=600&amp;amp;height=600&amp;amp;face=0_0_600_600,https://scrap.kakaocdn.net/dn/Cgwtq/hyFhNtF7nB/uisUDkbBY5IVvCAYyOb3ck/img.png?width=1844&amp;amp;height=1246&amp;amp;face=0_0_1844_1246');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;Jest &amp;middot;   Delightful JavaScript Testing&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;  Delightful JavaScript Testing&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;jestjs.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;해당 링크에서 확인하실 수 있듯이, mockImplementation 함수를 사용하면 실제 사용하고자 하는 함수를 재구현하는 것이 가능합니다.&lt;/p&gt;
&lt;p&gt;useSelector가 각 케이스 마다 다른 state를 반환해야 하므로 (-&amp;gt; access의 상태) 함수 역시 다르게 구현하였습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;F&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;react-hooks에 대한 테스트를 진행할 때 사용하는 &quot;react-hooks-testing-library&quot;에서 제공하는 함수입니다.&lt;/p&gt;
&lt;p&gt;renderHook은 hooks의 파라미터와 반환하는 값을 확인하기 위해 사용하여, 더욱 자세한 내용은 아래의 API 문서를 참고하시면 좋을 것 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://react-hooks-testing-library.com/reference/api#renderhook&quot;&gt;https://react-hooks-testing-library.com/reference/api#renderhook&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1584280833479&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;API Reference&quot; data-og-description=&quot;Simple and complete React hooks testing utilities that encourage good testing practices.&quot; data-og-host=&quot;react-hooks-testing-library.com&quot; data-og-source-url=&quot;https://react-hooks-testing-library.com/reference/api#renderhook&quot; data-og-url=&quot;https://react-hooks-testing-library.com/reference/api/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://react-hooks-testing-library.com/reference/api#renderhook&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://react-hooks-testing-library.com/reference/api#renderhook&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;API Reference&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;Simple and complete React hooks testing utilities that encourage good testing practices.&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;react-hooks-testing-library.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;G&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;컴포넌트의 렌더링을 하고자 할 때 render 함수를 이용합니다.&lt;/p&gt;
&lt;p&gt;해당 함수를 호출할 시 DOM과 관련된 다양한 쿼리들과 container 에 대한 정보를 제공받을 수 있는데, 여기서 container는 해당 컴포넌트의 최상위 DOM을 가리킵니다. (document.body에 추가된 container를 렌더링한다고 합니다.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;H&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;getByText() 함수는 받은 TextMatch를 토대로 일치하는 DOM이 있는지 검색하여 &lt;b&gt;HTMLElement&lt;/b&gt; 타입의 값을 반환합니다.&lt;/p&gt;
&lt;p&gt;해당 함수를 사용하면 내가 원하는 DOM을 선택할 수 있고, TextMatch는 Matcher 타입이기 때문에 &lt;b&gt;String&lt;/b&gt;, &lt;b&gt;RegExp&lt;/b&gt;, &lt;b&gt;MatcherFunction&lt;/b&gt; 셋 중 어느 타입의 값을 넘기더라도 문제가 없습니다,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;여기서, MatcherFunction의 타입은 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1584281140369&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type MatcherFunction = (content: string, element: HTMLElement) =&amp;gt; boolean;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;따라서, 해당 구문은 access의 존재 여부에 따라 서로 다른 컴포넌트가 Document 내에 존재하는지를 테스트 한다는 의미를 담고 있습니다.&lt;/p&gt;
&lt;p&gt;다만, toBeInTheDocument 함수는 jest에서 기본적으로 제공하는 속성이 아니기 때문에, 사용하기 위해서는 jest.config.js 파일에서 따로 &lt;b&gt;jest-dom&lt;/b&gt;에 대한 설정을 해야 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아래 링크를 참고하시면 됩니다 :D&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://stackoverflow.com/questions/56547215/react-testing-library-why-is-tobeinthedocument-not-a-function&quot;&gt;https://stackoverflow.com/questions/56547215/react-testing-library-why-is-tobeinthedocument-not-a-function&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1584281385241&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;react-testing-library why is toBeInTheDocument() not a function&quot; data-og-description=&quot;Can anyone help me please , I am really stuck on this. Here is my code for a tooltip that toggles the css property display: block on MouseOver and on Mouse Out display: none it('should show and ...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/56547215/react-testing-library-why-is-tobeinthedocument-not-a-function&quot; data-og-url=&quot;https://stackoverflow.com/questions/56547215/react-testing-library-why-is-tobeinthedocument-not-a-function&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bkdLxH/hyFjlWBMk1/RANzFfHOT9MNNDnd09frnk/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/56547215/react-testing-library-why-is-tobeinthedocument-not-a-function&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/56547215/react-testing-library-why-is-tobeinthedocument-not-a-function&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bkdLxH/hyFjlWBMk1/RANzFfHOT9MNNDnd09frnk/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;&gt;react-testing-library why is toBeInTheDocument() not a function&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;Can anyone help me please , I am really stuck on this. Here is my code for a tooltip that toggles the css property display: block on MouseOver and on Mouse Out display: none it('should show and ...&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;이상 RTL로 HOC with React-Hooks 테스트 작성하기에 대한 포스팅이었습니다.&lt;/p&gt;
&lt;p&gt;물론 상황에 따라 작성하는 방법은 언제든 달라질 수 있겠지만, 테스트를 하는 목적과 의도가 명확하다면 코드를 작성하는데에 있어서 큰 어려움은 없을 것 같습니다.&lt;/p&gt;
&lt;p&gt;수정되어야 하거나 개선되어야 할 부분이 있다면 언제든 코멘트로 남겨주세요 :D&lt;/p&gt;
&lt;p&gt;감사합니다!&amp;nbsp;&lt;/p&gt;</description>
      <category>React, Redux...</category>
      <category>hoc test</category>
      <category>jest react test</category>
      <category>react hoc 테스트</category>
      <category>react-hooks test</category>
      <category>react-testing-library</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/25</guid>
      <comments>https://pewww.tistory.com/25#entry25comment</comments>
      <pubDate>Sun, 15 Mar 2020 23:15:18 +0900</pubDate>
    </item>
    <item>
      <title>esModuleInterop 속성을 이용한 Import 에러 해결</title>
      <link>https://pewww.tistory.com/26</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;함수의 테스트를 진행하다,&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1584274387965&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import difference from 'lodash/difference';

difference();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;의 구문으로 인해&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1584274435506&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;TypeError: difference_1.default is not a function&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;라는 에러가 발생한 것을 확인했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;이번 포스팅에서는 관련된 내용에 대해 정리해 볼 예정입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;lodash에서는 CommonJS 스펙의 require를 사용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;따라서, 위 코드와 같이 CommonJS 모듈을 ES6 모듈 코드베이스로 가져오려고 할 때 문제가 발생합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;해당 문제를&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1584274798458&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1
require(~~~);

// 2
import * as ~~~&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;의 구문을 사용하여 해결할 수도 있지만,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;moment ( &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://www.npmjs.com/package/moment&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.npmjs.com/package/moment&lt;/a&gt;&lt;/u&gt;&lt;/span&gt; ) 와 같이, * 를 사용하여 import 하려는 대상의 타입이 Object가 아닌 경우에는 ES6의 모듈 사양에 호환되지 않게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;우리는 이 때, tsconfig의 컴파일 옵션 중 --esModuleInterop flag의 수정을 통해 이를 해결할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1584275028521&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// tsconfig.json - 저의 경우는 jest.tsconfig.json 입니다 :D

{
  &quot;compilerOptions&quot;: {
    &quot;module&quot;: &quot;commonjs&quot;,
    &quot;esModuleInterop&quot;: true,
    ...
  },
  ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;esModuleInterop 속성이 위의 코드 처럼 true로 설정될 경우, ES6 모듈 사양을 준수하여 CommonJS 모듈을 가져올 수 있게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;해당 옵션을 통해 위에서 예시로 들었던 코드는 아래와 같이 트랜스파일링 되며, 그 결과 정상적으로 import 하는 것이 가능해집니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1584275177875&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Before
import difference from 'lodash/difference';
difference();

// After
const difference = __importDefault(require('lodash/difference'));
difference();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;*&lt;/span&gt; 타입스크립트의 Compiler Options에 대한 정보를 좀 더 알고 싶다면&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #0593d3;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://www.typescriptlang.org/docs/handbook/compiler-options.html&quot;&gt;https://www.typescriptlang.org/docs/handbook/compiler-options.html&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1584275326661&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Handbook - Compiler Options&quot; data-og-description=&quot;A very high-level overview of the compiler options in TypeScript&quot; data-og-host=&quot;www.typescriptlang.org&quot; data-og-source-url=&quot;https://www.typescriptlang.org/docs/handbook/compiler-options.html&quot; data-og-url=&quot;https://www.typescriptlang.org/docs/handbook/compiler-options.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/compiler-options.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.typescriptlang.org/docs/handbook/compiler-options.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;Handbook - Compiler Options&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;A very high-level overview of the compiler options in TypeScript&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;www.typescriptlang.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;해당 링크를 참고하시면 좋을 듯 합니다 :D&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;포스팅 봐주셔서 감사합니다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;수정되어야 할 부분이 있으면 언제든 코멘트로 남겨주세요~&lt;/span&gt;&lt;/p&gt;</description>
      <category>Typescript</category>
      <category>commonJS</category>
      <category>difference_1.default is not a function</category>
      <category>ES6 Module</category>
      <category>esModuleInterop</category>
      <category>tsconfig.json</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/26</guid>
      <comments>https://pewww.tistory.com/26#entry26comment</comments>
      <pubDate>Sun, 15 Mar 2020 21:47:09 +0900</pubDate>
    </item>
    <item>
      <title>Jest를 이용한 Reducer 테스트</title>
      <link>https://pewww.tistory.com/24</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;이번에는 Jest를 이용한 Reducer 테스트에 대해 포스팅해보려 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;다만, 테스트를 위한 세팅에 대해서는 따로 설명하지 않을 예정이니 이 점 참고 부탁드립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;내용이 간단하여 어려운 점은 없을 것 같습니다 :D&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;원칙&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;color: #0593d3; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;a style=&quot;color: #0593d3; background-color: #ffffff;&quot; href=&quot;https://redux.js.org/recipes/writing-tests/#reducers&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://redux.js.org/recipes/writing-tests/#reducers&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1583761892538&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Redux&quot; data-og-description=&quot;# Writing Tests&quot; data-og-host=&quot;redux.js.org&quot; data-og-source-url=&quot;https://redux.js.org/recipes/writing-tests/#reducers&quot; data-og-url=&quot;https://redux.js.org/recipes/writing-tests&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://redux.js.org/recipes/writing-tests/#reducers&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://redux.js.org/recipes/writing-tests/#reducers&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;Redux&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;# Writing Tests&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;redux.js.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&quot;&lt;u&gt;리듀서는 액션을 이전의 상태에 적용한 후 새로운 상태를 반환해야 한다.&lt;/u&gt;&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;함수의 유닛 테스트와 같이 state와 action만 테스트 케이스에 따라 넘겨주고, 변경된 알맞은 값을 반환하는지, 그에 맞게 상태를 잘 변경하는지에 대해 테스트 코드를 작성하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;예시&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;
&lt;script src=&quot;https://gist.github.com/Pewww/fc9de94f3be8720bf3fe8d1724f4263e.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;script src=&quot;https://gist.github.com/Pewww/299ec7fdff77dee9c90051011579fc6d.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;다만 A 부분에서 현재 액션 생성 함수에 대한 테스트도 진행하고 있는데, 이미 redux-actions를 사용하고 있기 때문에 해당 라이브러리를 믿고 오히려 테스트 케이스를 작성하지 않는 것도 하나의 방법이 될 수 있을 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;redux-mock-store를 활용하여 개선해보기&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;u&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #0593d3;&quot;&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://github.com/dmitry-zaets/redux-mock-store&quot;&gt;https://github.com/dmitry-zaets/redux-mock-store&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1583762998134&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;object&quot; data-og-title=&quot;dmitry-zaets/redux-mock-store&quot; data-og-description=&quot;A mock store for testing Redux async action creators and middleware. - dmitry-zaets/redux-mock-store&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/dmitry-zaets/redux-mock-store&quot; data-og-url=&quot;https://github.com/dmitry-zaets/redux-mock-store&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/busgFJ/hyFdzWfTTG/RbhF55fi6fHjtiS6PyLra0/img.jpg?width=400&amp;amp;height=400&amp;amp;face=30_60_250_300&quot;&gt;&lt;a href=&quot;https://github.com/dmitry-zaets/redux-mock-store&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/dmitry-zaets/redux-mock-store&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/busgFJ/hyFdzWfTTG/RbhF55fi6fHjtiS6PyLra0/img.jpg?width=400&amp;amp;height=400&amp;amp;face=30_60_250_300');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;dmitry-zaets/redux-mock-store&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;A mock store for testing Redux async action creators and middleware. - dmitry-zaets/redux-mock-store&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;redux-mock-store는 리덕스의 비동기 액션 생성자와 미들웨어의 테스트를 위한 Mock Store입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;위에 링크로 걸어둔 redux.js.org에서도 async action creators에 대한 테스트를 진행할 때 해당 라이브러리를 사용하고 있는 모습을 확인하실 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;실제 공식 예제에서 볼 수 있듯이, (Synchronous actions)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;script src=&quot;https://gist.github.com/Pewww/898ef8fc71b9f4c3f4df9ec413d2dc88.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;addTodo 액션이 올바른 payload를 반환하는지에 대한 테스트를 진행하는 것을 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;*&lt;/span&gt; redux-mock-store는 상태를 업데이트 하지 않고 디스패치에 전달된 작업만 기록하기 때문에, store.dispatch() 구문 실행 후&amp;nbsp;store.getState()로 변경된 상태를 확인하는 것이 불가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;해당 라이브러리가 리듀서 관련 로직이 아닌 액션 관련 로직을 테스트하도록 설계되었기 때문에 이는 어쩔 수 없는 부분이 아닌가 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;다만, 액션과 리듀서를 결합한 복잡한 테스트의 경우 &quot;redux-actions-assertions&quot;를 참고할 수 있다고 하는데 실제로 사용해 본 적이 없어 설명은 어려울 것 같습니다.. : (&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;어쨌든, 위의 food.test.ts 테스트 코드 중&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;script src=&quot;https://gist.github.com/Pewww/9ce8d46d6a06d045c6eb4ba8ec18f044.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;해당 부분을 redux-mock-store를 활용하여 아래와 같이 개선이 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;script src=&quot;https://gist.github.com/Pewww/0010b7cfad4f1320fe1dcb1167cf5ef2.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;설명&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&lt;b&gt;A&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;실제 redux에서 configureStore함수는 reducer와 store를 연결하고자 할 때 사용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;해당 코드의 역할 역시 동일합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&lt;b&gt;B&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;기존에는 action creator와 reducer에 대한 테스트 코드가 같은 describe 내에 존재하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;성격이 다른 케이스들을 분리하는 것이 추후 유지보수를 하기에도 편리할 것 같아 describe 역시 분리하여 테스트 코드를 작성하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&lt;b&gt;C&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;공식 레포의 예제와 같이 saveFood 작업이 올바른 payload를 반환하는지 테스트합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;store.dispatch() 구문을 실행할 때의 action은 인스턴스 내부 배열에 저장되어 실행되기 때문에 getActions() 역시 배열을 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;따라서 toEqual Matcher를 사용해 값을 비교하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;&lt;b&gt;D&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;저장된 액션들을 초기화하는 역할을 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;store.getActions() 구문에 대해 각각 비교하는 것이 나을 것 같아 해당 코드를 추가하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;결과&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;test-result.png&quot; data-origin-width=&quot;1486&quot; data-origin-height=&quot;1286&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be01Vr/btqCym7W19f/GRUr2PTXyPkvinT2HmNr2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be01Vr/btqCym7W19f/GRUr2PTXyPkvinT2HmNr2k/img.png&quot; data-alt=&quot;테스트 커버리지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be01Vr/btqCym7W19f/GRUr2PTXyPkvinT2HmNr2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe01Vr%2FbtqCym7W19f%2FGRUr2PTXyPkvinT2HmNr2k%2Fimg.png&quot; data-filename=&quot;test-result.png&quot; data-origin-width=&quot;1486&quot; data-origin-height=&quot;1286&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테스트 커버리지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;마치며&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;Reducer가 순수 함수이기 때문에 테스트 코드를 작성하기 훨씬 수월했던 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;앞으로는 이런저런 테스트 코드 작성 방법과 예제들에 대한 포스팅도 진행해 볼 생각입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333;&quot;&gt;수정되어야 할 부분이 있으면 언제든 코멘트로 남겨주세요 :D&lt;/span&gt;&lt;/p&gt;</description>
      <category>React, Redux...</category>
      <category>jest reducer test</category>
      <category>jest reducer 테스트</category>
      <category>reducer test</category>
      <category>redux-mock-store</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/24</guid>
      <comments>https://pewww.tistory.com/24#entry24comment</comments>
      <pubDate>Mon, 9 Mar 2020 23:53:56 +0900</pubDate>
    </item>
    <item>
      <title>react-waypoint를 이용한 Infinite-scrolling 구현</title>
      <link>https://pewww.tistory.com/20</link>
      <description>&lt;h4 style=&quot;font-weight: 300;&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Nanum Gothic';&quot;&gt;들어가며&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;피드 관련 기능을 개발할 때 Infinite-scrolling을 구현해야 할 일이 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;구현할 때 react-waypoint를 활용했었는데, 이번 시간에는 구현 원리와 과정을 설명해볼까 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;react-waypoint: &lt;span style=&quot;background-color: #e6f5ff; color: #0593d3;&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0593d3;&quot; href=&quot;https://github.com/civiccc/react-waypoint&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/civiccc/react-waypoint&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1561816625571&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot;&gt;&lt;a href=&quot;https://github.com/civiccc/react-waypoint&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-original-url=&quot;https://github.com/civiccc/react-waypoint&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bwUM7x/hyBNZW9iT9/FDad9VwSTWSNiKshL8WEKK/img.jpg?width=200&amp;amp;height=200&amp;amp;face=0_0_200_200');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;civiccc/react-waypoint&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;A React component to execute a function whenever you scroll to an element. - civiccc/react-waypoint&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 style=&quot;font-weight: 300;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;코드&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1573372575182&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import * as React from 'react';
import {Waypoint} from 'react-waypoint';
import styled from 'styled-components';

interface Props {
  loadMore: () =&amp;gt; void;
  threshold?: string;
  hasMore: boolean;
  loader: React.ReactNode | React.ComponentType;
  children: React.ReactNode;
  className?: string;
}

const InfiniteScrollDiv = styled.div`
  padding-top: 35px;
`;

const InfiniteScroll: React.ExoticComponent&amp;lt;Props&amp;gt; = React.memo(({
  loadMore,
  threshold,
  hasMore,
  loader,
  children,
  className
}) =&amp;gt; (
  &amp;lt;InfiniteScrollDiv className={className}&amp;gt;
    {children}
    {hasMore &amp;amp;&amp;amp; (
      &amp;lt;Waypoint
        onEnter={loadMore}
        bottomOffset={threshold}
      &amp;gt;
        {loader}
      &amp;lt;/Waypoint&amp;gt;
    )}
  &amp;lt;/InfiniteScrollDiv&amp;gt;
));

export default InfiniteScroll;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;InfiniteScroll 컴포넌트의 구조는 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;Props부터 설명을 드리자면,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;b&gt;1. loadMore&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;데이터를 fetch하는 함수입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;초기 렌더링 시 데이터를 불러오거나, 스크롤을 내리면서 추가 데이터를 불러와야 할 때 필수로 사용됩니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;b&gt;2. threshold (optional)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;페이지의 최하단으로부터의 거리입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;스크롤이 페이지의 최하단에 닿기 전에 데이터를 미리 불러오고 싶을 때 활용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;만약 threshold를 &quot;200px&quot;라고 설정하면, 스크롤이 페이지 하단에서 200px의 거리에 있을 때 Waypoint 컴포넌트가 onEnter 됐다고 인식합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;b&gt;3. hasMore&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;불러와야 할 데이터가 더 있는지 판단하는 필드입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;값이 false라면, 더 이상 추가적인 데이터가 불러와지지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;b&gt;4. loader&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;데이터가 불러와지기 전에 사용자에게 보여지는 ReactNode 혹은 ReactComponent 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;로딩중이라는 것을 사용자에게 보여주기 위해 넘겨주는 필드입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;b&gt;5. children&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;실제로 렌더링될 (사용자의 눈에 보여지는) 요소입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;b&gt;6. className (optional)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;스타일 수정을 위해 className이라는 필드 역시 받도록 하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;다만, 필수적으로 필요하진 않기 때문에 threshold와 동일하게 optional로 설정하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;이제 실제로 return 되는 JSX 구문을 그림으로 나타내보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;111.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSFUfs/btqzD67Ujp1/E0ZF73Mb89KqJopAFxOodK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSFUfs/btqzD67Ujp1/E0ZF73Mb89KqJopAFxOodK/img.png&quot; data-alt=&quot;동작 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSFUfs/btqzD67Ujp1/E0ZF73Mb89KqJopAFxOodK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSFUfs%2FbtqzD67Ujp1%2FE0ZF73Mb89KqJopAFxOodK%2Fimg.png&quot; data-filename=&quot;111.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;동작 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;아직 데이터 fetch가 이루어지지 않았기 때문에, children은 렌더링 되기 전입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;따라서, 사용자에게는 loader가 보여지는데 이는 아래 그림과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;222.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wrLVf/btqzGqDrwV1/CTFGYIaFQGrky0TbsKikx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wrLVf/btqzGqDrwV1/CTFGYIaFQGrky0TbsKikx1/img.png&quot; data-alt=&quot;동작 2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wrLVf/btqzGqDrwV1/CTFGYIaFQGrky0TbsKikx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwrLVf%2FbtqzGqDrwV1%2FCTFGYIaFQGrky0TbsKikx1%2Fimg.png&quot; data-filename=&quot;222.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;동작 2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;Waypoint가 onEnter 됐으므로, props로 받은 loadMore 함수가 실행됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;실행이 완료되고 children이 렌더링되기 전 까지는 loader가 계속 사용자에게 보여지게 되며, 완료될 시에는 아래 그림의 형태를 띄게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;333.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUQXqz/btqzFdx1D7Q/1uik7Yd0MvpCf709s7RYZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUQXqz/btqzFdx1D7Q/1uik7Yd0MvpCf709s7RYZk/img.png&quot; data-alt=&quot;동작 3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUQXqz/btqzFdx1D7Q/1uik7Yd0MvpCf709s7RYZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUQXqz%2FbtqzFdx1D7Q%2F1uik7Yd0MvpCf709s7RYZk%2Fimg.png&quot; data-filename=&quot;333.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;동작 3&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;이제, 실제 데이터에 따라 렌더링된 요소가 이제 사용자에게 보여집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;스크롤을 내리면서 다시 로딩 컴포넌트를 마주쳤을 때, (= Waypoint가 onEnter 됐을 때) 추가 데이터가 fetch되며 결국 Infinite-scrolling이 가능하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;실제 예시&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;눈으로 확인하시면 이해가 빠르실 듯 하여, InfiniteScroll 컴포넌트를 활용한 피드 컴포넌트를 임의로 제작하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;예시는 아래에서 보여드리는 사진의 모습과 동일하며, 전체적인 코드는&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #0593d3; background-color: #e6f5ff;&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0593d3;&quot; href=&quot;https://github.com/Pewww/waypoint-infinite-scroll&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Pewww/waypoint-infinite-scroll&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1573374937049&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Pewww/waypoint-infinite-scroll&quot; data-og-description=&quot;Implementation of Infinite-Scrolling by using React-Waypoint. - Pewww/waypoint-infinite-scroll&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Pewww/waypoint-infinite-scroll&quot; data-og-url=&quot;https://github.com/Pewww/waypoint-infinite-scroll&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/BGufh/hyDEu1T3YN/hCK4qfK8yDj2LooG7ooCX1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://github.com/Pewww/waypoint-infinite-scroll&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Pewww/waypoint-infinite-scroll&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/BGufh/hyDEu1T3YN/hCK4qfK8yDj2LooG7ooCX1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;Pewww/waypoint-infinite-scroll&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;Implementation of Infinite-Scrolling by using React-Waypoint. - Pewww/waypoint-infinite-scroll&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;에서 확인하실 수 있습니다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;1111.png&quot; width=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvYvHK/btqzE1R8gmw/RN5ZQVMcWqPYhPaFoVioi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvYvHK/btqzE1R8gmw/RN5ZQVMcWqPYhPaFoVioi1/img.png&quot; data-alt=&quot;첫 렌더링 시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvYvHK/btqzE1R8gmw/RN5ZQVMcWqPYhPaFoVioi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvYvHK%2FbtqzE1R8gmw%2FRN5ZQVMcWqPYhPaFoVioi1%2Fimg.png&quot; data-filename=&quot;1111.png&quot; width=&quot;600&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;첫 렌더링 시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&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;imageblock alignCenter&quot; data-filename=&quot;2222.png&quot; width=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QYPoh/btqzFWo335u/2DekfpUrWzgjhlMnDJWROk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QYPoh/btqzFWo335u/2DekfpUrWzgjhlMnDJWROk/img.png&quot; data-alt=&quot;로딩중&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QYPoh/btqzFWo335u/2DekfpUrWzgjhlMnDJWROk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQYPoh%2FbtqzFWo335u%2F2DekfpUrWzgjhlMnDJWROk%2Fimg.png&quot; data-filename=&quot;2222.png&quot; width=&quot;600&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;로딩중&lt;/figcaption&gt;
&lt;/figure&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;3333.png&quot; width=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rLU5B/btqzEEiBhGj/b0pYddiXY8jI9CMKGEwf2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rLU5B/btqzEEiBhGj/b0pYddiXY8jI9CMKGEwf2k/img.png&quot; data-alt=&quot;추가적인 렌더링 완료 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rLU5B/btqzEEiBhGj/b0pYddiXY8jI9CMKGEwf2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrLU5B%2FbtqzEEiBhGj%2Fb0pYddiXY8jI9CMKGEwf2k%2Fimg.png&quot; data-filename=&quot;3333.png&quot; width=&quot;600&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;추가적인 렌더링 완료 후&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;마치며&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;설명이 빈약할 수도 있기 때문에 궁금하신 점이나 수정되어야 할 부분들은 &lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;모두 코멘트로 달아주시면 감사하겠습니다!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;이상, react-waypoint를 활용한 Infinite-scrolling 구현 포스팅이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;봐주셔서 정말 감사합니다!&lt;/span&gt;&lt;/p&gt;</description>
      <category>React, Redux...</category>
      <category>infinite-scrolling</category>
      <category>infinite-scrolling 구현</category>
      <category>react-infinite-scroll</category>
      <category>react-waypoint</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/20</guid>
      <comments>https://pewww.tistory.com/20#entry20comment</comments>
      <pubDate>Sun, 10 Nov 2019 17:52:31 +0900</pubDate>
    </item>
    <item>
      <title>Codility - FrogRiverOne 풀이</title>
      <link>https://pewww.tistory.com/22</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333; font-weight: 400 !important;&quot;&gt;Lesson4. FrogRiverOne&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333; font-family: 'Nanum Gothic';&quot;&gt;안녕하세요!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;오늘은 Lesson4의 두 번째 문제인 FrogRiverOne에 대해 풀이해보려 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;span style=&quot;font-weight: 400 !important;&quot;&gt;Question&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #0593d3; background-color: #e6f5ff; font-family: 'Nanum Gothic';&quot;&gt;&lt;a style=&quot;color: #0593d3; background-color: #e6f5ff;&quot; href=&quot;https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/&quot;&gt;https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1571752073691&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;FrogRiverOne coding task - Learn to Code - Codility&quot; data-og-description=&quot;Find the earliest time when a frog can jump to the other side of a river.&quot; data-og-host=&quot;app.codility.com&quot; data-og-source-url=&quot;https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/&quot; data-og-url=&quot;https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;FrogRiverOne coding task - Learn to Code - Codility&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;Find the earliest time when a frog can jump to the other side of a river.&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;app.codility.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333; font-family: 'Nanum Gothic';&quot;&gt;개구리가 강 반대편으로 점프할 수 있는 가장 빠른 시간을 찾아야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333; font-family: 'Nanum Gothic';&quot;&gt;목적지를 나타내는 X와 각 요소의 범위가 1 ~ X로 이루어진 배열 A가 주어지는데, 배열 A를 탐색하며 1부터 X 까지의 수가 모두 나타났을 때의 index를 반환하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;만약 X가 5, A가 [1, 3, 1, 4, 2, 3, 5, 4] 라고 했을 때, 1부터 5까지의 수가 모두 나타난 배열 A의 index는 6이므로 6을 반환하면 되고, 혹시나 나타나지 않았을 경우에는 -1을 반환하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;span style=&quot;font-weight: 400 !important;&quot;&gt;Answer&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;이번에는 자료구조 중 하나인 Set을 활용하여 풀이해보았습니다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;*&lt;/span&gt; Set은 중복된 value를 저장하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;1. 새로운 Set 변수 s를 생성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;2. A 배열의 루프를 돌며, s에 값( A[idx] )을 추가합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;3. 만약 s의 길이가 X와 같다면, 1 부터 X 까지의 수가 모두 채워졌다는 의미이므로 해당 index를 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;&amp;nbsp; &amp;nbsp; -&amp;gt; 배열 A 내의 요소의 범위가 1 ~ X라는 전제가 깔려있기 때문에 가능한 로직입니다!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;4. 루프를 돌고 난 뒤에도 index가 반환되지 않았을 경우에는 -1을 최종적으로 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333; font-family: 'Nanum Gothic';&quot;&gt;풀이 코드는 아래와 같습니다. (&amp;nbsp;&lt;u&gt;시간 복잡도는 O(N)&lt;/u&gt;&amp;nbsp;)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1571751958653&quot; class=&quot;javascript&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 15px; color: #383a42; background: #f6f7f8; font-size: 14px; border-radius: 3px; font-family: Menlo, Consolas, Monaco, monospace; border: 1px solid #dddddd; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;function solution(X, A) {
  const s = new Set();
   
  for (let idx = 0, leng = A.length; idx &amp;lt; leng; idx++) {
    const value = A[idx];
    s.add(value);
        
    if (s.size === X) {
      return idx;
    }
  }
    
  return -1;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;frogriverone.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oh8Pn/btqzf6MxatD/gwOY08pV6bhcW4uYgSVDfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oh8Pn/btqzf6MxatD/gwOY08pV6bhcW4uYgSVDfK/img.png&quot; data-alt=&quot;풀이 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oh8Pn/btqzf6MxatD/gwOY08pV6bhcW4uYgSVDfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Foh8Pn%2Fbtqzf6MxatD%2FgwOY08pV6bhcW4uYgSVDfK%2Fimg.png&quot; data-filename=&quot;frogriverone.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;풀이 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; font-weight: 400 !important; color: #333333;&quot;&gt;The End&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;문제를 이해하고 난 후엔 그리 어렵지 않게 풀 수 있었던 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;다음 시간에는 Lesson4의 세 번째 문제인 MaxCounters에 대해 풀이해보려 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;봐주셔서 감사합니다!&lt;/span&gt;&lt;/p&gt;</description>
      <category>Codility</category>
      <category>Codility FrogRiverOne</category>
      <category>FrogRiverOne</category>
      <category>코딜리티 FrogRiverOne</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/22</guid>
      <comments>https://pewww.tistory.com/22#entry22comment</comments>
      <pubDate>Tue, 22 Oct 2019 23:20:03 +0900</pubDate>
    </item>
    <item>
      <title>Javascript - 나를 위한 클로저 예제 분석</title>
      <link>https://pewww.tistory.com/21</link>
      <description>&lt;blockquote data-ke-style=&quot;normal&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;들어가며&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1564248889617&quot; class=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var text = 'Hello, ';

function greeting() {
  var name = 'Pewww';
  
  return function() {
    console.log(text + name);
  }
}

var g = greeting();
g(); // 'Hello, Pewww' 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;예전에도 클로저 예제 분석에 대한 글을 썼었지만, (&lt;s&gt;지금은 삭제한 상태&lt;/s&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;제대로 이해하지 못한 상태였고, 저 스스로도 확실히 과정이나 결과에 대해 납득하기 어려웠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;계속 그렇게 찝찝한 상태로 있다가 얼마 전, 내용을 다시 정리해보고 싶다는 생각이 들었고,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;저번 보다는 좀 더 이해도가 높아졌다고 생각하여 글을 다시 써보려고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;솔직히 완벽히 이해했다고는 말할 수 없지만, 제가 고민하며 정리한 내용을 보고 다른 분들께서도 이해가 되지 않던, 혹은 풀리지 않던 문제의 실마리가 되었으면 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;다음에 다시 클로저 예제 분석에 대한 글을 쓸 때에는 완벽히 이해한 제 모습을 기대하며, 포스팅 시작해보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;normal&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;분석&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1564230324932&quot; class=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var i;

for (i = 0; i &amp;lt; 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, 0);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;아마 클로저에 대해 찾아보신 분들은 한 번쯤은 봤을 법한 예제입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;모두가 결과물이 0, 1, 2, 3, 4가 출력되는 것이 아닌 5가 5번 출력이 된다고 알고 있지만, 막상 그 결과에 대해 쉽게 납득하기 어려운 분들도 많을 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;이해하기 쉽게 그림을 그리며 한 번 설명해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&lt;span style=&quot;color: #333333; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;1. for 루프 시 setTimeout 구문이 실행되며, setTimeout은 콜스택에 쌓인다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 0.94em;&quot;&gt;&lt;span style=&quot;color: #333333; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;※ setTimeout 내부 익명함수는 Anonymous Function의 약자인 A.F로 축약하여 사용하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 0.94em;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-1.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjkX8l/btqw56hG0Kz/Atv3KE4tZWS3QOPwsQJfw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjkX8l/btqw56hG0Kz/Atv3KE4tZWS3QOPwsQJfw1/img.png&quot; data-alt=&quot;1번 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjkX8l/btqw56hG0Kz/Atv3KE4tZWS3QOPwsQJfw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjkX8l%2Fbtqw56hG0Kz%2FAtv3KE4tZWS3QOPwsQJfw1%2Fimg.png&quot; data-filename=&quot;c-1.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;1번 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;i&gt;2. 웹 API 중 하나인 타이머가 생성되며, 익명함수(A.F)는 Web APIs로 이동합니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-2.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcRPHI/btqw3kOPyx8/0f8ibuYO5M0E4TpcKCORc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcRPHI/btqw3kOPyx8/0f8ibuYO5M0E4TpcKCORc1/img.png&quot; data-alt=&quot;2번 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcRPHI/btqw3kOPyx8/0f8ibuYO5M0E4TpcKCORc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdcRPHI%2Fbtqw3kOPyx8%2F0f8ibuYO5M0E4TpcKCORc1%2Fimg.png&quot; data-filename=&quot;c-2.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;2번 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;i&gt;3. setTimeout이 완료되고 콜스택에서 제거됩니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-3.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sDM7N/btqw3PgKWBt/KLFAoYNGrVT2SyZAospiRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sDM7N/btqw3PgKWBt/KLFAoYNGrVT2SyZAospiRk/img.png&quot; data-alt=&quot;3번 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sDM7N/btqw3PgKWBt/KLFAoYNGrVT2SyZAospiRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsDM7N%2Fbtqw3PgKWBt%2FKLFAoYNGrVT2SyZAospiRk%2Fimg.png&quot; data-filename=&quot;c-3.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;3번 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;i&gt;4. 설정한 타이머가 지난 후 익명함수(A.F)는 콜백 큐로 이동됩니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;타이머를 0으로 설정했지만, 실제로는 최소 4ms가 지난후에야 콜백 큐로 이동된다고 합니다!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-4.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tOibb/btqw7O1sZOf/UlB9LqKiZJXIEdpMk9ZJR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tOibb/btqw7O1sZOf/UlB9LqKiZJXIEdpMk9ZJR0/img.png&quot; data-alt=&quot;4번 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tOibb/btqw7O1sZOf/UlB9LqKiZJXIEdpMk9ZJR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtOibb%2Fbtqw7O1sZOf%2FUlB9LqKiZJXIEdpMk9ZJR0%2Fimg.png&quot; data-filename=&quot;c-4.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;4번 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;i&gt;5. 이 작업이 5번 반복되고, for 루프는 종료됩니다. (- 콜백 큐에는 5개의 익명함수가 차례로 쌓인 상태입니다.)&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-5.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nxgys/btqw4o4hoAE/jBKH108iZENwbLiH472oBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nxgys/btqw4o4hoAE/jBKH108iZENwbLiH472oBk/img.png&quot; data-alt=&quot;5번 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nxgys/btqw4o4hoAE/jBKH108iZENwbLiH472oBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnxgys%2Fbtqw4o4hoAE%2FjBKH108iZENwbLiH472oBk%2Fimg.png&quot; data-filename=&quot;c-5.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;5번 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;i&gt;6. 루프가 모두 종료되어 현재 콜스택이 비어있는 상태이므로, 이벤트 루프는 콜백큐의 익명함수를 하나씩 콜스택으로 올립니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-6.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I3Lbo/btqw7cBM9ND/RK5u9j7GyyK8Ai02zVjzQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I3Lbo/btqw7cBM9ND/RK5u9j7GyyK8Ai02zVjzQK/img.png&quot; data-alt=&quot;6번 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I3Lbo/btqw7cBM9ND/RK5u9j7GyyK8Ai02zVjzQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI3Lbo%2Fbtqw7cBM9ND%2FRK5u9j7GyyK8Ai02zVjzQK%2Fimg.png&quot; data-filename=&quot;c-6.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;6번 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;i&gt;7. 익명함수가 실행됩니다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;이해를 돕기 위해 선행적으로 알아야 하는 개념을 말씀드리자면,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;1. 함수는 선언될 때 스코프가 생성되며, 우리는 이것을 &lt;b&gt;렉시컬 스코핑&lt;/b&gt;이라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1564240799344&quot; class=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var name = 'Hello';

function showName() {
  // 함수는 선언될 때 스코프가 생성됩니다.
  // 따라서 console 구문에서의 name은 전역에 선언된 name(= 'Hello')를 가리킵니다.
  console.log(name);
}

function callShowName() {
  var name = 'Bye';
  // 만약 name = 'Bye'의 구문이었다면, 전역 변수 name의 값이 'Bye'로 바뀌기 때문에
  // showName 함수를 호출 했을 때, 콘솔은 'Hello'가 아닌 'Bye'를 출력하게 됩니다.
  showName();
}

callShowName(); // 'Hello' 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;위의 예제에서 'Bye'가 아닌 'Hello'가 출력되는 이유 역시 렉시컬 스코핑 때문이며, 이에 따라 함수의 &lt;b&gt;스코프 체인&lt;/b&gt; 역시 선언 시에 결정됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;2. 함수는 호출될 때, &lt;b&gt;컨텍스트&lt;/b&gt;가 생성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;함수는 호출될 때, &lt;b&gt;함수 실행 컨텍스트&lt;/b&gt;가 생성됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;이에 따라 활성 객체가 만들어지는데, 쉽게 말해 해당 컨텍스트에서 실행에 필요한 여러 정보들이 담긴 자바스크립트 객체라고 생각하시면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;크게, 변수 객체(Variable Object), 스코프 체인(Scope Chain), this의 프로퍼티들로 나뉘어 지는데 앞으로 V.O, S.C, this로 축약하여 설명 이어가도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;함수가 호출되기 전 생성되는 &lt;b&gt;전역 실행 컨텍스트&lt;/b&gt;를 먼저 살펴보자면 다음과 같이 나타낼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-7.png&quot; width=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qmGDj/btqw7Pe4scN/PUsJm1QydFGm444QRIV6uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qmGDj/btqw7Pe4scN/PUsJm1QydFGm444QRIV6uk/img.png&quot; data-alt=&quot;전역 실행 컨텍스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qmGDj/btqw7Pe4scN/PUsJm1QydFGm444QRIV6uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqmGDj%2Fbtqw7Pe4scN%2FPUsJm1QydFGm444QRIV6uk%2Fimg.png&quot; data-filename=&quot;c-7.png&quot; width=&quot;400&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전역 실행 컨텍스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;arguments는 없는 상황이고, i라는 변수가 등록되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;스코프 체인은 전역 변수 객체가 연결되어 있으며, this는 window를 가리킵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;그럼 이제 실제 익명함수가 호출되었을 때의 함수 실행 컨텍스트를 살펴볼까요?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-8.png&quot; width=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkZ06T/btqw6n4EyW2/v3i08w4ot7u4Cmt0srIvU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkZ06T/btqw6n4EyW2/v3i08w4ot7u4Cmt0srIvU0/img.png&quot; data-alt=&quot;함수 실행 컨텍스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkZ06T/btqw6n4EyW2/v3i08w4ot7u4Cmt0srIvU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkZ06T%2Fbtqw6n4EyW2%2Fv3i08w4ot7u4Cmt0srIvU0%2Fimg.png&quot; data-filename=&quot;c-8.png&quot; width=&quot;400&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;함수 실행 컨텍스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;arguments와 variable 모두 없는 상황이고 this는 여전히 window를 가리키고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;스코프 체인은 자기 자신 (= 익명 함수의 변수 객체)과 전역 변수 객체가 연결 되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;익명 함수가 실행될 때, 콘솔에 i를 출력하려 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;하지만, 자신의 변수 객체에 i라는 프로퍼티를 찾을 수 없는 상황입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;그럼 그냥 undefined를 출력할까요?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;스코프 체인으로 전역 변수 객체가 연결되어 있기 때문에, 우리는 보다 상위 스코프인 전역 스코프를 탐색할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;(우리는 이것을&amp;nbsp;&lt;b&gt;스코프 체이닝&lt;/b&gt;이라고 부릅니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;탐색 시, i를 성공적으로 찾았는데 문제는 for 루프가 모두 돌면서 i는 이미 5로 변화된 상태라는 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;따라서, 현재 콜 스택에 있는 익명함수와 콜백 큐에 대기 중인 익명함수는 유감스럽게도 모두 5로 변화된 i를 참조하고 있는 것이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;그렇기 때문에, 우리는 0, 1, 2, 3, 4가 콘솔에 출력되길 바랐지만 정작 5가 5번 출력되는 현상을 볼 수 밖에 없던 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;그림으로 간단히 나타내보자면, 아마 위와 같은 상황일 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C1xDn/btqw3knIlgg/Pr2eGwaAjBXZynj6yMvoHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C1xDn/btqw3knIlgg/Pr2eGwaAjBXZynj6yMvoHk/img.png&quot; data-alt=&quot;상황&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C1xDn/btqw3knIlgg/Pr2eGwaAjBXZynj6yMvoHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC1xDn%2Fbtqw3knIlgg%2FPr2eGwaAjBXZynj6yMvoHk%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;/&gt;&lt;/span&gt;&lt;figcaption&gt;상황&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;그렇다면, 해결책 중 하나인 IIFE를 적용하면 어떻게 될까요?&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;normal&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;IIFE로 해결하기&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1564242412884&quot; class=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var i;

for (i = 0; i &amp;lt; 5; i++) {
  (function(j) {
    setTimeout(function() {
      console.log(j);
    }, 0);
  })(i);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;함수가 선언될 때 스코프가 생성되고 스코프 체인 역시 정해진다고 말씀 드렸었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;따라서, IIFE는 자기 자신 (IIFE의 변수 객체)과 더불어 스코프 체인으로 전역 변수 객체 역시 연결되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;setTimeout 내부 익명함수는 자기 자신(익명 함수의 변수 객체)과 함께, 상위 스코프들인 IIFE와 전역 변수 객체가 연결될 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;이제 실제 루프를 돌며, IIFE가 호출되고 IIFE의 컨텍스트 역시 생성이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;아까와 다른 점은 i를 j라는 이름의 인자로 받고 있다는 점 인데, 이를 그림으로 나타내보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-10.png&quot; width=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FmQY3/btqw56hKQBz/r7VNr1Qra7kB9G9vYBkHtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FmQY3/btqw56hKQBz/r7VNr1Qra7kB9G9vYBkHtk/img.png&quot; data-alt=&quot;IIFE 실행 컨텍스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FmQY3/btqw56hKQBz/r7VNr1Qra7kB9G9vYBkHtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFmQY3%2Fbtqw56hKQBz%2Fr7VNr1Qra7kB9G9vYBkHtk%2Fimg.png&quot; data-filename=&quot;c-10.png&quot; width=&quot;400&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IIFE 실행 컨텍스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;또한, IIFE 함수가 실행되면 setTimeout 구문 역시 실행되고, 내부의 익명함수가 호출됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;함수가 호출되면, 자연스럽게 컨텍스트가 생성되며 익명함수의 컨텍스트는&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTDpqi/btqw7OUL5Ex/RenkDK1GKO6C8qDeF4xzp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTDpqi/btqw7OUL5Ex/RenkDK1GKO6C8qDeF4xzp1/img.png&quot; data-alt=&quot;익명 함수 실행 컨텍스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTDpqi/btqw7OUL5Ex/RenkDK1GKO6C8qDeF4xzp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTDpqi%2Fbtqw7OUL5Ex%2FRenkDK1GKO6C8qDeF4xzp1%2Fimg.png&quot; width=&quot;400&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;익명 함수 실행 컨텍스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;위와 같을 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;따라서, 루프가 모두 돌고 나서는 서로 다른 5개의 컨텍스트들이 생성될 것이고,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;컨텍스트 내에서, 스코프&amp;nbsp;체인을&amp;nbsp;통해&amp;nbsp;상위&amp;nbsp;스코프의&amp;nbsp;변수&amp;nbsp;객체에&amp;nbsp;접근&amp;nbsp;가능한 전체적인 모습을&amp;nbsp;나타내보면&amp;nbsp;아마&amp;nbsp;아래와&amp;nbsp;같지&amp;nbsp;않을까&amp;nbsp;생각합니다.&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-15.png&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PHUt4/btqw4oKc1s2/X1GkmMShi2FDnNnmxkbFmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PHUt4/btqw4oKc1s2/X1GkmMShi2FDnNnmxkbFmk/img.png&quot; data-alt=&quot;유기적으로 연결되어 있는 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PHUt4/btqw4oKc1s2/X1GkmMShi2FDnNnmxkbFmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPHUt4%2Fbtqw4oKc1s2%2FX1GkmMShi2FDnNnmxkbFmk%2Fimg.png&quot; data-filename=&quot;c-15.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;/&gt;&lt;/span&gt;&lt;figcaption&gt;유기적으로 연결되어 있는 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;어쨌든, 익명함수가 실행되고 콘솔에 j를 출력하고자 할 때, 아까와 마찬가지로 자신의 변수 객체에 j를 찾을 수 없는 상황입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;따라서, 스코프 체이닝으로 바로 윗 단계인 IIFE 스코프를 탐색하게 되고, 해당 변수 객체에서 j를 성공적으로 찾게 되어 체이닝은 종료됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;각 IIFE 컨텍스트 내부 변수 객체에서 j는 0, 1, 2, 3, 4의 값을 가지므로 콘솔에는 우리가 원하던 결과인 0, 1, 2, 3, 4가 출력됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;normal&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;주의&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1564247508725&quot; class=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1번
var i;

for (i = 0; i &amp;lt; 5; i++) {
  (function() {
    setTimeout(function() {
      console.log(i);
    }, 0);
  })();
}

// 2번
var i;

for (i = 0; i &amp;lt; 5; i++) {
  setTimeout((
    function(j) {
      console.log(j);
    }
  )(i), 1000);
}
  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;주의할 1번 예제를 보면, IIFE를 실행하는데 i를 넘겨주지 않고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;즉, IIFE 컨텍스트 내부 변수 객체는 arguments와 variable 모두 null이 되는 것이죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;따라서, 실제 setTimeout 내부 익명함수가 실행되어 콘솔에 i를 출력하고자 할 때,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;자신의 변수 객체에서는 i를 찾을 수 없으니 상위 스코프인 IIFE 스코프를 탐색하게 되고, 이 곳에서도 찾을 수 없으니 결국은 전역 스코프를 탐색하여 이미 5로 변해버린 i를 참조하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;그리고 2번 예제에서는, setTimeout 내부에서 IIFE를 실행하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;이 경우 함수가 즉시 실행되기 때문에, 콘솔에 원하는 결과가 출력 될 수는 있어도 설정한 timer(1000ms)는 무시됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;normal&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;정리&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;함수는 호출할 때 환경(컨텍스트)이 만들어집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;함수가 만들어질 때, 그 시점의 환경에 대한 참조를 물고 가는 것을 우리는 &lt;b&gt;클로저&lt;/b&gt;라고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;참조를 물고 가기 때문에, 이미 외부 함수의 생명 주기가 끝났더라도, 내부 함수는 그 외부 함수의 변수를 참조할 수 있게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;하나 더 간단한 예시를 들어보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1564248961945&quot; class=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var text = 'Hello, ';

function greeting() { // 외부 함수
  var name = 'Pewww';
  
  return function() { // 내부 함수
    console.log(text + name);
  }
}

var g = greeting();
g(); // 'Hello, Pewww' 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;위의 코드에서, greeting() 함수는 익명 함수를 반환하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;var g = greeting(); 구문에서 greeting() 함수는 실행된 이후, 실행 컨텍스트 스택에서 제거됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;이에 따라, 변수인 name도 같이 소멸되어 내부 함수의 console 구문에서 name에 대해 접근할 수 없어 보이는데, 실제로 g()를 실행했을 때&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;콘솔에는 정상적으로 'Hello, Pewww'가 출력됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;위에서 설명했던 내용들을 곱씹어보면, 그다지 이해하기 어렵지 않은 내용일 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;greeting() 함수 실행 컨텍스트의 활성 객체는 사라지지 않고 유효하기 때문에 (&lt;b&gt;활성 상태 유지&lt;/b&gt;), 외부함수인 greeting이 종료되더라도 내부 익명 함수에서는 name에 대한 접근이 가능하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;(아래는 이해를 돕기 위해 &lt;b&gt;[[Scopes]]&lt;/b&gt; 프로퍼티를 찍은 모습입니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;c-14.png&quot; width=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zE1nr/btqw3OPI2sA/RXU8tXOqK2OIXCRSf3zTjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zE1nr/btqw3OPI2sA/RXU8tXOqK2OIXCRSf3zTjK/img.png&quot; data-alt=&quot;[[Scopes]] 프로퍼티&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zE1nr/btqw3OPI2sA/RXU8tXOqK2OIXCRSf3zTjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzE1nr%2Fbtqw3OPI2sA%2FRXU8tXOqK2OIXCRSf3zTjK%2Fimg.png&quot; data-filename=&quot;c-14.png&quot; width=&quot;700&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[[Scopes]] 프로퍼티&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;자바스크립트에서 가비지 콜렉터(일명 G.C) 는 참조(&lt;b&gt;Reference&lt;/b&gt;)를 바탕으로 동작하는데, 이처럼 클로저에 의해 참조 되고 있으면 가비지 콜렉터는 정상적으로 메모리를 회수하지 못 하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;이 점 때문에, 클로저를 사용할 경우 메모리 누수에 대해 조심해야 한다고 얘기하는 것 이며,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;사용 후 참조를 없애주는 것이 중요합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;실제 브라우저 상에서 가비지 콜렉터가 동작하는 모습을 간접적으로(?) 확인할 수 있는데, 이 부분에 대해서는 추후 포스팅 해 볼 예정입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;normal&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;마치며&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;내용을 완벽히 이해하려면, 더욱 폭넓은 지식이 필요하다는 것을 깨달았습니다.&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;최대한 자세히 내용을 담아보려 했는데, 그러지 못 한 것 같아 아쉬움이 많이 남습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;Ps. &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;저 역시 공부하는 입장이기 때문에, 오해의 소지나 잘못된 내용이 있을 수도 있습니다...&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;그런 부분들이 존재 할 경우 댓글로 정정해주시면 정말 감사하겠습니다!&amp;nbsp; &lt;/span&gt;&lt;/p&gt;</description>
      <category>Javascript</category>
      <category>javascript closure</category>
      <category>스코프</category>
      <category>자바스크립트 클로저</category>
      <category>컨텍스트</category>
      <category>클로저</category>
      <category>클로저 예제</category>
      <author>Pewww</author>
      <guid isPermaLink="true">https://pewww.tistory.com/21</guid>
      <comments>https://pewww.tistory.com/21#entry21comment</comments>
      <pubDate>Sun, 28 Jul 2019 03:59:34 +0900</pubDate>
    </item>
  </channel>
</rss>