<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kwondk.log</title>
        <link>https://velog.io/</link>
        <description>동균이다</description>
        <lastBuildDate>Sat, 24 May 2025 10:10:38 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kwondk.log</title>
            <url>https://velog.velcdn.com/images/dongkyun-kwon/profile/96274849-ce8a-4239-8027-047a89dd7065/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kwondk.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dongkyun-kwon" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[React AtoZ] `useEffect`와 의존성 배열, 그리고 EsLint]]></title>
            <link>https://velog.io/@dongkyun-kwon/useEffect%EC%99%80-%EC%9D%98%EC%A1%B4%EC%84%B1-%EB%B0%B0%EC%97%B4-%EA%B7%B8%EB%A6%AC%EA%B3%A0-EsLint</link>
            <guid>https://velog.io/@dongkyun-kwon/useEffect%EC%99%80-%EC%9D%98%EC%A1%B4%EC%84%B1-%EB%B0%B0%EC%97%B4-%EA%B7%B8%EB%A6%AC%EA%B3%A0-EsLint</guid>
            <pubDate>Sat, 24 May 2025 10:10:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>React에서 <code>useEffect</code>를 쓸 때 가장 많이 부딪히는 부분 중 하나가 <strong>의존성 배열(dependency array)</strong> 설정입니다. 적게 넣으면 버그 나고, 많이 넣으면 무한루프... 😵</p>
<p>이 글에서는 <code>useEffect</code>와 의존성 배열을 언제, 어떻게 설정해야 하는지 완전 정리해봅니다.</p>
</blockquote>
<hr>
<h2 id="useeffect란"><code>useEffect</code>란?</h2>
<p><code>useEffect</code>는 <strong>컴포넌트가 렌더링된 이후에 실행되는 side-effect 처리 함수</strong>입니다. React의 선언적 UI 렌더링 흐름과 별개로, 아래와 같은 &quot;부수효과&quot; 작업에 사용합니다.:</p>
<ul>
<li>API 요청</li>
<li>DOM 조작</li>
<li>이벤트 등록</li>
<li>타이머 설정 등…</li>
</ul>
<p>즉, 리액트의 <strong>순수 렌더링 외</strong>의 모든 부가 작업을 처리합니다.</p>
<pre><code class="language-tsx">useEffect(() =&gt; {
  // 여기가 side effect 영역
}, [deps]);</code></pre>
<hr>
<h2 id="의존성-배열이란">의존성 배열이란?</h2>
<p>의존성 배열(dependency array)은 <code>useEffect</code>의 재실행 조건을 정의하는 역할을 합니다.</p>
<table>
<thead>
<tr>
<th>의존성 배열</th>
<th>실행 시점</th>
</tr>
</thead>
<tbody><tr>
<td>생략</td>
<td>모든 렌더링 후 실행</td>
</tr>
<tr>
<td><code>[]</code></td>
<td>마운트 시 1회만 실행</td>
</tr>
<tr>
<td><code>[a, b]</code></td>
<td>a나 b가 변경될 때만 실행</td>
</tr>
</tbody></table>
<h3 id="예시">예시</h3>
<pre><code class="language-tsx">useEffect(() =&gt; {
  console.log(count);
}, [count]);</code></pre>
<p>→ <code>count</code>가 바뀔 때만 effect 실행</p>
<hr>
<h2 id="useeffect의-실행-순서">useEffect의 실행 순서</h2>
<blockquote>
<p><strong>렌더링 → DOM 업데이트 → useEffect 실행</strong></p>
</blockquote>
<ul>
<li>이 말은 곧, <code>useEffect</code>는 화면이 바뀐 뒤 실행된다는 뜻입니다.</li>
<li><code>useEffect</code>는 비동기적으로 실행되며, 렌더링을 막지 않습니다.</li>
</ul>
<h4 id="uselayouteffect와의-차이점">useLayoutEffect와의 차이점?</h4>
<ul>
<li><code>useLayoutEffect</code>: DOM 업데이트 <strong>이전</strong>에 실행됨 (동기)</li>
<li><code>useEffect</code>: DOM 업데이트 <strong>이후</strong>에 실행됨 (비동기)</li>
</ul>
<hr>
<h2 id="클린업-함수란">클린업 함수란?</h2>
<p><code>useEffect</code>는 필요에 따라 정리(clean-up) 작업을 할 수 있습니다. 예를 들어 이벤트 리스너 제거, 타이머 정리 등:</p>
<pre><code class="language-tsx">useEffect(() =&gt; {
  const handler = () =&gt; console.log(&quot;scroll&quot;);
  window.addEventListener(&quot;scroll&quot;, handler);

  // 컴포넌트가 unmount 되거나, 의존성이 바뀔 때 실행됨
  return () =&gt; {
    window.removeEventListener(&quot;scroll&quot;, handler);
  };
}, []);
</code></pre>
<h4 id="클린업-함수는-다음-시점에-실행됩니다">클린업 함수는 다음 시점에 실행됩니다:</h4>
<ul>
<li>컴포넌트가 언마운트될 때</li>
<li>의존성 배열이 바뀔 때 → 기존 effect 정리 후 새로운 effect 실행</li>
</ul>
<hr>
<h2 id="⚠️-의존성-배열-왜-중요할까">⚠️ 의존성 배열, 왜 중요할까?</h2>
<h3 id="👍-올바르게-설정-시">👍 올바르게 설정 시</h3>
<ul>
<li>불필요한 재실행 방지 → <strong>성능 최적화</strong></li>
<li>최신 데이터 값 사용 → <strong>정확한 로직 보장</strong></li>
</ul>
<h3 id="👎-잘못-설정-시">👎 잘못 설정 시</h3>
<ul>
<li><strong>무한 루프</strong> 발생(setState → 렌더링 → effect → 다시 setState ...)</li>
<li><strong>stale data(오래된 값)</strong> 사용 → 예측 불가한 버그 발생</li>
</ul>
<hr>
<h2 id="의존성-배열-설정-원칙">의존성 배열 설정 원칙</h2>
<p><code>Effect</code> 내부에서 사용하는 모든 외부 변수(<code>state</code>, <code>props</code>, 함수 등)는 반드시 의존성 배열에 포함해야한다.</p>
<pre><code class="language-tsx">useEffect(() =&gt; {
  console.log(user.name); // user 사용
}, [user]); // 반드시 user를 넣어야 함</code></pre>
<hr>
<h2 id="eslint가-도와주는-이유">ESLint가 도와주는 이유</h2>
<ul>
<li>React 팀에서 만든 공식 ESLint 플러그인</li>
<li>코드의 <strong>문법 오류, 버그 가능성, 스타일 문제</strong>를 미리 찾아주는 도구<ul>
<li>React 프로젝트에서는 보통 <code>eslint-plugin-react-hooks</code>라는 플러그인을 함께 사용</li>
<li><strong>React 훅의 사용 규칙</strong>, 특히 <code>useEffect</code>, <code>useCallback</code>, <code>useMemo</code> 같은 훅의 <strong>의존성 배열</strong>을 자동으로 검사한다.</li>
</ul>
</li>
</ul>
<h3 id="예시-1">예시</h3>
<pre><code class="language-tsx">useEffect(() =&gt; {
  console.log(count); // 사용 중
}, []); // ❌ ESLint 경고!</code></pre>
<p>➡️ <code>count</code>를 사용했는데 의존성 배열에 없음 → <strong>stale data 위험!</strong></p>
<br />

