<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>인생은 단 한 번뿐, 대충 살아서는 행복할 수 없어!</title>
    <link>https://jeongeuni.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 6 Aug 2026 16:42:40 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>정니정은니</managingEditor>
    <image>
      <title>인생은 단 한 번뿐, 대충 살아서는 행복할 수 없어!</title>
      <url>https://tistory1.daumcdn.net/tistory/5416111/attach/546948765a3b45b9a1453f7621653a8c</url>
      <link>https://jeongeuni.tistory.com</link>
    </image>
    <item>
      <title>제어 컴포넌트, 비제어 컴포넌트</title>
      <link>https://jeongeuni.tistory.com/121</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;b&gt;input같이 form 관련된 컴포넌트를 다룰 때 사용되는 개념&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 개념을 요약하자면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제어 컴포넌트는 &lt;b&gt;React로 폼 데이터를 관리하는 방식(useState)&lt;/b&gt;이고, &lt;br /&gt;비제어 컴포넌트는 &lt;b&gt;React의 상태를 사용하지 않고 폼 데이터를 관리하는 방식&lt;b&gt;(useRef)&lt;/b&gt;&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useState로 불필요한 렌더링이 필요없는 경우에는 useRef를 사용하는 것이 더 좋으니&lt;br /&gt;각각의 상황에 따라 선택하여 사용해보자!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제어 컴포넌트 VS 비제어 컴포넌트&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;lt;제어 컴포넌트&amp;gt; (use&lt;span data-token-index=&quot;0&quot;&gt;State&lt;/span&gt;)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 입력을 기반으로 자신의 state를 관리하고 업데이트한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 사용자의 입력을 받는 컴포넌트에 event 객체를 이용해 setState()로 값을 저장하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용자가 입력한 값과 저장되는 값이 실시간으로 동기화된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제어 컴포넌트의 값은&amp;nbsp;&lt;b&gt;항상 최신값&lt;/b&gt;을 유지한다. 새로운 입력 값이 생길때 마다 상태를 새롭게 갱신한다. &lt;br /&gt;이는 데이터와 UI에서 입력한 값이 항상 동기화됨을 알 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1701749040171&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  const [input, setInput] = useState(&quot;&quot;);
  const onChange = (e) =&amp;gt; {
    setInput(e.target.value);
  };

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;input onChange={onChange} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;lt;비제어 컴포넌트&amp;gt; &lt;span data-token-index=&quot;0&quot;&gt;(useRef)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 바닐라 자바스크립트와 크게 다르지 않은 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 바닐라 자바스크립트를 사용할 때 폼을 제출할때 (submit button)을 클릭할 때 요소 내부의 값을 얻어왔다. &lt;br /&gt;비제어 컴포넌트 또한 이와 유사한 방식으로 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;비제어 컴포넌트는 값이 실시간으로 동기화 되지 않는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드에서 값을 트리거 해야 값을 얻을 수 있다. 사진에선 [전송] 버튼을 클릭하면 console에 값이 찍힌다. &lt;br /&gt;[전송]버튼을 &lt;b&gt;클릭해 트리거 하기 전까지의 값은 변경되지 않는다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1701749106901&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function App() {
  const inputRef = useRef(); // ref 사용
  const onClick = () =&amp;gt; {
    console.log(inputRef.current.value);
  };

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;input ref={inputRef} /&amp;gt;
      &amp;lt;button type=&quot;submit&quot; onClick={onClick}&amp;gt;
        전송
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;제어 컴포넌트 &amp;rArr; 사용자가 입력을 하는 액션을 취할때마다 리렌더링을 발생시킴 &lt;br /&gt;비제어 컴포넌트 &amp;rArr; 사용자가 직접 트리거 하기 전까지는 리렌더링을 발생시키지도 않고 값을 동기화 시키지도 않음(클릭을 해야함)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1. 즉각적으로 값에 대한 피드백이 필요하다. =&amp;gt; 제어 컴포넌트 사용 (useState)&lt;br /&gt;ex) 즉각적인 유효성 검사, 버튼 disable처리, input에 숫자만 입력가능한 상황&lt;br /&gt;&lt;br /&gt;2. 즉각적인 피드백이 불필요하고 최종적인 값만 필요하다. 불필요한 렌더링 필요없다. =&amp;gt; 비제어 컴포넌트 사용 (useRef)&lt;br /&gt;ex) [전송]버튼 클릭 후, 값 체크&lt;/blockquote&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;- 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://velog.io/@yukyung/React-제어-컴포넌트와-비제어-컴포넌트의-차이점-톺아보기&quot;&gt;https://velog.io/@yukyung/React-제어-컴포넌트와-비제어-컴포넌트의-차이점-톺아보기&lt;/a&gt;&lt;/p&gt;</description>
      <category>프론트엔드 개발자가 될거야./react</category>
      <category>useRef</category>
      <category>useState</category>
      <category>비제어컴포넌트</category>
      <category>제어컴포넌트</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/121</guid>
      <comments>https://jeongeuni.tistory.com/121#entry121comment</comments>
      <pubDate>Tue, 5 Dec 2023 13:06:27 +0900</pubDate>
    </item>
    <item>
      <title>Map()과 Set(), iterable 객체</title>
      <link>https://jeongeuni.tistory.com/120</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;순회 가능한 객체 = &lt;span data-token-index=&quot;1&quot;&gt;iterable 객체&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;내부 요소를 하나씩 차례로 반환할 수 있는 객체이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;for of 루프를 통해 각 요소를 차례로 순회할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 배열(Array), 문자열(String), Map, Set&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;일반객체는 iterable 객체가 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반객체는 각 요소를 순회하려면 Object.keys / Object.values / Object.entries 사용하고 그 다음에 for of 루프를 적용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Map = 키-값 쌍을 저장하는 자료 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;순회 가능한(iterable)객체&lt;/b&gt;여서 &lt;b&gt;for...of문&lt;/b&gt;을 사용하여 Map의 내용을 순회할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 특징&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;키의 타입 유연성&lt;/b&gt;: 어떤 타입의 키도 허용한다. 객체나 함수 등도 키로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;순서 보장&lt;/b&gt;: 원소를 추가한 순서대로 순회된다. 이는 &lt;b&gt;객체가 키의 순서를 보장하지 않는 것과 대조적&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;크기 측정&lt;/b&gt;: size 프로퍼티를 통해 저장된 항목의 개수를 쉽게 알 수 있다. &amp;rArr; console.log(userMap.size); // 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가독성&lt;/b&gt;과 &lt;b&gt;성능&lt;/b&gt;면에서 이점을 얻을 수 있다. &lt;br /&gt;다만, &lt;b&gt;단순한 키-값 저장이 목적이라면 여전히 객체를 사용&lt;/b&gt;하는 것도 유효한 선택일 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1701662762746&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 키-값 쌍을 저장할 때
const myMap = new Map();
myMap.set('key1', 'value1');
myMap.set('key2', 'value2');&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1701662800961&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 키의 타입 유연성
const objKeyMap = new Map();
const keyObj = { id: 1 };
objKeyMap.set(keyObj, 'Value associated with an object key');
console.log(objKeyMap.get(keyObj)); // Value associated with an object key&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1701662837344&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 순서 보장
const orderedMap = new Map([
  ['three', 3],
  ['one', 1],
  ['four', 4],
  ['two', 2],
]);

for (const [key, value] of orderedMap) {
  console.log(key, value);
}
// three 3
// one 1
// four 4
// two 2&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;Set = 중복없이 유일한 값을 저장하는 자료 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;순회 가능한(iterable)객체&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;여서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;for...of문&lt;/b&gt;을 사용하여 Set의 내용을 순회할 수 있다.&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;Set 내의 값은 모두 유일해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Set은 순서가 있는 열거 가능한 요소의 집합이다.&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;- Set으로 배열에서 중복을 제거할 때&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1701662917010&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const array = [1, 2, 3, 1, 2, 4, 5];
const uniqueArray = [...new Set(array)];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Set을 이용하여 중복을 제거한 후, 전개 연산자(...)를 사용하여 다시 배열로 변환한다. &lt;br /&gt;결과적으로 uniqueArray는 중복이 제거된 배열이 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span data-token-index=&quot;0&quot;&gt;Set 생성하기&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1701663108223&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const uniqueNumbers = new Set();&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 data-token-index=&quot;0&quot;&gt;값 추가하기 (add &lt;/span&gt;&lt;span data-token-index=&quot;2&quot;&gt;메서드)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1701663120721&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;uniqueNumbers.add(1);
uniqueNumbers.add(2);
uniqueNumbers.add(3);
uniqueNumbers.add(1); // 이미 존재하는 값을 추가해도 무시됨 (중복 허용 X)&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 data-token-index=&quot;2&quot;&gt;- &lt;span data-token-index=&quot;0&quot;&gt;값이 존재하는지 확인하기 &lt;span style=&quot;color: #333333; text-align: start;&quot; data-token-index=&quot;0&quot;&gt;(has &lt;/span&gt;메서드)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1701663131201&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(uniqueNumbers.has(2)); // true
console.log(uniqueNumbers.has(4)); // false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;2&quot;&gt;&lt;span data-token-index=&quot;2&quot;&gt;- &lt;span data-token-index=&quot;0&quot;&gt;값 삭제하기 &lt;span style=&quot;color: #333333; text-align: start;&quot; data-token-index=&quot;0&quot;&gt;(delete&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;메서드)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1701663139683&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;uniqueNumbers.delete(2);&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 data-token-index=&quot;2&quot;&gt;&lt;span data-token-index=&quot;2&quot;&gt;- &lt;span data-token-index=&quot;0&quot;&gt;Set 비우기 &lt;span style=&quot;color: #333333; text-align: start;&quot; data-token-index=&quot;0&quot;&gt;(clear&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;메서드)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1701663151416&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;uniqueNumbers.clear();&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 data-token-index=&quot;2&quot;&gt;&lt;span data-token-index=&quot;2&quot;&gt;- &lt;span data-token-index=&quot;0&quot;&gt;Set의 크기 확인하기 &lt;span style=&quot;color: #333333; text-align: start;&quot; data-token-index=&quot;0&quot;&gt;(size&lt;span&gt;&amp;nbsp;프로퍼티&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1701663164599&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(uniqueNumbers.size); // 2 (삭제된 값이 반영되지 않은 크기)&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 data-token-index=&quot;2&quot;&gt;&lt;span data-token-index=&quot;2&quot;&gt;- &lt;span data-token-index=&quot;0&quot;&gt;Set 순회하기 (for...of문 또는 forEach 메서드 사용)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1701663174699&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for (const number of uniqueNumbers) {
  console.log(number);
}

