<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩 헬스장</title>
    <link>https://ji-musclecode.tistory.com/</link>
    <description>공부 기록 및 일상 글 작성을 위한 블로그 입니다~</description>
    <language>ko</language>
    <pubDate>Fri, 26 Jun 2026 13:07:37 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>김관장</managingEditor>
    <image>
      <title>코딩 헬스장</title>
      <url>https://tistory1.daumcdn.net/tistory/5262185/attach/5f4d06cc5bb94f24a12c7f770bc15278</url>
      <link>https://ji-musclecode.tistory.com</link>
    </image>
    <item>
      <title>매개변수(Parameter)와 인자(Argument)의 차이점</title>
      <link>https://ji-musclecode.tistory.com/78</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ 매개변수와 인자는 프로그래밍에서 자주 쓰이는 용어인데, 간단한 용어이지만 서로 헷갈릴 수 있는 개념이기 때문에 짧게 정리해봅니다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p id=&quot;️-nextconfigjs&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bD0ESy/btrSM4aL1IH/TiwRtExyp4rj9UumG7D4Wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bD0ESy/btrSM4aL1IH/TiwRtExyp4rj9UumG7D4Wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bD0ESy/btrSM4aL1IH/TiwRtExyp4rj9UumG7D4Wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbD0ESy%2FbtrSM4aL1IH%2FTiwRtExyp4rj9UumG7D4Wk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;946&quot; height=&quot;244&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;244&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매개변수 (Parameter) : 함수를 정의할 때 사용되는 변수 (&lt;b&gt;variable)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;인자 (Argument) : 실제로 함수를 호출할 때 넘기는 변수값 (&lt;b&gt;value)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&amp;nbsp;참고한&lt;span&gt;&amp;nbsp;&lt;/span&gt;글&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670134816528&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;매개변수(Parameter)와 인자(Argument)의 차이점은 무엇일까?&quot; data-og-description=&quot;매개변수와 인자는 프로그래밍에서 자주 사용되는 용어입니다. 영어로는 Parameter(매개변수), Argument(인수, 인자)로 정의되고 쓰이는데요. 프로그래밍을 할 때 자주 쓰이는 용어인 만큼 명확하게 &quot; data-og-host=&quot;7942yongdae.tistory.com&quot; data-og-source-url=&quot;https://7942yongdae.tistory.com/155&quot; data-og-url=&quot;https://7942yongdae.tistory.com/155&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bQa83a/hyQMDTSmbH/uk91LJJC93ujfdBvaitKsk/img.png?width=540&amp;amp;height=540&amp;amp;face=0_0_540_540,https://scrap.kakaocdn.net/dn/cuSleY/hyQMx0qFdU/dZXFc3tC3SvSLTOsKbb1z1/img.png?width=540&amp;amp;height=540&amp;amp;face=0_0_540_540,https://scrap.kakaocdn.net/dn/fomlA/hyQNR36uyM/rXNNixFRebEWtGCRP3CUbK/img.png?width=946&amp;amp;height=244&amp;amp;face=0_0_946_244&quot;&gt;&lt;a href=&quot;https://7942yongdae.tistory.com/155&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://7942yongdae.tistory.com/155&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bQa83a/hyQMDTSmbH/uk91LJJC93ujfdBvaitKsk/img.png?width=540&amp;amp;height=540&amp;amp;face=0_0_540_540,https://scrap.kakaocdn.net/dn/cuSleY/hyQMx0qFdU/dZXFc3tC3SvSLTOsKbb1z1/img.png?width=540&amp;amp;height=540&amp;amp;face=0_0_540_540,https://scrap.kakaocdn.net/dn/fomlA/hyQNR36uyM/rXNNixFRebEWtGCRP3CUbK/img.png?width=946&amp;amp;height=244&amp;amp;face=0_0_946_244');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;매개변수(Parameter)와 인자(Argument)의 차이점은 무엇일까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;매개변수와 인자는 프로그래밍에서 자주 사용되는 용어입니다. 영어로는 Parameter(매개변수), Argument(인수, 인자)로 정의되고 쓰이는데요. 프로그래밍을 할 때 자주 쓰이는 용어인 만큼 명확하게&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;7942yongdae.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>개인수련실</category>
      <category>매겨변수와 인자</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/78</guid>
      <comments>https://ji-musclecode.tistory.com/78#entry78comment</comments>
      <pubDate>Sun, 4 Dec 2022 15:20:22 +0900</pubDate>
    </item>
    <item>
      <title>JS - 1급 객체 (First Class Object)</title>
      <link>https://ji-musclecode.tistory.com/77</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;✅ JavaScript의 함수는 1급 객체(First Class Object)입니다. 그렇다면 1급 객체란 무엇인지, 왜 중요한지에 대해 살펴보겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  1급 시민(First Class Citizen)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;1급 객체란, 1급 시민의 조건을 충족하는 객체&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;입니다. 따라서 1급 객체를 알아보기 전 1급 시민의 개념부터 알아 볼 필요가 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1급 시민이란, 함수를 변수처럼 사용할 수 있다. 라는 의미로 해석할 수 있으며, 조건은 아래와 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8; color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;u&gt;&lt;b&gt;* 단, 함수와 변수를 동일한 개념으로 생각하면 안됩니다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;변수에 담을 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;함수의 인자(Parameter)로 전달할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;함수의 반환 값으로 전달할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1669818418744&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 예시

let numValue = 1; // [1] 충족

function addNum(param){ // [2] 충족
	let addValue = param + 1;
    return addValue; // [3] 충족
}

console.log(addNum(numValue)); // [2] 충족&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위 예시처럼 대부분의 프로그래밍 언어에서는 숫자/문자형은 1급 시민의 조건을 충족합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;JavaScript에서는 기본 자료형( Number, String, Boolean, Null, Undefined, Symbol, Object-(Function, Array) )이 1급 시민의 조건을 충족합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  1급 객체(First Class Object)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1급 객체는 1급 시민의 조건을 충족하는 객체를 뜻합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;JavaScript에서는 객체는 1급 시민의 조건을 모두 충족하기 때문에, 1급 객체입니다.&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1669818943971&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let user = { id: '1급 객체' }  // [1. 변수에 담을 수 있습니다.]

function setUser (param) {  // [2. 함수의 인자로 전달할 수 있습니다.]
    let tempUser = param;
    tempUser.pwd = 'q1w2e3r4';
    return tempUser;  // [3. 함수의 반환 값으로 전달할 수 있습니다.]
}

console.log(setUser(user)) // { id: '1급 객체', pwd: 'q1w2e3r4' }&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;JavaScript에서 함수는 prototype을 통해 객체를 상속받아 사용합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;따라서 &lt;i&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;함수도 객체로 취급하고 있기 때문에 함수도 1급 객체(함수)라고 칭합니다.&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;단 1급 함수는 1급 시민의 조건과 더불어 추가적인 조건들이 존재합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;런타임 시 생성이 가능해야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;익명 생성이 가능해야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1670077896961&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// [1. 변수에 담을 수 있습니다.]
let add = function addFn(a,b) { 
	return a + b;
}

// [익명 생성이 가능해야합니다.]
let add2 = function(a,b) {
	return a + b;
}

// [2. 함수의 인자로 전달할 수 있습니다.]
let add3 = function(func) {
  return func(); // [3. 함수의 반환 값으로 전달할 수 있습니다.]
}

console.log(add3(()=&amp;gt;add2(10,20))); // 30 [2. 함수의 인자로 전달할 수 있습니다.]&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  함수가 1급 객체인 것이 중요한 이유&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;고차 함수를 만들 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;함수를 인자 또는 매개변수로 받거나 함수를 리턴하는 함수&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;를 말합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;JavaScript의 &lt;span style=&quot;background-color: #ffffff;&quot;&gt;Array.prototype(배열)에서 자주 사용하는&lt;br /&gt;&lt;u&gt;.forEach(), .map(), .find(), .findIndex(), .filter(), .reduce(), .sort(), .some(), .every()&lt;/u&gt;&lt;br /&gt;가 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;콜백을 사용할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;함수를 다른 함수의 인자로서 사용하는 것&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;을 말합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;콜백이 유용한 이유는, 콜백 함수만 바꿔주면 하나의 함수를 여러 가지로 응용할 수 있기 때문입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1670086347002&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function add2(a, b) {
	return a + b;
}

function add3(a, b, c){
	return a + b + c;
}

function addNumber(addFn) {
	return &quot;합계 : &quot; + addFn
}

console.log(addNumber(add2(1, 2))); // 합계 : 3
console.log(addNumber(add3(10, 20, 30))); // 합계 : 60

/* addNumber함수는 고차함수, 인자로 전달된 add2, add3함수는 콜백함수 !! */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt; &amp;nbsp; 정리&amp;nbsp;!&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;JavaScript에서는 기본 자료형은 1급 시민의 조건을 충족합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;[ 1급 시민의 조건 ]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;변수에 담을 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;함수의 인자(Parameter)로 전달할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;함수의 반환 값으로 전달할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;1급 객체란 1급 시민의 조건을 충족하는 객체입니다.&lt;br /&gt;&lt;br /&gt;[ 1급 함수가 중요한 이유 ]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;고차 함수를 만들 수 있습니다. (함수를 인자 또는 매개변수로 받거나 함수를 리턴하는 함수)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;콜백을 사용할 수 있습니다. (함수를 다른 함수의 인자로서 사용하는 것)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&amp;nbsp;참고한&lt;span&gt;&amp;nbsp;&lt;/span&gt;글&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670087220862&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[Javascript] 1급 객체 - doodoo's coding&quot; data-og-description=&quot;I really love solving computer problem. I wanna grow today more than yesterday.&quot; data-og-host=&quot;0xd00d00.github.io&quot; data-og-source-url=&quot;https://0xd00d00.github.io/2021/11/27/js_first_object.html&quot; data-og-url=&quot;https://0xd00d00.github.io/2021/11/27/js_first_object.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://0xd00d00.github.io/2021/11/27/js_first_object.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://0xd00d00.github.io/2021/11/27/js_first_object.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; data-ke-size=&quot;size16&quot;&gt;[Javascript] 1급 객체 - doodoo's coding&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I really love solving computer problem. I wanna grow today more than yesterday.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;0xd00d00.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>JavaScript</category>
      <category>1급 객체</category>
      <category>1급 시민</category>
      <category>1급 함수</category>
      <category>javascript</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/77</guid>
      <comments>https://ji-musclecode.tistory.com/77#entry77comment</comments>
      <pubDate>Sun, 4 Dec 2022 14:59:39 +0900</pubDate>
    </item>
    <item>
      <title>JS - 동작원리와 비동기처리</title>
      <link>https://ji-musclecode.tistory.com/76</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;✅ 헷갈릴 수 있는 용어들에 대한 간략한 설명입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;블로킹은 느린 동작이 스택에 남아있는 것을 의미합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;호출 스케줄링(scheduling a call)은 일정 시간이 지난 후에 원하는 함수를 예약 실행(호출)할 수 있게 하는 것을 의미합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;매크로태스크큐와 마이크로태스크큐는 서로 다른 별로의 큐 입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;매크로태스크 큐(MacroTask Queue) : 기존의 태스크 큐&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;마이크로태스크(MicroTask Queue 혹은 Job Queue) : ES6에서 Promise와 함께 소개된 개념으로 매크로태스크 큐보다 처리 우선순위가 높습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  자바스크립트 엔진&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NEX3g/btrQPMEqNO4/yMftoJ3mivitpSXmZPKgo0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NEX3g/btrQPMEqNO4/yMftoJ3mivitpSXmZPKgo0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NEX3g/btrQPMEqNO4/yMftoJ3mivitpSXmZPKgo0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNEX3g%2FbtrQPMEqNO4%2FyMftoJ3mivitpSXmZPKgo0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;646&quot; height=&quot;311&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;자바스크립트 엔진은 자바스크립트 코드를 해석하고 실행하는 인터프리터입니다. (크롬과 Node.js에서 사용되는 V8엔진이 대표적)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Memory Heap&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/i&gt; &lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;메모리 할당이 일어나는 곳, 콜 스택의 요소인 실행 컨텍스트는 힙에 저장된 객체를 참조합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;객체는 원시값과 달리 크기가 정해져 있지 않기 때문에 할당해야 할 메모리 공간의 크기는 동적 할당 됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;i&gt;&lt;b&gt;Call Stack&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;함수를 호출하면 함수 실행 컨텍스트가 순차적으로 콜 스택에 푸시되어 동기적으로 실행됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;자바스크립트는 싱글스레드 언어입니다. &lt;b&gt;이는 하나의 싱글 호출 스택(Call Stack)만 가지고 있다는 뜻이며, 자바스크립트의 엔진은 한 번에 하나의 task만 실행할 수 있는 동기 프로그래밍 언어입니다.&amp;nbsp;&lt;/b&gt;하나의 작업이 끝나면 pop하고 바로 아래의 함수나 코드를 실행합니다. 작업을 차례대로 실행하므로 하나의 작업이 끝날 때까지 또 다른 작업을 실행하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;아래와 같은 코드를 실행하면&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668060545366&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function first(){
    second();
    console.log(&quot;첫번째&quot;);
}
function second(){
    third();
    console.log(&quot;두번째&quot;);
}
function third(){
    console.log(&quot;세번째&quot;);
}
first(); // 세번째 두번째 첫번째&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;먼저 first 함수가 호출(push)되고, 그안의 second함수가 호출되고, 마지막으로 그 안의 third 함수가 호출됩니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mlf7W/btrQOPhltca/QxacouYLByyk1KFkD5wwc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mlf7W/btrQOPhltca/QxacouYLByyk1KFkD5wwc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mlf7W/btrQOPhltca/QxacouYLByyk1KFkD5wwc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMlf7W%2FbtrQOPhltca%2FQxacouYLByyk1KFkD5wwc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;326&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;main() 함수는 처음 실행시 전역 컨텍스트(함수가 호출 되었을때 생성되는 환경)입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;함수의 실행이 완료되면 콜 스택에서 지워집니다. third, second, first, main 순으로 pop되기 때문에 &quot;세번째, 두번째, 첫번째&quot; 순으로 콘솔에 찍히며 최종적으로 호출 스택이 지워이 비워집니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  자바스크립트 런타임&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nUNRC/btrQRmSUtou/WOCppRzikEeJNdoX4KJp20/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nUNRC/btrQRmSUtou/WOCppRzikEeJNdoX4KJp20/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nUNRC/btrQRmSUtou/WOCppRzikEeJNdoX4KJp20/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnUNRC%2FbtrQRmSUtou%2FWOCppRzikEeJNdoX4KJp20%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;801&quot; height=&quot;447&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;자바스크립트 런타임(환경)이란 자바스크립트가 구동되는 환경을 말합니다. 자바스크립트 런타임의 종류로는 웹 브라우저(크롬, 파이어폭스 등..)와 Node.js라는 프로그램이 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;자바스크립트 런타임은 자바스크립트 엔진(&lt;span style=&quot;background-color: #ffffff;&quot;&gt;Memory heap, Call stack), Web apis, Task queue, Event loop를 갖습니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Web API &lt;span style=&quot;background-color: #ffffff;&quot;&gt;(&lt;a style=&quot;background-color: #ffffff;&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API&lt;/a&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/i&gt; &lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;Web API는 브라우저에서 제공되는 API입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;자바스크립트 엔진에서 정의되지 않았던 setTimeout, HTTP 요청 메소드(Ajax), DOM 이벤트 등의 메소드를 지원합니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;i&gt;&lt;b&gt;Task Queue&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;setTimeout, setInterval과 같은 비동기 함수들의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;태스크 큐에 일시적으로 보관된 함수들은 비동기 처리 방식으로 동작합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;이벤트 루프가 정한 순서대로 줄을 서 있으므로 콜백 큐(Callback Queue)라고도 합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;&lt;i&gt;Event Loop&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 그리고 태스크 큐에 대기 중인 함수가 있는지 반복해서 확인합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;만약 콜 스택이 비어있고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적으로 태스크 큐에 대기 중인 함수를 콜 스택으로 이동시킨다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;큐(Queue) - FIFO (First In First Out) 구조 입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  자바스크립트 비동기 처리의 필요성&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1668068438731&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 비동기 처리 전
const sleep = (func, delay) =&amp;gt; {
  const delayUntil = Date.now() + delay;
  while (Date.now() &amp;lt; delayUntil);
  func();
};