<h3 id="해결">해결</h3>
<pre><code class="language-tsx">useEffect(() =&gt; {
  console.log(count);
}, [count]); // ✅ 최신 값 동기화 보장</code></pre>
<hr>
<h2 id="eslint-경고-무시해도-될까">ESLint 경고, 무시해도 될까?</h2>
<p>가끔은 무시해도 됩니다. <strong>정말 필요한 경우에만!</strong></p>
<h3 id="예-마운트-시-단-1회만-실행">예: 마운트 시 단 1회만 실행</h3>
<pre><code class="language-tsx">useEffect(() =&gt; {
  fetchData(); // 내부에서 state를 사용하지 않는다면 괜찮음
}, []);</code></pre>
<hr>
<h2 id="함수와-객체는-왜-주의해야-할까">함수와 객체는 왜 주의해야 할까?</h2>
<h3 id="1-함수">1. 함수</h3>
<ul>
<li><p>자바스크립트에서 함수와 객체는 참조값이 중요 !</p>
<pre><code class="language-jsx">  const obj = { name: &quot;Alice&quot; };
  const another = { name: &quot;Alice&quot; };
  console.log(obj === another); // false</code></pre>
<p>  ➡️ 내용이 같아도, 객체나 함수는 새로 만들면 다른 것으로 간주된다.
  ➡️ 즉, 매번 새로 생성되면 이전 값과 비교해서 &#39;변했다&#39;고 판단!</p>
</li>
</ul>
<br />

<h4 id="예시-코드">예시 코드</h4>
<pre><code class="language-tsx">function App() {
  const fetchData = () =&gt; {
    console.log(&quot;데이터 요청&quot;);
  };

  useEffect(() =&gt; {
    fetchData();
  }, [fetchData]);
}</code></pre>
<p>➡️ 위 코드는 매 렌더링마다 <code>fetchData</code> 함수가 새로 만들어지기 때문에 <code>useEffect</code>도 <strong>매번 실행</strong>됩니다. ⛔</p>
<br />

<h4 id="해결-방법-usecallback">해결 방법: <code>useCallback</code></h4>
<ul>
<li><p><code>useCallback</code> : 함수의 참조값을 고정해주는 훅이다.</p>
<pre><code class="language-tsx">const fetchData = useCallback(() =&gt; {
  console.log(&quot;데이터 요청&quot;);
}, []);</code></pre>
<p>➡️ 이제 <code>fetchData</code>는 참조값이 고정되므로, <code>useEffect</code>도 안정적으로 동작합니다.</p>
</li>
</ul>
<hr>
<h3 id="2-객체">2. 객체</h3>
<ul>
<li>객체 또한 렌더링마다 새로 생성된다.<pre><code class="language-tsx">useEffect(() =&gt; {
  console.log(&quot;옵션 변경됨&quot;);
}, [{ size: 10 }]); // 매번 다른 객체로 인식됨!</code></pre>
</li>
</ul>
<br />

<h4 id="해결-방법-usememo">해결 방법: <code>useMemo</code></h4>
<ul>
<li><p><code>useMemo</code>는 객체를 처음 한 번만 생성하고, 의존성 배열이 변하지 않는 한 재사용합니다.</p>
<pre><code class="language-tsx">const options = useMemo(() =&gt; ({ size: 10 }), []);