// 또는 forEach 메서드 사용
uniqueNumbers.forEach((number) =&amp;gt; {
  console.log(number);
});&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS지식</category>
      <category>ES6</category>
      <category>iterable</category>
      <category>iterable 객체</category>
      <category>map</category>
      <category>set</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/120</guid>
      <comments>https://jeongeuni.tistory.com/120#entry120comment</comments>
      <pubDate>Mon, 4 Dec 2023 13:13:17 +0900</pubDate>
    </item>
    <item>
      <title>리액트 렌더링 최적화</title>
      <link>https://jeongeuni.tistory.com/119</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 랜더링 최적화에 대해 알아보기 전에 알아야할 사전지식을 먼저 정리하고 시작한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 리액트에서의 렌더링 = 함수를 호출하는 것&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-14 오후 9.15.30.png&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;330&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SA03s/btsAmtfg4yC/unK3D0w1Fv00MTV6VKQrbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SA03s/btsAmtfg4yC/unK3D0w1Fv00MTV6VKQrbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SA03s/btsAmtfg4yC/unK3D0w1Fv00MTV6VKQrbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSA03s%2FbtsAmtfg4yC%2FunK3D0w1Fv00MTV6VKQrbK%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;600&quot; height=&quot;143&quot; data-filename=&quot;스크린샷 2023-11-14 오후 9.15.30.png&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;330&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;App 컴포넌트가 호출되고 -&amp;gt; 내부 로직들이 싱행되고 -&amp;gt; return문의 리액트 element 반환하는 것&lt;br /&gt;이것이 리액트에서의 렌더링이다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;- 리렌더링 되는 조건&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. state가 바뀌었을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. props가 바뀌었을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 부모컴포넌트가 바뀌었을 때&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 불필요한 렌더링 발생 확인 지표&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. console.log&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. React Developer Tools &amp;rarr; Profiler&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 웹사이트의 컴포넌트들이 어떻게 렌더링되고 있는지를 보여주는 도구 &lt;br /&gt;: 어디 부분에서 렌더링이 오래 걸리고 불필요한 렌더링이 걸리는지 확인해야 한다면 용이!&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;- 리액트에서의 렌더링 과정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. render phase = 재조정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 호출하여 React Element를 반환하고 새로운 Virtual DOM을 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 이번이 첫번째 렌더링이 아니라면!!&lt;br /&gt;&lt;b&gt;이전 Virtual DOM과 현재 Virtual DOM을 비교하는 재조정 과정을 거친 후,&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Real DOM에 변경이 필요한 목록들을 체크해둔다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. commit phase&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;render phase에서 체크해놓았던 변경이 필요한 부분들을 Real DOM에 반영해주는 단계&lt;/b&gt;!!!&lt;br /&gt;만약, 변경이 필요한 부분들이 없다면 commit phase는 skip 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;불필요한 렌더링 방지하기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-14 오후 9.22.10.png&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXbqZK/btsAnBcNcdc/Y1rZQFKaNdWLvzBfDlGmN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXbqZK/btsAnBcNcdc/Y1rZQFKaNdWLvzBfDlGmN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXbqZK/btsAnBcNcdc/Y1rZQFKaNdWLvzBfDlGmN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXbqZK%2FbtsAnBcNcdc%2FY1rZQFKaNdWLvzBfDlGmN0%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;1392&quot; height=&quot;630&quot; data-filename=&quot;스크린샷 2023-11-14 오후 9.22.10.png&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;630&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;부모요소인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Parent 컴포넌트, 자식요소인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;FirstChild 컴포넌트,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;SecondChild 컴포넌트이다.&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;valueForFirstChild state에게 변경이 생기면&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Parent 컴포넌트와 FirstChild 컴포넌트는 본인들이 사용하는 값(state, props)에 변경이 생겨서 &lt;br /&gt;변경이 된 값을 보여줘야하므로 리렌더링이 되는 것이 당연하다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;그런데 SecondChild 컴포넌트 입장에서는 변경된 값(state, props)도 없는데 &lt;br /&gt;똑같은 정보를 보여주기 위해 리렌더링 되는 게 불필요해 보인다. &lt;br /&gt;더불어서 SecondChild 컴포넌트가 리렌더링이 되면 약 1000개의 GrandChild 컴포넌트들도 리렌더링이 될 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SecondChild 컴포넌트는 Parent 컴포넌트의 변경된 state가 아닌 함수만을 props로 받고 있기 때문에 &lt;br /&gt;리렌더링이 안될 것도 같지만 리렌더링이 되고있다.&lt;br /&gt;왜냐하면 &lt;b&gt;Parent 컴포넌트가 매번 리렌더링 될 때마다 handleClick이라는 함수도 재생성&lt;/b&gt;이 되고 &lt;br /&gt;&lt;b&gt;이전 handleClick과 현재 handleClick 함수는 서로 다른 참조값을 가지게 되며 이 둘은 서로 다른 함수&lt;/b&gt;이다. &lt;br /&gt;즉, handleClick도 props이니 달라지면서 컴포넌트가 리렌더링 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;handleClick 함수의 참조값이 바뀌지 않도록 해주면 불필요한 리렌더링을 방지해 줄 수 있지 않을까? &lt;br /&gt;어떻게 매번 리렌더링 될 때마다 함수의 참조값을 유지할 수 있을까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;함수를 메모이제이션 해주는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;useCallback&lt;/b&gt;&lt;/span&gt; 사용하자!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;근데.. console.log를 찍어보니 여전히 리렌더링이 되고있다.&lt;br /&gt;그렇다면 효과가 전혀 없는 것일까? 아니다. 그래도 효과는 있다.&amp;nbsp;&lt;br /&gt;&lt;b&gt;render phase는 실행되지만 &lt;span data-token-index=&quot;0&quot;&gt;commit phase는 실행되지 않는다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;더 자세히 설명하자면 &lt;br /&gt;리액트에서 렌더링이 일어날 때마다 &lt;br /&gt;render phase와 commit phase의 렌더링 프로세스를 거치게 되는데 &lt;br /&gt;render phase는 실행되지만 &lt;br /&gt;useCallback을 활용해서 props 값을 이전과 같게 유지해주었기 때문에 &lt;br /&gt;render phase의 재조정과정에서 Real DOM에 변경이 필요하지 않다고 판단을 해준다. &lt;br /&gt;그래서 &lt;span data-token-index=&quot;1&quot;&gt;commit phase는 실행되지 않는다.&lt;/span&gt;&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;span data-token-index=&quot;1&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;render phase도 막아줄 수는 없을까? 아직도 SecondChild 컴포넌트가 리렌더링 되고있는데..&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;React.memo&lt;/b&gt;&lt;/span&gt;도 사용하자!!!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React.memo는&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전달받은 props가 이전 props와 비교했을 때 같으면 컴포넌트의 리렌더링을 막아주고 &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마지막으로 렌더링된 결과를 재사용하는 고차 컴포넌트&lt;/span&gt;&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 props를 비교할 때 기본적으로 얕은 비교를 통해서 진행한다. &lt;br /&gt;얕은 비교란 원시타입은 값이 다른지 비교하고 참조타입은 참조값이 같은지 비교하는 것이다. &lt;br /&gt;(콜스택만 비교한다. 메모리힙은 비교하지 않는다.)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SecondChild 컴포넌트에 React.memo를 적용하면 &lt;br /&gt;SecondChild 컴포넌트가 렌더링 과정에 진입하기 전에 &lt;br /&gt;props 값인 onClick에 대해서 이전 값과 현재 값이 다른지를 비교해준다. &lt;br /&gt;서로 같은 값이면 SecondChild 컴포넌트의 렌더링 과정은 진행이되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;그렇다면.. 함수가 아닌 객체를 props로 넘겨주게 된다면 리렌더링이 발생할까?&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-14 오후 9.34.56.png&quot; data-origin-width=&quot;2740&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8S9ab/btsAjnz3fcV/2Cr3TNjKMcuLVQM6F56Wz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8S9ab/btsAjnz3fcV/2Cr3TNjKMcuLVQM6F56Wz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8S9ab/btsAjnz3fcV/2Cr3TNjKMcuLVQM6F56Wz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8S9ab%2FbtsAjnz3fcV%2F2Cr3TNjKMcuLVQM6F56Wz0%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;2740&quot; height=&quot;924&quot; data-filename=&quot;스크린샷 2023-11-14 오후 9.34.56.png&quot; data-origin-width=&quot;2740&quot; data-origin-height=&quot;924&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SecondChild 컴포넌트 입장에서는 Parent 컴포넌트로부터 매번 다른 item을 전달받기 때문이다.&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;Parent 컴포넌트가 리렌더링 될 때마다 &lt;br /&gt;item 객체가 새로 생성이 되고&amp;nbsp;매번 다른 참조값을 가지게 되는 것이다. &lt;br /&gt;그래서 React.memo가 정상적으로 작동되지 않는다.&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;객체 props에 React.memo가 정상적으로 작동되게 하기 위해서는&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 값을 메모이제이션해주는&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; useMemo&lt;/b&gt;&lt;/span&gt;를 사용하자!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 useCallback, React.memo, useMemo로 렌더링 최적화하는 방법에 대해 알아보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지만.. 이를 남발하는 것은 좋지 않다...!!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 또한 하나하나가 메모리를 차지하고 비용이 드는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못 사용한다면 최적화가 아니라 오히려 더 성능을 망칠 수가 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리렌더링이 자주 되는 컴포넌트라고 해서 컴포넌트 내부의 함수를 무작정 useCallback으로 감싸주는 경우, &lt;br /&gt;부모로부터 전달받은 props가 매번 바뀔 수 밖에 없는 상황에서 자식 컴포넌트에 React.memo를 적용해주는 경우에서는 &lt;br /&gt;최적화를 시도하기 전보다 웹 사이트 성능이 더 안 좋아질 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제대로 이해를 하고 써야하는데 사실 복잡한 로직 속에서 이를 제대로 쓰기란 쉽지 않을 것이다.&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;그래서 useCallback, React.memo, useMemo를 사용하기 전에,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드적으로 개선할 수 있는 방법은 리팩토링을 해서 개선하도록 해야한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예를들어, 불필요하게 리렌더링이 되는 자식요소는&amp;nbsp;&lt;span data-token-index=&quot;1&quot;&gt;children으로 주입&lt;/span&gt;하자! &lt;/b&gt;&lt;br /&gt;이렇게 리팩토링 해주면 리렌더링 되지 않는다. &lt;br /&gt;왜냐하면 부모컴포넌트 return문에는 children에 대한 React.createElement가 존재하지 않기 때문에 &lt;br /&gt;부모 컴포넌트가 렌더링되더라도 자식 컴포넌트는 호출되지 않기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 것은.. &lt;br /&gt;&lt;b&gt;미리 성급하게 최적화를 하지않고 정말 최적화가 필요할 때 최적화를 해주는 것이다.&amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;너무나도 많은 도움이 된 테코톡 앨버님의 영상!! 너무 감사합니다 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://youtu.be/1YAWshEGU6g?si=sWHdyM1A4YhVvKjT&quot;&gt;https://youtu.be/1YAWshEGU6g?si=sWHdyM1A4YhVvKjT&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=1YAWshEGU6g&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/b6NNQd/hyUuWvEd7V/jg5qy97R0NB9WYUjxWG8Tk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=886_300_964_384&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-original-url=&quot;&quot; data-video-title=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/1YAWshEGU6g&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;</description>
      <category>CS지식</category>
      <category>React.memo</category>
      <category>useCallback</category>
      <category>useMemo</category>
      <category>리액트 랜더링 최적화</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/119</guid>
      <comments>https://jeongeuni.tistory.com/119#entry119comment</comments>
      <pubDate>Tue, 14 Nov 2023 21:43:20 +0900</pubDate>
    </item>
    <item>
      <title>주소창에 google.com을 입력하면 일어나는 일</title>
      <link>https://jeongeuni.tistory.com/118</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;주소창에 google.com을 입력하면 일어나는 과정을 공부했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각보다 너무너무..!!!! 복잡했다..&lt;br /&gt;10개 넘는 블로그, 5개 넘은 동영상을 시청하며 드디어 이 과정을 나름대로 이해하고 정리할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단은 비교적 간단하게 정리해보았지만 하나하나 더 깊게 들어가서 마스터 하고싶다.  &lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;사용자가 웹 브라우저를 통해 www.google.com(URL)을&amp;nbsp; 입력한다.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. &lt;span data-token-index=&quot;0&quot;&gt;브라우저는 먼저 4단계의 캐싱된 DNS 기록을 확인한다.&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 4단계&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 캐시 &amp;rarr; OS 캐시 &amp;rarr; router 캐시(집에서 사용하는 공유기) &amp;rarr; ISP 캐시(SK 브로드밴드)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 왜 이런 캐시들이 있을까? 인터넷 스피드를 최대한 빨리 하기 위해서!&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;3. 있다면 DNS 서버로 연결하지 않고 IP 주소를 반환한다.&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;4. &lt;span data-token-index=&quot;0&quot;&gt;없다면 ISP의 DNS 서버가 IP 주소를 찾기위해 DNS 쿼리를 날린다.&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNS Recursor(= DNS 서버)가 아래와 같은 순서로 com부터 역순으로 물어보며 IP 주소를 찾는다. &lt;br /&gt;(이를 Recursive search라고 한다.)&lt;br /&gt;: Root domain(.) &amp;rarr; Top-level domains(com) &amp;rarr; Second-level domains(google) &amp;rarr; Third-level domains(www)&lt;span data-token-index=&quot;0&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;5.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;DNS 서버는 사용자가 입력한 URL 정보와 함께 IP 주소를 전송한다.&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;6. 브라우저가 서버와 TCP 연결을 한다.&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: TCP 연결은 &lt;b&gt;송신자와 수신자간의 연결에 신뢰성을 유지&lt;/b&gt;할 수 있도록 해준다.&lt;span data-token-index=&quot;1&quot;&gt; &lt;br /&gt;&lt;/span&gt;: 즉, 클라이언트와 서버간 데이터 패킷들이 오가려면 TCP 연결이 되어야한다. &lt;br /&gt;: TCP 연결 방법은 &lt;b&gt;3 way handshaking&lt;/b&gt;으로 한다. &lt;br /&gt;: 클라이언트와 서버가 &lt;b&gt;&lt;span data-token-index=&quot;3&quot;&gt;SYN&lt;/span&gt;(&lt;span data-token-index=&quot;5&quot;&gt;연결요청&lt;/span&gt;)&lt;/b&gt;과 &lt;b&gt;&lt;span data-token-index=&quot;7&quot;&gt;ACK&lt;/span&gt;(&lt;span data-token-index=&quot;9&quot;&gt;승인&lt;/span&gt;)&lt;/b&gt;로 &lt;b&gt;3번의 프로세스&lt;/b&gt;를 거친 후 연결이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;3 way handshaking&lt;/b&gt;&lt;br /&gt;(1) 클라이언트가 SYN 신호보내며 연결 가능한지 묻고&lt;br /&gt;(2) 서버가 SYN과 ACK를 응답하고&lt;br /&gt;(3) 클라이언트가 서버에게 잘 받았다고 ACK를 보낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 서로 안전하게 정보를 교환할 수 있는 길이 연결되는 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;7. TCP 연결이 된 후, 브라우저가 웹 서버에게 HTTP 요청을 한다.&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;: &lt;b&gt;요청 헤더&lt;/b&gt;에 &lt;b&gt;&lt;span data-token-index=&quot;1&quot;&gt;요청에 대한 정보(URL, Method)&lt;/span&gt;&lt;/b&gt;와 &lt;b&gt;&lt;span data-token-index=&quot;3&quot;&gt;클라이언트에 대한 정보(accept, user-agent, cookie)&lt;/span&gt;&lt;/b&gt;를 담아서 함께 보낸다. &lt;br /&gt;: 저는 헤더에 이러이러한 스택을 가진 클라이언트인데 구글 홈페이지를 get 하고 싶습니다. 라고 말하는 것이다.&lt;br /&gt;: accept) 어떤 타입의 응답 컨텐츠를 수용할 수 있는지 &lt;br /&gt;: user-agent) 브라우저 버전 및 종류, 운영체제 종류 &lt;br /&gt;: cookie) 브라우저에서 얻은 쿠키 정보&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-14 오후 4.34.31.png&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nBL3V/btsAmtTC4d1/ukytkQU9GrQRz750OrKETK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nBL3V/btsAmtTC4d1/ukytkQU9GrQRz750OrKETK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nBL3V/btsAmtTC4d1/ukytkQU9GrQRz750OrKETK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnBL3V%2FbtsAmtTC4d1%2FukytkQU9GrQRz750OrKETK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;331&quot; data-filename=&quot;스크린샷 2023-11-14 오후 4.34.31.png&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;8. 서버가 브라우저의 요청 헤더를 확인하고 HTTP 응답을 한다.&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 응답 헤더) 응답에 대한 부가적인 내용들 &lt;br /&gt;: 응답 바디) HTML 문서&lt;br /&gt;: 상태 코드) 서버 요청에 따른 상태&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-14 오후 4.35.22.png&quot; data-origin-width=&quot;1851&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YkdBR/btsAi5MXXYF/hSQSfkNcjmk2LKkIcAK90k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YkdBR/btsAi5MXXYF/hSQSfkNcjmk2LKkIcAK90k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YkdBR/btsAi5MXXYF/hSQSfkNcjmk2LKkIcAK90k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYkdBR%2FbtsAi5MXXYF%2FhSQSfkNcjmk2LKkIcAK90k%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;1851&quot; height=&quot;372&quot; data-filename=&quot;스크린샷 2023-11-14 오후 4.35.22.png&quot; data-origin-width=&quot;1851&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;- 상태 코드&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1xx: (정보) 요청을 받았으며 프로세스를 계속한다. &lt;br /&gt;2xx: (성공) 요청을 성공적으로 받았으며 인식해서 처리했다. &lt;br /&gt;3xx: (리다이렉션) 요청 완료를 위해 추가 작업 조치가 필요하다.&lt;br /&gt;4xx: (클라이언트 에러) 요청의 문법이 잘못되었거나 요청을 처리할 수 없다. &lt;br /&gt;5xx: (서버 에러) 서버가 명백히 유효한 요청에 대해 충족을 실패했다.&lt;span data-token-index=&quot;0&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;9. &lt;span data-token-index=&quot;0&quot;&gt;브라우저는 서버에게 응답받은 리소스로 파싱하여 화면에 렌더링을 한다.&lt;/span&gt;&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기타 개념들&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DNS 서버 (Domain Name System)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 이름과 IP 주소에 대한 정보를 관리하는 시스템으로 DNS가 도메인 네임을 IP 주소로 바꿔줘서 인터넷 사용자는 어려운 IP 주소를 몰라도 이런저런 사이트에 쉽게 접근할 수 있다.&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;DNS 동작 과정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 먼저 브라우저의 캐쉬에 해당 도메인의 IP 주소를 가지고 있나 확인한다. &amp;rarr; 없으면 DNS 서버에게 IP를 요청한다.&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;DNS 계층 구조: 도메인을 계층적이게 관리하여 서버를 분리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계층의 탐색 순서는 거꾸로 탐색한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒤에서부터 해당 도메인 이름에 맞는 지역 DNS를 탐색하며, root DNS 서버가 나올때까지 거꾸로 탐색한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-14 오후 4.41.09.png&quot; data-origin-width=&quot;1843&quot; data-origin-height=&quot;939&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmeaA8/btsAiCquXDK/zkn9raVjGTl88UkLODh5iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmeaA8/btsAiCquXDK/zkn9raVjGTl88UkLODh5iK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmeaA8/btsAiCquXDK/zkn9raVjGTl88UkLODh5iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmeaA8%2FbtsAiCquXDK%2Fzkn9raVjGTl88UkLODh5iK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;255&quot; data-filename=&quot;스크린샷 2023-11-14 오후 4.41.09.png&quot; data-origin-width=&quot;1843&quot; data-origin-height=&quot;939&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고한 블로그 및 영상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/YahjHM9UNCA?si=Mtx1Hk1jCsmoOysC&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/YahjHM9UNCA?si=Mtx1Hk1jCsmoOysC&lt;/a&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=YahjHM9UNCA&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/b4L9qe/hyUuXVxXMQ/Z3Ua7uaUz6JLiS2VfYqLRK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=1044_428_1148_542&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;www.naver.com을 주소창에 치면 무슨 일이 일어날까요?&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/YahjHM9UNCA&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&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;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://aws-hyoh.tistory.com/entry/TCPIP-쉽게-이해하기&quot;&gt;https://aws-hyoh.tistory.com/entry/TCPIP-쉽게-이해하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699947938130&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;TCP/IP 쉽게 이해하기&quot; data-og-description=&quot;IT 분야에서 실무를 담당하시는 분들뿐만 아니라 학생, IT 쪽에 조금이라도 관심이 있는 분들이라면 TCP/IP에 대해 들어보셨을 겁니다. 저 또한 학부시절에 TCP/IP에 대해서 여러 번 들어보았는데요.&quot; data-og-host=&quot;aws-hyoh.tistory.com&quot; data-og-source-url=&quot;https://aws-hyoh.tistory.com/entry/TCPIP-쉽게-이해하기&quot; data-og-url=&quot;https://aws-hyoh.tistory.com/57&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/l893k/hyUuUR4e67/kCm0wXKwKQqSKf0edvoz80/img.png?width=400&amp;amp;height=310&amp;amp;face=0_0_400_310,https://scrap.kakaocdn.net/dn/ev8YFi/hyUuWbhE0U/KycP8EDQawlilfIZLNKKHk/img.png?width=400&amp;amp;height=310&amp;amp;face=0_0_400_310,https://scrap.kakaocdn.net/dn/c9nCNd/hyUuVpT3c1/XBSNpkCjKOQNmNLS1vsa60/img.png?width=1280&amp;amp;height=731&amp;amp;face=0_0_1280_731&quot;&gt;&lt;a href=&quot;https://aws-hyoh.tistory.com/entry/TCPIP-쉽게-이해하기&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aws-hyoh.tistory.com/entry/TCPIP-쉽게-이해하기&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/l893k/hyUuUR4e67/kCm0wXKwKQqSKf0edvoz80/img.png?width=400&amp;amp;height=310&amp;amp;face=0_0_400_310,https://scrap.kakaocdn.net/dn/ev8YFi/hyUuWbhE0U/KycP8EDQawlilfIZLNKKHk/img.png?width=400&amp;amp;height=310&amp;amp;face=0_0_400_310,https://scrap.kakaocdn.net/dn/c9nCNd/hyUuVpT3c1/XBSNpkCjKOQNmNLS1vsa60/img.png?width=1280&amp;amp;height=731&amp;amp;face=0_0_1280_731');&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;TCP/IP 쉽게 이해하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;IT 분야에서 실무를 담당하시는 분들뿐만 아니라 학생, IT 쪽에 조금이라도 관심이 있는 분들이라면 TCP/IP에 대해 들어보셨을 겁니다. 저 또한 학부시절에 TCP/IP에 대해서 여러 번 들어보았는데요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;aws-hyoh.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://velog.io/@eassy/www.google.com을-주소창에서-입력하면-일어나는-일&quot;&gt;https://velog.io/@eassy/www.google.com을-주소창에서-입력하면-일어나는-일&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699947952889&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;'www.google.com'을 주소창에서 입력하면 일어나는 일&quot; data-og-description=&quot;_개발자로서 웹이 어떤 과정으로 동작하게 되는지, 무슨일이 어떻게 일어나는지에 대해 제대로 이해하지 못한 채 그냥 만들고 보여지는데에만 집중했던 것 같다. 어느 정도 큰 그림으로라도 이&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@eassy/www.google.com을-주소창에서-입력하면-일어나는-일&quot; data-og-url=&quot;https://velog.io/@eassy/www.google.com을-주소창에서-입력하면-일어나는-일&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ceq1LM/hyUylmWtxc/oINWGyylBry5GTwNMVis0k/img.jpg?width=792&amp;amp;height=290&amp;amp;face=0_0_792_290,https://scrap.kakaocdn.net/dn/bbOd8e/hyUyq9Daf0/lgDoKhMQcE65yQNrNLwKz0/img.jpg?width=792&amp;amp;height=290&amp;amp;face=0_0_792_290,https://scrap.kakaocdn.net/dn/b4opkZ/hyUuUR4e8J/0bk57uVRNVNYHyqljbe9NK/img.jpg?width=1922&amp;amp;height=1922&amp;amp;face=0_0_1922_1922&quot;&gt;&lt;a href=&quot;https://velog.io/@eassy/www.google.com을-주소창에서-입력하면-일어나는-일&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@eassy/www.google.com을-주소창에서-입력하면-일어나는-일&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ceq1LM/hyUylmWtxc/oINWGyylBry5GTwNMVis0k/img.jpg?width=792&amp;amp;height=290&amp;amp;face=0_0_792_290,https://scrap.kakaocdn.net/dn/bbOd8e/hyUyq9Daf0/lgDoKhMQcE65yQNrNLwKz0/img.jpg?width=792&amp;amp;height=290&amp;amp;face=0_0_792_290,https://scrap.kakaocdn.net/dn/b4opkZ/hyUuUR4e8J/0bk57uVRNVNYHyqljbe9NK/img.jpg?width=1922&amp;amp;height=1922&amp;amp;face=0_0_1922_1922');&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;'www.google.com'을 주소창에서 입력하면 일어나는 일&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;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/0jV7xOUcKog?si=5fpGxzq1l1QkDlB2&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/0jV7xOUcKog?si=5fpGxzq1l1QkDlB2&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS지식</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/118</guid>
      <comments>https://jeongeuni.tistory.com/118#entry118comment</comments>
      <pubDate>Tue, 14 Nov 2023 16:42:20 +0900</pubDate>
    </item>
    <item>
      <title>동기와 비동기, 자바스크립트에서 비동기 처리가 가능한 이유, 비동기 프로그래밍</title>
      <link>https://jeongeuni.tistory.com/117</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;동기와 비동기&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 동기 처리: 반드시 코드가 작성된 &lt;span style=&quot;color: #ee2323;&quot;&gt;순서대로&lt;/span&gt; 진행된다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점: 실행 순서 보장 &lt;br /&gt;단점: 블로킹 발생, 하나의 작업이 너무 오래 걸리게 되면 오래 걸리는 하나의 작업때문에 모든 작업이 올스탑되어 처리속도가 매우 느려져 성능 상에 문제가 발생하게 된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 비동기 처리: 현재 실행중인 코드가 완료되지 않더라도 &lt;span style=&quot;color: #ee2323;&quot;&gt;기다리지 않고&lt;/span&gt; 다음 코드를 실행하는 방식이다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행중인 태스크가 종료되지 않은 상태라 해도 다음 태스크를 곧바로 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이벤트 핸들러, &lt;b&gt;setTimeout, &lt;b&gt;setInteraval, &lt;b&gt;HTTP 요청&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&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;장점: 블로킹 발생 X &lt;br /&gt;단점: 실행 순서 보장 X&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그런데 싱글스레드인 자바스크립트에서 어떻게 비동기 처리가 가능할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자바스크립트 엔진&lt;/b&gt;은 싱글스레드라서 실행 대기 중인 태스크가 쌓이는 콜스택(실행컨텍스트 스택)을 하나만 가지고 있다. 최상단부터 하나씩 실행되기 때문에 한번에 하나의 태스크만 실행 가능하다. 동시에 여러개의 함수를 실행할 수 없다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;브라우저 내부&lt;/b&gt;에는 자바스크립트 엔진의 싱글스레드의 한계를 극복하기 위해 비동기로 동작할 수 있도록 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;web APIs, 콜백큐, 이벤트 루프&lt;/b&gt;&lt;/span&gt;를 제공한다. 즉, 브라우저 내부에는 자바스크립트 엔진을 뿐만아니라 이벤트 리스너, setTimeout 같이 기다림이 필요한 비동기 함수들이 들어가는 &lt;b&gt;Web APIs&lt;/b&gt;, 그러한 비동기 함수들이 차례차례 쌓이는 &lt;b&gt;콜백큐&lt;/b&gt;, 콜스택이 비워질 때를 체크해서 콜백큐에 대기중인 비동기 함수를 콜스택에 보내주는 &lt;b&gt;이벤트 루프&lt;/b&gt;가 있다. 이벤트 루프는 이 작업을 반복(loop)하고 이러한 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;브라우저의 동작원리 덕분에&lt;/span&gt;&lt;/b&gt; 자바스크립트가 싱글 스레드 언어여도 비동기 작업을 처리할 수 있도록 해주는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-11 오후 3.42.41.png&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FcEAT/btsz9nmv8Ml/BqQrFd4tRThtDQi6DjPCF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FcEAT/btsz9nmv8Ml/BqQrFd4tRThtDQi6DjPCF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FcEAT/btsz9nmv8Ml/BqQrFd4tRThtDQi6DjPCF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFcEAT%2Fbtsz9nmv8Ml%2FBqQrFd4tRThtDQi6DjPCF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;343&quot; data-filename=&quot;스크린샷 2023-11-11 오후 3.42.41.png&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;비동기 프로그래밍이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기적으로 실행되는 것을 동기적으로 코딩하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;비동기 프로그래밍이 중요한 이유&lt;/b&gt;는&lt;br /&gt;서버에 요청한 데이터가 도착하기 전에도 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;사용자와의 인터랙션을 유지할 수 있으므로 사용자 경험을 향상시킬 수 있게 된다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 이미지가 렌더링되는 동안 사용자는 또 다른 작업을 할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;비동기 프로그래밍 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Callback 함수 ex) 이벤트리스너, setTimeout&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정의: 함수의 파라미터로 들어가는 함수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;용도: 순차적으로 실행하고 싶을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 여러개의 비동기를 처리할 때 콜백지옥 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 가독성 저하&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 에러핸들링 어려움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 함수 안에서만 결과값 처리와 결과값을 알 수 있어서 매번 비동기함수를 싱행해야함&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. Promise 객체 (ES6)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 작업의 결과값이 Promise 객체에 저장되기 때문에 &lt;br /&gt;로직 밖에서도 .then 메소드를 통해 저장되어 있는 성공(resolve 반환), 실패(reject 반환) 결과값을 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;원하는 때&lt;/span&gt;&lt;/b&gt;에 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성공 시, then 메소드 실행 &lt;br /&gt;실패 시, catch의 메소드 실행 &lt;br /&gt;&amp;rarr; 하나의 catch만으로 상위에 체이닝되어있는 어떤 함수에서 에러가 나더라도 에러 핸들링이 가능하다. &lt;br /&gt;성공 실패 여부 상관없이, finally 메소드 실행 &lt;br /&gt;&amp;rarr; 무조건 실행되어야 할 로직을 짜는 곳에 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Promise의 3가지 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pending : 비동기 처리 미완료(ful,rej 이전)&lt;br /&gt;fulfilled:&amp;nbsp;비동기&amp;nbsp;처리&amp;nbsp;성공: resolve 호출, then에 비동기 처리 결과를 전달&amp;nbsp; &lt;br /&gt;rejected : 비동기 처리 실패, 오류: reject 호출, catch에 에러 결과를 전달&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;- 단점: 지나친 then의 사용은 콜백지옥과 비슷한 문제가 발생한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. async/awail (ES8)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 쉽고 직관적으로 Promise를 이용할 수 있다. 가독성이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise의 후속처리메소드 없이, 마치 동기적으로 Promise를 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용법&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 앞에 async를 붙혀주면 그 함수는 자동적으로 Promise를 리턴하는 비동기 처리 함수가 된다.&lt;/li&gt;
