<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>윥이 개발노트</title>
    <link>https://yoon-dev.tistory.com/</link>
    <description>개발 노트

</description>
    <language>ko</language>
    <pubDate>Fri, 12 Jun 2026 17:38:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>멍발윤</managingEditor>
    <image>
      <title>윥이 개발노트</title>
      <url>https://tistory1.daumcdn.net/tistory/5701165/attach/56540343c0e346868264326b5b3630ba</url>
      <link>https://yoon-dev.tistory.com</link>
    </image>
    <item>
      <title>[JavaScript] TDZ(Temporal Dead Zone)와 가비지 컬렉터(Garbage Collector)</title>
      <link>https://yoon-dev.tistory.com/58</link>
      <description>&lt;p data-end=&quot;349&quot; data-start=&quot;68&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;349&quot; data-start=&quot;68&quot; data-ke-size=&quot;size16&quot;&gt;JavaScript와 같은 언어에서는 프로그래밍을 하면서 종종 중요한 개념들인 TDZ(Temporal Dead Zone)와 가비지 컬렉터(Garbage Collector)가 등장합니다. 이 두 가지는 각각 다른 목적을 가지고 있지만, 메모리 관리와 관련된 공통적인 특성을 공유하기 때문에 이 둘에 대해 잘 이해하는 것이 중요합니다. 이번 블로그 포스팅에서는 TDZ와 가비지 컬렉터가 무엇인지, 그 각각의 개념을 상세히 설명하고, 이들 간의 관계를 이해하는 데 도움을 줄 수 있도록 자세히 다뤄보겠습니다.&lt;/p&gt;
&lt;hr data-end=&quot;354&quot; data-start=&quot;351&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;391&quot; data-start=&quot;356&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. TDZ(Temporal Dead Zone):&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;409&quot; data-start=&quot;393&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.1. TDZ의 정의&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;639&quot; data-start=&quot;411&quot; data-ke-size=&quot;size16&quot;&gt;TDZ(Temporal Dead Zone)는 JavaScript에서 변수의 선언과 초기화 사이의 구간을 의미합니다. let, const, class로 선언된 변수는 그 선언 이전에 참조할 수 없으며, 이 구간에 접근하려고 할 때 ReferenceError가 발생합니다. TDZ는 코드의 실행 순서에 따른 변수의 유효성 문제로, 변수가 선언되기 전에 접근하는 경우를 방지하기 위한 메커니즘입니다.&lt;/p&gt;
&lt;h3 data-end=&quot;660&quot; data-start=&quot;641&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.2. TDZ의 동작 원리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;843&quot; data-start=&quot;662&quot; data-ke-size=&quot;size16&quot;&gt;JavaScript에서는 변수 선언이 호이스팅(hoisting)됩니다. 즉, var로 선언된 변수는 실제 코드 내 위치와 관계없이 변수 선언이 가장 상단으로 끌어올려져 실행됩니다. 그러나 let, const, class와 같은 변수들은 선언이 끌어올려지긴 하지만 초기화가 되지 않으면 TDZ에 존재하게 됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1739954747383&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(x); // ReferenceError: Cannot access 'x' before initialization let x = 10;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1091&quot; data-start=&quot;952&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1091&quot; data-start=&quot;952&quot; data-ke-size=&quot;size16&quot;&gt;위의 코드에서 let x로 선언된 변수는 선언 이전에 접근하려고 하면 ReferenceError가 발생합니다. 이는 x가 TDZ에 있기 때문입니다. 즉, 변수 x는 선언 이후 초기화되기 전까지는 접근할 수 없는 상태로 존재하게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;1091&quot; data-start=&quot;952&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1109&quot; data-start=&quot;1093&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.3. TDZ의 목적&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;1245&quot; data-start=&quot;1111&quot; data-ke-size=&quot;size16&quot;&gt;TDZ의 주된 목적은 변수를 선언하기 전에 참조하거나 사용할 수 없도록 제한하여, 개발자가 오류를 쉽게 찾을 수 있도록 돕는 것입니다. 또한, 이를 통해 예기치 못한 버그를 방지할 수 있고, 변수 초기화 전 값을 참조하는 실수를 줄여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-end=&quot;1250&quot; data-start=&quot;1247&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1290&quot; data-start=&quot;1252&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-end=&quot;1290&quot; data-start=&quot;1252&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 가비지 컬렉터(Garbage Collector):&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;1312&quot; data-start=&quot;1292&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1. 가비지 컬렉터의 정의&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;1530&quot; data-start=&quot;1314&quot; data-ke-size=&quot;size16&quot;&gt;가비지 컬렉터(Garbage Collector)는 프로그래밍 언어에서 더 이상 사용되지 않는 객체나 메모리를 자동으로 관리하고 해제하는 시스템입니다. 메모리 관리의 중요한 기능으로, 프로그래머가 메모리 할당과 해제를 명시적으로 처리하지 않아도 되도록 도와줍니다. JavaScript를 비롯한 많은 언어에서는 이 메커니즘을 통해 메모리 누수를 방지하고, 효율적인 메모리 관리를 지원합니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1555&quot; data-start=&quot;1532&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.2. 가비지 컬렉터의 동작 원리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;1689&quot; data-start=&quot;1557&quot; data-ke-size=&quot;size16&quot;&gt;가비지 컬렉터는 프로그램 실행 중 동적으로 메모리 할당과 해제를 자동으로 처리합니다. 주로 '참조 카운팅'과 '마크 앤 스윕(Mark-and-Sweep)' 알고리즘을 사용하여 더 이상 참조되지 않는 객체를 식별하고 메모리에서 해제합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1936&quot; data-start=&quot;1691&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1806&quot; data-start=&quot;1691&quot;&gt;&lt;b&gt;참조 카운팅(Reference Counting):&lt;/b&gt; 객체가 참조될 때마다 카운터가 증가하고, 참조가 끊기면 카운터가 감소합니다. 카운터가 0이 되면 객체를 가비지로 간주하고 메모리에서 해제합니다.&lt;/li&gt;
&lt;li data-end=&quot;1936&quot; data-start=&quot;1811&quot;&gt;&lt;b&gt;마크 앤 스윕(Mark-and-Sweep):&lt;/b&gt; 이 방식은 객체들이 더 이상 사용되지 않음을 확인하고 메모리에서 제거하는 방법입니다. 먼저, 살아 있는 객체들을 마크한 후, 살아 있지 않은 객체를 스윕(삭제)합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-end=&quot;1961&quot; data-start=&quot;1938&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.3. 가비지 컬렉터의 주요 역할&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2124&quot; data-start=&quot;1963&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2050&quot; data-start=&quot;1963&quot;&gt;&lt;b&gt;자동 메모리 관리:&lt;/b&gt; 프로그래머가 명시적으로 메모리를 할당하거나 해제하지 않아도, 가비지 컬렉터가 자동으로 이를 관리하여 메모리 누수를 방지합니다.&lt;/li&gt;
&lt;li data-end=&quot;2124&quot; data-start=&quot;2051&quot;&gt;&lt;b&gt;효율성:&lt;/b&gt; 가비지 컬렉터는 필요 없는 메모리를 해제함으로써, 프로그램이 실행되는 동안 메모리 자원을 효율적으로 관리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-end=&quot;2129&quot; data-start=&quot;2126&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;2161&quot; data-start=&quot;2131&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-end=&quot;2161&quot; data-start=&quot;2131&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. TDZ와 가비지 컬렉터의 상관관계:&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;2347&quot; data-start=&quot;2163&quot; data-ke-size=&quot;size16&quot;&gt;TDZ와 가비지 컬렉터는 직접적인 관계는 없지만, 둘 다 메모리 관리와 관련된 중요한 역할을 합니다. TDZ는 변수의 유효성 및 초기화 상태를 관리하며, 가비지 컬렉터는 메모리에서 불필요한 객체를 자동으로 제거합니다. 이 두 개념이 서로 다른 방식으로 동작하더라도, 모두 개발자가 더 안전하고 효율적인 코드를 작성하도록 돕습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2526&quot; data-start=&quot;2362&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2447&quot; data-start=&quot;2362&quot;&gt;&lt;b&gt;TDZ:&lt;/b&gt; 주로 변수의 선언과 초기화 순서를 관리하는 데 초점을 둡니다. 이는 개발자가 변수를 안전하게 초기화하고 사용할 수 있도록 도와줍니다.&lt;/li&gt;
&lt;li data-end=&quot;2526&quot; data-start=&quot;2451&quot;&gt;&lt;b&gt;가비지 컬렉터:&lt;/b&gt; 메모리에서 더 이상 사용되지 않는 객체를 자동으로 제거하여, 메모리 자원을 효율적으로 관리하는 시스템입니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category> 내가방/ JavaScript</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/58</guid>
      <comments>https://yoon-dev.tistory.com/58#entry58comment</comments>
      <pubDate>Wed, 19 Feb 2025 17:47:46 +0900</pubDate>
    </item>
    <item>
      <title>[React] State와 Props : 개념 및 상관관계</title>
      <link>https://yoon-dev.tistory.com/57</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. State란 무엇인가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;state&lt;/span&gt;는 컴포넌트 내부에서 관리되는 &lt;b&gt;동적 데이터&lt;/b&gt;입니다. 사용자가 애플리케이션과 상호작용할 때 데이터가 변경될 수 있으며, 이 변화는 React에 의해 자동으로 UI에 반영됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React의 &lt;span&gt;useState&lt;/span&gt; 훅을 사용하여 상태를 정의하고 업데이트합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;내부 데이터:&lt;/b&gt; &lt;span&gt;state&lt;/span&gt;는 컴포넌트 내부에서 선언되고 관리되며, 다른 컴포넌트가 직접 접근할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;변경 가능:&lt;/b&gt; &lt;span&gt;state&lt;/span&gt;는 React의 상태 관리 메서드를 통해 변경할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;UI 업데이트 트리거:&lt;/b&gt; 상태가 변경되면 해당 상태를 사용하는 컴포넌트는 리렌더링됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드 예제: Counter 컴포넌트&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1736601642023&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