useEffect(() =&gt; {
  console.log(&quot;옵션 변경됨&quot;);
}, [options]);</code></pre>
<p>➡️ 객체 참조를 고정해서 <code>useEffect</code>가 불필요하게 실행되지 않도록 합니다.</p>
</li>
</ul>
<hr>
<h2 id="요약-정리">요약 정리</h2>
<table>
<thead>
<tr>
<th>상황</th>
<th>의존성 배열에 넣어야 할까?</th>
<th>해결 방법</th>
</tr>
</thead>
<tbody><tr>
<td>내부에서 state, props 사용</td>
<td>✅ 예</td>
<td>배열에 직접 포함</td>
</tr>
<tr>
<td>함수 사용</td>
<td>⚠️ 항상 새로운 참조</td>
<td><code>useCallback</code>으로 감싸기</td>
</tr>
<tr>
<td>객체/배열 사용</td>
<td>⚠️ 새로 생성됨</td>
<td><code>useMemo</code>로 감싸기</td>
</tr>
<tr>
<td>마운트 시 1회 실행</td>
<td>✅ <code>[]</code></td>
<td>클린한 로직 보장해야 함</td>
</tr>
<tr>
<td>ESLint 경고 무시</td>
<td>⛔ 가급적 피하기</td>
<td>주석으로 의도 설명하기</td>
</tr>
</tbody></table>
<hr>
<h2 id="마무리">마무리</h2>
<p><code>useEffect</code>는 단순해 보이지만, 의존성 배열을 잘못 쓰면 <strong>예측 불가능한 버그</strong>로 이어질 수 있습니다. 다음 원칙만 기억하기:</p>
<ul>
<li><code>useEffect</code> 안에서 쓰는 <strong>모든 변수는 의존성 배열에 넣기</strong></li>
<li><strong>함수나 객체는 useCallback / useMemo로 감싸기</strong></li>
<li><strong>불필요한 ESLint 무시는 금물</strong></li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React AtoZ] JSX와 HTML의 차이는 무엇인가?]]></title>
            <link>https://velog.io/@dongkyun-kwon/React-AtoZ-JSX%EC%99%80-HTML%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@dongkyun-kwon/React-AtoZ-JSX%EC%99%80-HTML%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Mon, 28 Apr 2025 05:05:15 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>리액트로 개발할 때 우리는 매일 JSX를 사용합니다. 하지만 처음 접하면 HTML과 너무 비슷해 보이기 때문에 &quot;이거 그냥 HTML 아냐?&quot;라고 착각하기 쉽습니다.(😂) 
JSX 문법이 HTML과 매우 유사하게 보이지만, 실제로는 중요한 차이점(<strong>작동 방식</strong>부터 <strong>문법 규칙</strong>까지)들이 있습니다.</p>
</blockquote>
<hr/>