&lt;li&gt;await 키워드는 promise가 resolve한 결과값을 반환한다.&lt;/li&gt;
&lt;li&gt;await을 비동기 함수의 호출 앞에 붙히면 await이 붙은 함수의 호출은 뒤에있는 함수가 끝나기 전까지 아래에 있는 코드를 수행하지 않는다.&lt;/li&gt;
&lt;li&gt;Promise의 후속처리메소드 없이, 마치 동기적으로 Promise를 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;await는 실패하면 에러가 나고 코드가 멈추기때문에 try/catch를 사용하여 에러 처리를 할 수 있다.&lt;/li&gt;
&lt;li&gt;then과 달리 어떤 지점에서 에러가 발생했는지 쉽게 찾을 수 있다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS지식</category>
      <category>async await</category>
      <category>Promist</category>
      <category>동기와 비동기</category>
      <category>브라우저 동작원리</category>
      <category>비동기 프로그래밍</category>
      <category>콜백함수</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/117</guid>
      <comments>https://jeongeuni.tistory.com/117#entry117comment</comments>
      <pubDate>Sat, 11 Nov 2023 15:53:34 +0900</pubDate>
    </item>
    <item>
      <title>리액트의 재선언, Virtual DOM 동작원리, Diffing 알고리즘</title>
      <link>https://jeongeuni.tistory.com/116</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리액트가 빠른 반응형 웹이 될 수 있었던 이유는 Virtual DOM 덕분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Virtual DOM이 변화한 부분만 캐치하여 최소한의 변경사항만 Raal DOM에 업데이트 해주기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 맞는 말 이지만...&lt;br /&gt;너무 겉햛기식으로만 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Virtual DOM을 이해하고 있기에 이번에 더 깊게 Virtual DOM을 공부해보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Virtual DOM 관련하여 테코톡에 세 개의 영상이 올라와 있었고&lt;br /&gt;세 영상으로 더 깊게 알게된 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Virtual DOM에 대해 정리해보려고 한다!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(테코톡 최고..)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Virtual&amp;nbsp;DOM 등장이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;과거에 비해 현대의 웹 페이지는 UI/UX가 굉장히 매력적이고 복잡하다.&lt;/li&gt;