const str = () =&amp;gt; console.log(&quot;시작&quot;);
const end = () =&amp;gt; console.log(&quot;끝&quot;);

sleep(str, 5 * 1000);
end();

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

// 비동기 처리 후 : setTimeout
const str = () =&amp;gt; console.log('시작');
const end = () =&amp;gt; console.log('끝');

setTimeout(str, 5 * 1000);
end();&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;극단적인 예로 위 비동기 처리 전 스크립트를 실행하면 5초 뒤에 &quot;시작 끝&quot;가 콘솔로 찍히는 것을 확인할 수 있습니다. 이런 로직들은 사용자들이 사이트가 느리다고 생각하는 주요 원인이 될 것입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;비동기 처리 후 스크립트를 실행하면 콘솔에 &quot;끝&quot;가 찍히고 몇초 뒤에 &quot;시작&quot;이 콘솔로 찍힙니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;이처럼 오래 걸리는 태스크를 처리할 때 발생하는 &lt;i&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;블로킹(느린 동작이 스택에 남아있는 것)&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;을 막고, 싱글스레드 언어인 자바스크립트의 동기적인 실행 컨텍스트 스택을 효율적으로 스케줄링하기 위해 비동기 처리를 사용합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;setTimeout, setInterval, HTTP request, DOM Event 모두 비동기 처리 방식으로 동작합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;즉, API를 통해 Data를 받아오는 과정, Data를 서버에 업데이트하는 과정, HTML요소로 만든 애니메이션 효과 등은 모두 비동기적으로 처리가 됩니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  자바스크립트 비동기 처리과정&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LlgGu/btrQVaD0UIk/K2nkaKJyhS55icCYAovUy1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LlgGu/btrQVaD0UIk/K2nkaKJyhS55icCYAovUy1/img.gif&quot; data-alt=&quot;자바스크립트의 비동기 처리 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LlgGu/btrQVaD0UIk/K2nkaKJyhS55icCYAovUy1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/LlgGu/btrQVaD0UIk/K2nkaKJyhS55icCYAovUy1/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;720&quot; height=&quot;405&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;자바스크립트의 비동기 처리 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668087378889&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const middleFn = () =&amp;gt; console.log('중간');

console.log('시작');

setTimeout(middleFn, 5 * 1000);

console.log('끝');

// 시작 끝 중간 순으로 콘솔에 찍힘.&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;더 자세하게 위 코드를 통해서 어떻게 비동기가 처리되는지 알아보겠습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;(이미지가 많아 접은 글로 작성하였습니다. 아래 더보기를 클릭해주세요.)&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;1. 먼저 전역 컨텍스트 main() 함수가 콜 스택에 쌓이고 그 다음으로 console.log('시작')이 콜 스택에 쌓입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;u&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;현재 &lt;/span&gt;실행 컨텍스트 : log(&quot;시작&quot;)&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m4Gaz/btrQSZqnNyP/kNUsvdjghbTgRXcBazGWik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m4Gaz/btrQSZqnNyP/kNUsvdjghbTgRXcBazGWik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m4Gaz/btrQSZqnNyP/kNUsvdjghbTgRXcBazGWik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm4Gaz%2FbtrQSZqnNyP%2FkNUsvdjghbTgRXcBazGWik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;562&quot; height=&quot;357&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;2. &quot;시작&quot;이 콘솔에 찍히고 종료되고 콜 스택에서 pop됩니다. 그리고 다음으로 setTimeout 함수가 실행되면서 콜 스택에 쌓입니다&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;u&gt;현재 실행 컨텍스트 : setTimeout()&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GykLO/btrQVZ9VtHR/49ty4sd5TlRC2d5NI0mkb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GykLO/btrQVZ9VtHR/49ty4sd5TlRC2d5NI0mkb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GykLO/btrQVZ9VtHR/49ty4sd5TlRC2d5NI0mkb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGykLO%2FbtrQVZ9VtHR%2F49ty4sd5TlRC2d5NI0mkb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;356&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;3. setTimeout()함수가 실행되면 해당 함수는 자바스크립트 엔진이 처리하지 않고 Web API가 처리하므로 콜백 함수를 전달하고 setTimeout 작업을 요청합니다(&lt;span style=&quot;background-color: #fafafa;&quot;&gt;콜백함수의 호출 스케줄링)&lt;/span&gt;. 그리고 종료되어 콜 스택에서 pop 합니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;* 호출&amp;nbsp;스케줄링(scheduling&amp;nbsp;a&amp;nbsp;call)이란?&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;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;이때 호출 스케줄링, 즉 타이머 설정과 타이머가 만료되면 콜백 함수를 태스크 큐에 푸시하는 것은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;i&gt;브라우저의 역할&lt;/i&gt;&lt;/b&gt;&lt;/span&gt; 입니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;u&gt;현재 실행 컨텍스트 : setTimeout()&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zjfUr/btrQVrMmLI7/fJlZksQKwtBabI7nOwcNPk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zjfUr/btrQVrMmLI7/fJlZksQKwtBabI7nOwcNPk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zjfUr/btrQVrMmLI7/fJlZksQKwtBabI7nOwcNPk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzjfUr%2FbtrQVrMmLI7%2FfJlZksQKwtBabI7nOwcNPk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;561&quot; height=&quot;355&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S5VZw/btrQUa5xWtG/2LZ1xN1MnTbsH4tKhEphpk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S5VZw/btrQUa5xWtG/2LZ1xN1MnTbsH4tKhEphpk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S5VZw/btrQUa5xWtG/2LZ1xN1MnTbsH4tKhEphpk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS5VZw%2FbtrQUa5xWtG%2F2LZ1xN1MnTbsH4tKhEphpk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;355&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;4. 다음으로 &lt;span style=&quot;background-color: #fafafa;&quot;&gt;&amp;nbsp;console.log('끝')이 콜 스택에 쌓입니다.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;⭐&amp;nbsp; 브라우저에서 수행하는 setTimeout 작업과 자바스크립트 엔진이 수행하는 log(&quot;끝&quot;)이 병렬로 처리됩니다.&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;( ) &lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;i&gt;브라우저에서 수행되는 작업&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;브라우저는 타이머(setTimeout에서 설정한)를 설정하고 타이머의 만료를 기다립니다. 이후 타이머가 만료되면 콜백 함수&amp;nbsp; middleFn이 태스크 큐에 푸시됩니다. 그리고 콜 스택이 빈 상태가 될 때까지 대기하다가 호출됩니다.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;( )&lt;i&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; 자바스크립트 엔진&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;i&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;에서 수행되는 작업&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;console.log(&quot;끝&quot;)이 호출되어 실행 컨텍스트가 생성되고 콜 스택에 푸시되어 현재 실행 중인 컨텍스트가 됩니다. 이후 종료되면 콜 스택에서 pop됩니다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;현재 실행 컨텍스트 : log('끝')&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tQSUQ/btrQV0OwiUS/lEjQUUQrgMgV4ytlYa19qk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tQSUQ/btrQV0OwiUS/lEjQUUQrgMgV4ytlYa19qk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tQSUQ/btrQV0OwiUS/lEjQUUQrgMgV4ytlYa19qk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtQSUQ%2FbtrQV0OwiUS%2FlEjQUUQrgMgV4ytlYa19qk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;561&quot; height=&quot;355&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;5. 그리고 마지막으로 남아있던 전역 컨텍스트 main()이 종료되고 콜 스택에서 pop됩니다. 따라서 현재 콜 스택에는 아무런 실행 컨텍도 남아있지 않게 됩니다.그리고 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;setTimeout에서 설정한 지연 시간에 따라 4 ~ 5번 과정 진행 중 혹은 진행 완료 후에 콜백 함수가 태스크 큐에 푸시되어 대기 중 입니다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;(위 예시에서는 대기 시간을 5초 설정했기때문에 main()까지 pop된 상태에서 콜백함수가 태스크 큐에 푸시되었을 것 입니다.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;&lt;u&gt;현재 실행 컨텍스트 : 없음&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKOMRt/btrQVzp0N3b/OP79P3wj7eBxG1eRarTt5k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKOMRt/btrQVzp0N3b/OP79P3wj7eBxG1eRarTt5k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKOMRt/btrQVzp0N3b/OP79P3wj7eBxG1eRarTt5k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKOMRt%2FbtrQVzp0N3b%2FOP79P3wj7eBxG1eRarTt5k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;561&quot; height=&quot;355&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;6. 이벤트 루프에 의해 콜 스택이 비어있음이 감지되고 태스트 큐에서 대기 중인 콜백함수 middleFn이 이벤트 루프에 의해 콜 스택에 푸시됩니다. 즉 콜백 함수 middleFn의 실행 컨텍스트가 생성되고 콜 스택에 푸시되어 현재 실행 중인 컨텍스트가 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;u&gt;현재 실행 컨텍스트 : setTimeout의 콜백함수인 middleFn()&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bARYY2/btrQTEGevvA/YxhI5llUNhMgiXHoHtWJZ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bARYY2/btrQTEGevvA/YxhI5llUNhMgiXHoHtWJZ0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bARYY2/btrQTEGevvA/YxhI5llUNhMgiXHoHtWJZ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbARYY2%2FbtrQTEGevvA%2FYxhI5llUNhMgiXHoHtWJZ0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;561&quot; height=&quot;355&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;7. 이후 콜백함수가 종료되어 콜 스택에서 pop되며 위 코드의 처리 과정이 종료됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/shEif/btrQTVHBPUD/vKKskBCMQVt0SPQlnuX9jK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/shEif/btrQTVHBPUD/vKKskBCMQVt0SPQlnuX9jK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/shEif/btrQTVHBPUD/vKKskBCMQVt0SPQlnuX9jK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FshEif%2FbtrQTVHBPUD%2FvKKskBCMQVt0SPQlnuX9jK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;356&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  자바스크립트 비동기 처리과정 - Promise 와 이벤트 루프&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위에서 정리한 내용을 바탕으로 setTimeout, setInterval과 같은&amp;nbsp;비동기 함수들의 콜백 함수 또는 이벤트 핸들러는 태스크 큐에 푸시해두었다가 콜 스택이 비었을 때 이벤트 루프에 의해서 콜 스택에 푸시되어 실행된다는 것을 알았습니다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그렇다면 ES6에서 비동기 처리를 위해 추가된 Promise는 어떻게 처리가 확인해보갰습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668091064628&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve()
  .then(function() {
    console.log('promise1');
  })
  .then(function() {
    console.log('promise2');
  });

console.log('script end');