<h2 id="jsx란-무엇인가">JSX란 무엇인가?</h2>
<p><code>JSX</code>(<code>JavaScript XML</code>)는 React에서 UI를 구성하기 위해 사용하는 JavaScript의 확장 문법입니다. 외관상 HTML과 유사하지만, 실제로는 JavaScript 객체로 변환되어 React 엘리먼트를 생성합니다.</p>
<ul>
<li><p>쉽게 말하면, <strong>자바스크립트 안에서 HTML처럼 보이는 코드를 작성할 수 있는 문법</strong>입니다.</p>
<pre><code class="language-jsx">const element = (
  &lt;div className=&quot;container&quot;&gt;
    &lt;h1&gt;안녕하세요!&lt;/h1&gt;
  &lt;/div&gt;
);</code></pre>
</li>
<li><p>이 코드는 겉으로 보기엔 <code>HTML</code> 같지만 브라우저에서 직접 실행되지 않고, <code>Babel</code>과 같은 트랜스파일러를 통해 다음과 같은 JavaScript 코드로 변환됩니다:</p>
<pre><code class="language-jsx">  const element = React.createElement(
    &#39;div&#39;,
    { className: &#39;container&#39; },
    React.createElement(&#39;h1&#39;, null, &#39;안녕하세요!&#39;)
  );</code></pre>
</li>
</ul>
<p>→ <strong>즉, JSX는 브라우저가 바로 이해할 수 없고, 컴파일 과정(Babel 등)을 거쳐 자바스크립트 코드로 변환된다는 것</strong>이 가장 큰 포인트입니다.</p>
<hr>
<h2 id="jsx와-html의-주요-차이점">JSX와 HTML의 주요 차이점</h2>
<h3 id="1-속성attributes-명명-규칙">1. 속성(Attributes) 명명 규칙</h3>
<p><strong>HTML</strong>:</p>
<ul>
<li><p>속성 이름은 대소문자를 구분하지 않습니다.</p>
</li>
<li><p>케밥 케이스(kebab-case)를 사용합니다.</p>
<blockquote>
<h4 id="케밥-케이스kebab-case란">케밥 케이스(kebab-case)란?</h4>
<ul>
<li><h5 id="케밥-케이스는-프로그래밍과-웹-개발에서-사용되는-명명-규칙naming-convention-중-하나입니다">케밥 케이스는 프로그래밍과 웹 개발에서 사용되는 명명 규칙(naming convention) 중 하나입니다.</h5>
</li>
<li><h5 id="이름이-재미있게도-케밥에서-유래했는데-단어들이-하이픈--기호로-연결되어-마치-케밥-꼬치처럼-보이기-때문입니다">이름이 재미있게도 &quot;케밥&quot;에서 유래했는데, 단어들이 하이픈(<code>-</code>) 기호로 연결되어 마치 케밥 꼬치처럼 보이기 때문입니다.</h5>
<h4 id="케밥-케이스의-특징">케밥 케이스의 특징:</h4>
<h5 id="1-단어-사이에-하이픈--사용-모든-단어가-소문자로-작성되고-단어-사이는-하이픈으로-구분합니다">1. <strong>단어 사이에 하이픈(<code>-</code>) 사용</strong>: 모든 단어가 소문자로 작성되고, 단어 사이는 하이픈으로 구분합니다.</h5>
<h5 id="2-예시-background-color-margin-top-user-select-font-family">2. <strong>예시</strong>: <code>background-color</code>, <code>margin-top</code>, <code>user-select</code>, <code>font-family</code></h5>
</li>
</ul>
</blockquote>
</li>
</ul>
<ul>
<li><p><code>class</code>, <code>for</code> 같은 키워드를 그대로 사용합니다.</p>
<pre><code class="language-html">&lt;div class=&quot;container&quot; tabindex=&quot;-1&quot; data-value=&quot;example&quot;&gt;&lt;/div&gt;</code></pre>
</li>
</ul>
<p><strong>JSX</strong>:</p>
<ul>
<li><p>속성 이름은 카멜 케이스(camelCase)를 사용합니다.</p>
<blockquote>
<h4 id="카멜-케이스camelcase란">카멜 케이스(camelCase)란?</h4>
<ul>
<li><h5 id="카멜-케이스는-프로그래밍에서-흔히-사용되는-명명-규칙naming-convention-중-하나입니다">카멜 케이스는 프로그래밍에서 흔히 사용되는 명명 규칙(naming convention) 중 하나입니다.</h5>
</li>
<li><h5 id="이름이-낙타camel에서-유래했는데-단어들이-대소문자로-구분되어-낙타의-등처럼-올라갔다-내려갔다-하는-모양을-연상시키기-때문입니다">이름이 &quot;낙타(camel)&quot;에서 유래했는데, 단어들이 대소문자로 구분되어 낙타의 등처럼 올라갔다 내려갔다 하는 모양을 연상시키기 때문입니다.</h5>
<h4 id="카멜-케이스의-특징">카멜 케이스의 특징:</h4>
<h5 id="1-첫-단어는-소문자로-시작-첫-번째-단어는-모두-소문자로-작성합니다">1. <strong>첫 단어는 소문자로 시작</strong>: 첫 번째 단어는 모두 소문자로 작성합니다.</h5>
<h5 id="2-이후-단어는-대문자로-시작-두-번째-단어부터는-첫-글자만-대문자로-작성합니다">2. <strong>이후 단어는 대문자로 시작</strong>: 두 번째 단어부터는 첫 글자만 대문자로 작성합니다.</h5>
<h5 id="3-단어-사이에-공백이나-특수문자-없음-모든-단어가-붙어있고-대소문자로만-구분됩니다">3. <strong>단어 사이에 공백이나 특수문자 없음</strong>: 모든 단어가 붙어있고 대소문자로만 구분됩니다.</h5>
<h5 id="4-예시-backgroundcolor-username-isloggedin-handlesubmit">4. <strong>예시</strong>: <code>backgroundColor</code>, <code>userName</code>, <code>isLoggedIn</code>, <code>handleSubmit</code></h5>
→ JavaScript와 React에서는 카멜 케이스가 변수, 함수, 메서드, 그리고 JSX 속성에 대한 표준 명명 규칙으로 사용됩니다</li>
</ul>
</blockquote>
</li>
</ul>
<ul>
<li><p>HTML 속성과 다른 이름을 사용하는 경우가 있습니다(예: class → className).</p>
<ul>
<li><p>이유는 간단합니다.
<code>class</code>와 <code>for</code>는 자바스크립트에서 이미 특별한 의미를 가지는 키워드이기 때문에, 이름을 살짝 바꿔야 합니다.</p>
<pre><code class="language-jsx">  &lt;div className=&quot;container&quot; tabIndex=&quot;-1&quot; data-value=&quot;example&quot;&gt;&lt;/div&gt;</code></pre>
</li>
</ul>
</li>
</ul>
<hr />

<h3 id="2-javascript-표현식-사용">2. JavaScript 표현식 사용</h3>
<p><strong>HTML</strong>:</p>
<ul>
<li><p>JavaScript 코드를 직접 삽입할 수 없습니다.</p>
</li>
<li><p>HTML에서는 텍스트만 적으면 텍스트로 보입니다.</p>
<pre><code class="language-html">  &lt;p&gt;2 + 2&lt;/p&gt;  &lt;!-- 브라우저에는 &quot;2 + 2&quot;로 표시 -→</code></pre>
</li>
</ul>
<p><strong>JSX</strong>:</p>
<ul>
<li>중괄호 <code>{}</code>를 사용하여 JavaScript 표현식을 직접 삽입할 수 있습니다.</li>
</ul>
<pre><code class="language-jsx">    const name = &quot;React&quot;;
    const element = &lt;h1&gt;Hello, {name}!&lt;/h1&gt;;

    // 조건부 렌더링
    const showElement = true;
    const conditionalElement = (
      &lt;div&gt;
        {showElement &amp;&amp; &lt;p&gt;이 요소는 조건에 따라 렌더링됩니다.&lt;/p&gt;}
      &lt;/div&gt;
    );

    &lt;p&gt;{2 + 2}&lt;/p&gt;  // 결과: 4</code></pre>
<hr />


<h3 id="3-스타일-적용-방식">3. 스타일 적용 방식</h3>
<p><strong>HTML</strong>:</p>
<ul>
<li><p>인라인 스타일은 문자열로 정의합니다.</p>
<pre><code class="language-html">  &lt;div style=&quot;color: blue; margin-top: 20px;&quot;&gt;&lt;/div&gt;</code></pre>
</li>
</ul>
<p><strong>JSX</strong>:</p>
<ul>
<li><p>인라인 스타일은 JavaScript 객체로 정의합니다.</p>
<pre><code class="language-jsx">  const divStyle = {
    color: &#39;blue&#39;,
    marginTop: &#39;20px&#39; // 카멜 케이스 사용
  };

  const element = &lt;div style={divStyle}&gt;&lt;/div&gt;;
  // 또는
  const element = &lt;div style={{ color: &#39;blue&#39;, marginTop: &#39;20px&#39; }}&gt;&lt;/div&gt;;</code></pre>
</li>
</ul>
<hr />

<h3 id="4-태그-닫기self-closing-tags">4. 태그 닫기(Self-closing tags)</h3>
<p><strong>HTML</strong>:</p>
<ul>
<li><p>HTML에서는 <code>&lt;img&gt;</code>, <code>&lt;input&gt;</code> 태그처럼 일부 태그는 닫을 필요가 없습니다.</p>
<pre><code class="language-html">  &lt;input type=&quot;text&quot;&gt;
  &lt;br&gt;
  &lt;img src=&quot;image.jpg&quot;&gt;</code></pre>
</li>
</ul>
<p><strong>JSX</strong>:</p>
<ul>
<li><p>모든 태그는 반드시 닫아야 합니다. 안 닫으면 컴파일 에러가 발생합니다.</p>
<pre><code class="language-jsx">  &lt;input type=&quot;text&quot; /&gt;
  &lt;br /&gt;
  &lt;img src=&quot;image.jpg&quot; /&gt;</code></pre>
</li>
</ul>
<hr />


<h3 id="5-주석-작성-방식">5. 주석 작성 방식</h3>
<p><strong>HTML</strong>:</p>
<pre><code class="language-html">&lt;!-- 이것은 HTML 주석입니다 --&gt;</code></pre>
<p><strong>JSX</strong>:</p>
<pre><code class="language-jsx">{/* 이것은 JSX 내부의 주석입니다 */}</code></pre>
<hr />

<h3 id="6-예약어와-충돌">6. 예약어와 충돌</h3>
<p><strong>HTML</strong>:</p>
<ul>
<li>예약어 사용에 제한이 없습니다.</li>
</ul>
<p><strong>JSX</strong>:</p>
<ul>
<li><p>JavaScript 예약어와 충돌을 피하기 위해 일부 속성명이 변경되었습니다.</p>
<ul>
<li><p><code>class</code> → <code>className</code></p>
</li>
<li><p><code>for</code> → <code>htmlFor</code></p>
<pre><code class="language-jsx">  &lt;label className=&quot;form-label&quot; htmlFor=&quot;username&quot;&gt;사용자 이름:&lt;/label&gt;</code></pre>
</li>
</ul>
</li>
</ul>
<hr />

<h3 id="7-데이터-바인딩">7. 데이터 바인딩</h3>
<p><strong>HTML</strong>:</p>
<ul>
<li>동적 데이터 바인딩을 위해서는 별도의 JavaScript 코드가 필요합니다.</li>
</ul>
<p><strong>JSX</strong>:</p>
<ul>
<li><p>직접적인 JavaScript 표현식을 통한 데이터 바인딩이 가능합니다.</p>
<pre><code class="language-jsx">  const items = [&#39;사과&#39;, &#39;바나나&#39;, &#39;오렌지&#39;];

  const element = (
    &lt;ul&gt;
      {items.map((item, index) =&gt; (
        &lt;li key={index}&gt;{item}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );</code></pre>
</li>
</ul>
<hr />

<h2 id="jsx를-사용하는-이유">JSX를 사용하는 이유</h2>
<ol>
<li><strong>가독성 향상</strong>: HTML과 유사한 문법으로 UI 구조를 더 명확하게 표현할 수 있습니다.</li>
<li><strong>JavaScript의 모든 기능 활용</strong>: 조건부 렌더링, 반복 렌더링 등 JavaScript의 강력한 기능을 UI 구성에 활용할 수 있습니다.</li>
<li><strong>컴포넌트 기반 개발</strong>: 재사용 가능한 컴포넌트를 쉽게 만들고 조합할 수 있습니다.</li>
<li><strong>Type 안전성</strong>: TypeScript와 함께 사용하면 컴파일 시점에 오류를 감지할 수 있습니다.</li>
</ol>
<hr />

<h2 id="정리-jsx-vs-html">정리: JSX vs HTML</h2>
<table>
<thead>
<tr>
<th>구분</th>
<th>HTML</th>
<th>JSX</th>
</tr>
</thead>
<tbody><tr>
<td>사용 대상</td>
<td>브라우저</td>
<td>리액트</td>
</tr>
<tr>
<td>문법 해석</td>
<td>브라우저가 직접 해석</td>
<td>Babel 등으로 변환 후 JS 실행</td>
</tr>
<tr>
<td>속성 이름</td>
<td>class, for</td>
<td>className, htmlFor</td>
</tr>
<tr>
<td>태그 닫기</td>
<td>선택 가능</td>
<td>필수</td>
</tr>
<tr>
<td>JS 표현식</td>
<td>불가</td>
<td>중괄호 <code>{}</code> 사용</td>
</tr>
</tbody></table>
<hr />

<h2 id="결론">결론</h2>
<ul>
<li>JSX는 HTML과 외형적으로 유사하지만, 진짜 HTML은 아닙니다. <strong>실제로는 JavaScript의 확장 문법으로 다양한 차이점이 있습니다.</strong></li>
<li>리액트의 렌더링 로직 안에서 <strong>자바스크립트 객체를 만들기 위한 문법</strong>이라고 이해하는 게 정확합니다.</li>
<li>이러한 차이점을 이해하고 JSX의 특성과 장점을 활용하면 React에서 더 효율적으로 UI를 구성할 수 있습니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 상태 관리: useState와 useReducer의 차이점과 적절한 사용법 ⚛️]]></title>
            <link>https://velog.io/@dongkyun-kwon/React-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC-useState%EC%99%80-useReducer%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90%EA%B3%BC-%EC%A0%81%EC%A0%88%ED%95%9C-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@dongkyun-kwon/React-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC-useState%EC%99%80-useReducer%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90%EA%B3%BC-%EC%A0%81%EC%A0%88%ED%95%9C-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Sun, 16 Mar 2025 08:58:37 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<p>React에서 상태를 관리하는 방법에는 여러 가지가 있지만, <code>useState</code>와 <code>useReducer</code>는 가장 많이 사용되는 두 가지 훅입니다. 
이 둘은 비슷하게 보일 수 있지만, 각각의 사용 목적과 특징이 다릅니다. 
이번 포스트에서는 <code>useState</code>와 <code>useReducer</code>를 비교하며, 언제 각 훅을 사용하는 것이 적합한지에 대해 알아보겠습니다.</p>
<hr>
<h2 id="1-usestate">1. <code>useState</code></h2>
<p><code>useState</code>는 React 컴포넌트 내에서 간단한 상태를 관리할 수 있는 훅입니다. 상태 값과 그 상태를 변경하는 함수를 반환하여, 상태를 직접 관리할 수 있게 해줍니다.</p>
<h3 id="사용법"><strong>사용법</strong></h3>
<pre><code class="language-javascript">import React, { useState } from &#39;react&#39;;

function Counter() {
  const [count, setCount] = useState(0);

  const increment = () =&gt; {
    setCount(count + 1);
  };

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={increment}&gt;Increment&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<h3 id="🔥-특징"><strong>🔥 특징</strong></h3>
<ul>
<li><strong>단일 상태 값 관리</strong>: <code>useState</code>는 간단한 값 하나를 관리할 때 적합합니다.</li>
<li><strong>상태값과 업데이트 함수</strong>: <code>useState</code>는 상태값과 이를 갱신하는 함수를 함께 반환합니다.</li>
<li><strong>간단한 상태 업데이트</strong>: 상태 업데이트가 단순할 때 매우 직관적이고 사용하기 쉽습니다.</li>
</ul>
<h3 id="💡-언제-사용하나요"><strong>💡 언제 사용하나요?</strong></h3>
<ul>
<li>상태가 하나일 때</li>
<li>상태 로직이 간단할 때</li>
</ul>
<h3 id="✅-장점">✅ 장점</h3>
<ul>
<li><strong>간단함</strong>: 단순한 상태 관리에 매우 직관적이고 사용하기 쉽습니다.</li>
<li><strong>직관적인 코드</strong>: 상태와 업데이트 함수가 한 번에 반환되므로 코드가 깔끔하고 직관적입니다.</li>
<li><strong>빠른 설정</strong>: 설정이 매우 간단하고, 빠르게 구현할 수 있습니다.</li>
</ul>
<h3 id="❌-단점">❌ 단점</h3>
<ul>
<li><strong>복잡한 상태 관리에는 한계</strong>: 상태가 많아지거나 복잡해지면 코드가 복잡해지고 관리하기 어려워질 수 있습니다.</li>
<li><strong>상태 업데이트 로직의 제어 부족</strong>: 상태 업데이트가 간단할 때는 괜찮지만, 여러 조건에 따라 복잡한 로직을 관리하려면 불편할 수 있습니다.</li>
</ul>
<hr>
<h2 id="2-usereducer">2. <code>useReducer</code></h2>
<p><code>useReducer</code>는 상태 업데이트가 복잡할 때 사용되는 훅입니다. 여러 가지 상태를 하나의 객체로 관리하거나, 상태 변화가 여러 가지 조건에 따라 달라져야 할 때 유용합니다. 리듀서 함수와 액션 객체를 사용하여 상태를 업데이트합니다.</p>
<h3 id="사용법-1"><strong>사용법</strong></h3>
<pre><code class="language-javascript">import React, { useReducer } from &#39;react&#39;;

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case &#39;increment&#39;:
      return { count: state.count + 1 };
    case &#39;decrement&#39;:
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {state.count}&lt;/p&gt;
      &lt;button onClick={() =&gt; dispatch({ type: &#39;increment&#39; })}&gt;Increment&lt;/button&gt;
      &lt;button onClick={() =&gt; dispatch({ type: &#39;decrement&#39; })}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<h3 id="🔥-특징-1"><strong>🔥 특징</strong></h3>
<ul>
<li><strong>복잡한 상태 관리</strong>: 여러 값이 연관되어 있거나 복잡한 상태 로직이 필요할 때 유용합니다.</li>
<li><strong>리듀서 함수 사용</strong>: 상태 업데이트 로직을 <code>switch</code>문으로 명확하게 정의할 수 있습니다.</li>
<li><strong>디스패치 방식</strong>: 액션 객체를 디스패치하여 상태를 업데이트합니다.</li>
</ul>
<h3 id="💡-언제-사용하나요-1"><strong>💡 언제 사용하나요?</strong></h3>
<ul>
<li>상태가 여러 개일 때</li>
<li>상태 변화가 복잡할 때</li>
<li>여러 액션에 따라 상태를 업데이트할 때</li>
</ul>
<h3 id="✅-장점-1">✅ 장점</h3>
<ul>
<li><strong>복잡한 상태 로직 처리</strong>: 여러 상태 값들이 연관되어 있거나 복잡한 상태 로직을 관리할 때 유용합니다.</li>
<li><strong>상태 업데이트 로직 명확화</strong>: reducer 함수 내에서 상태 업데이트 로직을 명확하게 분리할 수 있어 디버깅이 용이합니다.</li>
<li><strong>확장성</strong>: 여러 액션을 다루는 데 용이하여, 코드가 커져도 관리하기 수월합니다.</li>
</ul>
<h3 id="❌-단점-1">❌ 단점</h3>
<ul>
<li><strong>초기 설정 복잡</strong>: useState보다 설정이 복잡할 수 있으며, 작은 상태에 대해서는 과도할 수 있습니다.</li>
<li><strong>학습 곡선</strong>: reducer와 dispatch 개념을 이해하는 데 시간이 필요할 수 있습니다.</li>
<li><strong>불필요한 코드 중복</strong>: 상태 값이 매우 간단한 경우 useReducer는 오히려 코드가 복잡해지거나 불필요하게 느껴질 수 있습니다.</li>
</ul>
<hr>
<h2 id="usestate-vs-usereducer-비교"><code>useState</code> vs <code>useReducer</code> 비교</h2>
<table>
<thead>
<tr>
<th>특성</th>
<th><code>useState</code></th>
<th><code>useReducer</code></th>
</tr>
</thead>
<tbody><tr>
<td><strong>상태 관리 방식</strong></td>
<td>단일 값 관리</td>
<td>여러 값이나 복잡한 상태 관리</td>
</tr>
<tr>
<td><strong>상태 업데이트 방식</strong></td>
<td>직접 상태 값 설정</td>
<td>reducer 함수와 액션 객체를 통한 상태 업데이트</td>
</tr>
<tr>
<td><strong>디버깅 용이성</strong></td>
<td>간단한 상태 업데이트에 용이</td>
<td>상태 변화 로직을 명확하게 분리 가능</td>
</tr>
<tr>
<td><strong>복잡한 상태 로직</strong></td>
<td>상태 로직이 단순할 때 사용</td>
<td>상태 로직이 복잡하거나 여러 상태가 연관될 때 사용</td>
</tr>
<tr>
<td><strong>사용 예시</strong></td>
<td>카운터, 폼 입력 등 간단한 상태 관리</td>
<td>복잡한 애플리케이션 상태 관리</td>
</tr>
</tbody></table>
<hr>
<h2 id="💡-언제-usestate를-사용해야-할까요">💡 언제 <code>useState</code>를 사용해야 할까요?</h2>
<h4 id="단일-값-상태를-관리할-때"><strong>단일 값 상태를 관리할 때</strong></h4>
<ul>
<li>버튼 클릭으로 카운트를 증가시키는 간단한 상태 관리에는 <code>useState</code>가 매우 직관적이고 간결합니다.</li>
</ul>
<h4 id="상태-업데이트가-복잡하지-않을-때"><strong>상태 업데이트가 복잡하지 않을 때</strong></h4>
<ul>
<li>값 하나만 관리할 때 <code>useState</code>가 더 간단하고, 코드가 깔끔해집니다.</li>
</ul>
<br />

<h2 id="💡-언제-usereducer를-사용해야-할까요">💡 언제 <code>useReducer</code>를 사용해야 할까요?</h2>
<h4 id="상태가-여러-개일-때"><strong>상태가 여러 개일 때</strong>:</h4>
<ul>
<li>상태 값이 여러 개일 때 하나의 객체로 묶어서 관리할 수 있어, 코드가 더 깔끔하고 효율적입니다.</li>
</ul>
<h4 id="상태-변화가-복잡하거나-조건에-따라-달라질-때"><strong>상태 변화가 복잡하거나 조건에 따라 달라질 때</strong>:</h4>
<ul>
<li>여러 조건에 따라 상태가 변경되거나, 상태 업데이트 로직이 복잡할 때 <code>useReducer</code>가 적합합니다.<h4 id="여러-액션에-따른-상태-변화가-필요할-때"><strong>여러 액션에 따른 상태 변화가 필요할 때</strong>:</h4>
</li>
<li>여러 가지 액션을 다뤄야 할 때, <code>useReducer</code>는 코드가 더욱 명확하고 관리하기 쉬워집니다.</li>
</ul>
<hr>
<h2 id="결론-🚀">결론 🚀</h2>
<p><code>useState</code>와 <code>useReducer</code>는 각각의 특성에 맞게 사용해야 합니다.</p>
<ul>
<li><code>useState</code>는 간단한 상태를 다룰 때 적합하고, </li>
<li><code>useReducer</code>는 상태가 복잡하거나 여러 액션에 따라 변화하는 상태를 관리할 때 유용합니다. </li>
</ul>
<p>각각의 상황에 맞는 훅을 선택하여, 더 깔끔하고 효율적인 상태 관리가 가능하므로, 필요에 맞게 잘 활용해 보세요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 빌드 도구 비교: 왜 Vite가 대세인가?" 🚀]]></title>
            <link>https://velog.io/@dongkyun-kwon/React-%EB%B9%8C%EB%93%9C-%EB%8F%84%EA%B5%AC-%EB%B9%84%EA%B5%90-%EC%99%9C-Vite%EA%B0%80-%EB%8C%80%EC%84%B8%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@dongkyun-kwon/React-%EB%B9%8C%EB%93%9C-%EB%8F%84%EA%B5%AC-%EB%B9%84%EA%B5%90-%EC%99%9C-Vite%EA%B0%80-%EB%8C%80%EC%84%B8%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Fri, 28 Feb 2025 15:18:45 GMT</pubDate>
            <description><![CDATA[<h2 id="왜-vite인가">왜 Vite인가?</h2>
<blockquote>
<p>React 프로젝트를 만들 때 <code>create-react-app(CRA)</code>만 있는 게 아니라 <strong>Vite</strong>, <strong>Next.js</strong>, <strong>Parcel</strong>, <strong>Snowpack</strong> 같은 다양한 빌드 도구를 사용할 수 있습니다. 각각의 장점과 차이를 알아봅시다.</p>
</blockquote>
<hr>
<h3 id="✅-vite의-장점-설명">✅ <strong>Vite의 장점 설명</strong></h3>
<ul>
<li><p><strong>빠른 개발 서버</strong><br>기존 번들러(CRA)는 모든 파일을 한 번에 변환하고 서버를 시작하지만, Vite는 <strong>ES 모듈(ESM) 기반</strong>으로 동작해 필요한 파일만 즉시 변환해서 로드함. 덕분에 서버 실행 속도가 매우 빠름.  </p>
<p>📌 <strong>비유</strong>: CRA는 도서관에서 모든 책을 한 번에 복사해서 나눠주는 방식이라면, Vite는 요청할 때만 필요한 페이지를 바로 가져다주는 방식임.  </p>
</li>
<li><p><strong>빠른 빌드 속도</strong><br>Vite는 <code>esbuild</code>라는 초고속 번들러를 사용함. <code>esbuild</code>는 Go 언어로 만들어져 있어서, 기존 JavaScript 기반 번들러(Webpack)보다 <strong>10~100배 빠르게 코드 변환(트랜스파일링)</strong>이 가능함.  </p>
<p>📌 <strong>비유</strong>: Webpack이 수작업으로 종이 문서를 타이핑해서 만드는 방식이라면, esbuild는 스캐너로 즉시 디지털화하는 방식이라고 볼 수 있음.  </p>
</li>
<li><p><strong>HMR(Hot Module Replacement) 성능 우수</strong><br>HMR은 코드 변경 시 <strong>전체 페이지를 새로고침하지 않고</strong> 수정된 부분만 즉시 반영하는 기능임. Webpack 기반의 CRA도 HMR을 지원하지만, Vite는 <strong>변경된 모듈만 바로 적용</strong>하므로 속도가 훨씬 빠름.  </p>
<p>📌 <strong>비유</strong>: CRA는 옷을 한 벌 다 갈아입어야 하지만, Vite는 부분적으로 필요한 부분만 교체하는 방식임.  </p>
</li>
<li><p><strong>플러그인 확장성</strong><br>Vite는 <code>Rollup</code>을 기반으로 하므로 <strong>이미 잘 만들어진 Rollup 플러그인 생태계를 그대로 활용</strong>할 수 있음. 덕분에 빌드 과정에서 최적화, 코드 변환, 다양한 기능 확장이 가능함.  </p>
<p>📌 <strong>비유</strong>: Vite는 이미 인기 있는 Rollup 마켓에서 다양한 확장팩을 가져다 쓸 수 있는 게임 같은 느낌.  </p>
</li>
</ul>
<br />

<h3 id="❌-vite의-단점-설명">❌ <strong>Vite의 단점 설명</strong></h3>
<ul>
<li><p><strong>지원 브라우저 제한</strong><br>Vite는 <strong>ES 모듈(ESM)을 지원하는 최신 브라우저</strong>에서만 동작함. Internet Explorer(IE)처럼 오래된 브라우저에서는 ESM을 지원하지 않기 때문에, Vite 프로젝트를 실행할 수 없음.  </p>
<p>📌 <strong>비유</strong>: 최신 앱이 오래된 핸드폰에서 실행되지 않는 것과 비슷한 개념.  </p>
</li>
<li><p><strong>생태계가 CRA보다 상대적으로 작음</strong><br>CRA는 오랫동안 React 공식 추천 방식이었기 때문에 많은 자료와 강의가 존재하지만, Vite는 비교적 최근에 인기를 끌면서 아직 CRA만큼 <strong>압도적인 생태계를 갖추진 못함</strong>. 하지만 현재 빠르게 성장 중이라 이 문제는 점점 해결되고 있음.  </p>
<p>📌 <strong>비유</strong>: CRA는 오래된 대형 마트, Vite는 요즘 뜨는 핫한 편집숍. 아직 매장 수는 적지만, 트렌디하고 성장 가능성이 큼.  </p>
</li>
</ul>
<hr>
<h2 id="react-프로젝트-빌드-도구-비교">React 프로젝트 빌드 도구 비교</h2>
<table>
<thead>
<tr>
<th>빌드 도구</th>
<th>특징</th>
<th>장점</th>
<th>단점</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Vite</strong></td>
<td>최신 빌드 도구, ES 모듈 기반</td>
<td>빠른 속도, HMR 성능 우수, 경량</td>
<td>오래된 브라우저 지원 부족</td>
</tr>
<tr>
<td><strong>CRA (Create React App)</strong></td>
<td>전통적인 React 프로젝트 설정 도구</td>
<td>쉬운 설정, 익숙한 환경</td>
<td>느린 빌드 속도, 번들 크기 큼</td>
</tr>
<tr>
<td><strong>Next.js</strong></td>
<td>서버 사이드 렌더링(SSR) 지원</td>
<td>SEO 최적화, 정적/동적 페이지 지원</td>
<td>SSR 필요 없으면 무거울 수 있음</td>
</tr>
<tr>
<td><strong>Parcel</strong></td>
<td>설정 없이 바로 사용 가능, 빠른 번들링</td>
<td>Zero-config, 빠른 빌드</td>
<td>확장성이 낮음, 생태계 작음</td>
</tr>
<tr>
<td><strong>Snowpack</strong></td>
<td>ES 모듈 기반 빠른 개발 환경</td>
<td>빠른 개발 서버, HMR 우수</td>
<td>번들링 기능 부족, 유지보수 어려움</td>
</tr>
</tbody></table>
<hr>
<h2 id="결론">결론</h2>
<p>최근에는 <strong>Vite가 빠른 속도와 가벼운 설정 덕분에 가장 많이 사용</strong>되는 추세입니다.</p>
<p>하지만 <strong>SEO가 중요한 경우 Next.js</strong>, <strong>전통적인 방식이 필요하면 CRA</strong>도 고려할 수 있습니다.</p>
<p>프로젝트의 규모나 요구사항에 맞춰 적절한 빌드 도구를 선택하면 됩니다! 🚀</p>
]]></description>
        </item>
    </channel>
</rss>