&lt;li&gt;이러한 웹 페이지의 브라우저 렌더링 과정에서의 문제는 &lt;br /&gt;DOM에 변화가 발생할 때마다&amp;nbsp;렌더트리가 재생성되고 모든 요소들의 스타일을 다시 계산하고 Reflow, Rapaint 과정을 반복하게 된다는 것이다.&lt;/li&gt;
&lt;li&gt;브라우저 렌더링 과정은 생각보다 복잡하고 비용이 큰 작업인데.. 이는 정말 비효율적인 방식이었다.&lt;/li&gt;
&lt;li&gt;그래서 &lt;b&gt;DOM 업데이트를 어떻게 더 효율적으로 할 수 있을까?&lt;/b&gt;라는 고민에서 Virtual DOM이 등장했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Virtual DOM 이란?&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2023-11-11 오전 11.45.22.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N6oYC/btsz7PQ2SIc/sBsDZK44XIwL6B6fDcH3e1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N6oYC/btsz7PQ2SIc/sBsDZK44XIwL6B6fDcH3e1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N6oYC/btsz7PQ2SIc/sBsDZK44XIwL6B6fDcH3e1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN6oYC%2Fbtsz7PQ2SIc%2FsBsDZK44XIwL6B6fDcH3e1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;236&quot; data-filename=&quot;edited_스크린샷 2023-11-11 오전 11.45.22.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;236&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;오른쪽의 이미지가 바로 Virtual DOM 이다.&lt;/li&gt;
&lt;li&gt;Virtual DOM은 DOM 트리를 복제하여 메모리에 저장시킨 자바스크립트 객체이다.&lt;/li&gt;
&lt;li&gt;DOM 정보인 tagName, attributes, 자식들에 대한 정보는 가지고 있지만 &lt;br /&gt;DOM 조작 메서드인 innerHTML, replaceChildren 같은 거는 없다.&lt;/li&gt;
&lt;li&gt;즉, Real DOM을 경량화 시킨 것이다.&lt;/li&gt;
&lt;li&gt;자바스크립트 객체이기에 브라우저에서 직접 수정되지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메모리 상에서&lt;/b&gt; 변경사항을 계산하고 Virtual DOM을 통해 변경된 것들만 식별하여 DOM 업데이트를 &lt;b&gt;&lt;span data-token-index=&quot;1&quot;&gt;한 번&lt;/span&gt;&lt;/b&gt; 시킨다.&lt;/li&gt;
&lt;li&gt;즉, Reflow를 한번 시켜서 연산비용을 줄여 성능이 개선된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Virtual DOM 동작과정 = 재조정&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;JSX를 Babel을 이용하여 JS코드로 변환하면 React.createElement 함수를 호출하게 된다. &lt;br /&gt;호출되어 결과적으로 자바스크립트 객체가 나오는데 이 자바스크립트 객체가 Virtual DOM이다.&lt;/li&gt;
&lt;li&gt;이렇게 생성된 Virtual DOM을 ReactDOM 라이브러리의 render 메서드를 통해 실제 DOM에 반영한다.&lt;/li&gt;
&lt;li&gt;변경이 되면 React가 컴포넌트의 변화를 감지하고 상태가 변경된 컴포넌트의 Virtual DOM을 업데이트 시킨다.&lt;/li&gt;
&lt;li&gt;이후 업데이트 전과 후의 Virtual DOM을 비교하는 과정을 거치게 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;업데이트 후와 전의 Virtual DOM을 비교하는 과정&lt;/b&gt;은 &lt;b&gt;Diffing 알고리즘&lt;/b&gt;을 통해 거친다.&lt;/li&gt;
&lt;li&gt;Diffing 알고리즘은 type부터 확인을 한다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;type이 같다면, 두 Virtual DOM의 엘리먼트 속성을 확인하여 동일한 내역은 유지하고 변경된 속성들만 갱신한다. 이어서 해당 노드의 자식들도 처리힌다.&lt;/li&gt;
&lt;li&gt;type이 다르다면, 이전 Virtual DOM을 버리고 완전히 새로운 Virtual DOM을 생성한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;이러한 과정을 통해 변경된 내용만 Virtual DOM에 반영하여&lt;br /&gt;그 Virtual DOM을 다시 ReactDOM 라이브러리를 이용해 render 메서드를 통해서 변경된 것이 보이게 된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-11 오후 12.04.41.png&quot; data-origin-width=&quot;1412&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfTfcA/btsAcSMeyIU/pMCRa4cc7KjablEV5R17fK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfTfcA/btsAcSMeyIU/pMCRa4cc7KjablEV5R17fK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfTfcA/btsAcSMeyIU/pMCRa4cc7KjablEV5R17fK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfTfcA%2FbtsAcSMeyIU%2FpMCRa4cc7KjablEV5R17fK%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;1412&quot; height=&quot;132&quot; data-filename=&quot;스크린샷 2023-11-11 오후 12.04.41.png&quot; data-origin-width=&quot;1412&quot; data-origin-height=&quot;132&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;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;- 참고영상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 테코톡 엽토님&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/Bdk7QzbbcEI?si=MMAOzqMYAmSHpeih&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/Bdk7QzbbcEI?si=MMAOzqMYAmSHpeih&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 테코톡 지그님&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://youtu.be/PN_WmsgbQCo?si=LPOcRBJCEc_bSNyt&quot;&gt;https://youtu.be/PN_WmsgbQCo?si=LPOcRBJCEc_bSNyt&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 테코톡 돔하디님&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/6rDBqVHSbgM?si=t_S-xZmPdg317IWQ&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/6rDBqVHSbgM?si=t_S-xZmPdg317IWQ&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS지식</category>
      <category>Diffing 알고리즘</category>
      <category>virtual dom</category>
      <category>가상돔</category>
      <category>리액트의 재선언</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/116</guid>
      <comments>https://jeongeuni.tistory.com/116#entry116comment</comments>
      <pubDate>Sat, 11 Nov 2023 12:11:09 +0900</pubDate>
    </item>
    <item>
      <title>호이스팅, 호이스팅 원인, 호이스팅 종류</title>
      <link>https://jeongeuni.tistory.com/115</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-05 오후 2.15.40.png&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfTRho/btszOOwO7No/VMk1kOezI8lnmydVkRg7xK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfTRho/btszOOwO7No/VMk1kOezI8lnmydVkRg7xK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfTRho/btszOOwO7No/VMk1kOezI8lnmydVkRg7xK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfTRho%2FbtszOOwO7No%2FVMk1kOezI8lnmydVkRg7xK%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;1430&quot; height=&quot;428&quot; data-filename=&quot;스크린샷 2023-11-05 오후 2.15.40.png&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 콘솔을 보면&amp;nbsp;var는 undefined가 찍힌다. &lt;br /&gt;이처럼 선언 라인 전에도 변수를 참조할 수 있는 현상을 &lt;b&gt;'호이스팅'&lt;/b&gt; 이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;var 키워드는 선언과 함께 undefined로 초기화되어 메모리에 공간을 확보한다.&lt;br /&gt;let과 const 키워드는 선언만 되고 초기화되지 않은 상태로 선언만 환경레코드(메모리)에 등록된다. (선언 라인에 도달하기 전에는 메모리에 공간을 확보하지 못한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트의 모든 선언에는 호이스팅이 일어나지만 let, const를 이용한 선언문을 호이스팅이 발생하지 않는 것처럼 동작한다. &lt;br /&gt;let, const 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생하는데 &lt;br /&gt;이는 let과 const에도 호이스팅이 일어나기 때문에 에러를 일으키는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;let, const 키워드로 선언된 변수는 스코프의 시작에서 변수를 위한 메모리 공간이 확보되기(초기화 단계)까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 원인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진이 먼저 전체 코드를 스캔하면서 변수같은 정보를 실행컨텍스트의 환경레코드에 미리 등록해놓는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;환경레코드: 식별자와 식별자에 바인딩된 값을 기록해두는 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 변수는 어떻게 생성될까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수는 3단계에 걸쳐 생성된다. (선언: 실행컨텍스트의 레코드에 등록 &amp;rarr; 초기화: 메모리 공간 확보 &amp;rarr; 할당)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. var&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;var는 선언과 초기화가 한번에 이루어진다. &lt;br /&gt;즉, 스코프에 변수를 등록하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화한다. &lt;br /&gt;따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. &lt;br /&gt;다만 undefined를 반환한다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. const, let&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;const, let은 선언과 초기화가 따로 이루어진다. &lt;br /&gt;즉, 스코프에 변수를 등록하지만 초기화 단계는 변수 선언문에 도달했을 때 이뤄진다. &lt;br /&gt;초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다. &lt;br /&gt;변수를 위한 메모리 공간이 아직 확보되지 않았기 때문이다. &lt;br /&gt;따라서 스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다. &lt;br /&gt;스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 &amp;lsquo;일시적 사각지대(Temporal Dead Zone; TDZ)&amp;rsquo;라고 부른다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-05 오후 2.21.12.png&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c23JH7/btszM0dcSlf/56oEZI1bp85E0xlVigpegK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c23JH7/btszM0dcSlf/56oEZI1bp85E0xlVigpegK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c23JH7/btszM0dcSlf/56oEZI1bp85E0xlVigpegK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc23JH7%2FbtszM0dcSlf%2F56oEZI1bp85E0xlVigpegK%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;1454&quot; height=&quot;558&quot; data-filename=&quot;스크린샷 2023-11-05 오후 2.21.12.png&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 호이스팅 종류&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 변수 호이스팅 (var VS const, let)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- var 호이스팅&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수를 생성할 때, 환경레코드에 선언과 초기화를 동시에 한다. 그래서 선언 라인 전에 접근해도 undefined가 찍힌다.&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;-  const, let 호이스팅&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수를 생성할 때, 선언만하고 초기화는 하지 않는다. 그래서 선언 라인 전에 접근(참조)하면 Reference Error가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 일시적 사각지대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;let, const로 선언한 식별자는 선언 라인 이전에 참조할 수 없는데, 이 구역을 '일시적 사각지대'라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, var는 선언과 초기화가&amp;nbsp;동시에 이루어진다. &lt;br /&gt;let, const는 선언만하고 초기화는 하지 않는다. 그래서 선언 라인 전에는 변수를 참조할 수 없다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 함수 호이스팅: 함수 표현식(var VS const, let), 함수 선언문&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) var 함수 표현식: 선언문 이전에 실행하려고 하면 환경레코드에 메모리 공간이 확보되어 있는 값이 undefined이고 undefined라는 데이터 타입은 함수와 달리 호출될 수 없어서 타입에러가 발생한다.&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: #333333; text-align: start;&quot;&gt;(2) const, let&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;함수 표현식: 아직 환경레코드에 메모리 공간이 확보되어 있는 값이 없어 Reference Error가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 함수 선언문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 선언과 동시에 함수가 생성되어 선언&amp;nbsp;전에도&amp;nbsp;함수를 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 선언과 동시에 완성된 함수 객체를 생성해서 환경레코드에 메모리 공간이 확보한다. 함수가 에러없이 실행된다. 그래서 사용을 지양해야한다!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 함수 표현식과 함수 선언문의 차이점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 함수 표현식은 var 키워드 일 때는 환경레코드의 값을 undefined로 초기화해두는데 undefined를 호출하려해서 Type Error가 나고, let&amp;amp;const 일 때는 환경레코드에 값을 초기화해두지는 않아서 참조하려니까 Reference Error가 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 함수 선언문은 선언과 동시에 함수 생성을 마치고 온전히 환경레코드에 메모리 공간을 확보해서 저장해두기에 선언 라인 전에도 함수를 호출할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고&lt;br /&gt;- 하나몬님: &lt;a href=&quot;https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699162286149&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] 호이스팅(Hoisting)이란? - 하나몬&quot; data-og-description=&quot;❗️호이스팅이란? 호이스팅은 코드를 실행하기 전 변수선언/함수선언을 해당 스코프의 최상단으로 끌어올리는 것이 아니다. 호이스팅은 코드가 실행하기 전 변수선언/함수선언이 해당 스코프&quot; data-og-host=&quot;hanamon.kr&quot; data-og-source-url=&quot;https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/&quot; data-og-url=&quot;https://hanamon.kr/javascript-호이스팅이란-hoisting/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bWWONj/hyUnR2AlHe/KRVZVyTDVPsKtRnHjBoPb1/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024,https://scrap.kakaocdn.net/dn/cM2eZZ/hyUnMtun8E/jvTM6hwo8OD3Filulf8zz1/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024&quot;&gt;&lt;a href=&quot;https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bWWONj/hyUnR2AlHe/KRVZVyTDVPsKtRnHjBoPb1/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024,https://scrap.kakaocdn.net/dn/cM2eZZ/hyUnMtun8E/jvTM6hwo8OD3Filulf8zz1/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024');&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] 호이스팅(Hoisting)이란? - 하나몬&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;hanamon.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 테코콕 하루님 : &lt;a href=&quot;https://youtu.be/EWfujNzSUmw?si=ICfUnYVPczB2HqTh&quot;&gt;https://youtu.be/EWfujNzSUmw?si=ICfUnYVPczB2HqTh&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=EWfujNzSUmw&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bKgIZd/hyUrvcwl2T/rL4IAy2t4Gk8Df2QhymWj1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=934_170_992_232&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-original-url=&quot;&quot; data-video-title=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/EWfujNzSUmw&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS지식</category>
      <category>TDZ</category>
      <category>변수의 생성 단계</category>
      <category>호이스팅</category>
      <category>호이스팅 원인</category>
      <category>호이스팅 종류</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/115</guid>
      <comments>https://jeongeuni.tistory.com/115#entry115comment</comments>
      <pubDate>Sun, 5 Nov 2023 14:30:33 +0900</pubDate>
    </item>
    <item>
      <title>실행컨텍스트, 호이스팅, 스코프체이닝 (feat. 테코톡 하루님)</title>
      <link>https://jeongeuni.tistory.com/114</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;실행컨텍스트, 호이스팅, 스코프체이닝을 완벽하게 이해하고 싶은데&lt;br /&gt;호이스팅, 생성 단계, 실행 단계, 선언, 초기화, 일시적 사각지대, 함수 표현식, 함수 선언문, 식별자 결정, 스코프 체인, 스코프 체이닝 등의 여러 개념들이 얽혀있어서 정리가 잘 안됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 테코톡에서 하루님께서 실행컨텍스트를 발표해주신 영상을 보고 속이 시원할정도로 이해가 쏙쏙 잘됐다. 너무 감사했다..ㅠㅠ&lt;br /&gt;그래서 이 영상을 보며 개념을 정리해보았다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://youtu.be/EWfujNzSUmw?si=ICfUnYVPczB2HqTh&quot;&gt;https://youtu.be/EWfujNzSUmw?si=ICfUnYVPczB2HqTh&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=EWfujNzSUmw&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bSnCvG/hyUnTy9UhS/3L0KyDMd2SKRjKrH3aMXq0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=934_170_992_232&quot; data-video-width=&quot;500&quot; data-video-height=&quot;281&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-original-url=&quot;&quot; data-video-title=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/EWfujNzSUmw&quot; width=&quot;500&quot; height=&quot;281&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 2.54.10.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LZ1GD/btszM3nb1C4/zKe3yd9OT9ONC1AHvUlEtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LZ1GD/btszM3nb1C4/zKe3yd9OT9ONC1AHvUlEtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LZ1GD/btszM3nb1C4/zKe3yd9OT9ONC1AHvUlEtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLZ1GD%2FbtszM3nb1C4%2FzKe3yd9OT9ONC1AHvUlEtK%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;1372&quot; height=&quot;580&quot; data-filename=&quot;스크린샷 2023-11-04 오후 2.54.10.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행컨텍스트에는 Record가 있고 Outer가 있다. 이를 먼저 이해하면 최종적으로 실행컨텍스트를 더욱 이해할 수 있다!&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1.&amp;nbsp;Record로 JS 호이스팅 이해하기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 2.55.52.png&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blBobB/btszH75Q2E3/Di0Uh3HMrfNt3zP1uu5FNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blBobB/btszH75Q2E3/Di0Uh3HMrfNt3zP1uu5FNK/img.png&quot; data-alt=&quot; &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blBobB/btszH75Q2E3/Di0Uh3HMrfNt3zP1uu5FNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblBobB%2FbtszH75Q2E3%2FDi0Uh3HMrfNt3zP1uu5FNK%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;400&quot; height=&quot;350&quot; data-filename=&quot;스크린샷 2023-11-04 오후 2.55.52.png&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;350&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;이처럼 첫 콘솔을 보면 undefined가 찍히는데,&amp;nbsp;&lt;br /&gt;선언 라인 전에도 에러가 나지 않고 변수를 참조할 수 있는 현상을 &lt;b&gt;'호이스팅'&lt;/b&gt;이라고 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 이렇게 선언문이 마치 최상단에 끌어올려진 듯한 호이스팅 현상이 발생하는 것일까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진이 먼저 전체 코드를 스캔하면서 변수같은 정보를 실행컨텍스트의 &lt;b&gt;'Record'&lt;/b&gt;에 미리 기록해놓기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- &lt;span data-token-index=&quot;0&quot;&gt;Record = Environment Record = 환경레코드&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식별자와 식별자에 바인딩된 값을 기록해두는 객체이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 2.58.32.png&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcsK4k/btszLqiLHSb/oyqdbQ6LgPoKwouYlATsx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcsK4k/btszLqiLHSb/oyqdbQ6LgPoKwouYlATsx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcsK4k/btszLqiLHSb/oyqdbQ6LgPoKwouYlATsx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcsK4k%2FbtszLqiLHSb%2FoyqdbQ6LgPoKwouYlATsx0%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;700&quot; height=&quot;488&quot; data-filename=&quot;스크린샷 2023-11-04 오후 2.58.32.png&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 호이스팅으로 돌아가보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호이스팅에는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성단계: 실행컨텍스트를 생성하고 선언문만 먼저 실행해서 환경레코드에 미리 기록해두는 단계,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행단계: 선언문 외 나머지 코드 순차적으로 실행해서 환경레코드를 참조하거나 업데이트하는 단계가 있고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종류가 두가지가 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;호이스팅의 종류&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.&amp;nbsp; 변수 호이스팅 : var VS const, let&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&amp;lt; var &amp;gt;&lt;br /&gt;- 1. 생성단계 : 선언과 초기화가 동시에 이루어진다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.02.27.png&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tVefC/btszKDJFxus/OutWFYOcjgG2MzIYG0KuCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tVefC/btszKDJFxus/OutWFYOcjgG2MzIYG0KuCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tVefC/btszKDJFxus/OutWFYOcjgG2MzIYG0KuCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtVefC%2FbtszKDJFxus%2FOutWFYOcjgG2MzIYG0KuCk%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;1236&quot; height=&quot;520&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.02.27.png&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;var는 생선단계에서 실행컨텍스트를 생성하고 환경레코드에 undefined로 초기화도 같이한다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;- 2. 실행단계&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.03.28.png&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TFVMB/btszGP5HqkJ/hBkWKIdRZoMYiKcfSNsndk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TFVMB/btszGP5HqkJ/hBkWKIdRZoMYiKcfSNsndk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TFVMB/btszGP5HqkJ/hBkWKIdRZoMYiKcfSNsndk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTFVMB%2FbtszGP5HqkJ%2FhBkWKIdRZoMYiKcfSNsndk%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;1236&quot; height=&quot;520&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.03.28.png&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;코드 순차적으로 실행해서 TVChannel을 만나면 환경레코드 값을 업데이트 시켜준다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&amp;lt; const, let &amp;gt;&amp;nbsp;&lt;br /&gt;- 1. 생성단계 : &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;선언만하고 초기화는 하지 않는다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.06.06.png&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z8vbu/btszLY7uImt/51JCQY2F0f0xvuHhJSuf40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z8vbu/btszLY7uImt/51JCQY2F0f0xvuHhJSuf40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z8vbu/btszLY7uImt/51JCQY2F0f0xvuHhJSuf40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz8vbu%2FbtszLY7uImt%2F51JCQY2F0f0xvuHhJSuf40%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;1064&quot; height=&quot;462&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.06.06.png&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;TVChannel 식별자를 기록해두긴 하지만 값을 초기화하지는 않는다. 따라서 선언문 이전에 TVChannel를 참조하려고 하면 Reference Error가 발생한다.&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.07.14.png&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Linpc/btszM38z0Om/L4nbNJSonBvu4CAfsZCzzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Linpc/btszM38z0Om/L4nbNJSonBvu4CAfsZCzzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Linpc/btszM38z0Om/L4nbNJSonBvu4CAfsZCzzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLinpc%2FbtszM38z0Om%2FL4nbNJSonBvu4CAfsZCzzk%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;1064&quot; height=&quot;462&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.07.14.png&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;let, const로 선언한 식별자는 선언 라인 이전에 참조할 수 없는데, 이 구역을 &amp;lsquo;일시적 사각지대&amp;rsquo;라고 부른다. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- var와 let, const의 차이&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/xPfAv/btszK9aCoKZ/42uUFY9kkRP0DprbXTtrh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xPfAv/btszK9aCoKZ/42uUFY9kkRP0DprbXTtrh0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1224&quot; data-origin-height=&quot;586&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.09.19.png&quot; style=&quot;width: 49.7368%; margin-right: 10px;&quot; data-widthpercent=&quot;50.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xPfAv/btszK9aCoKZ/42uUFY9kkRP0DprbXTtrh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxPfAv%2FbtszK9aCoKZ%2F42uUFY9kkRP0DprbXTtrh0%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;1224&quot; height=&quot;586&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKZFCl/btszKHZH7ZF/11PFbkkKoMaLKvYDpIiLf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKZFCl/btszKHZH7ZF/11PFbkkKoMaLKvYDpIiLf1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;516&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.08.01.png&quot; data-widthpercent=&quot;49.68&quot; style=&quot;width: 49.1005%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKZFCl/btszKHZH7ZF/11PFbkkKoMaLKvYDpIiLf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKZFCl%2FbtszKHZH7ZF%2F11PFbkkKoMaLKvYDpIiLf1%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;1064&quot; height=&quot;516&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;var는 선언과 초기화가 동시에 이루어진다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;let, const는&amp;nbsp;&lt;/span&gt;선언만하고 초기화는 하지 않는다. 그래서 선언 라인 전에는 변수를 참조할 수 없다. &lt;/b&gt;&lt;br /&gt;이는 자바스크립트도 선언 라인 이전에는 변수를 참조할 수 없다는 일반적인 프로그래밍 방식을 추구할 수 있도록 &lt;br /&gt;언어 차원에서 보완된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.&amp;nbsp; 함수 호이스팅 : 함수 표현식(var VS const, let), 함수 선언식&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 함수 표현식 : 함수를 변수에 담을 수 있다. 변수 호이스팅과 동일하게 동작한다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&amp;lt; var &amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.13.46.png&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/luaTS/btszKFgpQEE/9bWWkWHeG1BGRzrGyhMH6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/luaTS/btszKFgpQEE/9bWWkWHeG1BGRzrGyhMH6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/luaTS/btszKFgpQEE/9bWWkWHeG1BGRzrGyhMH6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FluaTS%2FbtszKFgpQEE%2F9bWWkWHeG1BGRzrGyhMH6k%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;1140&quot; height=&quot;488&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.13.46.png&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;선언문 이전에 실행하려고 하면 환경레코드에 기록되어있는 값은 undefined이고 undefined라는 데이터타입은 함수와 달리 호출될 수 없기 때문에 타입 에러가 발생한다.&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&amp;lt; const, let &amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.14.19.png&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OFq4y/btszHRCjAym/jKHCKwiYggTFDiJkUoXK41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OFq4y/btszHRCjAym/jKHCKwiYggTFDiJkUoXK41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OFq4y/btszHRCjAym/jKHCKwiYggTFDiJkUoXK41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOFq4y%2FbtszHRCjAym%2FjKHCKwiYggTFDiJkUoXK41%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;1140&quot; height=&quot;480&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.14.19.png&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;아직 환경레코드에 기록된 값이 없어 Reference Error가 발생한다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 함수 선언문&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선언과 동시에 함수가 생성되어 선언 전에도 함수를 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선언과 동시에 완성된 함수 객체를 생성해서 환경레코드에 기록해둔다. 함수가 에러없이 실행된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 사용을 지양해야한다!!!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.15.27.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/riIyg/btszH5tsQgF/ThQ0RWazBbVh38zsrQFvx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/riIyg/btszH5tsQgF/ThQ0RWazBbVh38zsrQFvx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/riIyg/btszH5tsQgF/ThQ0RWazBbVh38zsrQFvx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FriIyg%2FbtszH5tsQgF%2FThQ0RWazBbVh38zsrQFvx1%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;700&quot; height=&quot;291&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.15.27.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;582&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;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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 함수 표현식은 var 키워드 일 때는 환경레코드의 값을 undefined로 초기화해두는데 undefined를 호출하려해서 Type Error가 나고, let&amp;amp;const 일 때는 환경레코드에 값을 초기화해두지는 않아서 참조하려니까 Reference Error가 난다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 함수 선언문은 함수 선언문은 선언과 동시에 함수 생성을 마치고 온전히 환경레코드에 저장해두기 때문에 선언 라인 전에도 함수를 호출할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.16.41.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AUMBq/btszNRtpOaL/17xAanFQ9oqlseuUnzydq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AUMBq/btszNRtpOaL/17xAanFQ9oqlseuUnzydq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AUMBq/btszNRtpOaL/17xAanFQ9oqlseuUnzydq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAUMBq%2FbtszNRtpOaL%2F17xAanFQ9oqlseuUnzydq1%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;1400&quot; height=&quot;514&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.16.41.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Outer로 JS 스코프체이닝 이해하기&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-&lt;span&gt; outer&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;outer는 외부 환경을 참조할 수 있게 해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.17.59.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn4pkt/btszKFU8qXn/uPMyvDXCpdWoLQuhBlRvi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn4pkt/btszKFU8qXn/uPMyvDXCpdWoLQuhBlRvi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn4pkt/btszKFU8qXn/uPMyvDXCpdWoLQuhBlRvi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn4pkt%2FbtszKFU8qXn%2FuPMyvDXCpdWoLQuhBlRvi1%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;1400&quot; height=&quot;486&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.17.59.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;486&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;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 함수선언문이라 선언하는 동시에 환경레코드에 생성된 함수가 통째로 기록되고&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.19.58.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqnKoG/btszM3U3iho/1gZl1O9ANVEeKkWeM4MzGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqnKoG/btszM3U3iho/1gZl1O9ANVEeKkWeM4MzGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqnKoG/btszM3U3iho/1gZl1O9ANVEeKkWeM4MzGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqnKoG%2FbtszM3U3iho%2F1gZl1O9ANVEeKkWeM4MzGk%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;1400&quot; height=&quot;592&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.19.58.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.&amp;nbsp;이 함수(goTo2F)를 실행하면 새로운 실행 컨텍스트가 생성된다.&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.20.11.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QpTSu/btszK6EXA90/Voe8EsIRSgHnpy06vxewr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QpTSu/btszK6EXA90/Voe8EsIRSgHnpy06vxewr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QpTSu/btszK6EXA90/Voe8EsIRSgHnpy06vxewr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQpTSu%2FbtszK6EXA90%2FVoe8EsIRSgHnpy06vxewr0%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;1400&quot; height=&quot;592&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.20.11.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. goTo2F 함수의 lamp = true 를 기록한다. 그리고 lamp의 값을 출력하려고 환경레코드를 보니, 불이 꺼진 lamp와 불이 켜진 lamp가 두개가 있다. 자바스크립트 엔진은 둘 중 뭘로 결정해야하나 고민에 빠진다. 이런 상황에서 변수나 함수의 값을 결정해내는 것을 &lt;span data-token-index=&quot;1&quot;&gt;&amp;lsquo;식별자 결정&amp;rsquo;&lt;/span&gt;이라고 한다.&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.20.38.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQRO5/btszK6LHMkG/MidRkisFFO2cGBhBwfVo9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQRO5/btszK6LHMkG/MidRkisFFO2cGBhBwfVo9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQRO5/btszK6LHMkG/MidRkisFFO2cGBhBwfVo9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQRO5%2FbtszK6LHMkG%2FMidRkisFFO2cGBhBwfVo9K%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;1400&quot; height=&quot;1150&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.20.38.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;4. 콜스택 안에 동일한 식별자가 여럿일 때, 자바스크립트 엔진이 어떻게 outer를 활용해서 의사결정을 할까?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. goTo2F 함수가 호출되는 시점으로 돌아가보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 goTo2F 함수가 호출되는 시점으로 돌아가보면, 함수의 실행 컨텍스트를 새로 생성하고, 이때 새로 생성된 실행 컨텍스트에 바깥 렉시컬 환경으로 돌아갈 수 있는 outer를 남겨놓는다. 이제 필요한 경우에 이전 실행 컨텍스트의 환경레코드에 저장된 식별자도 참조할 수 있게되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.22.07.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0Uiov/btszK3VG4st/L8yvA6XwrFIoJ80gJaZPHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0Uiov/btszK3VG4st/L8yvA6XwrFIoJ80gJaZPHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0Uiov/btszK3VG4st/L8yvA6XwrFIoJ80gJaZPHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0Uiov%2FbtszK3VG4st%2FL8yvA6XwrFIoJ80gJaZPHK%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;1400&quot; height=&quot;578&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.22.07.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;578&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;2. goTo2F 함수가 실행됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;lamp를 기록하고 goTo3F 함수가 기록되고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.23.35.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOsCHz/btszKIdflEZ/kSLVtrtyZYtMNFi28kaHuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOsCHz/btszKIdflEZ/kSLVtrtyZYtMNFi28kaHuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOsCHz/btszKIdflEZ/kSLVtrtyZYtMNFi28kaHuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOsCHz%2FbtszKIdflEZ%2FkSLVtrtyZYtMNFi28kaHuk%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;1400&quot; height=&quot;588&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.23.35.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;588&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;3. goTo2F 함수 안에서 다시 goTo3F 함수가 호출된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 실행컨텍스트가 새로 생성되고, 이전 렉시컬환경을 가리키는 outer를 현재의 실행컨텍스트에 저장한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.24.13.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2doQu/btszI2jj2k8/A9gejuto29rCogo4KZSIJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2doQu/btszI2jj2k8/A9gejuto29rCogo4KZSIJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2doQu/btszI2jj2k8/A9gejuto29rCogo4KZSIJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2doQu%2FbtszI2jj2k8%2FA9gejuto29rCogo4KZSIJk%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;1400&quot; height=&quot;1152&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.24.13.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1152&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;4. goTo3F 함수를 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3층에서 pet을 할당하고 원칙적으로 현재 활성화된 실행컨텍스트의 환경레코드를 먼저 보고 &lt;br /&gt;pet의 값이 puppy니까 puppy를 잘 출력해낸다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.24.57.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k9rNF/btszNSlylIr/1KUpSd9iZRAQq8BkvyppV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k9rNF/btszNSlylIr/1KUpSd9iZRAQq8BkvyppV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k9rNF/btszNSlylIr/1KUpSd9iZRAQq8BkvyppV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk9rNF%2FbtszNSlylIr%2F1KUpSd9iZRAQq8BkvyppV0%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;1400&quot; height=&quot;588&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.24.57.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;588&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;5. goTo3F 함수의 lamp를 찾으려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 활성화된 실행컨텍스트에는 lamp가 없어서 outer가 가리키는 바깥 렉시컬 환경으로 가서 lamp를 찾아서 값을 출력해낸다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.25.55.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFw18T/btszM3gqYhN/7tdtPfLog2MaNslTjDjyIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFw18T/btszM3gqYhN/7tdtPfLog2MaNslTjDjyIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFw18T/btszM3gqYhN/7tdtPfLog2MaNslTjDjyIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFw18T%2FbtszM3gqYhN%2F7tdtPfLog2MaNslTjDjyIk%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;1400&quot; height=&quot;1160&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.25.55.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;1160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 2층에서 lamp로 찾아서 1층으로 내려가지 않는다. &lt;br /&gt;이렇게 동일한 식별자로 인해 상위 스코프에서 선언된 식별자의 값이 가려지는 현상을 &lt;b&gt;&amp;lsquo;변수 섀도잉&amp;rsquo;&lt;/b&gt;이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;층층히 실행 컨텍스트가 쌓여있을 때, 현재 활성화된 실행 컨텍스트는 오직 하나이지만, 이전 렉시컬 환경을 가리키는 outer로 타고타고 갈 수 있다. &lt;br /&gt;이렇게 식별자를 결정할 때 활용하는 스코프들의 연결리스트를 &lt;b&gt;&amp;lsquo;스코프 체인&amp;rsquo;&lt;/b&gt;이라고 한다. &lt;br /&gt;식별자를 결정하기 위해 타고타고 가서 찾는 과정 자체를 &lt;b&gt;&amp;lsquo;스코프체이닝&amp;rsquo;&lt;/b&gt;이라고 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.26.58.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;656&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgrOtG/btszKJwtfj0/1JdzoRebQBfLKJr98ARsQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgrOtG/btszKJwtfj0/1JdzoRebQBfLKJr98ARsQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgrOtG/btszKJwtfj0/1JdzoRebQBfLKJr98ARsQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgrOtG%2FbtszKJwtfj0%2F1JdzoRebQBfLKJr98ARsQK%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;1400&quot; height=&quot;656&quot; data-filename=&quot;스크린샷 2023-11-04 오후 3.26.58.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;656&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 실행컨텍스트&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;실행하는데 필요한 환경을 제공하는 객체이다. 여기서 환경이란 코드 실행에 영향을 주는 조건이나 상태를 의미한다. &lt;br /&gt;즉, &lt;span data-token-index=&quot;1&quot;&gt;&lt;b&gt;코드를 실행하는데 필요한 조건이나 상태를 모아둔 객체&lt;/b&gt;가&lt;/span&gt; 바로 실행컨텍스트이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진은 실행컨텍스트만 보고도 값을 잘 결정해냈다. &lt;br /&gt;만약 자바스크립트 엔진이 lamp와 같은 식별자의 값을 정할 때마다 실행컨텍스트 외에 바깥의 다른 메모리를 참조해야 했다면 자바스크립트 엔진의 퍼포먼스는 지금보다 떨어졌을거다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 실행컨텍스트는 &lt;b&gt;식별자 결정을 더욱 효율적으로 하기 위한 수단으로, 필요한 정보를 한데 모아 제공하는 객체&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS지식</category>
      <category>생성 단계</category>
      <category>선언</category>
      <category>스코프체이닝</category>
      <category>실행 단계</category>
      <category>실행컨텍스트</category>
      <category>일시적 사각지대</category>
      <category>초기화</category>
      <category>함수 선언문</category>
      <category>함수 표현식</category>
      <category>호이스팅</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/114</guid>
      <comments>https://jeongeuni.tistory.com/114#entry114comment</comments>
      <pubDate>Sat, 4 Nov 2023 15:29:26 +0900</pubDate>
    </item>
    <item>
      <title>[리액트 공식문서 정독하기] 리액트 주요개념 - 3 (폼, 합성 vs 상속, React로 생각하기)</title>
      <link>https://jeongeuni.tistory.com/110</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-19 오후 7.50.19.png&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzbPcj/btsrB0fohSu/KZsDAxMzfdeYImXSpkBd31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzbPcj/btsrB0fohSu/KZsDAxMzfdeYImXSpkBd31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzbPcj/btsrB0fohSu/KZsDAxMzfdeYImXSpkBd31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzbPcj%2FbtsrB0fohSu%2FKZsDAxMzfdeYImXSpkBd31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;334&quot; data-filename=&quot;스크린샷 2023-08-19 오후 7.50.19.png&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;폼&lt;/span&gt;&lt;/h2&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;제어 컴포넌트와 비제어 컴포넌트&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;제어 컴포넌트(Controlled Component)와 비제어 컴포넌트(Uncontrolled Component)는&lt;br /&gt;React에서 폼(form) 관련 컴포넌트를 다룰 때 사용되는 개념이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 제어 컴포넌트(Controlled Component)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상태를 사용하여 폼 입력 요소들을 관리하는 방식&lt;/li&gt;