/* 콘솔에 찍히는 순서
script start
script end
promise1
promise2
setTimeout
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;setTimeout의 대기시간을 0으로 주었음에도 왜 Promise 보다 느리게 호출이 된 걸까? 라는 의문이 생깁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;⚙️ ES6 MicroTask Queue&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;MicroTask Queue(혹은 Job Queue)는 ES6에서 Promise와 함께 소개된 개념으로 마이크로태스크 큐를 사용하는 대표적인 함수가 Promise 입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;마이크로태스크 큐와 기존의 태스크 큐(매크로태스크 큐(MacroTask Queue))는 서로 다른 별도의 큐 입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;⭐ &lt;/span&gt;&lt;/b&gt;&lt;/i&gt;마이크로태스크 큐는 기존의 태스크 큐보다 처리 우선순위가 높습니다. 따라서 이벤트 루프는 콜 스택이 비었을 때 먼저 마이크로 태스크 큐에 대기하고 있던 함수를 가져와서 실행하고, 없다면 기존의 태스크 큐에서 대기하고 있던 함수를 가져와서 실행합니다.&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;⚙️ MacroTask Queue vs MicroTask Queue&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;Macrotask queue&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #121212;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이벤트 루프는 매크로 태스크 큐에 있는 것을 실행시키기 시작할 때 있는 매크로 태스크만 실행시킵니다.&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;&lt;i&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;매크로 태스크가 추가한 매크로 태스크는 다음 이벤트 루프가 실행될 때까지 실행되지 않습니다.&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;HTML 파싱, DOM 생성, 메인 스레드를 구성하는 JS Code, 페이지 로드나 네트워크 이벤트, 타이머와 같은 여러 이벤트를 포함합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;지연 시간이 0초인 setTimeout()을 통해 새로운 매크로태스크를 스케줄링 할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; background-color: #ffffff;&quot;&gt;Microtask queue&lt;br /&gt;&amp;nbsp;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;마이크로태스크들은 실행하면서 새로운 마이크로 태스크를 큐에 추가할 수도 있습니다.&lt;i&gt; &lt;u&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;새롭게 추가된 마이크로 태스크도 큐가 빌 때까지 계속해서 실행됩니다.&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;Promise의 후속 처리 메서드의 콜백 함수를 처리합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;다른 이벤트 핸들링, 렌더링, 매크로태스크가 실행되기 전에 완료됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;마이크로태스크는 바로 다음 마이크로태스크를 실행하기때문에 그 사이에 UI 혹은 네트워크 변화가 없습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;브라우저가 리렌더링 되기 전에 실행되기때문에 마이크로태스크 큐의 작업이 늦게 처리되면 브라우저의 UI 렌더링이 지연 될 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;* Macrotask queue를 이용하는 함수&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;: setTimeout(), setInterval(), setImmediate(), requestAnimationFrame, I/O, UI 렌더링 등등..&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;* Microtask queue를 이용하는 함수&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;process.nextTick(), Promise, queueMicrotask 등등..&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;495&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dp9nsa/btrQWmcUgrs/90IIwODAQFd6jdKVRDsykK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dp9nsa/btrQWmcUgrs/90IIwODAQFd6jdKVRDsykK/img.gif&quot; data-alt=&quot;마이크로태스크 큐와 매크로태스크 큐의 처리 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dp9nsa/btrQWmcUgrs/90IIwODAQFd6jdKVRDsykK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/dp9nsa/btrQWmcUgrs/90IIwODAQFd6jdKVRDsykK/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;880&quot; height=&quot;495&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;495&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마이크로태스크 큐와 매크로태스크 큐의 처리 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&amp;nbsp;참고한&lt;span&gt;&amp;nbsp;&lt;/span&gt;글&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668093211772&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;setTimeout(foo, 0)에서 foo는 정말 0ms 후에 실행될까?&quot; data-og-description=&quot;자바스크립트의 비동기 처리와 이벤트루프, 마이크로태스크 큐에 대해 설명합니다.&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@edie_ko/javascript-eventloop#1-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EA%B0%80-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC%EB%A5%BC-%ED%95%98%EB%8A%94-%EB%B0%A9%EC%8B%9D&quot; data-og-url=&quot;https://velog.io/@edie_ko/javascript-eventloop&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tg9nc/hyQwADbTfW/aIbjl2aCkZApiEeRWFihqk/img.png?width=1638&amp;amp;height=902&amp;amp;face=0_0_1638_902,https://scrap.kakaocdn.net/dn/M5PEd/hyQwIVwcRB/ZXUqOyAvI3BXOWquCPFrXK/img.png?width=1638&amp;amp;height=902&amp;amp;face=0_0_1638_902,https://scrap.kakaocdn.net/dn/5tWO0/hyQwElhgQf/xKzDOvgFwS4xG4aHn1vKQK/img.jpg?width=1080&amp;amp;height=1167&amp;amp;face=0_0_1080_1167&quot;&gt;&lt;a href=&quot;https://velog.io/@edie_ko/javascript-eventloop#1-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EA%B0%80-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC%EB%A5%BC-%ED%95%98%EB%8A%94-%EB%B0%A9%EC%8B%9D&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@edie_ko/javascript-eventloop#1-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EA%B0%80-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC%EB%A5%BC-%ED%95%98%EB%8A%94-%EB%B0%A9%EC%8B%9D&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tg9nc/hyQwADbTfW/aIbjl2aCkZApiEeRWFihqk/img.png?width=1638&amp;amp;height=902&amp;amp;face=0_0_1638_902,https://scrap.kakaocdn.net/dn/M5PEd/hyQwIVwcRB/ZXUqOyAvI3BXOWquCPFrXK/img.png?width=1638&amp;amp;height=902&amp;amp;face=0_0_1638_902,https://scrap.kakaocdn.net/dn/5tWO0/hyQwElhgQf/xKzDOvgFwS4xG4aHn1vKQK/img.jpg?width=1080&amp;amp;height=1167&amp;amp;face=0_0_1080_1167');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;setTimeout(foo, 0)에서 foo는 정말 0ms 후에 실행될까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트의 비동기 처리와 이벤트루프, 마이크로태스크 큐에 대해 설명합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1668093217507&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[JS] Javascript 동작 원리와 비동기처리&quot; data-og-description=&quot;자바스크립트는 싱글스레드이다. 어떻게 자바스크립트는 싱글스레드이면서 비동기인 것일까? 자바스크립트가 어떻게 동작하는지 내부 원리에 대해 알아보자.   Contents 자바스크립트 엔진 자&quot; data-og-host=&quot;ingg.dev&quot; data-og-source-url=&quot;https://ingg.dev/js-work/#async&quot; data-og-url=&quot;https://ingg.dev/js-work/#async&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/SFAtr/hyQxFizqPN/zDvTPj3FhlVTNN2x5LJsk0/img.png?width=590&amp;amp;height=326&amp;amp;face=0_0_590_326,https://scrap.kakaocdn.net/dn/bpBcDu/hyQxDrwm1M/3bMAnJYvPsPUwhhFInWjNk/img.png?width=590&amp;amp;height=284&amp;amp;face=0_0_590_284&quot;&gt;&lt;a href=&quot;https://ingg.dev/js-work/#async&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ingg.dev/js-work/#async&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/SFAtr/hyQxFizqPN/zDvTPj3FhlVTNN2x5LJsk0/img.png?width=590&amp;amp;height=326&amp;amp;face=0_0_590_326,https://scrap.kakaocdn.net/dn/bpBcDu/hyQxDrwm1M/3bMAnJYvPsPUwhhFInWjNk/img.png?width=590&amp;amp;height=284&amp;amp;face=0_0_590_284');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[JS] Javascript 동작 원리와 비동기처리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트는 싱글스레드이다. 어떻게 자바스크립트는 싱글스레드이면서 비동기인 것일까? 자바스크립트가 어떻게 동작하는지 내부 원리에 대해 알아보자.   Contents 자바스크립트 엔진 자&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ingg.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1668093220948&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;⭐️  JavaScript Visualized: Promises &amp;amp; Async/Await&quot; data-og-description=&quot;Ever had to deal with JS code that just... didn't run the way you expected it to? Maybe it seemed lik...&quot; data-og-host=&quot;dev.to&quot; data-og-source-url=&quot;https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot; data-og-url=&quot;https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bs1VTv/hyQwJNFIK1/Q0S23rqfJ7xQY44ZhCQzl0/img.png?width=1000&amp;amp;height=500&amp;amp;face=0_0_1000_500,https://scrap.kakaocdn.net/dn/USDjA/hyQwBvkkcP/aXRv2qkNOXskiv7osIHaF0/img.png?width=880&amp;amp;height=495&amp;amp;face=0_0_880_495,https://scrap.kakaocdn.net/dn/E4dLM/hyQxNVcFYA/Zh0o2riK2DmKdC0Eu4z5F0/img.png?width=880&amp;amp;height=491&amp;amp;face=0_0_880_491&quot;&gt;&lt;a href=&quot;https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bs1VTv/hyQwJNFIK1/Q0S23rqfJ7xQY44ZhCQzl0/img.png?width=1000&amp;amp;height=500&amp;amp;face=0_0_1000_500,https://scrap.kakaocdn.net/dn/USDjA/hyQwBvkkcP/aXRv2qkNOXskiv7osIHaF0/img.png?width=880&amp;amp;height=495&amp;amp;face=0_0_880_495,https://scrap.kakaocdn.net/dn/E4dLM/hyQxNVcFYA/Zh0o2riK2DmKdC0Eu4z5F0/img.png?width=880&amp;amp;height=491&amp;amp;face=0_0_880_491');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;⭐️  JavaScript Visualized: Promises &amp;amp; Async/Await&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ever had to deal with JS code that just... didn't run the way you expected it to? Maybe it seemed lik...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dev.to&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1668093225903&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;이벤트 루프와 매크로태스크, 마이크로태스크&quot; data-og-description=&quot;&quot; data-og-host=&quot;ko.javascript.info&quot; data-og-source-url=&quot;https://ko.javascript.info/event-loop&quot; data-og-url=&quot;https://ko.javascript.info/event-loop&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/82kfP/hyQxG2QyB1/2zth9rrA7gfbhoSjm8LQK1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/eBfk4G/hyQwB3amiA/LjwLirckNNZM7AbTd0lkSK/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://ko.javascript.info/event-loop&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ko.javascript.info/event-loop&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/82kfP/hyQxG2QyB1/2zth9rrA7gfbhoSjm8LQK1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/eBfk4G/hyQwB3amiA/LjwLirckNNZM7AbTd0lkSK/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;이벤트 루프와 매크로태스크, 마이크로태스크&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ko.javascript.info&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1668093256318&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;이벤트 루프와 태스크 큐 (마이크로 태스크, 매크로 태스크)&quot; data-og-description=&quot;자바스크립트는 싱글 스레드 기반의 언어이고, 자바스크립트 엔진은 하나의 호출 스택만을 사용한다. 이는 요청이 동기적으로 처리되어, 한 번에 한 가지 일만 처리할 수 있음을 의미한다. 만약&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@yejineee/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84%EC%99%80-%ED%83%9C%EC%8A%A4%ED%81%AC-%ED%81%90-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-%EB%A7%A4%ED%81%AC%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-g6f0joxx&quot; data-og-url=&quot;https://velog.io/@yejineee/이벤트-루프와-태스크-큐-마이크로-태스크-매크로-태스크-g6f0joxx&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fWiWC/hyQwMjhZHc/5FOnjcWiVpmUM9zo8sQcG1/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/fm87Y/hyQxHtUZ2K/5f7Yfc4sX8PuD8P4TtqoL1/img.png?width=700&amp;amp;height=733&amp;amp;face=0_0_700_733,https://scrap.kakaocdn.net/dn/4XrvN/hyQwADbTSd/ghw3jze6HTtDYDwsQG5UU1/img.jpg?width=626&amp;amp;height=417&amp;amp;face=0_0_626_417&quot;&gt;&lt;a href=&quot;https://velog.io/@yejineee/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84%EC%99%80-%ED%83%9C%EC%8A%A4%ED%81%AC-%ED%81%90-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-%EB%A7%A4%ED%81%AC%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-g6f0joxx&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@yejineee/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84%EC%99%80-%ED%83%9C%EC%8A%A4%ED%81%AC-%ED%81%90-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-%EB%A7%A4%ED%81%AC%EB%A1%9C-%ED%83%9C%EC%8A%A4%ED%81%AC-g6f0joxx&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fWiWC/hyQwMjhZHc/5FOnjcWiVpmUM9zo8sQcG1/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/fm87Y/hyQxHtUZ2K/5f7Yfc4sX8PuD8P4TtqoL1/img.png?width=700&amp;amp;height=733&amp;amp;face=0_0_700_733,https://scrap.kakaocdn.net/dn/4XrvN/hyQwADbTSd/ghw3jze6HTtDYDwsQG5UU1/img.jpg?width=626&amp;amp;height=417&amp;amp;face=0_0_626_417');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;이벤트 루프와 태스크 큐 (마이크로 태스크, 매크로 태스크)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트는 싱글 스레드 기반의 언어이고, 자바스크립트 엔진은 하나의 호출 스택만을 사용한다. 이는 요청이 동기적으로 처리되어, 한 번에 한 가지 일만 처리할 수 있음을 의미한다. 만약&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>JavaScript</category>
      <category>javascript</category>
      <category>자바스크립트 동작원리</category>
      <category>자바스크립트 비동기 동작원리</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/76</guid>
      <comments>https://ji-musclecode.tistory.com/76#entry76comment</comments>
      <pubDate>Fri, 11 Nov 2022 00:14:53 +0900</pubDate>
    </item>
    <item>
      <title>Next.js - .gitignore 가 적용되지 않을 때</title>
      <link>https://ji-musclecode.tistory.com/75</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;✅ 사이드프로젝트를 하면서 발생했던 이슈에 대해서 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Next.js에서 .gitignore 가 적용되지 않을 때&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p id=&quot;️-nextconfigjs&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;next 프로젝트로 사이드 프로젝트를 하면서 기초 설정을 하고 커밋을 하려 했는데, 몇천개의 커밋 건들이 올라왔습니다..! 분명 gitignore에 next 관련 폴더들을 제외시켜뒀는데, 계속 무시되어서 인터넷을 검색해보니 똑같은 경험을 하신 분들이 계셨습니다  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  .gitignore에 .next 경로 파일들이 무시되는 이유&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;.gitignore 파일 생성 전 이미 git 원격 저장소에 .next 디렉토리를 커밋했기 때문에 캐싱된 파일들이 잔존하고 있기 때문&lt;/span&gt;입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;  해결방법&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;.gitignore 에 .next 를 추가 !&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;아래 명령어를 순서대로 실행 !&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;그 이후로부터는 정상적으로 제외됩니다 !&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;$ git rm -rf --cached .
$ git add .
$ git commit -m &quot;커밋 메세지&quot;
$ git push&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;git rm&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;- 원격 저장소와 로컬 저장소에 있는 파일을 삭제합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;git rm --cached&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;- 원격 저장소에 있는 파일을 삭제한다. 로컬 저장소에 있는 파일은 삭제하지 않습니다. ( 로컬 저장소에는 존재하지만, 원격 저장소에 올라가진 않습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&amp;nbsp;참고한&lt;span&gt;&amp;nbsp;&lt;/span&gt;글&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1664206348243&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NextJS] .gitignore 적용되지 않을 때&quot; data-og-description=&quot;create-next-app으로 nextjs 프로젝트를 생성하여 혼자 스터디를 해보고 있었는데, .gitignore 파일 수정이 필요한 일이 생겼다. 깃헙 원격 저장소에 올리지 않아도 되는 파일들이 있어 .gitignore에 node_modul&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@xeptember/NextJS-.gitignore-%EC%A0%81%EC%9A%A9%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%84-%EB%95%8C&quot; data-og-url=&quot;https://velog.io/@xeptember/NextJS-.gitignore-적용되지-않을-때&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Dm1Nk/hyPVem6T14/GEf6Bnxj5LE5NTrDpeOME0/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666,https://scrap.kakaocdn.net/dn/PCbXl/hyPVopARBV/pKrtrlyM51wqMYj9wZ7vW1/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666,https://scrap.kakaocdn.net/dn/1SJdp/hyPVrNpqmZ/1E8qFS2KtuhkTjEIfonjeK/img.jpg?width=421&amp;amp;height=421&amp;amp;face=0_0_421_421&quot;&gt;&lt;a href=&quot;https://velog.io/@xeptember/NextJS-.gitignore-%EC%A0%81%EC%9A%A9%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%84-%EB%95%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@xeptember/NextJS-.gitignore-%EC%A0%81%EC%9A%A9%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%84-%EB%95%8C&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Dm1Nk/hyPVem6T14/GEf6Bnxj5LE5NTrDpeOME0/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666,https://scrap.kakaocdn.net/dn/PCbXl/hyPVopARBV/pKrtrlyM51wqMYj9wZ7vW1/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666,https://scrap.kakaocdn.net/dn/1SJdp/hyPVrNpqmZ/1E8qFS2KtuhkTjEIfonjeK/img.jpg?width=421&amp;amp;height=421&amp;amp;face=0_0_421_421');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NextJS] .gitignore 적용되지 않을 때&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;create-next-app으로 nextjs 프로젝트를 생성하여 혼자 스터디를 해보고 있었는데, .gitignore 파일 수정이 필요한 일이 생겼다. 깃헙 원격 저장소에 올리지 않아도 되는 파일들이 있어 .gitignore에 node_modul&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>개인수련실</category>
      <category>Next.js</category>
      <category>next.js에 .gitignore가 적용되지 않을 때</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/75</guid>
      <comments>https://ji-musclecode.tistory.com/75#entry75comment</comments>
      <pubDate>Tue, 27 Sep 2022 18:30:39 +0900</pubDate>
    </item>
    <item>
      <title>Next.js - Redirects &amp;amp; Rewrites</title>
      <link>https://ji-musclecode.tistory.com/74</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;✅ 사이드프로젝트를 하면서 발생했던 이슈에 대해서 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Redirects 와 Rewrites&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 id=&quot;️-nextconfigjs&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;⚙️ next.config.js&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;next.js에서 커스텀 설정을 하기 위해 프로젝트 디렉토리 루트에 next.config.js 파일을 만들어사용합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;next.config.js는 JSON 파일이 아닌 일반 Node.js 모듈이며, Next.js 서버 및 빌드 단계에서 사용되며 브라우저 빌드에는 포함되지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199; color: #ee2323;&quot;&gt;Redirects 와 Rewrites 옵션은 next.config.js 에서 사용하는 옵션&lt;/span&gt;&lt;/b&gt;입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;  Redirects&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1664199769496&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;module.exports = {

  async redirects() {
    return [
      {
        source: &quot;/requestPage&quot;,
        destination: &quot;/redirectPage&quot;,
        permanent: false,
      },
      /*
      위와 같은 객체형식으로 여러개 가능
      */
      
    ];
  },

};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMpbzH/btrM5PLAoYE/mhV6Yse9CYAFZRjpaWgmrk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMpbzH/btrM5PLAoYE/mhV6Yse9CYAFZRjpaWgmrk/img.gif&quot; data-alt=&quot;예시 동작&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMpbzH/btrM5PLAoYE/mhV6Yse9CYAFZRjpaWgmrk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cMpbzH/btrM5PLAoYE/mhV6Yse9CYAFZRjpaWgmrk/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;240&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;예시 동작&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;redirects()는 &lt;b&gt;&lt;span style=&quot;color: #ee2323; background-color: #f6e199;&quot;&gt;source, destination, permanent&lt;/span&gt;&lt;/b&gt; 속성이 있는 객체 배열을 반환하는 비동기 함수입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;source 경로를 destination 경로로 redirect 하도록 설정할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;source : 들어오는 요청 경로 (requset 경로)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;destination : 이동할, 라우팅할 특정 페이지의 경로 (redirect 경로)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;permanent : 브라우저나 검색엔진이 이 정보를 기억하는지 여부 (true - 308 status code&amp;nbsp; / false - 307 status code)&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;http-status-code-307-308&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;◼&amp;nbsp;HTTP Status Code 307, 308&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #ee2323;&quot;&gt;307 Temporary Redirect&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시 리다이렉트라고 해석할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약 oldblog.kr 이라는 블로그가 있는데 어떠한 이슈로 인해 잠시동안 temp.oldblog.kr 블로그를 만든 후에 이전 블로그의 접속자들을 리다이렉트 시켜주고 싶을 때 사용합니다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199; color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;308 Permanent Redirect&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;영구 리다이렉트라고 해석할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약 oldblog.kr 이라는 예전 블로그에서, 새로운 newblog.kr 블로그를 만든 후 이전 블로그 접속자들을 리다이렉트 시켜주고 싶을 때 사용합니다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;307 과 308 코드의 차이 !&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;임시적 이동인지, 영구적 이동인지에 따른 차이!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;  Rewrites&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1664201745935&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const API_KEY = process.env.API_KEY;