function Counter() {
  const [count, setCount] = useState(0); // state 초기화

  const increment = () =&amp;gt; setCount(count + 1); // state 업데이트
  const decrement = () =&amp;gt; setCount(count - 1);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Counter: {count}&amp;lt;/h1&amp;gt; {/* state 값 표시 */}
      &amp;lt;button onClick={increment}&amp;gt;+&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={decrement}&amp;gt;-&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Counter;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서 &lt;span&gt;count&lt;/span&gt;는 상태이며, &lt;span&gt;setCount&lt;/span&gt;를 통해 값을 업데이트하면 React가 UI를 자동으로 갱신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Props란 무엇인가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;props&lt;/span&gt;는 &lt;b&gt;부모 컴포넌트로부터 자식 컴포넌트로 전달되는 데이터&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;props&lt;/span&gt;는 컴포넌트 간의 데이터 전달에 사용되며, &lt;b&gt;읽기 전용&lt;/b&gt;입니다. 자식 컴포넌트는 전달받은 &lt;span&gt;props&lt;/span&gt;를 수정할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;외부 데이터:&lt;/b&gt; 부모 컴포넌트에서 전달된 데이터로, 자식 컴포넌트에서만 읽을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;불변성:&lt;/b&gt; &lt;span&gt;props&lt;/span&gt;는 변경할 수 없으며, 데이터를 수정하려면 부모에서 새로운 값을 전달해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;컴포넌트 간의 통신:&lt;/b&gt; 상위-하위 관계의 컴포넌트 간 데이터 공유에 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드 예제: Greeting 컴포넌트&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1736601693591&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Greeting({ name }) { // props를 구조 분해 할당
  return &amp;lt;h1&amp;gt;Hello, {name}!&amp;lt;/h1&amp;gt;; // props 값 표시
}

export default Greeting;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;부모 컴포넌트에서 props 전달&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1736601736414&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import Greeting from &quot;./Greeting&quot;;

function App() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Greeting name=&quot;Alice&quot; /&amp;gt; {/* props로 name 전달 */}
      &amp;lt;Greeting name=&quot;Bob&quot; /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. State와 Props의 차이점&lt;/b&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 100px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;State&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&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;b&gt;Props&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;관리 주체&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;컴포넌트 내부에서 관리&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;부모 컴포넌트에서 자식으로 전달&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;변경 가능 여부&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;React의 메서드를 통해 변경 가능&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;읽기 전용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;사용 목적&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;컴포넌트의 동적 데이터 관리&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;컴포넌트 간 데이터 전달&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;수정 주체&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;컴포넌트 자체에서 수정 가능&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;부모 컴포넌트만 수정 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. State와 Props의 상관관계&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 애플리케이션에서는 &lt;span&gt;state&lt;/span&gt;와 &lt;span&gt;props&lt;/span&gt;가 서로 긴밀히 연결되어 작동합니다. &lt;b&gt;부모 컴포넌트의 state는 자식 컴포넌트의 props로 전달&lt;/b&gt;될 수 있습니다. 이 구조를 통해 컴포넌트 간 데이터를 공유하고, 상위 컴포넌트에서 상태를 제어하면서 자식 컴포넌트의 UI를 동적으로 업데이트할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드 예제: 부모의 State를 자식의 Props로 전달&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1736601913834&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

function Display({ count }) { // 부모의 state를 props로 받음
  return &amp;lt;h1&amp;gt;Count: {count}&amp;lt;/h1&amp;gt;;
}

function Counter() {
  const [count, setCount] = useState(0); // 부모의 state
  const increment = () =&amp;gt; setCount(count + 1);
  const decrement = () =&amp;gt; setCount(count - 1);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Display count={count} /&amp;gt; {/* state를 props로 전달 */}
      &amp;lt;button onClick={increment}&amp;gt;+&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={decrement}&amp;gt;-&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Counter;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;동작&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;1.&lt;span&gt; &lt;/span&gt;&lt;span&gt;Counter&lt;/span&gt; 컴포넌트에서 &lt;span&gt;count&lt;/span&gt; 상태를 관리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;2.&lt;span&gt; &lt;/span&gt;&lt;span&gt;count&lt;/span&gt; 상태를 &lt;span&gt;Display&lt;/span&gt; 컴포넌트의 &lt;span&gt;props&lt;/span&gt;로 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;3.&lt;span&gt; &lt;/span&gt;상태가 변경될 때마다 &lt;span&gt;Display&lt;/span&gt; 컴포넌트도 자동으로 업데이트됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;State&lt;/b&gt;는 컴포넌트 내부에서 데이터를 관리하는 데 사용되며, 동적인 UI 업데이트를 가능하게 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;Props&lt;/b&gt;는 컴포넌트 간 데이터를 전달하는 데 사용되며, 데이터는 읽기 전용으로 자식 컴포넌트에서 수정할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;두 개념은 상호 보완적이며, 부모-자식 관계의 컴포넌트에서 유기적으로 결합되어 React 애플리케이션의 데이터 흐름을 형성합니다.&lt;/p&gt;</description>
      <category> 내가방/ React</category>
      <category>Props</category>
      <category>react</category>
      <category>state</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/57</guid>
      <comments>https://yoon-dev.tistory.com/57#entry57comment</comments>
      <pubDate>Sat, 11 Jan 2025 22:25:50 +0900</pubDate>
    </item>
    <item>
      <title>[React] emotion.js 소개 및 사용법 (feat. CSS-in-JS)</title>
      <link>https://yoon-dev.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSS-in-JS 라이브러리 중 하나인 &lt;b&gt;Emotion&lt;/b&gt;은 빠르고 유연하며 강력한 스타일링 솔루션을 제공합니다. React와 같은 JavaScript 기반 프레임워크에서 CSS를 더욱 효율적으로 관리할 수 있도록 설계되었으며, 개발자 경험을 극대화하는 도구로 널리 사랑받고 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Emotion CSS란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Emotion&lt;/b&gt;은 JavaScript를 사용하여 CSS를 작성할 수 있게 해주는 CSS-in-JS 라이브러리입니다. 기존의 CSS 파일 관리의 복잡함을 줄이고, 컴포넌트 기반 스타일링을 통해 코드 재사용성과 유지보수성을 높이는 데 초점이 맞춰져 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주요 특징&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;1.&lt;span&gt; &lt;/span&gt;&lt;b&gt;CSS-in-JS&lt;/b&gt;: JavaScript 파일 내에서 CSS를 작성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;2.&lt;span&gt; &lt;/span&gt;&lt;b&gt;스타일 컴포넌트 생성&lt;/b&gt;: CSS 클래스 이름 충돌을 방지하며, 동적으로 스타일링이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;3.&lt;span&gt; &lt;/span&gt;&lt;b&gt;성능 최적화&lt;/b&gt;: 필요한 CSS만 추출하여 적용하므로 성능이 우수합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;4.&lt;span&gt; &lt;/span&gt;&lt;b&gt;유연한 API 제공&lt;/b&gt;: &lt;span&gt;styled&lt;/span&gt;와 &lt;span&gt;css&lt;/span&gt; 같은 다양한 스타일링 방식 제공.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;5.&lt;span&gt; &lt;/span&gt;&lt;b&gt;TypeScript 지원&lt;/b&gt;: TypeScript와 완벽히 호환되어 타입 안전성을 보장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Emotion의 설치와 기본 사용법&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;설치 방법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Emotion은 두 가지 주요 패키지로 구성됩니다. &lt;b&gt;@emotion/react&lt;/b&gt;는 React와 함께 사용하기 위한 패키지이고, &lt;b&gt;@emotion/styled&lt;/b&gt;는 styled-components와 유사한 방식으로 사용됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736254180006&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 기본 패키지 설치
npm install @emotion/react @emotion/styled&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;기본 사용법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. CSS 스타일링&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;css&lt;/span&gt; 함수는 스타일을 JavaScript 객체 형태로 정의합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736254218858&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';

const buttonStyle = css`
  background-color: #3498db;
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
  cursor: pointer;
`;

function App() {
  return &amp;lt;button css={buttonStyle}&amp;gt;Click Me&amp;lt;/button&amp;gt;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. Styled Components 방식&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;@emotion/styled&lt;/span&gt;를 사용하면 styled-components와 비슷한 방식으로 스타일링이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736254242057&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import styled from '@emotion/styled';

const Button = styled.button`
  background-color: #2ecc71;
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
  cursor: pointer;
`;

function App() {
  return &amp;lt;Button&amp;gt;Click Me&amp;lt;/Button&amp;gt;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. Props를 사용한 동적 스타일링&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;styled&lt;/span&gt; 또는 &lt;span&gt;css&lt;/span&gt;를 사용하여 props에 따라 동적으로 스타일을 변경할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736254271204&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const Button = styled.button`
  background-color: ${(props) =&amp;gt; (props.primary ? '#e74c3c' : '#3498db')};
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
`;

function App() {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;Button primary&amp;gt;Primary Button&amp;lt;/Button&amp;gt;
      &amp;lt;Button&amp;gt;Secondary Button&amp;lt;/Button&amp;gt;
    &amp;lt;/&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Emotion의 장단점&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;1.&lt;span&gt; &lt;/span&gt;&lt;b&gt;CSS 클래스 이름 충돌 방지&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;Emotion은 자동으로 고유한 클래스 이름을 생성하므로, CSS 클래스 이름 충돌 문제를 완벽히 해결합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;2.&lt;span&gt; &lt;/span&gt;&lt;b&gt;모듈화와 재사용성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;스타일이 컴포넌트 내부에 캡슐화되어 있어 재사용성과 유지보수성이 뛰어납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;3.&lt;span&gt; &lt;/span&gt;&lt;b&gt;동적 스타일링&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;조건부 스타일링과 props를 사용한 동적 스타일링이 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;4.&lt;span&gt; &lt;/span&gt;&lt;b&gt;서버사이드 렌더링(SSR) 지원&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;Emotion은 SSR을 기본적으로 지원하며, 이를 통해 스타일이 초기 렌더링 시 바로 적용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;5.&lt;span&gt; &lt;/span&gt;&lt;b&gt;TypeScript와의 완벽한 호환성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;타입 정의를 통해 더욱 안전하고 효율적인 개발이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;6.&lt;span&gt; &lt;/span&gt;&lt;b&gt;강력한 성능&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&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;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;1.&lt;span&gt; &lt;/span&gt;&lt;b&gt;런타임 의존성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;스타일이 런타임에 생성되므로 빌드된 CSS에 비해 실행 시 약간의 성능 부담이 있을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;이를 해결하기 위해 Babel 플러그인을 사용해 스타일을 사전에 컴파일할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;2.&lt;span&gt; &lt;/span&gt;&lt;b&gt;학습 곡선&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;기존 CSS 방식에서 전환할 때 새로운 문법과 개념을 익혀야 하는 진입 장벽이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;3.&lt;span&gt; &lt;/span&gt;&lt;b&gt;도구 의존성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;Emotion은 특정 도구와의 통합(예: Babel 플러그인 설정)이 필요할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;실전 활용 예제&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 글로벌 스타일 적용&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Emotion을 사용하여 프로젝트 전역에 CSS를 적용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736254322309&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { Global, css } from '@emotion/react';

const globalStyles = css`
  body {
    margin: 0;
    font-family: 'Arial', sans-serif;
    background-color: #f4f4f4;
  }
`;

function App() {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;Global styles={globalStyles} /&amp;gt;
      &amp;lt;h1&amp;gt;Emotion CSS&amp;lt;/h1&amp;gt;
    &amp;lt;/&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 미디어 쿼리 사용&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미디어 쿼리를 사용하여 반응형 디자인을 구현할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736254347807&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const responsiveStyle = css`
  font-size: 16px;

  @media (min-width: 768px) {
    font-size: 24px;
  }

  @media (min-width: 1024px) {
    font-size: 32px;
  }
`;

function App() {
  return &amp;lt;div css={responsiveStyle}&amp;gt;Responsive Text&amp;lt;/div&amp;gt;;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category> 내가방/ React</category>
      <category>CSS</category>
      <category>cssinjs</category>
      <category>emotion</category>
      <category>리액트</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/56</guid>
      <comments>https://yoon-dev.tistory.com/56#entry56comment</comments>
      <pubDate>Tue, 7 Jan 2025 21:52:46 +0900</pubDate>
    </item>
    <item>
      <title>[React] useEffect와 useState</title>
      <link>https://yoon-dev.tistory.com/55</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;useState&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;useState란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;useState&lt;/span&gt;는 React에서 함수 컴포넌트 내부에서 상태(state)를 관리하기 위해 사용하는 Hook입니다. 이전에는 클래스 컴포넌트에서만 상태를 관리할 수 있었지만, Hook이 도입되면서 함수 컴포넌트에서도 상태를 관리할 수 있게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;사용법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;useState&lt;/span&gt;는 초기 상태를 인수로 받아들이며, 현재 상태 값과 상태를 업데이트할 수 있는 함수를 배열로 반환합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1735996042403&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const [state, setState] = useState(initialValue);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;span&gt;state&lt;/span&gt;: 현재 상태 값.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setState&lt;/span&gt;: 상태를 업데이트하는 함수.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;코드 예제&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1735995428918&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

function Counter() {
  const [count, setCount] = useState(0);
  const increment = () =&amp;gt; setCount(count + 1);
  const decrement = () =&amp;gt; setCount(count - 1);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;현재 카운트: {count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={increment}&amp;gt;증가&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={decrement}&amp;gt;감소&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Counter;&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;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;1.&lt;span&gt; &lt;/span&gt;&lt;b&gt;간단하고 직관적인 API&lt;/b&gt;: 함수 컴포넌트에서 상태를 쉽게 관리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;2.&lt;span&gt; &lt;/span&gt;&lt;b&gt;리렌더링 최적화&lt;/b&gt;: &lt;span&gt;setState&lt;/span&gt;를 호출하면 필요한 부분만 리렌더링됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;3.&lt;span&gt; &lt;/span&gt;&lt;b&gt;다양한 자료형 지원&lt;/b&gt;: &lt;span&gt;string&lt;/span&gt;, &lt;span&gt;number&lt;/span&gt;, &lt;span&gt;array&lt;/span&gt;, &lt;span&gt;object&lt;/span&gt; 등 모든 자료형을 상태로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;1.&lt;span&gt; &lt;/span&gt;&lt;b&gt;복잡한 상태 관리 제한&lt;/b&gt;: 상태가 복잡할수록 관리가 어려워질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;2.&lt;span&gt; &lt;/span&gt;&lt;b&gt;비동기 업데이트&lt;/b&gt;: 상태 업데이트가 비동기적으로 작동하기 때문에, 연산 결과를 즉시 확인할 수 없는 경우가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;useEffect&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;useEffect란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;useEffect&lt;/span&gt;는 React 함수 컴포넌트에서 사이드 이펙트(side effect)를 처리하기 위해 사용하는 Hook입니다. 컴포넌트가 렌더링되거나 업데이트될 때 특정 작업(데이터 가져오기, DOM 업데이트, 타이머 설정 등)을 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;사용법&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1735995493916&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  // 실행할 작업
  return () =&amp;gt; {
    // 클린업 작업
  };
}, [dependencyArray]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;첫 번째 매개변수&lt;/b&gt;: 수행할 작업을 정의하는 콜백 함수.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;b&gt;두 번째 매개변수&lt;/b&gt;: 의존성 배열(&lt;span&gt;dependencyArray&lt;/span&gt;)로, 배열 안에 포함된 값이 변경될 때만 콜백 함수가 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;코드 예제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기본 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1735995527391&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect } from &quot;react&quot;;

function Timer() {
  const [seconds, setSeconds] = useState(0);
  
  useEffect(() =&amp;gt; {
    const interval = setInterval(() =&amp;gt; {
      setSeconds((prev) =&amp;gt; prev + 1);
    }, 1000);

    return () =&amp;gt; clearInterval(interval); // 클린업
  }, []);

  return &amp;lt;p&amp;gt;타이머: {seconds}초&amp;lt;/p&amp;gt;;
}

export default Timer;&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;b&gt;의존성 배열 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1735995547019&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect } from &quot;react&quot;;

function UserGreeting({ name }) {
  useEffect(() =&amp;gt; {
    console.log(`안녕하세요, ${name}님!`);
  }, [name]); // name이 변경될 때만 실행

  return &amp;lt;p&amp;gt;환영합니다, {name}님!&amp;lt;/p&amp;gt;;
}

export default UserGreeting;&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;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;1.&lt;span&gt; &lt;/span&gt;&lt;b&gt;클래스 컴포넌트보다 간단&lt;/b&gt;: &lt;/span&gt;componentDidMount&lt;span&gt;, &lt;/span&gt;componentDidUpdate&lt;span&gt;, &lt;/span&gt;componentWillUnmount&lt;span&gt;를 하나로 통합했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;2.&lt;span&gt; &lt;/span&gt;&lt;b&gt;사이드 이펙트 처리 간소화&lt;/b&gt;: 데이터 패칭, 이벤트 리스너 등록 등 다양한 작업을 쉽게 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;3.&lt;span&gt; &lt;/span&gt;&lt;b&gt;의존성 배열로 최적화 가능&lt;/b&gt;: 의존성 배열을 통해 불필요한 호출을 방지할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;1.&lt;span&gt; &lt;/span&gt;&lt;b&gt;무한 루프 위험&lt;/b&gt;: 의존성 배열 설정을 잘못하면 무한히 반복 실행될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;2.&lt;span&gt; &lt;/span&gt;&lt;b&gt;가독성 저하&lt;/b&gt;: 복잡한 로직을 포함하면 코드가 길어지고 이해하기 어려워질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;3.&lt;span&gt; &lt;/span&gt;&lt;b&gt;의존성 관리 어려움&lt;/b&gt;: 상태 값이나 함수의 의존성을 놓치면 버그가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;useState와 useEffect를 함께 사용하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 Hook을 조합하면 상태 관리와 사이드 이펙트를 효율적으로 처리할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;코드 예제&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1735995606987&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect } from &quot;react&quot;;

function FetchData() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() =&amp;gt; {
    fetch(&quot;https://jsonplaceholder.typicode.com/posts&quot;)
      .then((response) =&amp;gt; response.json())
      .then((data) =&amp;gt; {
        setData(data);
        setLoading(false);
      })
      .catch((error) =&amp;gt; console.error(&quot;Error fetching data:&quot;, error));
  }, []); // 컴포넌트가 처음 렌더링될 때만 실행

  if (loading) return &amp;lt;p&amp;gt;로딩 중...&amp;lt;/p&amp;gt;;

  return (
    &amp;lt;ul&amp;gt;
      {data.map((item) =&amp;gt; (
        &amp;lt;li key={item.id}&amp;gt;{item.title}&amp;lt;/li&amp;gt;
      ))}
    &amp;lt;/ul&amp;gt;
  );
}

export default FetchData;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서 &lt;span&gt;useState&lt;/span&gt;와 &lt;span&gt;useEffect&lt;/span&gt;는 함수 컴포넌트의 필수적인 도구입니다. &lt;span&gt;useState&lt;/span&gt;는 상태 관리를 간단하게 만들어 주고, &lt;span&gt;useEffect&lt;/span&gt;는 사이드 이펙트를 처리하는 데 효과적입니다. 두 Hook을 적절히 활용하면 더 간결하고 유지 보수하기 쉬운 코드를 작성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;참고 자료&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;https://reactjs.org/docs/hooks-intro.html&quot;&gt;React 공식 문서 - Hooks&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;https://reactjs.org/docs/hooks-state.html&quot;&gt;useState 공식 문서&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&amp;bull;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;https://reactjs.org/docs/hooks-effect.html&quot;&gt;useEffect 공식 문서&lt;/a&gt;&lt;/p&gt;</description>
      <category> 내가방/ React</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/55</guid>
      <comments>https://yoon-dev.tistory.com/55#entry55comment</comments>
      <pubDate>Sat, 4 Jan 2025 22:00:53 +0900</pubDate>
    </item>
    <item>
      <title>[React] 바닐라 익스트랙트와 CSS</title>
      <link>https://yoon-dev.tistory.com/54</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;바닐라 익스트렉트(Vanilla Extract) 소개&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바닐라 익스트렉트(Vanilla Extract)는 CSS를 JavaScript처럼 사용할 수 있는 CSS-in-JS 라이브러리입니다. 기존 CSS 작성 방식의 단점을 보완하고 JavaScript의 장점을 활용해 스타일링을 더욱 체계적이고 효율적으로 관리할 수 있도록 돕습니다.&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;스프링클(Sprinkles)&lt;/b&gt;, &lt;b&gt;디파인드 프러퍼티(DefineProperties)&lt;/b&gt; 등의 함수를 통해 스타일 속성을 선언하고 재사용할 수 있는 기능을 제공합니다. 이를 통해 CSS 클래스 이름 충돌, 코드 중복, 관리 어려움 같은 문제를 해결하며, 더 나아가 &lt;b&gt;타입 안정성&lt;/b&gt;과 &lt;b&gt;제로 런타임(zero runtime)&lt;/b&gt;이라는 강력한 특징을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;바닐라 익스트렉트의 장점&lt;/b&gt;&lt;/h3&gt;
&lt;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;1. 제로 런타임&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바닐라 익스트렉트는 런타임에 스타일을 처리하지 않습니다. 모든 스타일은 빌드 타임에 생성된 CSS 파일에 포함되므로, 실행 중인 브라우저에서 JavaScript 없이도 스타일이 적용됩니다. 이는 런타임 비용을 줄이고 성능을 개선합니다.&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. 타입 안정성(Type Safety)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트(TypeScript)를 지원해 스타일 작성 시 타입 안정성을 제공합니다. 잘못된 CSS 클래스 이름이나 속성 값을 전달했을 때 컴파일 단계에서 에러를 발생시켜, 코드의 안정성을 높이고 디버깅 시간을 줄여줍니다.&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. 불가지론적(Agnostic)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 프레임워크에 종속되지 않고, React, Vue, Angular 등 어떤 환경에서도 사용할 수 있습니다. TS 파일을 통해 필요한 CSS 파일을 자동으로 생성하므로, 환경에 관계없이 쉽게 통합할 수 있습니다.&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;4. 유지보수 용이성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스타일을 JavaScript 또는 TypeScript 코드로 관리하기 때문에 컴포넌트 기반 개발에 적합합니다. 스타일 재사용, 테마 설정, 조건부 스타일링 등이 간편하며, 코드 스플리팅과 최적화 작업도 손쉽게 수행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;바닐라 익스트렉트의 단점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 학습 곡선&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;기존 CSS 방식에 익숙한 개발자라면, JavaScript 기반 스타일링 방식에 적응하는 데 시간이 걸릴 수 있습니다.&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. 빌드 설정 필요&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;바닐라 익스트렉트를 사용하려면 빌드 도구(Webpack, Vite 등)에 추가 설정이 필요합니다. 이 과정에서 처음 사용하는 개발자는 혼란을 겪을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;바닐라 익스트렉트 사용 예시&lt;/b&gt;&lt;/h3&gt;
&lt;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;1. 설치&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm install @vanilla-extract/css&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. 스타일 작성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;button.css.ts&lt;/span&gt; 파일에서 스타일을 작성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1735962292511&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { style } from '@vanilla-extract/css';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1735962331818&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const button = style({
  backgroundColor: '#6200ee',
  color: '#ffffff',
  padding: '10px 20px',
  borderRadius: '4px',
  border: 'none',
  cursor: 'pointer',
  ':hover': {
    backgroundColor: '#3700b3',
  },
});&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;b&gt;3. 스타일 적용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 컴포넌트에서 스타일을 적용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1735962362866&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from 'react';
import { button } from './button.css';

export const App = () =&amp;gt; (
  &amp;lt;button className={button}&amp;gt;Click Me&amp;lt;/button&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;바닐라 익스트렉트의 활용 사례&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 다크 모드와 테마 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바닐라 익스트렉트는 다양한 테마를 쉽게 정의하고 적용할 수 있어 다크 모드와 같은 사용자 정의 테마를 구현하기에 적합합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 디자인 시스템&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중앙 집중식으로 스타일을 관리할 수 있으므로 디자인 시스템을 구축하고 유지보수하는 데 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 대규모 프로젝트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입 안정성과 제로 런타임 덕분에 대규모 프로젝트에서도 효율적이고 안전하게 스타일을 관리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바닐라 익스트렉트는 JavaScript 기반으로 스타일을 체계적으로 관리할 수 있도록 돕는 CSS-in-JS 라이브러리입니다. 제로 런타임, 타입 안정성, 프레임워크 독립성 등 여러 장점을 통해 개발 생산성과 코드 품질을 높여줍니다. 특히 대규모 프로젝트나 디자인 시스템 관리에 적합하며, 다양한 테마와 조건부 스타일링을 손쉽게 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 특성 덕분에 바닐라 익스트렉트는 현대 웹 개발에서 점점 더 중요한 도구로 자리 잡고 있습니다.&amp;nbsp;&lt;/p&gt;</description>
      <category> 내가방/ React</category>
      <category>CSS</category>
      <category>라이브러리</category>
      <category>리액트</category>
      <category>바닐라익스트랙트</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/54</guid>
      <comments>https://yoon-dev.tistory.com/54#entry54comment</comments>
      <pubDate>Sat, 4 Jan 2025 12:48:51 +0900</pubDate>
    </item>
    <item>
      <title>브라우저에서 페이지를 렌더링하는 방식</title>
      <link>https://yoon-dev.tistory.com/53</link>
      <description>&lt;h1&gt;브라우저에서 페이지를 렌더링하는 방식&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;렌더러 프로세스(Renderer Process)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;렌더러 프로세스&lt;/b&gt;는 브라우저 탭 안에서 일어나는 모든 일들을 담당한다.&lt;/li&gt;
&lt;li&gt;렌더러 프로세스 안에서는 메인 스레드가 우리가 구현한 대부분의 코드를 처리하게 된다.&lt;/li&gt;
&lt;li&gt;웹 페이지를 효율적이고 부드럽게 렌더링하기 위해 별도의 컴포지터 스레드와 레스터 스레드가 렌더러 프로세스에서 실행된다.&lt;/li&gt;
&lt;li&gt;렌더러 프로세스의 핵심 역할은 HTML, CSS, JS를 사용자가 인터렉션 할 수 있는 웹페이지로 만드는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스레드 종류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메인 스레드 (Main Thread) : 웹 페이지를 실행하는 기본적인 스레드. 모든 UI 업데이트와 사용자 입력 처리, DOM 변경, JS 실행 등 기본 작업 실행 한다.&lt;/li&gt;
&lt;li&gt;워커 스레드 (Web Workers) : 메인 스레드와는 별개로 동작하는 백그라운드 스레드. CPU 집약적인 작업을 메인 스레드와 분리하여 처리 할 수 있게 해준다.&lt;/li&gt;
&lt;li&gt;컴포지터 스레드 (Compositor Thread) : 브라우저에서 화면 렌더링을 담당하는 스레드. 페이지의 각 요소를 렌더링하고 이를 조합하여 최종적으로화면에 표시되는 그림을 만든다.&lt;/li&gt;
&lt;li&gt;레스터 스레드 (Raster Thread) : 이미지나 비디오 등의 비트맵 데이터를 처리하는 스레드. 화면에 표시될 렌더링 데이터를 픽셀 단위로 변환하고 GPU를 활용해 이미지를 렌더링 하는 작업을 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DOM 구축&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;페이지를 이동하는 내비게이션 실행 메시지를 렌더러 프로세스가 받고 HTML 데이터를 수신하기 시작하면 렌더러 프로세스의 메인 스레드는 문자열(HTML)을 파싱해서 DOM으로 변환하기 시작한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DOM&lt;/b&gt;이란 페이지에 대한 브라우저의 내부 표현일 뿐만 아니라 웹 개발자가 자바스크립트를 통해 상호작용할 수 있는 데이터 구조 및 API이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바이트를 문자로, 문자열을 &amp;lt;body&amp;gt;와 같은 토큰으로, 토큰을 프로퍼티와 규칙을 가진 객체로 만들고 최종적으로 이 객체들을 서로 연결하면서 데이터 구조를 만드는 순서로 진행된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;하위리소스(subresource) 로딩&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 사이트는 일반적으로 이미지, CSS, JavaScript와 같은 외부 리소스를 사용한다.&lt;/li&gt;
&lt;li&gt;이러한 파일은 네트워크나 캐시에서 로딩해야 한다. 리소스를 만날 때마다 메인 스레드가 하나하나 요청하는 것 보다 속도를 높이기 위해 &amp;lsquo;프리로드(Preload) 스캐너&amp;rsquo;가 동시에 실행된다.&lt;/li&gt;
&lt;li&gt;HTML 문서에 &amp;lt;img&amp;gt; 또는 &amp;lt;link&amp;gt;와 같은 태그가 있으면 프리로드 스캐너는 HTML 파서가 생성한 토큰을 확인하고 브라우저 프로세스의 네트워크 스레드에 요청을 보낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;script&amp;gt; 태그를 만나면?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lt;script&amp;gt; 태그를 만나면 HTML 파서는 HTML 문서의 파싱을 일시 중지한 다음 JavaScript 코드를 로딩하고 파싱해야 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;**document.write()**과 같은 DOM 구조 전체를 바꿀 수 있는 메서드 사용 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;lt;script&amp;gt; 태그에 async 속성이나 defer 속성을 추가
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JavaScript 코드를 비동기적으로 실행한다. (HTML 파싱 막지 않음)&lt;/li&gt;
&lt;li&gt;JavaScript 모듈 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스타일 계산&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메인 스레드는 CSS를 파싱 하여 각 DOM 노드에 대한 계산된 스타일을 결정한다.&lt;/li&gt;
&lt;li&gt;CSS를 전혀 적용하지 않아도 DOM 노드에는 계산된 스타일이 적용되어 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;레이아웃&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레이아웃은 요소의 기하학적 속성을 찾는 과정이다.&lt;/li&gt;
&lt;li&gt;메인 스레드는 DOM과 계산된 스타일을 훑어가며 레이아웃 트리를 만든다.&lt;/li&gt;
&lt;li&gt;레이아웃 트리는 X,y 좌표, 박스 영역의 크기와 같은 정보를 가지고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;페인트&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메인 스레드는 페인트 기록을 생성하기 위해 레이아웃 트리를 순회한다.&lt;/li&gt;
&lt;li&gt;렌더링 파이프라인에서 파악해야 할 가장 중요한 점은 각 단계에서 이전 작업의 결과가 새 데이터를 만드는 데 사용된다는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;합성&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 페이지의 각 부분을 레이어로 분리해 별도로 래스터화하고 컴포지터 스레드라고 하는 별도의 스레드에서 웹 페이지로 합성하는 기술이다.&lt;/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;&lt;a href=&quot;https://ajdkfl6445.gitbook.io/study/web/browser-rendering&quot;&gt;https://ajdkfl6445.gitbook.io/study/web/browser-rendering&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/5237120&quot;&gt;https://d2.naver.com/helloworld/5237120&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> 내가방/ JavaScript</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/53</guid>
      <comments>https://yoon-dev.tistory.com/53#entry53comment</comments>
      <pubDate>Tue, 10 Dec 2024 16:13:37 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 실행컨텍스트와 클로저의 이해</title>
      <link>https://yoon-dev.tistory.com/52</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;731&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bggtGN/btsKV9EebOZ/FlJVldOZ9ZKmHWH2o8YNL1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bggtGN/btsKV9EebOZ/FlJVldOZ9ZKmHWH2o8YNL1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bggtGN/btsKV9EebOZ/FlJVldOZ9ZKmHWH2o8YNL1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbggtGN%2FbtsKV9EebOZ%2FFlJVldOZ9ZKmHWH2o8YNL1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;731&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;731&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;실행 컨텍스트란?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;실행 컨텍스트는 자바스크립트 코드가 평가되고 실행되는 환경을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;자바스크립트 엔진은 &lt;b&gt;코드 실행에 필요한 모든 정보를 실행 컨텍스트에 저장&lt;/b&gt;한다. 이는 변수, 함수, 선언, this의 값 등을 포함한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;왜냐하면 실행 컨텍스트는 코드가 실행될 때 필요한 환경 정보를 제공하며, 이는 코드의 실행 흐름을 관리하는데 필수적이기 때문이다. 실행 컨텍스트는 &lt;b&gt;전역 실행 컨텍스트&lt;/b&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;실행 컨텍스트는 콜 스택에 쌓이게 되며, 자바스크립트 엔진은 콜 스택의 최상단에 있는 실행 컨텍스트를 기준으로 코드를 실행한다. 이는 함수 호출 순서와 실행 흐름을 관리하는 데 중요한 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;클로저란?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;클로저(Closure)는 &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;span style=&quot;font-family: 'Nanum Gothic';&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;클로저는 자바스크립트에서 &lt;b&gt;비동기 처리, 모듈 패턴, 고차 함수 등 다양한 패턴과 기능을 구현하는 데 핵심적인 역할&lt;/b&gt;을 한다. 예를 들어, 이벤스 리스너나 setTimeout에서 클로저를 사용하여 외부 스코프의 변수를 참조할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;왜냐하면 클로저는 함수가 선언될 당시의 렉시컬 환경을 기억하기 때문이다. 이는 함수가 실행될 때 마다 새로운 스코프를 생성하는 대신, 기존의 스코프에 접근하여 효율적인 메모리 관리를 가능하게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;실행 컨텍스트와 클로저의 관계&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;실행 컨텍스트와 클로저는 밀접하게 연관되어 있다. 클로저는 함수가 선언된 실행 컨텍스트의 렉시컬 환경을 캡처하여, 함수가 외부 스코프의 변수에 접근할 수 있게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;왜냐하면 클로저는 함수가 선언된 시점의 실행 컨텍스트를 기억하고, 이를 통해 외부 스코프의 변수를 참조할 수 있기 때문이다. 이는 함수가 실행될 때 마다 해당 실행 컨텍스트에 접근하여 필요한 데이터를 사용할 수 있게 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 관계는 자바스크립트에서 비동기 처리나 데이터 은닉 등의 기능을 구현할 때 핵심적인 역할을 한다. 클로저를 통해 생성된 함수는 외부 함수의 실행이 종료된 후에도 외부 함수의 변수에 접근할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> 내가방/ JavaScript</category>
      <category>오블완</category>
      <category>티스토리챌린지</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/52</guid>
      <comments>https://yoon-dev.tistory.com/52#entry52comment</comments>
      <pubDate>Mon, 25 Nov 2024 16:34:12 +0900</pubDate>
    </item>
    <item>
      <title>[모던 자바스크립트] Ajax와 REST API</title>
      <link>https://yoon-dev.tistory.com/51</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ajax란 자바스크립트를 &lt;b&gt;사용하여 브라우저가 서버에게 비동기 방식으로 데이터를 요청하고, 서버가 응답한 데이터를 수신하여 웹페이지를 동적으로 갱신하는 프로그래밍 방식&lt;/b&gt;을 말한다. Ajax는 브라우저에서 제공하는 Web API인 XMLHttpRequest 객체를 기반으로 동작한다. XMLHttpRequest는 HTTP 비동기 통신을 위한 메서드와 프로퍼티를 제공한다.&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;Ajax의 등장은 이전의 전통적인 패러다임을 획기적으로 전환했다. 즉, 서버로부터 웹페이지의 변경에 필요한 데이터만 비동기 방식으로 전송받아 웹페이지를 변경할 필요가 없는 부분은 다시 렌더링하지 않고, 변경할 필요가 있는 부분만 한정적으로 렌더링하는 방식이 가능해진 것이다. Ajax는 전통적인 방식과 비교했을 때 다음과 같은 장점이 있다.&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. 변경할 부분을 갱신하는 데 필요한 데이터만 서버로부터 전송받기 때문에 불필요한 데이터 통신이 발생하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 변경할 필요가 없는 부분은 다시 렌더링하지 않는다. 따라서 화면이 순간적으로 깜박이는 현상이 발생하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 클라이언트외 서버와의 통신이 비동기 방식으로 동작하기 때문에 서버에게 요청을 보낸 이후 블로킹이 발생하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JSON&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSON은 클라이언트와 서버 간의 HTTP 통신을 위한 텍스트 데이터 포맷이다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;JSON 표기 방식&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSON은 자바스크립트의 객체 리터럴과 유사하게 키와 값으로 구성된 순수한 텍스트다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSON의 키는 반드시 &lt;b&gt;큰따옴표&lt;/b&gt;로 묶어야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1729683768030&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
	&quot;name&quot; : &quot;Lee&quot;,
    &quot;age&quot; : 20,
    &quot;alice&quot; : true,
    &quot;hobby&quot; : [&quot;traveling&quot;,&quot;tennis&quot;]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;JSON.stringify&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSON.stringify 메서드는 객체를 JSON 포맷의 문자열로 변환한다. 클라이언트가 서버로 객체를 전송하려면 객체를 문자열화해야 하는데 이를 &lt;b&gt;직렬화&lt;/b&gt;라 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSON.stringify 메서드는 객체뿐만 아니라 배열도 JSON 포맷의 문자열로 변환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1729684060377&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = {
	name: 'Lee',
    age: 20,
    alive: true,
    hobby: ['taveling', 'tennis']
};

// 객체를 JSON 포맷의 문자열로 변환한다.
const json = JSON.stringify(obj);&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;JSON.parse&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSON.parse 메서드는 JSON 포맷의 문자열을 객체로 변환한다. 서버로부터 클라이언트에게 전송된 JSON 데이터는 문자열이다. 이 문자열을 객체로서 사용하려면 JSON 포맷의 문자열을 객체화해야 하는데 이를 역직렬화라 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열이 JSON 포맷의 문자열로 변환되어 있는 경우 JSON.parse는 문자열을 배열 객체로 변환한다. 배열의 요소가 객체인 경우 배열의 요소까지 객체로 변환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1729684247624&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = {
	name: 'Lee',
    age: 20,
    alive: true,
    hobby: ['taveling', 'tennis']
};

// 객체를 JSON 포맷의 문자열로 변환한다.
const json = JSON.stringify(obj);

// JSON 포맷의 문자열을 객체로 변횐한다.
const parsed = JSON.parse(json);
console.log(typeof parsed, parsed);

// object {name: &quot;Lee&quot;,age: 20,alice:true, hobby: [&quot;traveling&quot;,&quot;tennis&quot;]&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;REST API&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;REST API의 구성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API는 &lt;b&gt;자원, 행위, 표현&lt;/b&gt;의 3가지 요소로 구성된다. REST는 자체 표현 구조로 구성되어 REST API만으로 HTTP 요청의 내용을 이해할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 78px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;구성 요소&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;내용&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;표현 방법&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;자원&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;자원&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;URL(엔드포인트)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;행위&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;자원에 대한 행위&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;HTTP 요청 메서드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 18px;&quot;&gt;표현&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 18px;&quot;&gt;자원에 대한 행위의 구체적 내용&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 18px;&quot;&gt;페이로드&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;REST API 설계 원칙&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST에서 가장 중요한 기본적인 원칙은 두가지다. &lt;b&gt;URI는 리소스를 표현하는 데 집중&lt;/b&gt;하고 &lt;b&gt;행위에 대한 정의는 HTTP 요청 메서드&lt;/b&gt;를 통해 하는 것이 REST API를 설계하는 중심 규칙이다.&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;1. URI는 리소르를 표현해야 한다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URI는 리소르를 표현하는데 중점을 두어야 하므로 식별할 수 있는 이름은 동사보다는 명사를 사용한다. 따라서 이름에 get 같은 행위에 대한 표현이 들어가서는 안 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1729684901990&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// bad
GET /getTodos/1
GET /todos/show/1

// good
GET /todos/1&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;b&gt;2. 리소스에 대한 행위는 HTTP 요청 메서드로 표현한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 요청 메서드는 클라이언트가 서버에게 요청의 종류외 목적을 알리는 방법이다. 주로 5가지 요청 메서드 (GET, POST, PUT, PATCH, DELETE 등)을 사용하여 CRUD를 구현한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;347&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFIiIS/btsKgduP04O/cxZP1AK0MRMxT8RqsRYGgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFIiIS/btsKgduP04O/cxZP1AK0MRMxT8RqsRYGgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFIiIS/btsKgduP04O/cxZP1AK0MRMxT8RqsRYGgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFIiIS%2FbtsKgduP04O%2FcxZP1AK0MRMxT8RqsRYGgk%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;347&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;347&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> 내가방/ JavaScript</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/51</guid>
      <comments>https://yoon-dev.tistory.com/51#entry51comment</comments>
      <pubDate>Wed, 23 Oct 2024 21:06:34 +0900</pubDate>
    </item>
    <item>
      <title>[모던 자바스크립트] this 키워드</title>
      <link>https://yoon-dev.tistory.com/50</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 상태를 나타내는 프로퍼티와 동작을 나타내는 메서드를 하나의 논리적인 단위로 묶은 복합적인 자료구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동작을 나타내는 메서드는 자신이 속한 객체의 상태, 즉 프로퍼티를 참조하고 변경할 수 있어야 한다. 이때 메서드가 자신이 속한 객체의 프로퍼티를 참조하려졈 먼저 &lt;b&gt;자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 리터럴 방식으로 생성한 객체의 경우 메서드 내부에서 메서드 자신이 속한 객체를 가리키는 식별자를 재귀적으로 참조할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1729593760227&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const circle = {
	// 프로퍼티 : 객체 고유의 상태 데이터
    radius: 5,
    // 메서드 : 상태 데이터를 참조하고 조작하는 동작
    getDiameter(){
    	// 이 메서드가 자신이 속한 객체의 프로퍼티나 다른 메서드를 참조하려면
        // 자신이 속한 객체인 circle을 참조할 수 있어야 한다.
        return 2 * circle.radius;
    }
};

console.log(circle.getDiameter()); // 10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getDiameter 메서드 내에서 메서드 자신이 속한 객체를 가리키는 식별자 circle을 참조하고 있다. 이 참조 표현식이 평가되는 시점은 getDiameter 메서드가 호출되어 함수 몸체가 실행되는 시점이다.&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;pre id=&quot;code_1729594207481&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Circle(radius){
	// 이 시점에는 생성자 함수 자신이 생성할 인스턴스를 가리키는 식별자를 알 수 없다.
    ????.radius = radius;
}

Circle.prototype.getDiameter = functio () {
	// 이 시점에는 생성자 함수 자신이 생성할 인스턴스를 가리키는 식별자를 알 수 없다.
    return 2 * ????.radius;
};

// 생성자 함수로 인스턴스를 생성하려면 먼저 생성자 함수를 정의해야 한다.
const circle = new Circle(5);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 함수에 의한 객체 생성 방식은 먼저 생성자 함수를 정의한 이후 new 연산자와 함께 생성자 함수를 호출하는 단계가 추가로 필요하다. 이를 위해 자바스크립트는 this라는 특수한 식별자를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다. this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;this는 자바스크립트 엔진에 의해 암묵적으로 생성되며, 코드 어디서든 참조할 수 있다. 함수를 호출하면 arguments 객체와 this가 암묵적으로 함수 내부에 전달된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, &lt;b&gt;this가 가리키는 값, this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1729595317808&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 객체 리터럴
const circle = {
	radius: 5,
    getDiameter() {
    	// this는 메서드를 호출한 객체를 가리킨다.
        return 2 * this.radius;
    }
};

console.log(cicle.getDiameter()); // 10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 리터럴의 메서드 내부에서의 this는 메서드를 호출한 객체, 즉 circle을 가리킨다.&lt;/p&gt;
&lt;pre id=&quot;code_1729595438219&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 생성자 함수
function Circle(radius){
	// this는 생성자 함수가 생성할 인스턴스를 가리킨다.
    this.radius = radius;
}

Circle.prototype.getDiameter = function () {
	// this는 생성자 함수가 생성할 인스턴스를 가리킨다.
    return 2 * this.radius;
}

// 인스턴스 생성
const circle = new Circle(5);
console.log(circle.getDiameter());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 함수 내부의 &lt;b&gt;this는 생성자 함수가 생성할 인스턴스&lt;/b&gt;를 가리킨다. 이처럼 this는 상황에 따라 가리키는 대상이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 &lt;b&gt;this는 코드 어디에서든 참조가 가능하다. 전역에서도 함수 내부에서도 참조할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;함수 호출 방식과 this 바인딩&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;this 바인딩(this에 바인딩될 값)은 함수 호출 방식, 즉 함수가 어떻게 호출되었는지에 따라 동적으로 결정된다. &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;*렉시컬 스코핑은 함수 정의가 평가되어 함수 객체가 생성되는 시점에 상위 스코프를 결정한다. 하지만 this 바인딩은 함수 호출 시점에 결정된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일반 함수 호출&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 this에는 전역 객체가 바인딩된다.&lt;/p&gt;
&lt;pre id=&quot;code_1729595921520&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function foo() {
	console.log(&quot;foo's this: &quot;, this); // window
    function bar() {
    	console.log(&quot;bar's this: &quot;, this); // window
    }
    bar();
}
foo();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;일반 함수로 호출하면 함수 내부의 this에는 전역 객체가 바인딩된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;메서드 호출&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;메서드 내부의 this에는 메서드를 호출한 객체, 즉 메서드를 호풀할 때 메서드 이름앞의 마침표 연산자 앞에 기술한 객체가 바인딩된다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1729596514864&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const person = {
	name: 'Lee',
    getName() {
    	// 메서드 내부의 this는 메서드를 호출한 객체에 바인딩된다.
        return this.name;
    }
};

// 메서드 getName을 호출한 객체는 perso이다.
console.log(person.getName()); // Lee&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제의 getName 메서드는 person 객체의 메서드로 정의되었다. 메서드는 프로퍼티에 바인딩된 함수다. 즉, person 객체의 getName 프로퍼티가 가리키는 함수 객체는 person 객체에 포함된 것이 아니라 독립적으로 존재하는 별도의 객체다. getName 프로퍼티가 함수 객체를 가리키고 있을 뿐이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;생성자 함수 호출&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 함수와 동일한 방법으로 생성자 함수를 정의하고 new 연산자와 함께 호출하면 해당 함수는 생성자 함수로 동작한다. 만약 new 연산자와 함께 생성자 함수를 호출하지 않으면 생성자 함수가 아니라 일반 함수로 동작 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1729597006672&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 생성자 함수
function Circle(radius) {
	// 생성자 함수 내부의 this는 생서자 함수가 생성할 인스턴스를 가리킨다.
    this.radius = radius;
    this.getDiameter = function (){
    	return 2 * this.radius;
    };
}

// 반지름이 5인 Circle 객체를 생성
const circle1 = new Circle(5);
// 반지름이 10인 Circle 객체를 생성
const circle2 = new Circle(10);

console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20

// new 연산자와 함께 호출하지 않으면 생성자 함수로 동작하지 않는다. 즉, 일방적인 함수의 호출이다.
const circle3 = Circle(15);

// 일반 함수로 호출된 Circle에는 반환문이 없으므로 암묵적으로 undefined를 반환한다.
console.log(circle3);

// 일반 함수로 호출된 Circle 내부의 this는 전역 객체를 가리킨다.
console.log(radius); // 15&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Function.prototype.apply/call/bind 메서드에 의한 간접 호출&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;apply, call, bind 메서드는 Function.prototype의 메서드다. 즉, 이들 메서드는 모든 함수가 상속받아 사용 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1729597331820&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getThisBinding() {
	return this;
}

// this로 사용할 객체
const thisArg = { a: 1 };

console.log(getThisBinding()); // window

// getThisBinding 함수를 호출하면서 인수로 전달한 객체를 getThisBinding 함수의 this에 바인딩한다.
console.log(getThisBinding.apply(thisArg)); // {a: 1}
console.log(getThisBinding.call(thisArg));; // {a: 1}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;apply와 call 메서드의 본질적인 기능은 함수롤 호출하는 것이다.&lt;/b&gt; apply와 call 메서드는 함수를 호출하면서 첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;apply 메서드는 호출할 함수의 인수를 배열로 묶어 전달한다. call 메서드는 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달한다. 이처럼 apply와 call 메서드는 호출할 함수에 인수를 전달하는 방식만 다를 뿐 this로 사용할 객체를 전달하면서 함수를 호출하는 것은 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Function.prototype.bind 메서드는 apply와 call 메서드와 달리 함수를 호출하지 않는다. 다만 첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1729597935752&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getThisBinding() {
	return this;
}

// this로 사용할 객체
const thisArg = { a: 1};

// bind 메서드는 첫 번째 이수로 전달한 thisArg로 this 바인딩이 교체된다.
// getThisBinding 함수를 새롭게 생성해 반환한다.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
console.log(getThisBinding.bind(thisArg)()); // {a: 1}&lt;/code&gt;&lt;/pre&gt;</description>
      <category> 내가방/ JavaScript</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/50</guid>
      <comments>https://yoon-dev.tistory.com/50#entry50comment</comments>
      <pubDate>Tue, 22 Oct 2024 20:53:53 +0900</pubDate>
    </item>
    <item>
      <title>[모던 자바스크립트] 배열 고차 함수 (sort, forEach, map, filter)</title>
      <link>https://yoon-dev.tistory.com/49</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고차 함수는 &lt;b&gt;함수를 인수로 전달 받거나 함수를 반환하는 함수&lt;/b&gt;를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트의 함수는 &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Glossary/First-class_Function&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;일급 객체&lt;/a&gt; 이므로 함수를 값처럼 인수로 전달할 수 있으며 반환할 수도 있다. 고차함수는 외부 상태의 변경이나 가변 데이터를 피하고&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Array.prototype.sort&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sort 메서드는 배열의 요소를 정렬한다. 원본 배열을 직접 변경하며 정렬된 배열을 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sort 메서드는 기본적으로 오름차순으로 요소를 정렬한다. 따라서 내림차순으로 요소를 정렬하려면 reverse 메서드를 사용하여 요소의 순서를 뒤집는다.&lt;/p&gt;
&lt;pre id=&quot;code_1729507156606&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const fruits = ['Banana', 'Orange', 'Apple'];

// 오름차순 (ascending) 정렬
fruits.sort();

// sort 메서드는 원본 배열을 직접 변경한다.
console.log(fruits); // ['Apple', 'Banana', 'Orange']

// 내림차순 정렬
fruits.reverse();
console.log(fruits); // ['Orange', 'Banana', 'Apple']&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열의 요소가 숫자 타입이라 할지라도 배열의 요소를 일시적으로 문자열로 변환한 후 유니코드 코드 포인트의 순서를 기준으로 정렬한다. 따라서 숫자 요소를 정렬할 때는 sort 메서드에 &lt;b&gt;정렬 순서를 정의하는 비교 함수를 인수로 전달&lt;/b&gt;해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1729507780855&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const points = [40, 100, 1, 5, 2, 25, 10];

// 숫자 배열의 오름차순 정렬, 비교 함수의 반환값이 0보다 작으면 a를 우선하여 정렬한다.
points.sort((a,b) =&amp;gt; a - b);
console.log(points); // [1, 2, 5, 10, 25, 40, 100];

// 숫자 배열에서 최솟값 최댓값
console.log(points[0], points[points.length - 1]); // 1 100

// 숫자 배열의 내림차순 정렬
points.sort((a,b) =&amp;gt; b - a);
console.log(points); // [100, 40, 25, 10, 5, 2, 1]&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;/p&gt;
&lt;pre id=&quot;code_1729508388736&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const todos = [
	{ id: 4, content: 'JavaScript'}.
    { id: 1, content: 'HTML'},
    { id: 2, comtent: 'CSS'}
];

// 비교함수, 매개변수 key는 프로퍼티 키다.
function compare(key) {
	// 프로퍼티 값이 문자열인 경우 - 산술 연산으로 비교하면 NaN이 나오므로 비교 연산을 사용한다.
    // 비교 함수 양수/음수/0을 반환하면 되므르 - 산술 연산 대신 비교 연산을 사용할 수 있다.
    return (a,b) =&amp;gt; (a[key] &amp;gt; b[key] ? 1 : (a[key] &amp;lt; b[key]) ? -1 : 0));
}

// id를 기준으로 오름차순 정렬
todos.sort(compare('id'));
console.log(todos); 
/*
[
{ id: 1, content: 'HTML'},
{ id: 2, comtent: 'CSS'},
{ id: 4, content: 'JavaScript'}
]
*/

// content를 기준으로 오름차순 정렬
todos.sort(compare('content');
console.log(todos);
/*
[
{ id: 2, comtent: 'CSS'},
{ id: 1, content: 'HTML'},
{ id: 4, content: 'JavaScript'}
]
*/&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;Array.prototype.forEach&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;forEach 메서드는 for 문을 대체할 수 있는 고차 함수이다. foreach 메서드는 자신의 내부에서 반복문을 실행한다.&amp;nbsp; 즉, forEach 메서드는 반복문을 추상화한 고차 함수로서 내부에서 반복문을 통해 자신을 호출한 배열을 순회하면서 수행해야 할 처리를 콜백 함수로 전달받아 반복 호출한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1729508920016&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const numbers = [1, 2, 3];
const pows = [];

// forEach 메서드는 numbers 배열의 모든 요소를 순회하면서 콜백함수를 반복 호출한다.
numbers.forEach(item =&amp;gt; pows.push(item ** 2));
console.log(pows); // [1, 4, 9]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;forEach 메서드의 콜백 함수는 &lt;b&gt;forEach 메서드를 호출한 배열의 요소값과 인덱스, forEach 메서드를 호출한 배열 자체, 즉 this를 순차적으로 전달&lt;/b&gt; 받을 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1729509189395&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//forEach 메서드는 콜백 함수를 호출하면서 3개(요소값, 인덱스, this)의 인수를 전달한다.
[1, 2, 3].forEach((item, index, arr) =&amp;gt; {
	console.log(`요소값: ${item}, 인덱스 : ${index}, this: ${JSON.stringify(arr)}`);
})

/*
요소값: 1, 인덱스: 0, this: [1,2,3]
요소값: 2, 인덱스: 1, this: [1,2,3]
요소값: 3, 인덱스: 2, this: [1,2,3]
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;forEach 메서드는 원본 배열(forEach 메서드를 호출한 배열, 즉 this)을 변경하지 않는다. 하지만 콜백 함수를 통해 원본 배열을 변경 할 수는 있다.&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;forEach 메서드의 반환값은 언제나 undefined다.&lt;/b&gt;&lt;/i&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;또한 forEach 메서드의 두 번째 인수로 forEach 메서드의 콜백 함수 내부에서 this로 사용할 객체를 전달할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1729509560583&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Numbers{
	numberArray = [];
    multiply(arr) {
    	arr.forEach(function (item) {
        	// TypeError: Cannot read property 'numberArray' of undefined
            this.numberArray.push(item * item);
        });
    }
}

const numbers = new Numbers();
numbers.multiply([]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;forEach 메서드의 콜백 함수는 일반 함수로 호출되므로 콜백 함수 내부의 this는 undefined를 가리킨다. this가 전역 객체가 아닌 undefined를 가리키는 이유는 클래스 내부의 모든 코드에는 암묵적으로 strict mode가 적용되기 때문이다.&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;forEach메서드는 for문에 비해 성능이 좋지는 않지만 가독성은 더 좋다. 따라서 요소가 대단히 많은 배열을 순회하거나 시간이 많이 걸리는 복잡한 코드 또는 높은 성능이 필요한 경우가 아니라면 for 문 대신 forEach 메서드를 사용할 것을 권장한다.&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;Array.prototype.map&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;map 메서드는 &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;forEach 메서드와 map 메서드의 공통점은 &lt;b&gt;자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출&lt;/b&gt;한다는 것이다. 하지만 forEach 메서드는 언제나 &lt;b&gt;undefined를 반환&lt;/b&gt;하고, map 메서드는 &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;&lt;b&gt;map 메서드가 생성하여 반환하는 새로운 배열의 length 프로퍼티 값은 map 메서드를 호출한 배열의 length 프로퍼티 값과 반드시 일치한다. 즉, map 메서드를 호출한 배열과 map 메서드가 생성하여 반환한 배열은 1:1 매핑한다.&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;또힌 forEach 메서드와 마찬가지로 map 메서드는 콜백 함수를 호출할 때 3개의 인수, 즉 map 메서드를 호출한 배열의 요소값과 인덱스 그리고 map 메서드를 호출한 배열(this)를 순차적으로 전달한다.&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;forEach 메서드외 마찬가지로 map 메서드의 두 번째 인수로 map 메서드의 콜백 함수 내부에서 this로 사용할 객체를 전달 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 나은 방법으로는 화살표 함수를 사용하는 것이다. 화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다. 따라서 화살표 함수 내부에서 this를 참조하면 상위 스코프, 즉 add 메서드 내부의 this를 그대로 참조 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1729510804402&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Prefixer{
	constructor(prefix){
    	this.prefix = prefix;
    }
}

add(arr) {
	// 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다.
    return arr.map(item =&amp;gt; this.prefix + item);
}

const prefixer = new Prefixer('-webkit-');
console.log(prefixer.add(['transition', 'user-select']));
// ['webkit-transition', '-webkit-user-select']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Array.prototype.filter&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;filter 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출한다. 그리고 &lt;b&gt;콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환&lt;/b&gt;한다.&lt;/p&gt;
&lt;pre id=&quot;code_1729511072488&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const numbers = [1,2,3,4,5];

// numbers 배열에서 홀수인 요소만 필터링한다. (1은 true로 평가된다.)
const odds = numbers.filter(item =&amp;gt; item % 2);
console.log(odds); // [1, 3, 5]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;forEach,map 메서드와 마찬가지로 filter 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출한다. forEach 메서드는 언제나 undefined를 반환하고, map 메서드는 콜백 함수의 반환값들로 구성된 새로은 배열을 반환하지만 filter 메서드는 콜백 함수의 &lt;b&gt;반환값이 true인 요소만 추출한 새로운 배열을 반환&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 filter 메서드가 생성하며 반환한 새로운 배열의 length 프로퍼티 값은 filter 메서드를 호출한 배열의 length 프로퍼티 값과 같거나 작다.&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;forEach, map 메서드와 마찬가지로 콜백 함수를 호출할 때 3개의 인수, 즉 filter 메서드를 호출한 배열의 요소값과 인덱스, filter 메서드를 호출한 배열(this)을 순차적으로 전달한다. 또한 filter 메서드의 두 번째 인수로 filter 메서드의 콜백 함수 내부에서 this로 사용할 객체를 전달 할 수 있다.&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;filter 메서드는 자신을 호출한 배열에서 특정 요소를 제거하기 위해 사용할 수도 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1729511639204&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Users {
	constructor(){
    	this.users = [
        	{ id:1, name: 'Lee'},
            { id:2, name: 'Kim'}
        ];
    }
    
    // 요소 추출
    findById(id){
    	// id가 일치하는 사용자만 반환한다.
        return this.users.filter(user =&amp;gt; user.id === id);
    }
    
    // 요소 제거
    remove(id){
    	this.users = this.users.filter(user =&amp;gt; user.id !== id);
    }
    
    const users = new Users();
    
    let user = users.findById(1);
    console.log(user); // [{ id: 1, name: 'Lee'}]
    
    // id가 1인 사용자를 제거한다.
    users.remove(1);
    
    user = users.findById(1);
    console.log(user); // []
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;filter 메서드를 사용해 특정 요소를 제거할 경우 특정 요소가 중복되어 있다면 중복된 요소가 모두 제거된다. 특정 요소를 하나만 제거하려면 indexOf 메서드를 통해 요소의 인덱스를 취득한 다음 splice 메서드를 사용한다.&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;Array.prototype.reduce&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reduec 메서드는 자신을 호출한 배열을 모든 요소를 순회하면 인수로 전달받은 콜백 함수를 반복 호출한다. 그리고 &lt;b&gt;콜백 함수의 반환값을 다음 순회 시에 콜백 함수의 첫 번째 인수로 전달하면서 콜백 함수를 호출하여 하나의 결과값을 만들어 반환&lt;/b&gt;한다. 이때 원본 배열은 변경되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reduce 메서드는 첫 번째 인수로 콜백 함수, 두 번째 인수로 초기값을 전달받는다. reduce 메서드의 콜백 함수에는 4개의 인수, 초기값 또는 콜백 함수의 이전 반환값, reduce 메서드를 호출한 배열의 요소값과 인덱스, reduce 메서드를 호출한 배열 자체, 즉 this가 전달된다.&lt;/p&gt;
&lt;pre id=&quot;code_1729511923525&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1부터 4까지 누적을 구한다.
const sum = [1, 2, 3, 4].reduce((accumulator, currentValue, index, array) =&amp;gt; accumulator + currentValue, 0);

console.log(sum); // 10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 reduce 메서드는 초기값과 배열의 첫 번째 요소값을 콜백 함수에게 인수로 전달하면서 호출하고 다음 순회에는 콜백 함수의 반환값과 두 번째 요소값을 콜백 함수의 인수로 전달하면서 호출한다. 이러한 과정을 반복하여 &lt;b&gt;reduce 메서드는 하나의 결과값을 반환&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category> 내가방/ JavaScript</category>
      <author>멍발윤</author>
      <guid isPermaLink="true">https://yoon-dev.tistory.com/49</guid>
      <comments>https://yoon-dev.tistory.com/49#entry49comment</comments>
      <pubDate>Mon, 21 Oct 2024 21:04:58 +0900</pubDate>
    </item>
  </channel>
</rss>