&lt;li&gt;사용자가 입력할 때마다 상태가 업데이트되며, 화면에 보이는 값과 상태가 항상 일치함&lt;/li&gt;
&lt;li&gt;React가 폼 데이터를 쉽게 다룰 수 있게 해줌&lt;/li&gt;
&lt;li&gt;useState를 사용하여 상태를 정의하고, onChange이벤트를 사용하여 입력값이 변경될 때마다 상태를 업데이트하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;lt;사용하는 경우&amp;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;/li&gt;
&lt;li&gt;폼의 입력값을 바로 React 상태로 가져와서 다루고 싶을 때&lt;/li&gt;
&lt;li&gt;유효성 검사 등의 로직을 통해 입력값을 제한하고 싶을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691499941942&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from 'react';

function ControlledComponentExample() {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) =&amp;gt; {
    setInputValue(event.target.value);
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;input type=&quot;text&quot; value={inputValue} onChange={handleChange} /&amp;gt;
      &amp;lt;p&amp;gt;현재 입력값: {inputValue}&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp; 비제어 컴포넌트(Uncontrolled Component)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React의 상태(state)를 사용하지 않고 폼 입력 요소를 관리하는 방식&lt;/li&gt;
&lt;li&gt;사용자의 입력에 따라 React 컴포넌트의 상태를 직접 업데이트하지 않음&lt;/li&gt;
&lt;li&gt;대신 ref를 사용하여 직접 입력값을 가져올 수 있음&lt;/li&gt;
&lt;li&gt;상태를 관리하지 않기 때문에 코드가 더 간단하지만, 상태 관리를 직접 처리해야 하는 단점&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;lt;사용하는 경우&amp;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;/li&gt;
&lt;li&gt;상태를 사용하지 않고 직접 입력값을 읽어오는 방식이 편리한 경우&lt;/li&gt;
&lt;li&gt;외부 라이브러리와의 통합 등에서 React 상태를 사용하지 않고 폼 데이터를 다루고 싶을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691499941945&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useRef } from 'react';