module.exports = {
  async rewrites() {
    return [
      {
        source: &quot;/api/test&quot;,
        destination: `https://api.test?api_key=${API_KEY}`,
      },
     /*
      위와 같은 객체형식으로 여러개 가능
      */
    ];
  },
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;API_KET 가 12345a678910b 라고 가정했을 때&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;* rewrites 설정을 하지 않은 경우 /api/test 로 GET 요청을 하면 https://api.test?api_key=12345a678910b 과 같이 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;API_KEY가 그대로 요청 URL에 노출&lt;/span&gt;됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;* rewirtes 설정을 위와 같이 하면 /api/test로 GET 요청을 하면 destination 경로로 매핑되어 https://api.test?api_key=12345a678910b 로 GET 요청을하는 것은 동일하지만 사용자는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;https://api.test 까지의 요청 URL만 확인&lt;/span&gt;할 수 있습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;  정리 !&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Redirects 와 Rewrites 옵션은 next.config.js 에서 사용하는 옵션 !&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Redirects는 source 경로를 destination 경로로 redirect 시키고, URL을 변경 !&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;permanent 옵션이 true이면 308 status code, false이면 307 status code.&lt;br /&gt;주로 308은 영구이동, 307은 임시 이동일 때 사용!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Rewrites는 URL 프록시 역할을 하고 destination 경로를 source 경로로 mask&lt;/span&gt;&amp;nbsp;!&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;프록시(Proxy)란 대신이란 의미로, 보안상의 문제로 직접 통신을 받을 수 없을 때 프록시를 이용해서 중계를 하는 개념&lt;/span&gt;!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;nbsp;참고한&lt;span&gt;&amp;nbsp;&lt;/span&gt;글&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1664204710722&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[NextJS] Redirects &amp;amp; Rewrites&quot; data-og-description=&quot;NextJS 공식문서   next.config.js redirects rewrites ⚙️ next.config.js Next.js에서 커스텀 고급(?) 설정을 하기 위해서 프로젝트 디렉터리 루트에 next.config.js 파일을 만들 수 있다. next.conf&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@eunnbi/NextJS-Redirects-Rewrites&quot; data-og-url=&quot;https://velog.io/@eunnbi/NextJS-Redirects-Rewrites&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/1IsHV/hyPVsr0OZL/BFhUAc84C7akiqS5HA0ur1/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350,https://scrap.kakaocdn.net/dn/bVGK76/hyPVjPl26Q/g8YrikXdkCzWqvS2yh4X61/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350,https://scrap.kakaocdn.net/dn/ewdQW0/hyPVupShuu/q6z9PcTSvKufZAT0zgCCSk/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350&quot;&gt;&lt;a href=&quot;https://velog.io/@eunnbi/NextJS-Redirects-Rewrites&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@eunnbi/NextJS-Redirects-Rewrites&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/1IsHV/hyPVsr0OZL/BFhUAc84C7akiqS5HA0ur1/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350,https://scrap.kakaocdn.net/dn/bVGK76/hyPVjPl26Q/g8YrikXdkCzWqvS2yh4X61/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350,https://scrap.kakaocdn.net/dn/ewdQW0/hyPVupShuu/q6z9PcTSvKufZAT0zgCCSk/img.png?width=700&amp;amp;height=350&amp;amp;face=0_0_700_350');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[NextJS] Redirects &amp;amp; Rewrites&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;NextJS 공식문서   next.config.js redirects rewrites ⚙️ next.config.js Next.js에서 커스텀 고급(?) 설정을 하기 위해서 프로젝트 디렉터리 루트에 next.config.js 파일을 만들 수 있다. next.conf&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1664204715477&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Nextjs Redirect 옵션에 Permanent는 뭐지?&quot; data-og-description=&quot;아직도 Next.js Redirect에 permanent 옵션 모르는 사람 있음? (나)&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@himprover/Nextjs-Redirect-%EC%98%B5%EC%85%98%EC%97%90-Permanent%EB%8A%94-%EB%AD%90%EC%A7%80&quot; data-og-url=&quot;https://velog.io/@himprover/Nextjs-Redirect-옵션에-Permanent는-뭐지&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cbK3yj/hyPVtqWiAt/KMkQztp9v8VGssyKZXkUJ1/img.png?width=431&amp;amp;height=286&amp;amp;face=0_0_431_286,https://scrap.kakaocdn.net/dn/b1eyGM/hyPVhcXbsi/ZxgImHVHPdKxJJK2mVkcjK/img.png?width=431&amp;amp;height=286&amp;amp;face=0_0_431_286,https://scrap.kakaocdn.net/dn/Kfy8p/hyPVsMjqMb/czWf6tUebgOAHlVHm01PbK/img.jpg?width=1920&amp;amp;height=2560&amp;amp;face=44_1084_856_1896&quot;&gt;&lt;a href=&quot;https://velog.io/@himprover/Nextjs-Redirect-%EC%98%B5%EC%85%98%EC%97%90-Permanent%EB%8A%94-%EB%AD%90%EC%A7%80&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@himprover/Nextjs-Redirect-%EC%98%B5%EC%85%98%EC%97%90-Permanent%EB%8A%94-%EB%AD%90%EC%A7%80&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cbK3yj/hyPVtqWiAt/KMkQztp9v8VGssyKZXkUJ1/img.png?width=431&amp;amp;height=286&amp;amp;face=0_0_431_286,https://scrap.kakaocdn.net/dn/b1eyGM/hyPVhcXbsi/ZxgImHVHPdKxJJK2mVkcjK/img.png?width=431&amp;amp;height=286&amp;amp;face=0_0_431_286,https://scrap.kakaocdn.net/dn/Kfy8p/hyPVsMjqMb/czWf6tUebgOAHlVHm01PbK/img.jpg?width=1920&amp;amp;height=2560&amp;amp;face=44_1084_856_1896');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Nextjs Redirect 옵션에 Permanent는 뭐지?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;아직도 Next.js Redirect에 permanent 옵션 모르는 사람 있음? (나)&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>개인수련실</category>
      <category>Next.js</category>
      <category>redirects</category>
      <category>rewrites</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/74</guid>
      <comments>https://ji-musclecode.tistory.com/74#entry74comment</comments>
      <pubDate>Tue, 27 Sep 2022 00:05:37 +0900</pubDate>
    </item>
    <item>
      <title>Next.js - dotenv로 환경변수 저장하기</title>
      <link>https://ji-musclecode.tistory.com/73</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;✅ 사이드프로젝트를 하면서 발생했던 이슈에 대해서 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;Next.js 환경에서 dotenv로 환경변수 저장하는 법&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  dotenv&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;dotenv 라이브러리는 .env 파일로부터 환경 변수를 읽을 수 있습니다. 따라서 .env 파일에 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot; data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;키=값&lt;/span&gt;&lt;/b&gt;&lt;/span&gt; 포멧으로 나열하고 dotenv 라이브러리를 이용해서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;process.env&lt;/b&gt;&lt;/span&gt; 에 설정할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;디폴트로 현재 디렉토리에 위치한 .env 파일을 읽어옵니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;만약 .env가 다른 경로에 있다면, config() 함수 호출 시 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;path 옵션&lt;/span&gt;&lt;/b&gt;을 넘겨주면 됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;◼ 설치&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;npm i dotenv&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;◼ 사용예시&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;저는 Next.js 에서 사용했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;264&quot; data-origin-height=&quot;537&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCsFND/btrM38ddkXv/KMK7dsJ5sYib3DKcHo7udK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCsFND/btrM38ddkXv/KMK7dsJ5sYib3DKcHo7udK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCsFND/btrM38ddkXv/KMK7dsJ5sYib3DKcHo7udK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCsFND%2FbtrM38ddkXv%2FKMK7dsJ5sYib3DKcHo7udK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;244&quot; height=&quot;496&quot; data-origin-width=&quot;264&quot; data-origin-height=&quot;537&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;config 폴더&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;pre id=&quot;code_1664180030355&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// .env.development
MODE= DEV


// .env.production
MODE= PROD&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;package.json&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1664180988748&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// scripts 부분

&quot;scripts&quot;: {
	...
    &quot;build:dev&quot;: &quot;NEXT_NODE_ENV=development next build&quot;,
    &quot;build:prod&quot;: &quot;NEXT_NODE_ENV=production next build&quot;,
    &quot;start:dev&quot;: &quot;NEXT_NODE_ENV=development next start -p 8080&quot;,
    &quot;start:prod&quot;: &quot;NEXT_NODE_ENV=production next start -p 8080&quot;
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;next.config.js&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1664181046187&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;require(&quot;dotenv&quot;).config({
  path: `./config/.env.development`,
});

module.exports = {
  reactStrictMode: false, // env와 무관
  swcMinify: true, // env와 무관

  env: {
    MODE: process.env.MODE,
  },
};&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;◼ 결과&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;npm run build:dev =&amp;gt; npm run start:dev 실행 시 process.env.MODE 값에 DEV 값이 담깁니다!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;npm run build:prod =&amp;gt; npm run build:prod 실행 시 process.env.MODE 값에 PROD 값이 담깁니다!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개인수련실</category>
      <category>dotenv</category>
      <category>next.js 환경변수</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/73</guid>
      <comments>https://ji-musclecode.tistory.com/73#entry73comment</comments>
      <pubDate>Mon, 26 Sep 2022 18:46:19 +0900</pubDate>
    </item>
    <item>
      <title>JS - 쓰로틀링(throttling)과 디바운싱(debouncing)</title>
      <link>https://ji-musclecode.tistory.com/72</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;✅ 쓰로틀링과 디바운싱은 모두 웹에서 발생하는 이벤트를 제어하는 방법으로 불필요한 이벤트가 호출되는 것을 방지합니다. 예를 들어 검색어 자동완성 기능, 스크롤 관련 동작과 같은 이벤트에서 매번 입력, 스크롤에 대한 콜백이 발생하고 계속해서 콜백을 수행하는 일은 큰 리소스를 요구하기 때문에 서비스의 성능 저하 및 사용자 경험 저하를 야기합니다. 따라서 상황에 맞게 쓰로틀링이나 디바운싱을 적용하면 최적화하는데 큰 도움이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  쓰로틀링(throttling)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;쓰로틀링은 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 제어하는 것 입니다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;개발자가 몇 초마다 한 번씩 실행되게 제한을 두는 것입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;주로 스크롤 이벤트에서 많이 사용합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;쓰로틀링 구현 포인트 !&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;1. 함수가 실행 중인지 체크하는 타이머 변수를 생성&lt;br /&gt;2. 함수를 호출하면 타이머를 동작시키기&lt;br /&gt;3. 일정 시간 내에 함수가 다시 호출되면 실행되지 않게 처리를 해야 하므로 타이머 값이 없을 때만 함수 동작시키기&lt;br /&gt;4. 함수가 완료되면 타이머를 다시 초기화하여 함수 호출이 가능하도록 처리하기&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #ef5369; background-color: #ffffff;&quot;&gt;&lt;b&gt;[ 쓰로틀링 적용 전 ]&lt;/b&gt;&lt;/span&gt; (코드는 더보기에서!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; background-color: #fafafa; caret-color: auto; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1662605756883&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect, useRef } from &quot;react&quot;;

function App() {
  const divRef = useRef&amp;lt;HTMLDivElement&amp;gt;(null);

  const scrollFunc = (): void =&amp;gt; {
    console.log(divRef.current?.scrollTop);
  };

  useEffect(() =&amp;gt; {
    const divRefValue = divRef.current ? divRef.current : null;

    divRefValue?.addEventListener(&quot;scroll&quot;, scrollFunc);

    return () =&amp;gt; {
      divRefValue?.removeEventListener(&quot;scroll&quot;, scrollFunc);
    };
  });

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;div
        ref={divRef}
        style={{
          position: &quot;fixed&quot;,
          overflow: &quot;scroll&quot;,
          width: &quot;80%&quot;,
          height: &quot;80%&quot;,
        }}
      &amp;gt;
        &amp;lt;div
          style={{
            height: &quot;300%&quot;,
            background: &quot;lightgreen&quot;,
          }}
        &amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1772&quot; data-origin-height=&quot;1518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8HUM1/btrLEcBBb8f/tHRSDb9kd8dzPiLKULVB50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8HUM1/btrLEcBBb8f/tHRSDb9kd8dzPiLKULVB50/img.png&quot; data-alt=&quot;쓰로틀링 적용 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8HUM1/btrLEcBBb8f/tHRSDb9kd8dzPiLKULVB50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8HUM1%2FbtrLEcBBb8f%2FtHRSDb9kd8dzPiLKULVB50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;644&quot; height=&quot;552&quot; data-origin-width=&quot;1772&quot; data-origin-height=&quot;1518&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;쓰로틀링 적용 전&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;위와 같이 스크롤 이벤트는 스크롤링할 때마다 발생하는데, 만약 이때마다 어떤 작업을 실행하게 된다면 성능 문제가 발생할 가능성이 클 것입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #ef5369;&quot;&gt;[ 쓰로틀링 적용 후 ]&lt;/span&gt;&lt;/b&gt;&amp;nbsp;(코드는 더보기에서!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1662612124710&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect, useRef } from &quot;react&quot;;

function App() {
  const divRef = useRef&amp;lt;HTMLDivElement&amp;gt;(null);
  const timer = useRef&amp;lt;ReturnType&amp;lt;typeof setTimeout&amp;gt; | null&amp;gt;(null); // 쓰로틀링을 체크할 timer

  /* 쓰로틀링 적용 */
  const scrollFunc = (): void =&amp;gt; {
    // timer가 없을 때
    if (!timer.current) {
      timer.current = setTimeout(() =&amp;gt; {
        console.log(`scrollTop :: ${divRef.current?.scrollTop}`);
        timer.current = null; // 로직이 끝나면 timer를 초기화
      }, 250);
    }
  };

  useEffect(() =&amp;gt; {
    const divRefValue = divRef.current ? divRef.current : null;

    divRefValue?.addEventListener(&quot;scroll&quot;, scrollFunc);

    return () =&amp;gt; {
      divRefValue?.removeEventListener(&quot;scroll&quot;, scrollFunc);
    };
  });

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;div
        ref={divRef}
        style={{
          position: &quot;fixed&quot;,
          overflow: &quot;scroll&quot;,
          width: &quot;80%&quot;,
          height: &quot;80%&quot;,
        }}
      &amp;gt;
        &amp;lt;div
          style={{
            height: &quot;300%&quot;,
            background: &quot;lightgreen&quot;,
          }}
        &amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1670&quot; data-origin-height=&quot;1270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dErm98/btrLF2LTWvP/fj3z2whERh3WZqHOao4wfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dErm98/btrLF2LTWvP/fj3z2whERh3WZqHOao4wfK/img.png&quot; data-alt=&quot;쓰로틀링 적용 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dErm98/btrLF2LTWvP/fj3z2whERh3WZqHOao4wfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdErm98%2FbtrLF2LTWvP%2Ffj3z2whERh3WZqHOao4wfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;516&quot; data-origin-width=&quot;1670&quot; data-origin-height=&quot;1270&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;쓰로틀링 적용 후&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;쓰로틀링을 적용한 결과 스크롤 이벤트를 일정 시간마다 호출하도록 제어할 수 있게 되었습니다!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  디바운싱(debouncing)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;디바운싱은 연속으로 호출되는 함수들 중 마지막에 호출되는 함수(또는 제일 처음 호출한 함수)만 실행되도록 하는 것입니다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이벤트를 그룹화하여 특정 시간이 지난 후 하나의 이벤트만 발생하도록 제어합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;주로 사용자 입력 이벤트 처리 (검색어 자동완성), 리사이즈(Resize) - 브라우저 창 크기 조절 이벤트에 많이 사용합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;디바운싱 구현 포인트 !&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. 함수가 실행 중인지 체크하는 타이머 변수를 생성&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. 함수를 호출하면 타이머를 동작시키기&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;3. 일정 시간 전에 함수 호출이 발생하면, 기존 타이머를 취소하고 시간을 재설정하여 새로운 함수 호출&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #ef5369;&quot;&gt;[ 디바운싱 적용 전 ]&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;(코드는 더보기에서!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1662629864955&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect, useRef } from &quot;react&quot;;

function App() {
  const inputRef = useRef&amp;lt;HTMLInputElement&amp;gt;(null);

  const inputFunc = (): void =&amp;gt; {
    console.log(inputRef.current?.value);
  };

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;div
        style={{ position: &quot;absolute&quot;, width: &quot;50%&quot;, margin: &quot;10% 25% 0 25%&quot; }}
      &amp;gt;
        &amp;lt;input ref={inputRef} onChange={inputFunc}&amp;gt;&amp;lt;/input&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYRetm/btrLJKSjqgA/KFB6rH9ut3ZU1bzdP9tkKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYRetm/btrLJKSjqgA/KFB6rH9ut3ZU1bzdP9tkKk/img.png&quot; data-alt=&quot;쓰로틀링 적용 전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYRetm/btrLJKSjqgA/KFB6rH9ut3ZU1bzdP9tkKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYRetm%2FbtrLJKSjqgA%2FKFB6rH9ut3ZU1bzdP9tkKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;550&quot; height=&quot;621&quot; data-origin-width=&quot;653&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;쓰로틀링 적용 전&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;위와 같이 인풋 이벤트는 입력할 때마다 발생하는 것을 확인할 수 있습니다. 따라서&amp;nbsp;예를 들어 사용자 입력에 따른 검색어 자동완성 기능을 구현하고자 한다면 필요 없는 API들을 상당히 많이 호출을 할 것입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #ef5369;&quot;&gt;[ 디바운싱 적용 후 ]&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;(코드는 더보기에서!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1662630334043&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect, useRef } from &quot;react&quot;;

function App() {
  const inputRef = useRef&amp;lt;HTMLInputElement&amp;gt;(null);
  const timer = useRef&amp;lt;ReturnType&amp;lt;typeof setTimeout&amp;gt; | null&amp;gt;(null);

  /* 디바운싱 적용 */
  const inputFunc = (): void =&amp;gt; {
    if (timer.current) {
      clearTimeout(timer.current);
    }

    timer.current = setTimeout(() =&amp;gt; {
      console.log(inputRef.current?.value);
    }, 250);
  };

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;div
        style={{ position: &quot;absolute&quot;, width: &quot;50%&quot;, margin: &quot;10% 25% 0 25%&quot; }}
      &amp;gt;
        &amp;lt;input ref={inputRef} onChange={inputFunc}&amp;gt;&amp;lt;/input&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnS3vj/btrLKapt79m/2AzcN88lk9uhCxX1vA0jt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnS3vj/btrLKapt79m/2AzcN88lk9uhCxX1vA0jt1/img.png&quot; data-alt=&quot;디바운싱 적용 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnS3vj/btrLKapt79m/2AzcN88lk9uhCxX1vA0jt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnS3vj%2FbtrLKapt79m%2F2AzcN88lk9uhCxX1vA0jt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;646&quot; height=&quot;403&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;디바운싱 적용 후&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;디바운싱을 적용한 결과 인풋 이벤트가 설정한 시간 동안 발생하지 않았을 때 마지막 이벤트를 호출하는 것을 확인할 수 있습니다!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  쓰로틀링(throttling) 과 &lt;b&gt;디바운싱(debouncing) 의 차이점&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F6zaP/btrLK6GFhi0/3ux5p6YkdtHLWxk4BKu6Yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F6zaP/btrLK6GFhi0/3ux5p6YkdtHLWxk4BKu6Yk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F6zaP/btrLK6GFhi0/3ux5p6YkdtHLWxk4BKu6Yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF6zaP%2FbtrLK6GFhi0%2F3ux5p6YkdtHLWxk4BKu6Yk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;487&quot; height=&quot;234&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;쓰로틀링은 연속되는 이벤트의 경우 설정한 특정 시간을 주기로 이벤트를 계속 실행&lt;/span&gt;합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;디바운싱은 연속되는 이벤트의 경우 모두 무시하고 설정한 특정 시간 동안 이벤트가 발생하지 않았을 때 맨 마지막 이벤트를 딱 한번 실행&lt;/span&gt;합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt; &lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&amp;nbsp; 정리&amp;nbsp;!&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;쓰로틀링과 디바운싱 모두 이벤트를 제어하는 방법으로 불필요한 이벤트가 연속으로 호출되는 것을 방지하여 서비스의 성능 향상 및 사용자 경험 최적화에 사용됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;쓰로틀링은 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 제어하는 것입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;디바운싱은 연속으로 호출되는 함수들 중 마지막에 호출되는 함수(또는 제일 처음 호출한 함수)만 실행되도록 하는 것입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;쓰로틀링과 디바운싱의 차이점은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;연속되는 이벤트에서&amp;nbsp;&lt;/span&gt;쓰로틀링은 적어도 X 초마다 정기적으로 기능 실행을 보장하나, 디바운싱은 모두 무시하고 특정 시간 동안 이벤트가 발생하지 않았을 때 마지막 이벤트를 딱 한번 실행합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;nbsp;참고한&lt;span&gt;&amp;nbsp;&lt;/span&gt;글&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1662631802166&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;How to Optimize web app with Debounce and Throttle&quot; data-og-description=&quot;In optimizing a product's performance, engineers end up designing a process that does the most with the least. This either by finding a way to minimize an appli&quot; data-og-host=&quot;blog.knoldus.com&quot; data-og-source-url=&quot;https://blog.knoldus.com/how-to-optimize-web-app-with-debounce-and-throttle/&quot; data-og-url=&quot;https://blog.knoldus.com/how-to-optimize-web-app-with-debounce-and-throttle/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ch3SXw/hyPIyF9fik/VuTASLpvKYpx8owuekyJsk/img.jpg?width=828&amp;amp;height=413&amp;amp;face=0_0_828_413,https://scrap.kakaocdn.net/dn/AEp0X/hyPJWk6zXT/QEyae1kkCvqz38WMECYu51/img.jpg?width=828&amp;amp;height=413&amp;amp;face=0_0_828_413,https://scrap.kakaocdn.net/dn/DKmfo/hyPIA415pQ/a8r84UKKng7hYGyCiKGQw1/img.jpg?width=828&amp;amp;height=413&amp;amp;face=0_0_828_413&quot;&gt;&lt;a href=&quot;https://blog.knoldus.com/how-to-optimize-web-app-with-debounce-and-throttle/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.knoldus.com/how-to-optimize-web-app-with-debounce-and-throttle/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ch3SXw/hyPIyF9fik/VuTASLpvKYpx8owuekyJsk/img.jpg?width=828&amp;amp;height=413&amp;amp;face=0_0_828_413,https://scrap.kakaocdn.net/dn/AEp0X/hyPJWk6zXT/QEyae1kkCvqz38WMECYu51/img.jpg?width=828&amp;amp;height=413&amp;amp;face=0_0_828_413,https://scrap.kakaocdn.net/dn/DKmfo/hyPIA415pQ/a8r84UKKng7hYGyCiKGQw1/img.jpg?width=828&amp;amp;height=413&amp;amp;face=0_0_828_413');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;How to Optimize web app with Debounce and Throttle&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;In optimizing a product's performance, engineers end up designing a process that does the most with the least. This either by finding a way to minimize an appli&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.knoldus.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>JavaScript</category>
      <category>debouncing</category>
      <category>javascript</category>
      <category>React로 쓰로틀링 디바운싱 구현</category>
      <category>Throttling</category>
      <category>디바운싱</category>
      <category>쓰로틀링</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/72</guid>
      <comments>https://ji-musclecode.tistory.com/72#entry72comment</comments>
      <pubDate>Thu, 8 Sep 2022 19:11:11 +0900</pubDate>
    </item>
    <item>
      <title>2022년 할 것들 [9월 목표] - update</title>
      <link>https://ji-musclecode.tistory.com/71</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2022년에 9월 목표를 세우고, 말일에 스스로 결과를 판단하여 회고해보자!&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;1. React 처음부터 다시 공부해보기&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #006dd7;&quot;&gt;&lt;b&gt;[ 목표 ]&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;FE 개발자로 현재 3년차.. 원래는 BE 개발자로 들어왔는데 당시 부서에 FE 신규 메뉴들이 많이 쌓여있었고 어쩌다 보니 BE 메뉴가 아닌 FE 메뉴들을 분장받아 개발하다 보니 그때부터 FE 개발자로 일하고 있다. 공부 없이 거의 바로 메뉴를 개발하다 보니 React의 개념 및 동작 과정에 대한 이해 같은 부분들이 가끔 부족하다는 생각이 든다! 따라서 React에 대해 심층적으로 학습하고 원래 알고 있었던 것들은 복습하면서 처음부터 다시 한번 공부해보기로 결정! (노션 페이지로 정리)&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;[ 결과 ]&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- 9월 30일에 업데이트 하기!&lt;br /&gt;&lt;/b&gt;기초 개념부터 천천히 정리해봤다. 원래는 한번 훑어볼 목적이었지만, 개념 정리를 하면서 깊게 들어갈수록 생각할 점이 상당히 많았다. (예를들면 컴포넌트 아키텍처같은 것들..) 그래서 &lt;span style=&quot;color: #000000;&quot;&gt;훑어볼 목적이 아닌 깊게 공부하여 사고의 폭을 넓히고싶어, 앞으로도 꾸준히 공부할 예정이다.&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;figure id=&quot;og_1664498010845&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;React.js&quot; data-og-description=&quot;https://react.vlpt.us/&quot; data-og-host=&quot;succulent-dog-eb0.notion.site&quot; data-og-source-url=&quot;https://succulent-dog-eb0.notion.site/React-js-bba2fc62b4254ccc9a19c3da7db8dfb3&quot; data-og-url=&quot;https://succulent-dog-eb0.notion.site/bba2fc62b4254ccc9a19c3da7db8dfb3&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://succulent-dog-eb0.notion.site/React-js-bba2fc62b4254ccc9a19c3da7db8dfb3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://succulent-dog-eb0.notion.site/React-js-bba2fc62b4254ccc9a19c3da7db8dfb3&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; data-ke-size=&quot;size16&quot;&gt;React.js&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;https://react.vlpt.us/&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;succulent-dog-eb0.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;2. Next.js로 사이드 프로젝트 진행하기!&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;[ 목표 ]&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;현 회사는 앱이 아닌 웹으로만 서비스를 제공하고 있다. 물론 Next.js 기반으로 서비스하는 앱도 있긴 하지만, 해당 서비스에서 메뉴 한 두 개 정도 개발해본 경험이 끝이다. 따라서 Next.js를 할 수 있다고 하기에도 사실 창피한 수준이다..  그래서 최근 사이드 프로젝트 팀(설계-2, 디자인-2, FE-2, BE-2)에 들어가서 11월 말까지 서비스를 목적으로&lt;/span&gt; &lt;span style=&quot;color: #ee2323; background-color: #dddddd;&quot;&gt;React Native&lt;/span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt; 기반 &lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #ee2323;&quot;&gt;TypeScript&lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt; + &lt;/span&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Next.js&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;형태의 하이브리드 앱을 기획 중이다. 아직 디자인 및 설계가 구체적으로 나오지 않았으므로(9월 말에 나올 것으로 예상), 9월 말까지는 Next.js의 강의를 듣고, 간단한 사이드 프로젝트를 할 것이다!&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;[ 결과 ]&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 9월 30일에 업데이트 하기!&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;먼저 Next.js에 대해 공부했다. 그리고 개인적인 사이드프로젝트를 진행하려고 했는데, 팀 프로젝트 설계가 빨리 나와서 프로젝트를 진행하고 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;figure id=&quot;og_1664498041989&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Next.js&quot; data-og-description=&quot;+ TypeScript ) https://noogoonaa.tistory.com/65&quot; data-og-host=&quot;succulent-dog-eb0.notion.site&quot; data-og-source-url=&quot;https://succulent-dog-eb0.notion.site/Next-js-3051e33e599543189b853c4a3bb021b6&quot; data-og-url=&quot;https://succulent-dog-eb0.notion.site/3051e33e599543189b853c4a3bb021b6&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://succulent-dog-eb0.notion.site/Next-js-3051e33e599543189b853c4a3bb021b6&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://succulent-dog-eb0.notion.site/Next-js-3051e33e599543189b853c4a3bb021b6&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; data-ke-size=&quot;size16&quot;&gt;Next.js&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;+ TypeScript ) https://noogoonaa.tistory.com/65&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;succulent-dog-eb0.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1664498066042&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - WE-O/WEO_FE_WEB: ⭐️ WE'O 식식물물 Front 소스 저장소 ⭐️&quot; data-og-description=&quot;⭐️ WE'O 식식물물 Front 소스 저장소 ⭐️. Contribute to WE-O/WEO_FE_WEB development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/WE-O/WEO_FE_WEB&quot; data-og-url=&quot;https://github.com/WE-O/WEO_FE_WEB&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bznadC/hyPXD0Z1y3/dq7LPxcmN3dYvSCWmXwLVK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/WE-O/WEO_FE_WEB&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/WE-O/WEO_FE_WEB&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bznadC/hyPXD0Z1y3/dq7LPxcmN3dYvSCWmXwLVK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - WE-O/WEO_FE_WEB: ⭐️ WE'O 식식물물 Front 소스 저장소 ⭐️&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;⭐️ WE'O 식식물물 Front 소스 저장소 ⭐️. Contribute to WE-O/WEO_FE_WEB development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;3. 클린 코드&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;[ 목표 ]&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;클린 코드란 무엇일까.. 간단한 것 같지만 어렵다.. 개발자마다 성향이 다르고 같은 로직을 짜는데 코드가 다르기 때문에 협업에 도움이 되며 스스로 이게 왜 클린 코드인 지 설명할 수 있도록 나만의 클린 코드 정의를 확실히 하자. &lt;span style=&quot;color: #000000;&quot;&gt;(노션 페이지로 정리)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;[ 결과 ]&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 9월 30일에 업데이트 하기!&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;보통 클린코드란 가독성과 유지보수가 좋은 코드이다. 그런데 회사/개인마다 생각하는 클린코드의 방법이 조금씩 다를 것이다. 그래서&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;공부할수록 클린코드라는 개념을 특정지어서 설명하기 힘든 것 같다.&lt;span&gt; &lt;/span&gt;&lt;/span&gt;아래는 공부하기 위해 들었던 강의인데, 강사분도 클린 코드라는 개념을 특정짓지 말라고 강의 초반에 말씀하신다. 더 생각해보고 공부해봐야겠다..&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;figure id=&quot;og_1664498772922&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;udemy_com:course&quot; data-og-title=&quot;클린코드 자바스크립트&quot; data-og-description=&quot;자바스크립트를 위한 코드 스타일부터 습관 그리고 클린 코드에 대해 함께 고민해보고 그 이유에 대해 탐구하고 또 학습해보는 시간을 가집니다.&quot; data-og-host=&quot;www.udemy.com&quot; data-og-source-url=&quot;https://www.udemy.com/course/clean-code-js/&quot; data-og-url=&quot;https://www.udemy.com/course/clean-code-js/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dr6sDE/hyPXCVm6AY/wQvpQ2y5kFmU0lsxKCIU80/img.jpg?width=480&amp;amp;height=270&amp;amp;face=0_0_480_270,https://scrap.kakaocdn.net/dn/bkyAm4/hyPXCVm6B7/P0qM1N9X8J6UkXPFzGopj1/img.jpg?width=480&amp;amp;height=270&amp;amp;face=0_0_480_270&quot;&gt;&lt;a href=&quot;https://www.udemy.com/course/clean-code-js/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.udemy.com/course/clean-code-js/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dr6sDE/hyPXCVm6AY/wQvpQ2y5kFmU0lsxKCIU80/img.jpg?width=480&amp;amp;height=270&amp;amp;face=0_0_480_270,https://scrap.kakaocdn.net/dn/bkyAm4/hyPXCVm6B7/P0qM1N9X8J6UkXPFzGopj1/img.jpg?width=480&amp;amp;height=270&amp;amp;face=0_0_480_270');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;클린코드 자바스크립트&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트를 위한 코드 스타일부터 습관 그리고 클린 코드에 대해 함께 고민해보고 그 이유에 대해 탐구하고 또 학습해보는 시간을 가집니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.udemy.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1664501629844&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;좋은 코드란 무엇일까?&quot; data-og-description=&quot;&amp;lsquo;성선설&amp;rsquo;에 기반하면 모든 개발자는 좋은 코드를 작성하고 싶으리라 생각한다. 누구나 관심 있어 하는 주제인 만큼 나 또한 여러 고민을 거듭해왔고 여태까지의 생각을 정리해보려고 한다. &quot; data-og-host=&quot;jbee.io&quot; data-og-source-url=&quot;https://jbee.io/etc/what-is-good-code/&quot; data-og-url=&quot;https://jbee.io/etc/what-is-good-code/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gjr5o/hyPXPHcYkV/xxzqk9x6ziMVgXkzeC0e90/img.png?width=800&amp;amp;height=508&amp;amp;face=0_0_800_508,https://scrap.kakaocdn.net/dn/DwoSH/hyPXJNLPj9/yxPC0KaZ91krZ3bX2dOk4K/img.png?width=800&amp;amp;height=508&amp;amp;face=0_0_800_508,https://scrap.kakaocdn.net/dn/bLl55Z/hyPXLri3vv/1wgg58KCiCjz2QXEkJkA80/img.png?width=1179&amp;amp;height=749&amp;amp;face=0_0_1179_749&quot;&gt;&lt;a href=&quot;https://jbee.io/etc/what-is-good-code/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jbee.io/etc/what-is-good-code/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gjr5o/hyPXPHcYkV/xxzqk9x6ziMVgXkzeC0e90/img.png?width=800&amp;amp;height=508&amp;amp;face=0_0_800_508,https://scrap.kakaocdn.net/dn/DwoSH/hyPXJNLPj9/yxPC0KaZ91krZ3bX2dOk4K/img.png?width=800&amp;amp;height=508&amp;amp;face=0_0_800_508,https://scrap.kakaocdn.net/dn/bLl55Z/hyPXLri3vv/1wgg58KCiCjz2QXEkJkA80/img.png?width=1179&amp;amp;height=749&amp;amp;face=0_0_1179_749');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;좋은 코드란 무엇일까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lsquo;성선설&amp;rsquo;에 기반하면 모든 개발자는 좋은 코드를 작성하고 싶으리라 생각한다. 누구나 관심 있어 하는 주제인 만큼 나 또한 여러 고민을 거듭해왔고 여태까지의 생각을 정리해보려고 한다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jbee.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>일상</category>
      <category>목표 일기</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/71</guid>
      <comments>https://ji-musclecode.tistory.com/71#entry71comment</comments>
      <pubDate>Fri, 2 Sep 2022 18:05:56 +0900</pubDate>
    </item>
    <item>
      <title>React - Infinite Scroll 직접 구현해보기</title>
      <link>https://ji-musclecode.tistory.com/70</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;✅ 전에 React 무한 스크롤을 구현해 본 경험이 있는데, 최근에 해당 기능을 또 구현해 볼 기회가 생겨서 이참에 공부한 내용을 정리하고자 글을 작성합니다. (잘못된 정보가 있다면 말씀해주시면 감사하겠습니다.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;저는 테스트 데이터를 msw를 사용하여 데이터를 &lt;span style=&quot;background-color: #ffffff;&quot;&gt;Mocking 하여 사용했습니다. (더보기 란에 간단한 설정법을 적어뒀습니다.)&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;msw 설치&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;npm install msw / yarn add msw&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;src 폴더 하위에 mocks 폴더 생성 후 browser.js, handlers.js 파일 만들기&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;index.js 에 mock 설정 코드 추가하기&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1661325026205&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*  browser.js */
import { setupWorker } from 'msw'
import { handlers } from './handlers'
export const worker = setupWorker(...handlers)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1661325051029&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* handlers.js */

import {rest} from 'msw'

const pageData = Array.from({length: 50}).map((dr, idx) =&amp;gt; {
    return {name: `${idx}`}
})

export const handlers = [
    rest.get(&quot;/api/getData&quot;, async (req, res, ctx) =&amp;gt; {

        const p = Number(req.url.searchParams.get(&quot;page&quot;));
        let returnData = {};

        returnData.data = pageData.slice(10 * (p - 1), 10 * p);
        returnData.page = p;
        returnData.hasNext = p &amp;lt; 5;

        await sleep(300);

        return res(ctx.status(200), ctx.json(returnData));
    }),
]

async function sleep(timeout) {
    return new Promise((resolve) =&amp;gt; {
        setTimeout(resolve, timeout);
    });
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1661325072430&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// index.js에 추가할 코드
if (process.env.NODE_ENV === 'development') {
    const {worker} = require('./mocks/browser')
    worker.start()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1308&quot; data-origin-height=&quot;66&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FDcnG/btrKqFrMbV2/PwAW4NHFxJQX9V9h25yYx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FDcnG/btrKqFrMbV2/PwAW4NHFxJQX9V9h25yYx0/img.png&quot; data-alt=&quot;Mocking 동작 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FDcnG/btrKqFrMbV2/PwAW4NHFxJQX9V9h25yYx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFDcnG%2FbtrKqFrMbV2%2FPwAW4NHFxJQX9V9h25yYx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1308&quot; height=&quot;66&quot; data-origin-width=&quot;1308&quot; data-origin-height=&quot;66&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mocking 동작 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  Infinite Scroll ?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;무한 스크롤은 페이지 하단 영역까지 이동할 경우 새로운 데이터를 추가로 페칭하여 화면에 나타내어, 스크롤을 무한히 이동하며 새로운 데이터를 불러오는 방식입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;사용자 참여 및 콘텐츠 탐색이 쉽고, 특히 모바일 환경에서 유용하게 적용됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;페이지 성능이 느려질 수 있으며, 특정 항목 검색 및 원하는 위치로 이동이 힘들다는 단점이 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;리액트에서 무한 스크롤을 구현하는 방법은 주로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;scroll 이벤트&lt;/span&gt;를 사용하거나 기본 Web API로 제공되는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;Intersection Observer를 사용&lt;/span&gt;하는 2가지 방법이 있습니다. (혹은 &quot;더보기&quot; 버튼과 같은 버튼 이벤트를 사용하는 경우도 있습니다.)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  Scroll 이벤트로 구현하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;1214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LbISD/btrKvg4rJi9/AX4luMvNzsv7802kqMDmgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LbISD/btrKvg4rJi9/AX4luMvNzsv7802kqMDmgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LbISD/btrKvg4rJi9/AX4luMvNzsv7802kqMDmgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLbISD%2FbtrKvg4rJi9%2FAX4luMvNzsv7802kqMDmgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;578&quot; height=&quot;520&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;1214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;8b56&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;scrollTop은 요소의 처음부터 현재 화면에 보이는 부분까지의 높이입니다. 요소의 처음부터 얼마나 내려왔는지 알 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li id=&quot;7a7e&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;scrollHeight는 요소에 들어있는 컨텐츠의 전체 높이입니다. (패딩과 보더 포함, 마진은 제외)&lt;/span&gt;&lt;/li&gt;
&lt;li data-selectable-paragraph=&quot;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;offsetHeight는 요소의 높이입니다. (패딩, 보더, 스크롤바 포함, 마진은 제외)&lt;/span&gt;&lt;/li&gt;
&lt;li id=&quot;2f90&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;clientHeight는 요소 내부의 높이, 즉 사용자에게 보여지는 요소의 높이 입니다. (패딩 포함, 스크롤바, 보더, 마진은 제외)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;구현 포인트 !&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;1. scroll이 영역의 끝에 닿았다고 판단하는 기준&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;middot; scrollTop + clientHeight &amp;gt;= clientHeight&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;=&amp;gt; 위 이미지를 보면 scrollTop(현재까지 내려온 위치), clientHeight(사용자에게 보여지는 높이)를 더한 값이 scrollHeight(요소 전체 높이)와 같거나 크면 스크롤이 영역의 끝에 닿았다고 판단할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;2. 다음 데이터를 불러오는 로직&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&amp;middot;&amp;nbsp;추가 데이터를 렌더링 할 로직 필요&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;u&gt;(소스 코드는 더보기란 참고해주세요)&lt;/u&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1661325395040&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, {useEffect, useState, useRef} from &quot;react&quot;;

const MainContainer1 = () =&amp;gt; {

    const ViewportRef = useRef(null); // 스크롤 위치를 탐색 및 이벤트 처리를 위해
    const throttle = useRef(null); // 쓰로틀링 처리를 위해

    const [nextInfo, setNextInfo] = useState({
        hasNext: false,
        nextPage: 0,
    }); // 다음 데이터 존재 여부
    const [totalData, setTotalData] = useState([]); // 렌더링되는 전체 데이터
    const [isLoading, setIsLoading] = useState(false); // 새로운 데이터를 추가로 불러올 때 로딩처리를 위해

    useEffect(() =&amp;gt; { // 스크롤 이벤트 정의
        ViewportRef.current.addEventListener(&quot;scroll&quot;, handleScroll);

        /*
            cleanup function ( 정리 함수 or 뒷 정리 함수 ) : 상태의 종료를 반환함수에 정의
                함수에 사용되었던 메모리 공간을 반환
                등록한 이벤트 리스너가 메모리 반환이 되지않아, 메모리 누수로 이어지는 현상을 항상 방지
         */
        return () =&amp;gt; {
            ViewportRef.current.removeEventListener(&quot;scroll&quot;, handleScroll);
        };
    });

    useEffect(() =&amp;gt; {
        callData(1); // 초기값 불러오기
    }, []);

    const callData = async (pageNum) =&amp;gt; { // 데이터 추가로 불러오는 로직

        setIsLoading(true); //로딩 true

        const selectData = await fetch(`/api/getData?page=${pageNum}`, {
            headers: {
                &quot;Content-type&quot;: &quot;application/json; charset=UTR-8;&quot;
            }
        }).then((res) =&amp;gt; {
            if (res.status === 200) {
                return res.json();
            }
        }); // 데이터 불러오기

        setTotalData((prev) =&amp;gt; [...prev, ...selectData.data]); // 불러온 데이터 추가

        setNextInfo((prev) =&amp;gt; ({
            ...prev,
            hasNext: selectData.hasNext,
            nextPage: selectData.page + 1,
        })); // 다음 데이터 존재 여부 최신화

        setIsLoading(false);  //로딩 false

    }

    const handleScroll = () =&amp;gt; { // 스크롤 이벤트

        if (!throttle.current) { // 쓰로틀링 처리

            throttle.current = setTimeout(async () =&amp;gt; {

                const scrollHeight = ViewportRef.current?.scrollHeight;
                const scrollTop = ViewportRef.current?.scrollTop;
                const clientHeight = ViewportRef.current?.clientHeight;

                if (scrollTop + clientHeight &amp;gt;= scrollHeight &amp;amp;&amp;amp; nextInfo.hasNext) { // 사용자 스크롤이 영역 하단에 위치할때 &amp;amp;&amp;amp; 다음 데이터가 존재할때
                    await callData(nextInfo.nextPage); // 추가 데이터 불러오기 로직 실행
                }

                throttle.current = null;

            }, 300);

        }

    }

    return (
        &amp;lt;div style={{
            position: &quot;absolute&quot;,
            width: '50%',
            height: '500px',
            overflow: 'auto',
        }} ref={ViewportRef}&amp;gt;

            {
                totalData.map((dr, idx) =&amp;gt; {
                    return &amp;lt;div key={idx} style={{
                        width: '200px',
                        height: '160px',
                        margin: &quot;20px&quot;,
                        border: &quot;1px solid black&quot;
                    }}&amp;gt; {dr.name} &amp;lt;/div&amp;gt;
                })
            }

            {
                isLoading &amp;amp;&amp;amp; &amp;lt;div&amp;gt; Loading &amp;lt;/div&amp;gt;
            }

        &amp;lt;/div&amp;gt;
    )

}

export default MainContainer1;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;scroll 이벤트로 구현 시 단점&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;스크롤 시 수많은 이벤트가 동기적으로 실행될 수 있습니다. 페이지 내 요소가 각각의 목적(광고, 레이지 로딩, 무한 스크롤 등 )의 이유로 scroll 이벤트를 리스닝하기 때문에 이에 상응하는 콜백이 무수히 많이 실행 될 수 있으며 이는 메인 스레드에 큰 부하를 줄 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;getBoundingClientRect (뷰포트에 상대적인 위치 정보를 제공하는 객체) 메서드는 호출 시 값(top, right 등)을 정확히 읽기 위하여 큐를 flush 하고 스타일을 적용함으로써 다 수의 reflow를 발생 시킬 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;* reflow&lt;/span&gt;&lt;/b&gt; : DOM이 화면에 표시되는 구조가 바뀔 때 또는 CSS클래스가 바뀔 때 일어나며, DOM 트리가 배치되는 위치를 전체적으로 다시 계산하여 화면에 출력하는 것을 의미합니다. 전체적인 위치를 다시 계산해야하므로 repaint 보다 자원 소모가 큽니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  Intersection Observer API로 구현하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;scroll 이벤트의 단점을 해결하기 위해 주로 사용하는 것이 Intersection Observer API 입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Intersection Observer API는 브라우저 Viewport와 Target으로 설정한 요소의 교차점을 관찰하여 그 Target이 Viewport에 포함되는지 구별하는 기능을 제공합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;new IntersectionObserver(callback, options) 를 통해 생성한 인스턴스로 관찰차를 초기화하고 관찰할 대상을 지정합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;상세 정보&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;u&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;1. callback 인수&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;middot; 관찰할 대상이 등록되거나 가시성(보이는지 안보이는지, threshold와 만날 때)에 변화가 생기면 콜백을 실행합니다.&lt;br /&gt;&amp;middot; 콜백은 2개의 인수를 가집니다. ( entries, observer )&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199;&quot;&gt;[ observer ]&lt;/span&gt;&lt;/b&gt;&amp;nbsp;&lt;/span&gt;:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;콜백이 실행되는 해당 인스터스를 참조합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;[ entries ]&lt;/span&gt;&lt;/b&gt; :&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;IntersectionObserverEntry(루트요소와 타겟요소 교차의 상황) 인스턴스를 담은 배열입니다. 포함된 프로퍼티들은 모두 읽기 전용 입니다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;
&lt;table style=&quot;border-collapse: collapse; width: 97.3934%; height: 187px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style16&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 27px;&quot;&gt;
&lt;td style=&quot;width: 1.21655%; height: 27px; text-align: left;&quot; colspan=&quot;2&quot; rowspan=&quot;7&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;nbsp;boundingClientRect&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;타겟 요소의 사각형(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly&quot;&gt;DOMRectReadOnly&lt;/a&gt;) 정보, reflow를 발생시키지 않음.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;nbsp;intersectionRect&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타겟 요소의 가시성&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly&quot;&gt;DOMRectReadOnly&lt;/a&gt;&lt;span style=&quot;color: #666666;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 감지된 부분의 정보&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8;&quot;&gt;&amp;nbsp;intersectionRatio&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타겟 요소가 루트 요소와 얼마나 교차하는지는지에 대한 정보&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8;&quot;&gt;&amp;nbsp;isIntersecting&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타겟 요소와 루트요소가 교차하는 지 여부를 Boolean 값으로 반환&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8;&quot;&gt;&amp;nbsp;rootBounds&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;루트 요소의 사각형 정보&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly&quot;&gt;DOMRectReadOnly&lt;/a&gt;&lt;span style=&quot;color: #666666;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 반환, rootMargin 옵션 설정에 영향을 받음.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8;&quot;&gt;&amp;nbsp;target&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타겟 요소 반환&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8;&quot;&gt;&amp;nbsp;time&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문서가 만들어진 표준 신간을 기준으로 타겟 요소와 루트 요소의 교차가 발생한 시간을 반환&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;2. option 인수&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&amp;middot; root, rootMargin, threshold 속성값을 지정할 수 있습니다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;table style=&quot;border-collapse: collapse; width: 97.3934%; height: 10px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style16&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 1.21655%; height: 10px; text-align: left;&quot; colspan=&quot;2&quot; rowspan=&quot;7&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;nbsp;root&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타겟의 가시성을 검사하기 위해 뷰포트 대신 사용할 요소 객체를 지정&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;타겟의 조상 요소로 지정하며, 지정하지 않거나 null(기본값) 인 경우 브라우저의 뷰포트가 기본 사용&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;nbsp;rootMargin&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여백을 이용해 루트 범위를 확장하거나 축소가 가능&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본값은 &quot;0px 0px 0px 0px&quot; 이며 단위 필수 입력 해야함&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #ef6f53; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8;&quot;&gt;&amp;nbsp;intersectionRatio&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵저버가 실행되기 위해 타겟의 가시성이 얼마나 필요한지 백분율로 표시&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기본값은 Array 타입의 [0] 이지만, Number 타입의 단일 값으로도 작성 가능&lt;br /&gt;&lt;br /&gt;Ex )&amp;nbsp;&lt;br /&gt;=&amp;gt; 0 : 타겟의 가장자리 픽셀이 루트 범위를 교차하는 순간 옵저버 실행&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;0.3 : 타겟의 가시성이 30% 일 때 옵저버 실행&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;[0, 0.3, 1] : 타겟의 가시성이 0%, 30%, 100% 일때 모두 옵저버 실행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;u&gt;3. Methods&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;middot; IntersectionObserver.observe(targetElement) : 타겟 요소 관찰 시작&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;middot; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;IntersectionObserver.unobserve(targetElement) : 타겟 요소 관찰 중지&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;middot; &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;IntersectionObserver.disconnect( ) : 인스턴스의 타겟 요소들에 대한 모든 관찰 중지&lt;/span&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;middot; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;IntersectionObserver.takerecords(targetElement) : IntersectionObserverEntry 인스턴스들의 배열을 리턴&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;u&gt;(소스 코드는 더보기란 참고해주세요)&lt;/u&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1661413036963&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, {useEffect, useState, useRef} from &quot;react&quot;;

const MainContainer1 = () =&amp;gt; {

    const [totalData, setTotalData] = useState([]); // 렌더링되는 전체 데이터
    const [isLoading, setIsLoading] = useState(false); // 새로운 데이터를 추가로 불러올 때 로딩처리를 위해
    const [nextInfo, setNextInfo] = useState({
        hasNext: false,
        nextPage: 0,
    }); // 다음 데이터 존재 여부

    useEffect(() =&amp;gt; {
        callData(1); // 초기값 불러오기
    }, []);

    const observerRef = useRef(null);

    const observer = (node) =&amp;gt; {

        if (isLoading) return;

        observerRef.current &amp;amp;&amp;amp; observerRef.current.disconnect();

        observerRef.current = new IntersectionObserver(async ([entry]) =&amp;gt; {
            if (entry.isIntersecting &amp;amp;&amp;amp; nextInfo.hasNext) {
                await callData(nextInfo.nextPage);
            }
        });

        node &amp;amp;&amp;amp; observerRef.current.observe(node);

    };

    const callData = async (pageNum) =&amp;gt; { // 데이터 추가로 불러오는 로직

        setIsLoading(true); //로딩 true

        const selectData = await fetch(`/api/getData?page=${pageNum}`, {
            headers: {
                &quot;Content-type&quot;: &quot;application/json; charset=UTR-8;&quot;
            }
        }).then((res) =&amp;gt; {
            if (res.status === 200) {
                return res.json();
            }
        }); // 데이터 불러오기

        setTotalData((prev) =&amp;gt; [...prev, ...selectData.data]); // 불러온 데이터 추가

        setNextInfo((prev) =&amp;gt; ({
            ...prev,
            hasNext: selectData.hasNext,
            nextPage: selectData.page + 1,
        })); // 다음 데이터 존재 여부 최신화

        setIsLoading(false);  //로딩 false

    }

    return (

        &amp;lt;div style={{
            position: &quot;absolute&quot;,
            width: '50%',
            height: '500px',
            overflow: 'auto',
        }}&amp;gt;

            {
                totalData.map((dr, idx) =&amp;gt; {
                    return &amp;lt;div key={idx} style={{
                        width: '200px',
                        height: '160px',
                        margin: &quot;20px&quot;,
                        border: &quot;1px solid black&quot;
                    }}&amp;gt; {dr.name} &amp;lt;/div&amp;gt;
                })
            }

            {
               nextInfo.hasNext &amp;amp;&amp;amp; &amp;lt;div ref={observer}/&amp;gt;
            }

            {
                isLoading &amp;amp;&amp;amp; &amp;lt;div&amp;gt; Loading &amp;lt;/div&amp;gt;
            }

        &amp;lt;/div&amp;gt;

    )

}

export default MainContainer1;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &amp;nbsp;참고한&amp;nbsp;글&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1661414336554&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;실전 Infinite Scroll with React&quot; data-og-description=&quot;시작하며 안녕하세요. 카카오엔터프라이즈 워크코어개발셀에서 프론트엔드 개발을 담당하고 있는 Denis(배형진) 입니다. 약 1년 전, 저는 프레임워크의 선택, React vs Angular 이라는 포스팅을 통해 &quot; data-og-host=&quot;tech.kakaoenterprise.com&quot; data-og-source-url=&quot;https://tech.kakaoenterprise.com/149&quot; data-og-url=&quot;https://tech.kakaoenterprise.com/149&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eAMDX/hyPzzkI4nS/igQfckOPHCDauo8EWMtwk1/img.jpg?width=800&amp;amp;height=360&amp;amp;face=0_0_800_360,https://scrap.kakaocdn.net/dn/wLyCt/hyPzuKoxPB/VPjNfPYjUFDphbMzjygUrk/img.jpg?width=800&amp;amp;height=360&amp;amp;face=0_0_800_360,https://scrap.kakaocdn.net/dn/3Q8du/hyPzvifJL0/JiDxK5RfTh8H3FNUx1QCr0/img.jpg?width=860&amp;amp;height=800&amp;amp;face=0_0_860_800&quot;&gt;&lt;a href=&quot;https://tech.kakaoenterprise.com/149&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tech.kakaoenterprise.com/149&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eAMDX/hyPzzkI4nS/igQfckOPHCDauo8EWMtwk1/img.jpg?width=800&amp;amp;height=360&amp;amp;face=0_0_800_360,https://scrap.kakaocdn.net/dn/wLyCt/hyPzuKoxPB/VPjNfPYjUFDphbMzjygUrk/img.jpg?width=800&amp;amp;height=360&amp;amp;face=0_0_800_360,https://scrap.kakaocdn.net/dn/3Q8du/hyPzvifJL0/JiDxK5RfTh8H3FNUx1QCr0/img.jpg?width=860&amp;amp;height=800&amp;amp;face=0_0_860_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;실전 Infinite Scroll with React&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시작하며 안녕하세요. 카카오엔터프라이즈 워크코어개발셀에서 프론트엔드 개발을 담당하고 있는 Denis(배형진) 입니다. 약 1년 전, 저는 프레임워크의 선택, React vs Angular 이라는 포스팅을 통해&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tech.kakaoenterprise.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1661414344763&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;실무에서 느낀 점을 곁들인 Intersection Observer API 정리&quot; data-og-description=&quot;실무에서 Intersection Observer API를 사용해보고 느낀 생각정리&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@elrion018/%EC%8B%A4%EB%AC%B4%EC%97%90%EC%84%9C-%EB%8A%90%EB%82%80-%EC%A0%90%EC%9D%84-%EA%B3%81%EB%93%A4%EC%9D%B8-Intersection-Observer-API-%EC%A0%95%EB%A6%AC#intersection-observer-api%EB%9E%80&quot; data-og-url=&quot;https://velog.io/@elrion018/실무에서-느낀-점을-곁들인-Intersection-Observer-API-정리&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d4v0PC/hyPzpoNe72/2q4F9gFneWx2hQXP2mssB0/img.jpg?width=493&amp;amp;height=456&amp;amp;face=0_0_493_456,https://scrap.kakaocdn.net/dn/b1KGIe/hyPzndswS9/9zGzOOCPVetN0fuKHdakz1/img.jpg?width=493&amp;amp;height=456&amp;amp;face=0_0_493_456,https://scrap.kakaocdn.net/dn/bENzij/hyPzvifJ6r/1SETAFG3hzzMwkTUiWgFFk/img.jpg?width=493&amp;amp;height=456&amp;amp;face=0_0_493_456&quot;&gt;&lt;a href=&quot;https://velog.io/@elrion018/%EC%8B%A4%EB%AC%B4%EC%97%90%EC%84%9C-%EB%8A%90%EB%82%80-%EC%A0%90%EC%9D%84-%EA%B3%81%EB%93%A4%EC%9D%B8-Intersection-Observer-API-%EC%A0%95%EB%A6%AC#intersection-observer-api%EB%9E%80&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@elrion018/%EC%8B%A4%EB%AC%B4%EC%97%90%EC%84%9C-%EB%8A%90%EB%82%80-%EC%A0%90%EC%9D%84-%EA%B3%81%EB%93%A4%EC%9D%B8-Intersection-Observer-API-%EC%A0%95%EB%A6%AC#intersection-observer-api%EB%9E%80&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d4v0PC/hyPzpoNe72/2q4F9gFneWx2hQXP2mssB0/img.jpg?width=493&amp;amp;height=456&amp;amp;face=0_0_493_456,https://scrap.kakaocdn.net/dn/b1KGIe/hyPzndswS9/9zGzOOCPVetN0fuKHdakz1/img.jpg?width=493&amp;amp;height=456&amp;amp;face=0_0_493_456,https://scrap.kakaocdn.net/dn/bENzij/hyPzvifJ6r/1SETAFG3hzzMwkTUiWgFFk/img.jpg?width=493&amp;amp;height=456&amp;amp;face=0_0_493_456');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;실무에서 느낀 점을 곁들인 Intersection Observer API 정리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;실무에서 Intersection Observer API를 사용해보고 느낀 생각정리&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>JavaScript/React</category>
      <category>Infinite Scroll</category>
      <category>javascript</category>
      <category>react</category>
      <category>무한 스크롤</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/70</guid>
      <comments>https://ji-musclecode.tistory.com/70#entry70comment</comments>
      <pubDate>Thu, 1 Sep 2022 18:10:26 +0900</pubDate>
    </item>
    <item>
      <title>React - Virtual Scroll 직접 구현해보기 (part. 1)</title>
      <link>https://ji-musclecode.tistory.com/69</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;✅ React 가상 스크롤은 렌더링 최적화 방법 중 하나입니다. 라이브러리를 사용하여 구현해본 경험은 있으나, 직접 구현해보고 더 자세히 이해하기 위한 과정을 글로 작성합니다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;* &lt;/span&gt;ps) 가상스크롤의 대표적인 라이브러리는 react-virtualized와 react-window 가 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  Virtual Scroll ?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;API를 호출하여 100, 1000개 이상의 데이터를 불러와 화면에 렌더링한다고 가정했을 때 스크롤이 뻑뻑하거나, 심할 경우 브라우저가 다운되는 현상이 발생합니다. 이는 DOM에 대한 작업이 브라우저에 큰 부하를 걸기 때문입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;이러한 현상을 개선하기 위해 Virtual Scroll 개념을 도입하면 많은 데이터라 하더라도 무리 없이 정상적으로 스크롤할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;&lt;b&gt;Virtual Scroll의 원리&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;- &lt;span style=&quot;background-color: #f6e199;&quot;&gt;전체 데이터(DOM)를 렌더링 하는 것이 아닌 현재 사용자가 보고 있는 화면의 스크롤 위치를 계산하여 해당 위치에 맞는 데이터(DOM)만 그려주는 원리&lt;/span&gt;입니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  어떻게 구현할까 ?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJVJSs/btrKcw2KhOQ/1zsSssTkHheaTtnkGtiTzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJVJSs/btrKcw2KhOQ/1zsSssTkHheaTtnkGtiTzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJVJSs/btrKcw2KhOQ/1zsSssTkHheaTtnkGtiTzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJVJSs%2FbtrKcw2KhOQ%2F1zsSssTkHheaTtnkGtiTzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;672&quot; height=&quot;378&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;가상 스크롤 개념에 대한 이미지를 보면서 생각해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;Total elemets&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;전체 데이터 높이만큼의 비어있는 박스 영역입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;실제로 전체 데이터를 렌더링하는 것이 아닌, 전체 데이터가 렌더링 되었다고 가정했을 때 그 높이만큼 계산하여 할당해주어야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;Rendered elements&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;렌더링을 한 데이터 영역입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;새롭게 렌더링 될 때마다 해당 영역의 위치를 계산하여&amp;nbsp;갱신시켜 주어야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;viewport&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;사용자가 실제로 보는 영역입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;구현 포인트 !&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; background-color: #f6e199;&quot;&gt;1. viewport가 최상위 컴포넌트, 그 하위로 Total elements, 마지막으로 Rendered elements 박스가 위치&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;middot; 사용자에게 보이는 영역인 viewport가 최상위 컴포넌트에 위치해야 합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;=&amp;gt; scroll 이벤트 처리가 필요합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;middot; 전체 데이터만큼의 높이를 가지는 Total elements 영역이 그 하위로 위치해야 합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;=&amp;gt; 보통 viewport 범위를 벗어나므로 viewport에서 overflow scroll 처리가 필요합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;middot; 실제로 렌더링되는 영역인 Rendered elements 영역이 마지막으로 위치합니다.&lt;br /&gt;=&amp;gt; 새로운 데이터가 렌더링이 되면 스크롤의 위치 갱신이 필요합니다. 갱신하지 않으면 Total elements의 영역 최상단에 붙어있기 때문에 어느 순간 viewport에 아무것도 보이지 않게 됩니다.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;2. viewport에서 스크롤의 위치에 따라 새로운 데이터를 렌더링 필요&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;middot;&lt;/span&gt;&amp;nbsp;addEventListener(&quot;scroll&quot;, 함수) 이벤트 사용 필요&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;middot;&lt;/span&gt;&amp;nbsp;새로운 데이터를 렌더링 할 로직 필요&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;  이제 코드로 살펴보겠습니다.&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;u&gt;(소스 코드는 더보기란 참고해주세요)&lt;/u&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;b&gt;1. Styled-Components를 사용하여 레더링 될 영역들의 CSS를 정의해줍니다.&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;import styled from 'styled-components';

export const Item = styled.div`
    height: 80px;
    margin: 10px;
    border: 1px solid black;
`;

export const Viewport = styled.div`
    position: absolute;
    width: 80%;
    height: 50%;
    overflow: scroll;
`

export const TotalElemets = styled.div`
    // position: relative;
    height:${props =&amp;gt; props.height}px;
`

export const RenderedElements = styled.div`
    // position: absolute;
    // width: 100%;
    transform: translateY(
        ${(props) =&amp;gt; props.offsetY}px
    );
`&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;b&gt;2. 가상 스크롤을 적용할 간단한 컴포넌트 하나를 만들어줍니다.&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;( 저의 경우 간단하게 이미지 3개가 들어가는 div를 1000개 렌더링 하는 컴포넌트를 만들었습니다. )&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1661237782096&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, {useEffect, useState, useRef} from &quot;react&quot;;
import {Viewport, TotalElemets, RenderedElements, Item} from &quot;../Style/css&quot;;

const MainContainer1 = () =&amp;gt; {

    const [totalData, setTotalData] = useState([]);

    useEffect(() =&amp;gt; {
        const Dt = [];
        for (let i = 0; i &amp;lt; 1000; i++) {
            Dt.push(&amp;lt;Item key={`item_${i}`}&amp;gt;
                {i}
                &amp;lt;img width=&quot;100px&quot; src={&quot;https://cdn.lamanus.kr/wp-content/uploads/2018/08/28225854/google-2048x1536.png&quot;}/&amp;gt;
                &amp;lt;img width=&quot;100px&quot; src={&quot;http://image.dongascience.com/Photo/2017/12/15130427942754.png&quot;}/&amp;gt;
                &amp;lt;img width=&quot;100px&quot; src={&quot;https://biz.chosun.com/resizer/mY58GeufwPAZxi09EAgkrIqCIx4=/616x0/smart/cloudfront-ap-northeast-1.images.arcpublishing.com/chosunbiz/YGC6GZ2VCZF3LA2PW3CYPTJZYA.png&quot;}/&amp;gt;
            &amp;lt;/Item&amp;gt;);
        }
        setTotalData(Dt);
    }, []);

    return (
        &amp;lt;Viewport&amp;gt;
            &amp;lt;TotalElemets&amp;gt;
                &amp;lt;RenderedElements&amp;gt;
                    {
                        totalData
                    }
                &amp;lt;/RenderedElements&amp;gt;
            &amp;lt;/TotalElemets&amp;gt;
        &amp;lt;/Viewport&amp;gt;
    )

}

export default MainContainer1;&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;818&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfwpMg/btrKpThvuZA/WSNdVEKR86xg7dq1EVQJeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfwpMg/btrKpThvuZA/WSNdVEKR86xg7dq1EVQJeK/img.png&quot; data-alt=&quot;예제 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfwpMg/btrKpThvuZA/WSNdVEKR86xg7dq1EVQJeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfwpMg%2FbtrKpThvuZA%2FWSNdVEKR86xg7dq1EVQJeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;440&quot; height=&quot;380&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;예제 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;b&gt;3. 가상 스크롤 적용 !&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1661243667269&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, {useEffect, useState, useRef} from &quot;react&quot;;
import {Viewport, TotalElemets, RenderedElements, Item} from &quot;../Style/css&quot;;

const MainContainer1 = () =&amp;gt; {

    const ViewportRef = useRef(null); // 스크롤 위치를 탐색하기 위해 필요

    const [totalData, setTotalData] = useState([]); // 전체 데이터
    const [dataRenderArr, setDataRenderArr] = useState([]); // 실제로 렌더링 할 데이터

    const [totalHeight, setTotalHeight] = useState(0); // 전체 데이터의 높이
    const [scrollTop, setScrollTop] = useState(0); // 현재 스크롤의 top 위치

    const curHeight = ViewportRef.current ? ViewportRef.current.clientHeight : 0; // 현재 Viewport 의 높이 (Viewport의 높이를 %로 주었기 때문에 따로 계산)
    const itemHeight = 100; // 렌더링되는 영역의 높이 (Item 태그의 경우 height 80px, margin 10px 로 총 80+10+10 = 100px 임)
    const nodePadding = Math.floor(curHeight / itemHeight) + 1; // 현재 화면에 보이는 아이템의 수

    const strIdx = Math.max(0, Math.floor(scrollTop / itemHeight) - nodePadding);
    const endIdx = strIdx + 2 * nodePadding + 1;
    /*
    strIdx, endIdx : 렌더링할 데이터 시작 idx(strIdx), 마지막 idx(endIdx)

    strIdx = Math.max(0, Math.floor(scrollTop / itemHeight) - nodePadding)의 의미
    - Math.floor(scrollTop / itemHeight) : 현재 Viewport 최상단에 보이는 데이터의 인덱스
    - nodePadding 은 현재 화면에 보이는 아이템의 수
    =&amp;gt; 스크롤을 내렸을 때 Viewport 에 보이는 최상단 데이터가 화면에 보이는 아이템의 수를 넘어갈 때부터 인덱스를 구하여 새로운 데이터를 렌더링 해야함 !!

    endIdx = strIdx + 2 * nodePadding + 1의 의미
    - strIdx + nodePadding : 현재 보이지 않는 스크롤로 내린 데이터
    - strIdx + 2 * nodePadding : Viewport 로 보이는 데이터
    - + 1 을 해준 이유는 Viewport 의 마지막 데이터가 가끔 누락되는 경우가 있어서!
     */

    const offsetY = strIdx * itemHeight; // 갱신할 Y축 위치

    useEffect(() =&amp;gt; {
        // 기본 데이터 만들기
        const Dt = [];
        for (let i = 0; i &amp;lt; 1000; i++) {
            Dt.push(&amp;lt;Item key={`item_${i}`}&amp;gt;
                {i}
                &amp;lt;img width=&quot;100px&quot;
                     src={&quot;https://cdn.lamanus.kr/wp-content/uploads/2018/08/28225854/google-2048x1536.png&quot;}/&amp;gt;
                &amp;lt;img width=&quot;100px&quot; src={&quot;http://image.dongascience.com/Photo/2017/12/15130427942754.png&quot;}/&amp;gt;
                &amp;lt;img width=&quot;100px&quot;
                     src={&quot;https://biz.chosun.com/resizer/mY58GeufwPAZxi09EAgkrIqCIx4=/616x0/smart/cloudfront-ap-northeast-1.images.arcpublishing.com/chosunbiz/YGC6GZ2VCZF3LA2PW3CYPTJZYA.png&quot;}/&amp;gt;
            &amp;lt;/Item&amp;gt;);
        }
        setTotalData(Dt);
        //

        setTotalHeight(Dt.length * itemHeight); // 전체 높이

        ViewportRef.current?.addEventListener(&quot;scroll&quot;, handleScrollHeight); // scroll 이벤트 연결

    }, []);

    // 전체 데이터가 바뀌거나, strIdx 가 바뀌면 새로운 데이터를 렌더링 해줘야함
    useEffect(() =&amp;gt; {
        setDataRenderArr(totalData.slice(strIdx, endIdx));
        console.log(strIdx, endIdx); // 콘솔로 인덱스 값을 체크하기위해
    }, [totalData, strIdx]);

    const handleScrollHeight = () =&amp;gt; {
        if (ViewportRef.current) {
            setScrollTop(ViewportRef.current.scrollTop); // 현재 스크롤 위치를 갱신
        }
    };

    return (
        &amp;lt;Viewport ref={ViewportRef}&amp;gt;
            &amp;lt;TotalElemets height={totalHeight}&amp;gt;
                &amp;lt;RenderedElements offsetY={`${offsetY}`}&amp;gt;
                    {
                        dataRenderArr
                    }
                &amp;lt;/RenderedElements&amp;gt;
            &amp;lt;/TotalElemets&amp;gt;
        &amp;lt;/Viewport&amp;gt;
    )

}

export default MainContainer1;&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2204&quot; data-origin-height=&quot;886&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y3KtS/btrKk9F8a0c/BNFkxFkkPKuS2yM8GeVdB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y3KtS/btrKk9F8a0c/BNFkxFkkPKuS2yM8GeVdB1/img.png&quot; data-alt=&quot;결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y3KtS/btrKk9F8a0c/BNFkxFkkPKuS2yM8GeVdB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY3KtS%2FbtrKk9F8a0c%2FBNFkxFkkPKuS2yM8GeVdB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;273&quot; data-origin-width=&quot;2204&quot; data-origin-height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;b&gt;4. 가상 스크롤 적용 전 후 비교&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9i5Ax/btrKpzcSSoB/c8dcKBEhI6uf3Ilufkzds1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9i5Ax/btrKpzcSSoB/c8dcKBEhI6uf3Ilufkzds1/img.png&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;288&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.1965%; margin-right: 10px;&quot; data-widthpercent=&quot;48.76&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9i5Ax/btrKpzcSSoB/c8dcKBEhI6uf3Ilufkzds1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9i5Ax%2FbtrKpzcSSoB%2Fc8dcKBEhI6uf3Ilufkzds1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1262&quot; height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CyVAr/btrKp5Cm59m/KFLGFKRkHrZWsCZviTP7H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CyVAr/btrKp5Cm59m/KFLGFKRkHrZWsCZviTP7H1/img.png&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;288&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;51.24&quot; style=&quot;width: 50.6407%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CyVAr/btrKp5Cm59m/KFLGFKRkHrZWsCZviTP7H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCyVAr%2FbtrKp5Cm59m%2FKFLGFKRkHrZWsCZviTP7H1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1326&quot; height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;좌 : 적용 전, 우 : 적용 후&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Chrome lighthouse로 분석해보면 performance 가 개선된 것을 확인할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt; &amp;nbsp;더 생각해 볼 것들&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;scroll 이벤트를 계속 호출하며 검사를 할 필요가 있을까 ? (&lt;span style=&quot;background-color: #ffffff;&quot;&gt;메모리 낭비, 메인스레드 부담)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;모바일 환경에서 scroll 이벤트가 동작하지 않는데, 어떻게 수정할까 ?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;미세한 화면 떨림 현상이 있는데 어떻게 수정할까 ?&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;공부하면서 여러 블로그 글을 읽어보고, 나름대로 구현을 해보면서 들었던 의문점들입니다. part. 2 에서는 이러한 의문점에 대해 개선해보고 생각한 내용들에 대해서 작성해보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt; &amp;nbsp; 정리&amp;nbsp;!&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;가상 스크롤은 많은 데이터를 렌더링 할 때 스크롤된 위치를 계산하여 그 위치에 해당하는 DOM만 그려주는 방식입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;렌더링 개선에 큰 효과 !&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt; &amp;nbsp;참고한&amp;nbsp;글&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1661299543865&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Implementing virtual scroll using react - TechBoxWeb&quot; data-og-description=&quot;You might need to deal with a huge amount of data and that data need to be rendered on DOM.So here virtual croll comes for rescue&quot; data-og-host=&quot;www.techboxweb.com&quot; data-og-source-url=&quot;https://www.techboxweb.com/implementing-virtual-scroll-using-react/&quot; data-og-url=&quot;https://www.techboxweb.com/implementing-virtual-scroll-using-react/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/LHKTC/hyPyHQGD30/esIREn6ozoCVyf0WPVzKvk/img.jpg?width=365&amp;amp;height=207&amp;amp;face=0_0_365_207,https://scrap.kakaocdn.net/dn/VVAQ4/hyPyEzCVLm/tVVWkb1TMiUc8NssrPcASK/img.jpg?width=365&amp;amp;height=207&amp;amp;face=0_0_365_207,https://scrap.kakaocdn.net/dn/ObinB/hyPyBpmnwz/I4PrUXLepObwIhIMeKe2KK/img.jpg?width=365&amp;amp;height=207&amp;amp;face=0_0_365_207&quot;&gt;&lt;a href=&quot;https://www.techboxweb.com/implementing-virtual-scroll-using-react/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.techboxweb.com/implementing-virtual-scroll-using-react/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/LHKTC/hyPyHQGD30/esIREn6ozoCVyf0WPVzKvk/img.jpg?width=365&amp;amp;height=207&amp;amp;face=0_0_365_207,https://scrap.kakaocdn.net/dn/VVAQ4/hyPyEzCVLm/tVVWkb1TMiUc8NssrPcASK/img.jpg?width=365&amp;amp;height=207&amp;amp;face=0_0_365_207,https://scrap.kakaocdn.net/dn/ObinB/hyPyBpmnwz/I4PrUXLepObwIhIMeKe2KK/img.jpg?width=365&amp;amp;height=207&amp;amp;face=0_0_365_207');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Implementing virtual scroll using react - TechBoxWeb&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;You might need to deal with a huge amount of data and that data need to be rendered on DOM.So here virtual croll comes for rescue&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.techboxweb.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1661245146423&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;||Project1|| #5 Virtual List 직접 구현하기 (feat. useThrottle)&quot; data-og-description=&quot;VirtualList를 구현하면서 어려웠던 부분을 추려본다.&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@parfaite73/Project1-5-Virtual-ListThrottle-feat.Express-%EC%84%9C%EB%B2%84&quot; data-og-url=&quot;https://velog.io/@parfaite73/Project1-5-Virtual-ListThrottle-feat.Express-서버&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/boWSdp/hyPyzYvEgt/n8m67Dhpj8JNmsUbSBrfdk/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/dvnnE7/hyPyMp0Ehb/wLDtcj2of2sBp5QzgsdtQ1/img.jpg?width=1536&amp;amp;height=2049&amp;amp;face=0_0_1536_2049,https://scrap.kakaocdn.net/dn/c21Wiy/hyPxm0JhsP/jWKWWYu4KhLBnbTG4Dzeg0/img.png?width=1244&amp;amp;height=1380&amp;amp;face=0_0_1244_1380&quot;&gt;&lt;a href=&quot;https://velog.io/@parfaite73/Project1-5-Virtual-ListThrottle-feat.Express-%EC%84%9C%EB%B2%84&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@parfaite73/Project1-5-Virtual-ListThrottle-feat.Express-%EC%84%9C%EB%B2%84&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/boWSdp/hyPyzYvEgt/n8m67Dhpj8JNmsUbSBrfdk/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/dvnnE7/hyPyMp0Ehb/wLDtcj2of2sBp5QzgsdtQ1/img.jpg?width=1536&amp;amp;height=2049&amp;amp;face=0_0_1536_2049,https://scrap.kakaocdn.net/dn/c21Wiy/hyPxm0JhsP/jWKWWYu4KhLBnbTG4Dzeg0/img.png?width=1244&amp;amp;height=1380&amp;amp;face=0_0_1244_1380');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;||Project1|| #5 Virtual List 직접 구현하기 (feat. useThrottle)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;VirtualList를 구현하면서 어려웠던 부분을 추려본다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>JavaScript/React</category>
      <category>javascript</category>
      <category>react</category>
      <category>Virtual Scroll</category>
      <category>가상스크롤</category>
      <author>김관장</author>
      <guid isPermaLink="true">https://ji-musclecode.tistory.com/69</guid>
      <comments>https://ji-musclecode.tistory.com/69#entry69comment</comments>
      <pubDate>Tue, 23 Aug 2022 18:10:43 +0900</pubDate>
    </item>
  </channel>
</rss>