function UncontrolledComponentExample() {
  const inputRef = useRef(null);

  const handleButtonClick = () =&amp;gt; {
    const inputValue = inputRef.current.value;
    console.log('입력값:', inputValue);
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;input type=&quot;text&quot; ref={inputRef} /&amp;gt;
      &amp;lt;button onClick={handleButtonClick}&amp;gt;입력값 확인&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;비제어 컴포넌트는 상태를 관리하지 않기 때문에 코드가 간단해질 수 있지만,&lt;br /&gt;상태 관리를 직접 처리해야 하므로 제어 컴포넌트보다 예측하기 어려울 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다시 정리하자면&lt;br /&gt;제어 컴포넌트는 React가 폼 데이터를 관리하는 방식이고, 비제어 컴포넌트는 React의 상태를 사용하지 않고 폼 데이터를 관리하는 방식이다. 어떤 방식을 선택할지는 폼의 복잡성과 상태 관리의 용이성 등을 고려하여 각각의 상황에 따라 선&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;택하여 사용하면 된다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;합성 vs 상속&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;합성&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종종 컴포넌트에 여러 개의 &amp;ldquo;구멍&amp;rdquo;이 필요할 수도 있다. 이런 경우에는 children 대신 자신만의 고유한 방식을 적용할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 공식문서에서는 이런 코드로 합성을 설명해주고 있다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-19 오후 10.06.31.png&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dby5bm/btsrDD4OO1W/lQ6Gnxmm7Nqzcn2rKP7Kk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dby5bm/btsrDD4OO1W/lQ6Gnxmm7Nqzcn2rKP7Kk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dby5bm/btsrDD4OO1W/lQ6Gnxmm7Nqzcn2rKP7Kk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdby5bm%2FbtsrDD4OO1W%2FlQ6Gnxmm7Nqzcn2rKP7Kk0%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;564&quot; height=&quot;698&quot; data-filename=&quot;스크린샷 2023-08-19 오후 10.06.31.png&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;698&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-19 오후 10.07.02.png&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;1070&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cr34YL/btsrCwZpRWl/gcfpuXnQ4WLrfDZVZ68tpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cr34YL/btsrCwZpRWl/gcfpuXnQ4WLrfDZVZ68tpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cr34YL/btsrCwZpRWl/gcfpuXnQ4WLrfDZVZ68tpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcr34YL%2FbtsrCwZpRWl%2FgcfpuXnQ4WLrfDZVZ68tpk%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;838&quot; height=&quot;1070&quot; data-filename=&quot;스크린샷 2023-08-19 오후 10.07.02.png&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;1070&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-19 오후 10.10.35.png&quot; data-origin-width=&quot;1894&quot; data-origin-height=&quot;686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6B4KL/btsrwCmkHbZ/emBUjEV0SZ86fdFutxlxxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6B4KL/btsrwCmkHbZ/emBUjEV0SZ86fdFutxlxxK/img.png&quot; data-alt=&quot;App 컴포넌트 레이아웃&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6B4KL/btsrwCmkHbZ/emBUjEV0SZ86fdFutxlxxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6B4KL%2FbtsrwCmkHbZ%2FemBUjEV0SZ86fdFutxlxxK%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;1894&quot; height=&quot;686&quot; data-filename=&quot;스크린샷 2023-08-19 오후 10.10.35.png&quot; data-origin-width=&quot;1894&quot; data-origin-height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;App 컴포넌트 레이아웃&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;React로 생각하기&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;단일 책임 원칙&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 컴포넌트는 한 가지 일을 하는게 이상적이라는 원칙이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 컴포넌트가 커지게 된다면 이는 보다 작은 하위 컴포넌트로 분리되어야 한다.&lt;/p&gt;</description>
      <category>프론트엔드 개발자가 될거야./react</category>
      <category>단일 책임 원칙</category>
      <category>리액트 공식문서</category>
      <category>리액트 공식문서 요약</category>
      <category>리액트 공식문서 정독</category>
      <category>상속</category>
      <category>폼</category>
      <category>합성</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/110</guid>
      <comments>https://jeongeuni.tistory.com/110#entry110comment</comments>
      <pubDate>Sat, 19 Aug 2023 22:13:19 +0900</pubDate>
    </item>
    <item>
      <title>[리액트 공식문서 정독하기] 리액트 주요개념 - 2 (이벤트 처리하기, React에서 콜백 함수 사용 시 주의할 점)</title>
      <link>https://jeongeuni.tistory.com/109</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-19 오후 7.50.19.png&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWTSKB/btsrDECCcYx/jBuzx7GmiwlYa5rIqi73b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWTSKB/btsrDECCcYx/jBuzx7GmiwlYa5rIqi73b1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWTSKB/btsrDECCcYx/jBuzx7GmiwlYa5rIqi73b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWTSKB%2FbtsrDECCcYx%2FjBuzx7GmiwlYa5rIqi73b1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;334&quot; data-filename=&quot;스크린샷 2023-08-19 오후 7.50.19.png&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;이벤트 처리하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 엘리먼트에서 이벤트를 처리하는 방식은 DOM 엘리먼트에서 이벤트를 처리하는 방식과 매우 유사하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷해도 크게 세가지의 차이점은 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;세가지 차이점&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;React의 이벤트는 소문자 대신 &lt;b&gt;캐멀 케이스(camelCase) 사용&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;JSX를 사용하여 문자열이 아닌 &lt;b&gt;함수로 이벤트 핸들러 전달&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;hsp&quot;&gt;&lt;code&gt;// HTML
&amp;lt;button onclick=&quot;activateLasers()&quot;&amp;gt;
  Activate Lasers
&amp;lt;/button&amp;gt;

// React -&amp;gt; 캐멀 케이스, 함수로 이벤트 핸들러 전달
&amp;lt;button onClick={activateLasers}&amp;gt;
  Activate Lasers
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.&amp;nbsp; React에서는 false를 반환해도 기본 동작을 방지할 수 없다. &lt;s&gt;반드시 preventDefault를 명시적으로 호출하여 폼을 제출할 때 가지고 있는 기본 동작을 방지해야한다.&lt;/s&gt;&amp;nbsp; &lt;b&gt;=&amp;gt; 공식문서에서 이 부분은 틀린 것 같다. React에서는 합성 이벤트를 사용하여 브라우저의 기본 동작을 막을 수 있다. 따라서 React의 이벤트 핸들러에서는 명시적으로 preventDefault()를 호출하지 않아도, 기본 동작이 막힌다. &lt;br /&gt;&lt;br /&gt;따라서, React에서 폼을 제출할 때 기본 동작을 방지하려면 명시적으로 preventDefault()를 호출할 필요가 없다.&lt;br /&gt;React는 이를 자동으로 처리하여 폼 제출 시 기본 동작인 페이지 새로고침을 막아준다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// HTML
&amp;lt;form onsubmit=&quot;console.log('You clicked submit.'); return false&quot;&amp;gt;
  &amp;lt;button type=&quot;submit&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
&amp;lt;/form&amp;gt;

// React
function Form() {
  function handleSubmit(e) {
    console.log('You clicked submit.');
  }

  return (
    &amp;lt;form onSubmit={handleSubmit}&amp;gt;
      &amp;lt;button type=&quot;submit&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;e는 합성 이벤트&lt;/b&gt;인데, React는 &lt;a href=&quot;https://www.w3.org/TR/DOM-Level-3-Events/&quot;&gt;W3C 명세&lt;/a&gt;에 따라 합성 이벤트를 정의하기 때문에 &lt;b&gt;브라우저 호환성에 대해 걱정할 필요가 없다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 합성 이벤트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;합성 이벤트(Synthetic Event)는 React에서 이벤트 처리를 간편하게 하기 위한 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, 이벤트란 사용자가 웹 페이지에서 어떤 동작(예: 클릭, 입력 등)을 하거나 브라우저에서 발생하는 일(예: 로딩 완료 등)을 의미하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서는 이벤트를 다루기 위해 합성 이벤트를 사용한다.&lt;br /&gt;합성 이벤트는 React가 브라우저의 기본 이벤트를 추상화한 것으로, 브라우저 호환성과 관련된 문제를 해결하고, 다양한 브라우저에서 일관성 있는 이벤트 동작을 보장해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 사용자가 웹 페이지의 버튼을 클릭하면 클릭 이벤트가 발생하는데 이 때, React는 해당 클릭 이벤트를 브라우저가 제공하는 기본 이벤트와 동일하게 다루는 것이 아니라, 합성 이벤트를 사용하여 브라우저 이벤트와 비슷하지만, React에서 정의된 방식으로 다룬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;합성 이벤트를 사용하면 브라우저 호환성과 관련된 문제를 걱정할 필요가 없어지며, 모든 브라우저에서 동일한 방식으로 이벤트를 다룰 수 있다. 이렇게 함으로써 개발자는 다양한 브라우저 환경에서도 일관성 있는 이벤트 처리를 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 말하면, &lt;b&gt;합성 이벤트는 React에서 이벤트를 처리하기 위해 사용되는 도구로서, 브라우저 호환성과 이벤트 처리를 편리하게 해주는 개념이다. 이를 통해 React 개발자는 더욱 편리하고 일관성 있게 웹 애플리케이션을 개발할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그리고 위에서 말했듯이, React 이벤트는 브라우저 고유 이벤트와 정확히 동일하게 동작하지는 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폼 제출 시 기본적으로 페이지를 새로고침하는 것이 기본 동작이지만 &lt;br /&gt;React 이벤트는 e.preventDefault()를 호출하지 않아도 폼 제출 시 기본 동작인 페이지 새로고침을 막는 것이 그 예이다.&lt;br /&gt;이렇듯 React로 폼을 제출할 땐 굳이 뭘 하지 않아도 페이지 전체가 새로고침되지 않고 부분적인 데이터 갱신이 가능하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 기본 동작의 차이로 React를 사용하면 더욱 유연하게 개발할 수 있는 것 같다.&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 data-token-index=&quot;0&quot;&gt;React에서 콜백 함수 사용 시 주의할 점 : &lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;성능 면에서의 차이를 알아보자!&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1691492892899&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. &amp;lt;button onClick={handleClick}&amp;gt;

2. &amp;lt;button onClick={() =&amp;gt; handleClick()}&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두 가지 방식은 둘 다 동작은 비슷하나 성능 면에서 차이가 있다.&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 어쩔 때는 1번처럼, 어쩔 때는 2번처럼 썼다. 이유는 그냥이다.. 그냥 손으로 코드가 써지는 대로 썼었다.&lt;br /&gt;두 방식에 이러한 성능적인 차이가 있는지 몰랐는데 충격이다.... 이젠 무조건 1번 방식을 사용하도록 해야겠다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&amp;lt;button onClick={handleClick}&amp;gt;&lt;/b&gt;: 이 방식은 함수를 감싸지 않고 바로 콜백으로 사용한다. 이렇게 사용하면 함수를 새로 만들지 않고 기존의 함수를 그대로 재사용한다. 따라서 &lt;b&gt;함수를 새로 만들 필요가 없기 때문에 성능이 좋아진다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;lt;button onClick={() =&amp;gt; handleClick()}&amp;gt;&lt;/b&gt;: 이 방식은 콜백으로 사용할 때마다 새로운 함수를 만든다.. &lt;b&gt;화살표 함수(() =&amp;gt; ...)를 사용해서 새로운 함수를 만들기 때문에 메모리에 새로운 함수가 계속해서 생성된다. 이렇게 하면 성능에 영향을 미칠 수 있다.&lt;/b&gt; 작은 규모의 애플리케이션에서는 큰 문제가 되지 않지만, 큰 규모의 애플리케이션에서는 불필요한 함수 생성이 많아져 성능에 영향을 줄 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 설명하자면 2번의 문제점은 버튼이 클릭될 때마다 새로운 콜백 함수가 생성된다. 간단히 말하면, onClick={() =&amp;gt; handleClick()} 방식은 버튼을 클릭할 때마다 함수가 계속 만들어진다. 일반적으로 이러한 콜백 함수 생성은 아주 큰 문제가 되지 않겠지만&lt;b&gt; 만약 이 콜백 함수가 다른 하위 컴포넌트에 props로 전달된다면, 그 하위 컴포넌트들도 같이 다시 렌더링될 수 있다. &lt;/b&gt;렌더링은 컴퓨터의 작업 중에서 비용이 큰 작업 중 하나이기에 따라서 불필요한 렌더링은 성능 저하로 이어질 수 있다.&lt;/p&gt;</description>
      <category>프론트엔드 개발자가 될거야./react</category>
      <category>리액트 공식문서</category>
      <category>리액트 공식문서 정독하기</category>
      <category>리액트 주요개념</category>
      <category>리액트 콜백 함수</category>
      <author>정니정은니</author>
      <guid isPermaLink="true">https://jeongeuni.tistory.com/109</guid>
      <comments>https://jeongeuni.tistory.com/109#entry109comment</comments>
      <pubDate>Wed, 9 Aug 2023 21:51:43 +0900</pubDate>
    </item>
  </channel>
</rss>