<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>react - Naver Ending Study</title>
	<atom:link href="https://nangchang.nes.or.kr/tag/react/feed/" rel="self" type="application/rss+xml" />
	<link>https://nangchang.nes.or.kr</link>
	<description></description>
	<lastBuildDate>Sun, 27 Jul 2025 12:20:21 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8</generator>
	<item>
		<title>⤴️ 상태 끌어올리기 – 컴포넌트 간 데이터 공유하는 법</title>
		<link>https://nangchang.nes.or.kr/%e2%a4%b4%ef%b8%8f-%ec%83%81%ed%83%9c-%eb%81%8c%ec%96%b4%ec%98%ac%eb%a6%ac%ea%b8%b0-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%ea%b0%84-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ea%b3%b5%ec%9c%a0%ed%95%98/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e2%25a4%25b4%25ef%25b8%258f-%25ec%2583%2581%25ed%2583%259c-%25eb%2581%258c%25ec%2596%25b4%25ec%2598%25ac%25eb%25a6%25ac%25ea%25b8%25b0-%25ec%25bb%25b4%25ed%258f%25ac%25eb%2584%258c%25ed%258a%25b8-%25ea%25b0%2584-%25eb%258d%25b0%25ec%259d%25b4%25ed%2584%25b0-%25ea%25b3%25b5%25ec%259c%25a0%25ed%2595%2598</link>
					<comments>https://nangchang.nes.or.kr/%e2%a4%b4%ef%b8%8f-%ec%83%81%ed%83%9c-%eb%81%8c%ec%96%b4%ec%98%ac%eb%a6%ac%ea%b8%b0-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%ea%b0%84-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ea%b3%b5%ec%9c%a0%ed%95%98/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Sun, 27 Jul 2025 12:20:18 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=966</guid>

					<description><![CDATA[<p>리액트에서는 기본적으로 상태(state)는 해당 컴포넌트 내부에서만 유효합니다.하지만 때때로 여러 컴포넌트가 같은 데이터를 공유해야 할 때가 있어요. 이럴 때 사용하는 방법이 바로 상태 끌어올리기(Lifting State Up)입니다. 1. 📦 문제 상황: 두 자식 컴포넌트가 같은 상태를 써야 할 때 예를 들어, 하나는 입력을 받고, 다른 하나는 그 값을 출력하는 구조를 생각해볼 수 있어요. 그런데 입력 컴포넌트의 상태를 [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/%e2%a4%b4%ef%b8%8f-%ec%83%81%ed%83%9c-%eb%81%8c%ec%96%b4%ec%98%ac%eb%a6%ac%ea%b8%b0-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%ea%b0%84-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ea%b3%b5%ec%9c%a0%ed%95%98/">⤴️ 상태 끌어올리기 – 컴포넌트 간 데이터 공유하는 법</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>리액트에서는 기본적으로 <strong>상태(state)는 해당 컴포넌트 내부에서만 유효</strong>합니다.<br>하지만 때때로 <strong>여러 컴포넌트가 같은 데이터를 공유</strong>해야 할 때가 있어요.</p>



<p>이럴 때 사용하는 방법이 바로 <strong>상태 끌어올리기(Lifting State Up)</strong>입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 문제 상황: 두 자식 컴포넌트가 같은 상태를 써야 할 때</h3>



<p>예를 들어, 하나는 입력을 받고, 다른 하나는 그 값을 출력하는 구조를 생각해볼 수 있어요.</p>



<p>그런데 입력 컴포넌트의 상태를 출력 컴포넌트에서 사용할 수 없어요.<br><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/27a1.png" alt="➡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>해결책은?</strong> 부모 컴포넌트로 상태를 끌어올리는 것입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 예제 코드</h3>



<pre class="wp-block-code"><code class="">function Parent() {
  const [name, setName] = useState('');

  return (
    &lt;div&gt;
      &lt;NameInput name={name} setName={setName} /&gt;
      &lt;NameDisplay name={name} /&gt;
    &lt;/div&gt;
  );
}

function NameInput({ name, setName }) {
  return (
    &lt;input
      value={name}
      onChange={(e) =&gt; setName(e.target.value)}
      placeholder="이름을 입력하세요"
    /&gt;
  );
}

function NameDisplay({ name }) {
  return &lt;p&gt;안녕하세요, {name}님!&lt;/p&gt;;
}
</code></pre>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 핵심은 <strong>상태(name)와 상태 변경 함수(setName)</strong>를 부모에서 만들고, 자식들에게 props로 전달하는 것입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 이렇게 이해해보세요</h3>



<ul class="wp-block-list">
<li>데이터의 “원본”은 항상 부모에 존재</li>



<li>입력 컴포넌트는 값을 수정할 수 있는 <code>setName</code>을 받음</li>



<li>출력 컴포넌트는 그 값을 표시하기만 함</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f5bc.png" alt="🖼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 상태 끌어올리기 흐름도</h3>



<p>아래 그림은 부모 컴포넌트에 상태를 올리고, 자식들끼리 데이터를 공유하는 흐름을 보여줍니다:</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="683" height="1024" src="https://nangchang.nes.or.kr/wp-content/uploads/2025/07/image-683x1024.png" alt="" class="wp-image-967" srcset="https://nangchang.nes.or.kr/wp-content/uploads/2025/07/image-683x1024.png 683w, https://nangchang.nes.or.kr/wp-content/uploads/2025/07/image-200x300.png 200w, https://nangchang.nes.or.kr/wp-content/uploads/2025/07/image-768x1152.png 768w, https://nangchang.nes.or.kr/wp-content/uploads/2025/07/image-624x936.png 624w, https://nangchang.nes.or.kr/wp-content/uploads/2025/07/image.png 1024w" sizes="(max-width: 683px) 100vw, 683px" /></figure><p>The post <a href="https://nangchang.nes.or.kr/%e2%a4%b4%ef%b8%8f-%ec%83%81%ed%83%9c-%eb%81%8c%ec%96%b4%ec%98%ac%eb%a6%ac%ea%b8%b0-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%ea%b0%84-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ea%b3%b5%ec%9c%a0%ed%95%98/">⤴️ 상태 끌어올리기 – 컴포넌트 간 데이터 공유하는 법</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/%e2%a4%b4%ef%b8%8f-%ec%83%81%ed%83%9c-%eb%81%8c%ec%96%b4%ec%98%ac%eb%a6%ac%ea%b8%b0-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%ea%b0%84-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ea%b3%b5%ec%9c%a0%ed%95%98/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[React] 📋 React에서 배열 데이터 화면에 출력하기 – 리스트 렌더링</title>
		<link>https://nangchang.nes.or.kr/%f0%9f%93%8b-react%ec%97%90%ec%84%9c-%eb%b0%b0%ec%97%b4-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%99%94%eb%a9%b4%ec%97%90-%ec%b6%9c%eb%a0%a5%ed%95%98%ea%b8%b0-%eb%a6%ac%ec%8a%a4%ed%8a%b8-%eb%a0%8c/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25f0%259f%2593%258b-react%25ec%2597%2590%25ec%2584%259c-%25eb%25b0%25b0%25ec%2597%25b4-%25eb%258d%25b0%25ec%259d%25b4%25ed%2584%25b0-%25ed%2599%2594%25eb%25a9%25b4%25ec%2597%2590-%25ec%25b6%259c%25eb%25a0%25a5%25ed%2595%2598%25ea%25b8%25b0-%25eb%25a6%25ac%25ec%258a%25a4%25ed%258a%25b8-%25eb%25a0%258c</link>
					<comments>https://nangchang.nes.or.kr/%f0%9f%93%8b-react%ec%97%90%ec%84%9c-%eb%b0%b0%ec%97%b4-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%99%94%eb%a9%b4%ec%97%90-%ec%b6%9c%eb%a0%a5%ed%95%98%ea%b8%b0-%eb%a6%ac%ec%8a%a4%ed%8a%b8-%eb%a0%8c/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Sun, 22 Jun 2025 05:32:22 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=944</guid>

					<description><![CDATA[<p>사용자 목록, 댓글 목록, 상품 리스트처럼 여러 개의 항목을 반복해서 화면에 보여줘야 하는 경우, React에서는 map() 함수를 사용해서 JSX를 반복 렌더링합니다. 이번 글에서는 리스트 렌더링의 기본과 함께, 꼭 필요한 key 속성에 대해 설명합니다. 1. 🌀 배열을 JSX로 바꾸기 – map() 함수 JS의 map() 함수는 배열을 반복해 각각의 요소를 원하는 형태로 바꿔줍니다. 위 코드에서 fruits 배열의 [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%93%8b-react%ec%97%90%ec%84%9c-%eb%b0%b0%ec%97%b4-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%99%94%eb%a9%b4%ec%97%90-%ec%b6%9c%eb%a0%a5%ed%95%98%ea%b8%b0-%eb%a6%ac%ec%8a%a4%ed%8a%b8-%eb%a0%8c/">[React] 📋 React에서 배열 데이터 화면에 출력하기 – 리스트 렌더링</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>사용자 목록, 댓글 목록, 상품 리스트처럼 <strong>여러 개의 항목을 반복해서 화면에 보여줘야 하는 경우</strong>, React에서는 <code>map()</code> 함수를 사용해서 JSX를 반복 렌더링합니다.</p>



<p>이번 글에서는 리스트 렌더링의 기본과 함께, <strong>꼭 필요한 key 속성</strong>에 대해 설명합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f300.png" alt="🌀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 배열을 JSX로 바꾸기 – map() 함수</h3>



<p>JS의 <code>map()</code> 함수는 배열을 반복해 각각의 요소를 원하는 형태로 바꿔줍니다.</p>



<pre class="wp-block-code"><code class="">const fruits = ['사과', '바나나', '딸기'];

function FruitList() {
  return (
    &lt;ul&gt;
      {fruits.map((fruit) =&gt; (
        &lt;li&gt;{fruit}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}
</code></pre>



<p>위 코드에서 <code>fruits</code> 배열의 요소들을 <code>&lt;li&gt;</code> 태그로 반복 출력하고 있어요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> key 속성은 꼭 넣자!</h3>



<p>React는 리스트를 렌더링할 때 <strong>각 항목을 구분하기 위해 key</strong>를 사용합니다. key가 없거나 중복되면 성능 저하나 UI 문제(예: 깜빡임)가 생길 수 있어요.</p>



<p>위 예제를 개선해볼게요:</p>



<pre class="wp-block-code"><code class="">{fruits.map((fruit, index) =&gt; (
  &lt;li key={index}&gt;{fruit}&lt;/li&gt;
))}
</code></pre>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 여기선 <code>index</code>를 key로 썼지만, <strong>가능하면 고유한 값</strong>(예: id)을 사용하는 것이 더 좋습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 고유 ID가 있는 경우</h3>



<pre class="wp-block-code"><code class="">const users = [
  { id: 1, name: '철수' },
  { id: 2, name: '영희' }
];

function UserList() {
  return (
    &lt;ul&gt;
      {users.map(user =&gt; (
        &lt;li key={user.id}&gt;{user.name}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}
</code></pre>



<p><strong>key={user.id}</strong>는 최적의 방식입니다. 이 값은 항목이 변해도 유지되기 때문이죠.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 정리</h3>



<ul class="wp-block-list">
<li>React에서 배열을 출력할 땐 <code>map()</code>을 사용해 반복합니다</li>



<li><code>key</code>는 필수이며, 각 항목을 고유하게 구분하는 역할을 합니다</li>



<li>가능하면 <strong>index 대신 고유한 id</strong>를 key로 사용하세요</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f5bc.png" alt="🖼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 리스트 렌더링 흐름도</h3>



<p>아래 그림은 배열 → 반복 → JSX → 렌더링 과정을 시각화한 흐름도입니다:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="683" src="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-5-1024x683.png" alt="" class="wp-image-945" srcset="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-5-1024x683.png 1024w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-5-300x200.png 300w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-5-768x512.png 768w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-5-624x416.png 624w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-5.png 1536w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure><p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%93%8b-react%ec%97%90%ec%84%9c-%eb%b0%b0%ec%97%b4-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%99%94%eb%a9%b4%ec%97%90-%ec%b6%9c%eb%a0%a5%ed%95%98%ea%b8%b0-%eb%a6%ac%ec%8a%a4%ed%8a%b8-%eb%a0%8c/">[React] 📋 React에서 배열 데이터 화면에 출력하기 – 리스트 렌더링</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/%f0%9f%93%8b-react%ec%97%90%ec%84%9c-%eb%b0%b0%ec%97%b4-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%99%94%eb%a9%b4%ec%97%90-%ec%b6%9c%eb%a0%a5%ed%95%98%ea%b8%b0-%eb%a6%ac%ec%8a%a4%ed%8a%b8-%eb%a0%8c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[React] 🎭 조건부 렌더링 – 리액트에서 보여줄지 말지 결정하기</title>
		<link>https://nangchang.nes.or.kr/%f0%9f%8e%ad-%ec%a1%b0%ea%b1%b4%eb%b6%80-%eb%a0%8c%eb%8d%94%eb%a7%81-%eb%a6%ac%ec%95%a1%ed%8a%b8%ec%97%90%ec%84%9c-%eb%b3%b4%ec%97%ac%ec%a4%84%ec%a7%80-%eb%a7%90%ec%a7%80-%ea%b2%b0%ec%a0%95/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25f0%259f%258e%25ad-%25ec%25a1%25b0%25ea%25b1%25b4%25eb%25b6%2580-%25eb%25a0%258c%25eb%258d%2594%25eb%25a7%2581-%25eb%25a6%25ac%25ec%2595%25a1%25ed%258a%25b8%25ec%2597%2590%25ec%2584%259c-%25eb%25b3%25b4%25ec%2597%25ac%25ec%25a4%2584%25ec%25a7%2580-%25eb%25a7%2590%25ec%25a7%2580-%25ea%25b2%25b0%25ec%25a0%2595</link>
					<comments>https://nangchang.nes.or.kr/%f0%9f%8e%ad-%ec%a1%b0%ea%b1%b4%eb%b6%80-%eb%a0%8c%eb%8d%94%eb%a7%81-%eb%a6%ac%ec%95%a1%ed%8a%b8%ec%97%90%ec%84%9c-%eb%b3%b4%ec%97%ac%ec%a4%84%ec%a7%80-%eb%a7%90%ec%a7%80-%ea%b2%b0%ec%a0%95/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Sun, 22 Jun 2025 03:13:21 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=941</guid>

					<description><![CDATA[<p>리액트를 쓰다 보면, 상황에 따라 화면에 보이게 하거나 숨겨야 할 요소가 자주 등장합니다.예를 들어, 로그인을 한 사람에게만 “로그아웃” 버튼을 보여준다거나, 경고 메시지를 조건에 따라 표시하는 경우죠. 이럴 때 사용하는 것이 조건부 렌더링입니다. 1. ✅ 가장 기본적인 방법 – if문 JSX 밖에서 조건을 검사한 뒤, 원하는 UI를 리턴할 수 있어요. 단점은 간단한 조건이라도 코드가 길어진다는 점입니다. [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%8e%ad-%ec%a1%b0%ea%b1%b4%eb%b6%80-%eb%a0%8c%eb%8d%94%eb%a7%81-%eb%a6%ac%ec%95%a1%ed%8a%b8%ec%97%90%ec%84%9c-%eb%b3%b4%ec%97%ac%ec%a4%84%ec%a7%80-%eb%a7%90%ec%a7%80-%ea%b2%b0%ec%a0%95/">[React] 🎭 조건부 렌더링 – 리액트에서 보여줄지 말지 결정하기</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>리액트를 쓰다 보면, 상황에 따라 <strong>화면에 보이게 하거나 숨겨야 할 요소</strong>가 자주 등장합니다.<br>예를 들어, 로그인을 한 사람에게만 “로그아웃” 버튼을 보여준다거나, 경고 메시지를 조건에 따라 표시하는 경우죠.</p>



<p>이럴 때 사용하는 것이 <strong>조건부 렌더링</strong>입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 가장 기본적인 방법 – if문</h3>



<p>JSX 밖에서 조건을 검사한 뒤, 원하는 UI를 리턴할 수 있어요.</p>



<pre class="wp-block-code"><code class="">function WelcomeMessage({ isLoggedIn }) {
  if (isLoggedIn) {
    return &lt;p&gt;환영합니다!&lt;/p&gt;;
  } else {
    return &lt;p&gt;로그인 해주세요.&lt;/p&gt;;
  }
}
</code></pre>



<p>단점은 <strong>간단한 조건이라도 코드가 길어진다</strong>는 점입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> JSX 안에서는 삼항 연산자 사용</h3>



<p>JSX 안에서는 <code>{조건 ? A : B}</code> 형태로 간결하게 쓸 수 있어요.</p>



<pre class="wp-block-code"><code class="">function WelcomeMessage({ isLoggedIn }) {
  return (
    &lt;p&gt;{isLoggedIn ? '환영합니다!' : '로그인 해주세요.'}&lt;/p&gt;
  );
}
</code></pre>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 삼항 연산자는 **조건에 따라 두 가지 경우를 나눌 때** 쓰면 좋습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f646-200d-2640-fe0f.png" alt="🙆‍♀️" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 특정 조건일 때만 표시 – &amp;&amp; 연산자</h3>



<p>조건이 참일 때만 어떤 요소를 보여주고, 거짓이면 아무것도 안 보이게 하고 싶을 땐 <strong><code>&amp;&amp;</code> 연산자</strong>를 사용합니다.</p>



<pre class="wp-block-code"><code class="">function Alert({ show }) {
  return (
    &lt;div&gt;
      {show &amp;&amp; &lt;p style={{ color: 'red' }}&gt;경고: 잘못된 접근입니다.&lt;/p&gt;}
    &lt;/div&gt;
  );
}
</code></pre>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>show</code>가 false일 경우에는 아무것도 렌더링되지 않습니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 정리</h3>



<ul class="wp-block-list">
<li><strong><code>if</code>문</strong>은 JSX 바깥에서 조건 분기를 할 때 사용</li>



<li><strong>삼항 연산자 <code>?:</code></strong>는 간단한 두 갈래 분기를 JSX 안에서 처리할 때 유용</li>



<li><strong><code>&amp;&amp;</code> 연산자</strong>는 특정 조건이 참일 때만 요소를 보여주고 싶을 때 사용</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 추가 팁</h3>



<ul class="wp-block-list">
<li>조건이 복잡해지면 컴포넌트를 나누는 것이 더 깔끔해요</li>



<li><code>null</code>을 반환하면 아무것도 표시되지 않습니다 (렌더링 생략)</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f5bc.png" alt="🖼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 조건부 렌더링 흐름도</h3>



<p>다음 그림은 조건에 따라 화면에 보이는 컴포넌트가 어떻게 달라지는지를 보여줍니다:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="683" height="1024" src="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-4-683x1024.png" alt="" class="wp-image-942" srcset="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-4-683x1024.png 683w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-4-200x300.png 200w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-4-768x1152.png 768w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-4-624x936.png 624w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-4.png 1024w" sizes="(max-width: 683px) 100vw, 683px" /></figure><p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%8e%ad-%ec%a1%b0%ea%b1%b4%eb%b6%80-%eb%a0%8c%eb%8d%94%eb%a7%81-%eb%a6%ac%ec%95%a1%ed%8a%b8%ec%97%90%ec%84%9c-%eb%b3%b4%ec%97%ac%ec%a4%84%ec%a7%80-%eb%a7%90%ec%a7%80-%ea%b2%b0%ec%a0%95/">[React] 🎭 조건부 렌더링 – 리액트에서 보여줄지 말지 결정하기</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/%f0%9f%8e%ad-%ec%a1%b0%ea%b1%b4%eb%b6%80-%eb%a0%8c%eb%8d%94%eb%a7%81-%eb%a6%ac%ec%95%a1%ed%8a%b8%ec%97%90%ec%84%9c-%eb%b3%b4%ec%97%ac%ec%a4%84%ec%a7%80-%eb%a7%90%ec%a7%80-%ea%b2%b0%ec%a0%95/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[React] 📨 React에서 폼 제출 처리하기 – preventDefault()로 새로고침 막기</title>
		<link>https://nangchang.nes.or.kr/%f0%9f%93%a8-react%ec%97%90%ec%84%9c-%ed%8f%bc-%ec%a0%9c%ec%b6%9c-%ec%b2%98%eb%a6%ac%ed%95%98%ea%b8%b0-preventdefault%eb%a1%9c-%ec%83%88%eb%a1%9c%ea%b3%a0%ec%b9%a8-%eb%a7%89%ea%b8%b0/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25f0%259f%2593%25a8-react%25ec%2597%2590%25ec%2584%259c-%25ed%258f%25bc-%25ec%25a0%259c%25ec%25b6%259c-%25ec%25b2%2598%25eb%25a6%25ac%25ed%2595%2598%25ea%25b8%25b0-preventdefault%25eb%25a1%259c-%25ec%2583%2588%25eb%25a1%259c%25ea%25b3%25a0%25ec%25b9%25a8-%25eb%25a7%2589%25ea%25b8%25b0</link>
					<comments>https://nangchang.nes.or.kr/%f0%9f%93%a8-react%ec%97%90%ec%84%9c-%ed%8f%bc-%ec%a0%9c%ec%b6%9c-%ec%b2%98%eb%a6%ac%ed%95%98%ea%b8%b0-preventdefault%eb%a1%9c-%ec%83%88%eb%a1%9c%ea%b3%a0%ec%b9%a8-%eb%a7%89%ea%b8%b0/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Sat, 21 Jun 2025 03:10:11 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=934</guid>

					<description><![CDATA[<p>HTML 폼은 기본적으로 submit 시 새로고침이 발생해요. 하지만 리액트는 SPA(Single Page Application)이기 때문에, 새로고침이 일어나면 안 됩니다. 이를 막기 위해 사용하는 것이 바로 preventDefault()예요. 1. ⛔ 기본 동작을 막는 이유 아래처럼 작성하면, 폼을 제출했을 때 전체 페이지가 리로드됩니다. 👉 이때 handleSubmit 함수에서 e.preventDefault()를 꼭 호출해줘야 합니다. 2. ✅ 기본 예제 코드 3. 📌 핵심 요약 [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%93%a8-react%ec%97%90%ec%84%9c-%ed%8f%bc-%ec%a0%9c%ec%b6%9c-%ec%b2%98%eb%a6%ac%ed%95%98%ea%b8%b0-preventdefault%eb%a1%9c-%ec%83%88%eb%a1%9c%ea%b3%a0%ec%b9%a8-%eb%a7%89%ea%b8%b0/">[React] 📨 React에서 폼 제출 처리하기 – preventDefault()로 새로고침 막기</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>HTML 폼은 기본적으로 <strong>submit 시 새로고침</strong>이 발생해요. 하지만 리액트는 SPA(Single Page Application)이기 때문에, 새로고침이 일어나면 안 됩니다.</p>



<p>이를 막기 위해 사용하는 것이 바로 <strong><code>preventDefault()</code></strong>예요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/26d4.png" alt="⛔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 기본 동작을 막는 이유</h3>



<p>아래처럼 작성하면, 폼을 제출했을 때 전체 페이지가 리로드됩니다.</p>



<pre class="wp-block-code"><code class="">&lt;form onSubmit={handleSubmit}>
  &lt;input />
  &lt;button type="submit">제출&lt;/button>
&lt;/form>
</code></pre>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 이때 <strong>handleSubmit 함수에서 <code>e.preventDefault()</code></strong>를 꼭 호출해줘야 합니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 기본 예제 코드</h3>



<pre class="wp-block-code"><code class="">import { useState } from 'react';

function SignupForm() {
  const [form, setForm] = useState({
    name: '',
    email: ''
  });

  function handleChange(e) {
    const { name, value } = e.target;
    setForm(prev =&amp;gt; ({
      ...prev,
      [name]: value
    }));
  }

  function handleSubmit(e) {
    e.preventDefault(); // 새로고침 방지
    console.log('폼 제출됨:', form);
    alert(`${form.name}님, 가입이 완료되었습니다!`);
  }

  return (
    &lt;form onSubmit={handleSubmit}>
      &lt;input
        name="name"
        value={form.name}
        onChange={handleChange}
        placeholder="이름"
      />
      &lt;input
        name="email"
        value={form.email}
        onChange={handleChange}
        placeholder="이메일"
      />
      &lt;button type="submit">가입하기&lt;/button>
    &lt;/form>
  );
}
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 핵심 요약</h3>



<ul class="wp-block-list">
<li><code>form</code> 태그를 사용할 때 <strong><code>onSubmit</code> 이벤트</strong>로 처리합니다</li>



<li><strong><code>e.preventDefault()</code>를 호출</strong>해야 페이지가 새로고침되지 않아요</li>



<li>제출 시 입력값을 저장하거나 서버로 보낼 수 있습니다</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f5bc.png" alt="🖼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 폼 제출 처리 흐름도</h3>



<p>입력 → 상태 저장 → 제출 → 기본 동작 막기 → 데이터 처리 흐름을 아래 그림으로 정리해보세요.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="683" height="1024" src="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-3-683x1024.png" alt="" class="wp-image-935" srcset="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-3-683x1024.png 683w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-3-200x300.png 200w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-3-768x1152.png 768w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-3-624x936.png 624w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-3.png 1024w" sizes="auto, (max-width: 683px) 100vw, 683px" /></figure><p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%93%a8-react%ec%97%90%ec%84%9c-%ed%8f%bc-%ec%a0%9c%ec%b6%9c-%ec%b2%98%eb%a6%ac%ed%95%98%ea%b8%b0-preventdefault%eb%a1%9c-%ec%83%88%eb%a1%9c%ea%b3%a0%ec%b9%a8-%eb%a7%89%ea%b8%b0/">[React] 📨 React에서 폼 제출 처리하기 – preventDefault()로 새로고침 막기</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/%f0%9f%93%a8-react%ec%97%90%ec%84%9c-%ed%8f%bc-%ec%a0%9c%ec%b6%9c-%ec%b2%98%eb%a6%ac%ed%95%98%ea%b8%b0-preventdefault%eb%a1%9c-%ec%83%88%eb%a1%9c%ea%b3%a0%ec%b9%a8-%eb%a7%89%ea%b8%b0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[React] 🧾 React에서 여러 입력 필드를 한 번에 관리하는 법</title>
		<link>https://nangchang.nes.or.kr/%f0%9f%a7%be-react%ec%97%90%ec%84%9c-%ec%97%ac%eb%9f%ac-%ec%9e%85%eb%a0%a5-%ed%95%84%eb%93%9c%eb%a5%bc-%ed%95%9c-%eb%b2%88%ec%97%90-%ea%b4%80%eb%a6%ac%ed%95%98%eb%8a%94-%eb%b2%95/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25f0%259f%25a7%25be-react%25ec%2597%2590%25ec%2584%259c-%25ec%2597%25ac%25eb%259f%25ac-%25ec%259e%2585%25eb%25a0%25a5-%25ed%2595%2584%25eb%2593%259c%25eb%25a5%25bc-%25ed%2595%259c-%25eb%25b2%2588%25ec%2597%2590-%25ea%25b4%2580%25eb%25a6%25ac%25ed%2595%2598%25eb%258a%2594-%25eb%25b2%2595</link>
					<comments>https://nangchang.nes.or.kr/%f0%9f%a7%be-react%ec%97%90%ec%84%9c-%ec%97%ac%eb%9f%ac-%ec%9e%85%eb%a0%a5-%ed%95%84%eb%93%9c%eb%a5%bc-%ed%95%9c-%eb%b2%88%ec%97%90-%ea%b4%80%eb%a6%ac%ed%95%98%eb%8a%94-%eb%b2%95/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Wed, 18 Jun 2025 14:29:33 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=929</guid>

					<description><![CDATA[<p>리액트를 쓰다 보면 이름, 이메일, 비밀번호 등 입력필드가 여러 개인 경우가 생깁니다. 그럴 때마다 useState를 하나씩 만들면 너무 복잡해지겠죠? 오늘은 객체 상태를 사용해서 여러 입력값을 하나의 상태로 관리하는 방법을 배워봅시다! 1. 👨‍👩‍👧‍👦 상태를 객체로 만들어요 아래와 같이 form 상태를 객체 형태로 만들고, 각 입력 필드의 이름을 키(key)로 사용합니다. 이제 입력값이 바뀔 때마다 해당 키만 업데이트하면 [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%a7%be-react%ec%97%90%ec%84%9c-%ec%97%ac%eb%9f%ac-%ec%9e%85%eb%a0%a5-%ed%95%84%eb%93%9c%eb%a5%bc-%ed%95%9c-%eb%b2%88%ec%97%90-%ea%b4%80%eb%a6%ac%ed%95%98%eb%8a%94-%eb%b2%95/">[React] 🧾 React에서 여러 입력 필드를 한 번에 관리하는 법</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>리액트를 쓰다 보면 <strong>이름, 이메일, 비밀번호 등</strong> 입력필드가 여러 개인 경우가 생깁니다. 그럴 때마다 <code>useState</code>를 하나씩 만들면 너무 복잡해지겠죠?</p>



<p>오늘은 <strong>객체 상태</strong>를 사용해서 여러 입력값을 하나의 상태로 관리하는 방법을 배워봅시다!</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f468-200d-1f469-200d-1f467-200d-1f466.png" alt="👨‍👩‍👧‍👦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 상태를 객체로 만들어요</h3>



<p>아래와 같이 <code>form</code> 상태를 객체 형태로 만들고, 각 입력 필드의 이름을 키(key)로 사용합니다.</p>



<pre class="wp-block-code"><code class="">const [form, setForm] = useState({
  name: '',
  email: ''
});</code></pre>



<p>이제 입력값이 바뀔 때마다 <strong>해당 키만 업데이트</strong>하면 돼요!</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/270f.png" alt="✏" class="wp-smiley" style="height: 1em; max-height: 1em;" /> onChange 함수 재사용하기</h3>



<p>모든 <code>input</code>에 같은 <code>handleChange</code> 함수를 연결해도 됩니다. <code>e.target.name</code>을 활용해 어떤 필드가 바뀌었는지 자동으로 구분하거든요.</p>



<pre class="wp-block-code"><code class="">function handleChange(e) {
  const { name, value } = e.target;
  setForm(prev =&amp;gt; ({
    ...prev,
    [name]: value
  }));
}
</code></pre>



<p>이제 <code>name="email"</code> 또는 <code>name="name"</code> 속성만 잘 붙이면 완성!</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 전체 예제 코드</h3>



<pre class="wp-block-code"><code class="">function SignupForm() {
  const [form, setForm] = useState({
    name: '',
    email: ''
  });

  function handleChange(e) {
    const { name, value } = e.target;
    setForm(prev =&amp;gt; ({
      ...prev,
      [name]: value
    }));
  }

  return (
    &lt;div>
      &lt;input
        name="name"
        value={form.name}
        onChange={handleChange}
        placeholder="이름"
      />
      &lt;input
        name="email"
        value={form.email}
        onChange={handleChange}
        placeholder="이메일"
      />
      &lt;p>
        이름: {form.name} &lt;br />
        이메일: {form.email}
      &lt;/p>
    &lt;/div>
  );
}
</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f5bc.png" alt="🖼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 상태 업데이트 흐름도</h3>



<p>아래 그림은 입력값이 객체 상태에 저장되고, 해당 값을 UI에 반영하는 과정을 보여줍니다:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="683" height="1024" src="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-2-683x1024.png" alt="" class="wp-image-930" srcset="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-2-683x1024.png 683w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-2-200x300.png 200w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-2-768x1152.png 768w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-2-624x936.png 624w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-2.png 1024w" sizes="auto, (max-width: 683px) 100vw, 683px" /></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 핵심 요약</h3>



<ul class="wp-block-list">
<li>여러 입력값은 <strong>객체로 묶어서 상태 관리</strong>하면 훨씬 간단해요</li>



<li><code>name</code> 속성과 <code>e.target.name</code>을 활용하면 <strong>onChange 함수 재사용</strong>이 가능해요</li>



<li><code>...prev</code>로 이전 값을 보존한 후 업데이트하세요</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%a7%be-react%ec%97%90%ec%84%9c-%ec%97%ac%eb%9f%ac-%ec%9e%85%eb%a0%a5-%ed%95%84%eb%93%9c%eb%a5%bc-%ed%95%9c-%eb%b2%88%ec%97%90-%ea%b4%80%eb%a6%ac%ed%95%98%eb%8a%94-%eb%b2%95/">[React] 🧾 React에서 여러 입력 필드를 한 번에 관리하는 법</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/%f0%9f%a7%be-react%ec%97%90%ec%84%9c-%ec%97%ac%eb%9f%ac-%ec%9e%85%eb%a0%a5-%ed%95%84%eb%93%9c%eb%a5%bc-%ed%95%9c-%eb%b2%88%ec%97%90-%ea%b4%80%eb%a6%ac%ed%95%98%eb%8a%94-%eb%b2%95/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[React]  리액트 상태(state)란? – useState로 버튼 클릭 수 세기</title>
		<link>https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%83%81%ed%83%9cstate%eb%9e%80-usestate%eb%a1%9c-%eb%b2%84%ed%8a%bc-%ed%81%b4%eb%a6%ad-%ec%88%98-%ec%84%b8%ea%b8%b0/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25f0%259f%25a7%25a0-%25eb%25a6%25ac%25ec%2595%25a1%25ed%258a%25b8-%25ec%2583%2581%25ed%2583%259cstate%25eb%259e%2580-usestate%25eb%25a1%259c-%25eb%25b2%2584%25ed%258a%25bc-%25ed%2581%25b4%25eb%25a6%25ad-%25ec%2588%2598-%25ec%2584%25b8%25ea%25b8%25b0</link>
					<comments>https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%83%81%ed%83%9cstate%eb%9e%80-usestate%eb%a1%9c-%eb%b2%84%ed%8a%bc-%ed%81%b4%eb%a6%ad-%ec%88%98-%ec%84%b8%ea%b8%b0/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Tue, 17 Jun 2025 12:23:20 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=925</guid>

					<description><![CDATA[<p>리액트에서 UI를 바꾸는 핵심 원리는 바로 &#8220;상태(state)&#8221;에 있습니다.오늘은 useState 훅(Hook)을 이용해 버튼을 클릭할 때마다 숫자가 올라가는 아주 기본적인 예제를 만들어볼 거예요. 1. 🎯 상태(state)는 무엇인가요? 상태란 컴포넌트 내부에서 바뀌는 값입니다. 예를 들어 버튼을 클릭할 때마다 숫자가 올라간다면, 이 숫자가 바로 상태입니다. 리액트에서는 useState라는 함수를 사용해서 상태를 만듭니다. 2. 🔧 useState 기본 사용법 useState는 리액트에서 제공하는 [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%83%81%ed%83%9cstate%eb%9e%80-usestate%eb%a1%9c-%eb%b2%84%ed%8a%bc-%ed%81%b4%eb%a6%ad-%ec%88%98-%ec%84%b8%ea%b8%b0/">[React]  리액트 상태(state)란? – useState로 버튼 클릭 수 세기</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>리액트에서 <strong>UI를 바꾸는 핵심 원리</strong>는 바로 &#8220;상태(state)&#8221;에 있습니다.<br>오늘은 <strong>useState 훅(Hook)</strong>을 이용해 버튼을 클릭할 때마다 숫자가 올라가는 아주 기본적인 예제를 만들어볼 거예요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 상태(state)는 무엇인가요?</h3>



<p>상태란 <strong>컴포넌트 내부에서 바뀌는 값</strong>입니다. 예를 들어 버튼을 클릭할 때마다 숫자가 올라간다면, 이 숫자가 바로 상태입니다.</p>



<p>리액트에서는 <code>useState</code>라는 함수를 사용해서 상태를 만듭니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f527.png" alt="🔧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> useState 기본 사용법</h3>



<p><code>useState</code>는 리액트에서 제공하는 Hook 중 하나로, 이렇게 사용합니다:</p>



<pre class="wp-block-code"><code class="">import { useState } from 'react';

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

  return (
    &lt;div&gt;
      &lt;p&gt;지금까지 {count}번 클릭했어요!&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;
        클릭!
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 설명:</p>



<ul class="wp-block-list">
<li><code>useState(0)</code>: <strong>초깃값 0</strong>으로 상태(count)를 만들어요</li>



<li><code>setCount</code>: 상태를 바꾸는 함수입니다</li>



<li><code>onClick</code> 이벤트로 클릭할 때 <code>setCount</code>를 실행합니다</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f5bc.png" alt="🖼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 상태 변경 흐름 그림</h3>



<p>아래 그림은 버튼을 누를 때마다 상태가 어떻게 바뀌는지를 나타냅니다:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="683" src="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-1-1024x683.png" alt="" class="wp-image-926" srcset="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-1-1024x683.png 1024w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-1-300x200.png 300w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-1-768x512.png 768w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-1-624x416.png 624w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-1.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>클릭할 때마다 새로운 값으로 다시 렌더링되어 숫자가 업데이트됩니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 정리</h3>



<ul class="wp-block-list">
<li><code>useState</code>를 사용하면 상태를 만들 수 있다</li>



<li>상태가 바뀌면 컴포넌트는 <strong>자동으로 다시 그려진다</strong></li>



<li><code>set함수</code>를 호출해야만 상태가 바뀐다</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 직접 실습해보기</h3>



<p>아래 코드를 <code>App.jsx</code> 안에 붙여서 직접 실습해보세요!</p>



<pre class="wp-block-code"><code class="">import { useState } from 'react';

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

  return (
    &lt;div style={{ textAlign: 'center', marginTop: '50px' }}&gt;
      &lt;h1&gt;클릭 수: {count}&lt;/h1&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;누르기&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%83%81%ed%83%9cstate%eb%9e%80-usestate%eb%a1%9c-%eb%b2%84%ed%8a%bc-%ed%81%b4%eb%a6%ad-%ec%88%98-%ec%84%b8%ea%b8%b0/">[React]  리액트 상태(state)란? – useState로 버튼 클릭 수 세기</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%83%81%ed%83%9cstate%eb%9e%80-usestate%eb%a1%9c-%eb%b2%84%ed%8a%bc-%ed%81%b4%eb%a6%ad-%ec%88%98-%ec%84%b8%ea%b8%b0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[React] 🚀 리액트 앱 시작하기 – 첫 번째 컴포넌트 만들기</title>
		<link>https://nangchang.nes.or.kr/%f0%9f%9a%80-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%95%b1-%ec%8b%9c%ec%9e%91%ed%95%98%ea%b8%b0-%ec%b2%ab-%eb%b2%88%ec%a7%b8-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%eb%a7%8c%eb%93%a4%ea%b8%b0/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25f0%259f%259a%2580-%25eb%25a6%25ac%25ec%2595%25a1%25ed%258a%25b8-%25ec%2595%25b1-%25ec%258b%259c%25ec%259e%2591%25ed%2595%2598%25ea%25b8%25b0-%25ec%25b2%25ab-%25eb%25b2%2588%25ec%25a7%25b8-%25ec%25bb%25b4%25ed%258f%25ac%25eb%2584%258c%25ed%258a%25b8-%25eb%25a7%258c%25eb%2593%25a4%25ea%25b8%25b0</link>
					<comments>https://nangchang.nes.or.kr/%f0%9f%9a%80-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%95%b1-%ec%8b%9c%ec%9e%91%ed%95%98%ea%b8%b0-%ec%b2%ab-%eb%b2%88%ec%a7%b8-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%eb%a7%8c%eb%93%a4%ea%b8%b0/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Sun, 15 Jun 2025 04:42:27 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=919</guid>

					<description><![CDATA[<p>리액트를 이해하려면 &#8220;컴포넌트&#8221;를 직접 만들어보는 게 가장 빠른 길입니다.이번 글에서는 리액트 앱을 만드는 첫 단계부터, 기본 컴포넌트를 만들고 사용하는 방법까지 아주 쉽게 알려드릴게요. 1. 🧰 리액트 앱 만드는 법 리액트를 처음부터 설치하는 가장 쉬운 방법은 Vite 또는 Create React App을 쓰는 것입니다.요즘은 Vite가 빠르고 가벼워서 많이 사용되고 있어요. 👉 http://localhost:5173 에 접속하면 리액트 앱이 실행됩니다! [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%9a%80-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%95%b1-%ec%8b%9c%ec%9e%91%ed%95%98%ea%b8%b0-%ec%b2%ab-%eb%b2%88%ec%a7%b8-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%eb%a7%8c%eb%93%a4%ea%b8%b0/">[React] 🚀 리액트 앱 시작하기 – 첫 번째 컴포넌트 만들기</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>리액트를 이해하려면 <strong>&#8220;컴포넌트&#8221;</strong>를 직접 만들어보는 게 가장 빠른 길입니다.<br>이번 글에서는 리액트 앱을 만드는 첫 단계부터, <strong>기본 컴포넌트를 만들고 사용하는 방법</strong>까지 아주 쉽게 알려드릴게요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f9f0.png" alt="🧰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 리액트 앱 만드는 법</h3>



<p>리액트를 처음부터 설치하는 가장 쉬운 방법은 <strong>Vite</strong> 또는 <strong>Create React App</strong>을 쓰는 것입니다.<br>요즘은 <strong>Vite</strong>가 빠르고 가벼워서 많이 사용되고 있어요.</p>



<pre class="wp-block-code"><code class=""># 설치 (Node.js가 필요해요)
npm create vite@latest my-react-app --template react
cd my-react-app
npm install
npm run dev
</code></pre>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>http://localhost:5173</code> 에 접속하면 리액트 앱이 실행됩니다!</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4c1.png" alt="📁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 폴더 구조 간단히 보기</h3>



<pre class="wp-block-code"><code class="">my-react-app/
├─ src/
│  ├─ App.jsx      ← 우리가 편집할 메인 컴포넌트
│  └─ main.jsx     ← 앱 시작 지점 (entry point)
├─ index.html
└─ package.json
</code></pre>



<p>우리는 <code>App.jsx</code> 파일에서 화면에 나타날 내용을 작성할 거예요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f9e9.png" alt="🧩" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 첫 번째 컴포넌트 만들기</h3>



<p>컴포넌트는 그냥 <strong>함수 하나</strong>라고 생각하면 됩니다.</p>



<pre class="wp-block-code"><code class="">function Hello() {
  return &lt;h1&gt;안녕하세요, React!&lt;/h1&gt;;
}
</code></pre>



<p>이제 이 컴포넌트를 <code>App.jsx</code> 안에서 사용해볼 수 있어요.</p>



<pre class="wp-block-code"><code class="">function App() {
  return (
    &lt;div&gt;
      &lt;Hello /&gt;;
    &lt;/div&gt;;
  );
}
</code></pre>



<p><code>&lt;Hello /&gt;</code>는 우리가 만든 컴포넌트를 HTML 태그처럼 사용하는 것입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f5bc.png" alt="🖼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 컴포넌트 구조 다이어그램</h3>



<p>아래 그림은 컴포넌트가 실제로 어떻게 작동하는지를 보여줍니다:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="683" src="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-1024x683.png" alt="" class="wp-image-920" srcset="https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-1024x683.png 1024w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-300x200.png 300w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-768x512.png 768w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image-624x416.png 624w, https://nangchang.nes.or.kr/wp-content/uploads/2025/06/image.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>App 컴포넌트가 Hello 컴포넌트를 불러오고, 최종적으로 브라우저에는 &#8220;안녕하세요, React!&#8221;가 나타납니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4. <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f5e3.png" alt="🗣" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 꼭 알아둘 문법 2가지</h3>



<ul class="wp-block-list">
<li><strong>컴포넌트 이름은 반드시 대문자로 시작!</strong><br><code>hello()</code> <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> → <code>Hello()</code> <img src="https://s.w.org/images/core/emoji/15.1.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>



<li><strong>return 안에는 JSX 사용</strong><br>JSX는 JavaScript 안에 HTML처럼 코드를 쓸 수 있는 문법입니다.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f501.png" alt="🔁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 실습 팁: 나만의 인사말 만들기</h3>



<pre class="wp-block-code"><code class="">function Greeting(props) {
  return &lt;h2&gt;안녕하세요, {props.name}님&lt;/h&gt;;
}
</code></pre>



<p>그리고 이렇게 써보세요:</p>



<pre class="wp-block-code"><code class="">&lt;Greeting name="지민" /&gt;;
&lt;Greeting name="민수" /&gt;;
</code></pre>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 리액트는 <code>props</code>(속성)을 통해 다른 데이터를 전달할 수 있어요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 정리</h3>



<ul class="wp-block-list">
<li>리액트 앱은 Vite로 간단히 만들 수 있다</li>



<li>컴포넌트는 함수다! → <code>&lt;컴포넌트이름 /&gt;</code> 으로 사용</li>



<li>JSX 문법을 사용해서 HTML처럼 UI를 작성한다</li>



<li>props를 통해 컴포넌트에 값을 전달할 수 있다</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity" id="block-efe38406-e07c-49d2-9f11-886b01e1ed01"/><p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%9a%80-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%95%b1-%ec%8b%9c%ec%9e%91%ed%95%98%ea%b8%b0-%ec%b2%ab-%eb%b2%88%ec%a7%b8-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%eb%a7%8c%eb%93%a4%ea%b8%b0/">[React] 🚀 리액트 앱 시작하기 – 첫 번째 컴포넌트 만들기</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/%f0%9f%9a%80-%eb%a6%ac%ec%95%a1%ed%8a%b8-%ec%95%b1-%ec%8b%9c%ec%9e%91%ed%95%98%ea%b8%b0-%ec%b2%ab-%eb%b2%88%ec%a7%b8-%ec%bb%b4%ed%8f%ac%eb%84%8c%ed%8a%b8-%eb%a7%8c%eb%93%a4%ea%b8%b0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[React] 🧠 리액트란 무엇인가?</title>
		<link>https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8%eb%9e%80-%eb%ac%b4%ec%97%87%ec%9d%b8%ea%b0%80/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25f0%259f%25a7%25a0-%25eb%25a6%25ac%25ec%2595%25a1%25ed%258a%25b8%25eb%259e%2580-%25eb%25ac%25b4%25ec%2597%2587%25ec%259d%25b8%25ea%25b0%2580</link>
					<comments>https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8%eb%9e%80-%eb%ac%b4%ec%97%87%ec%9d%b8%ea%b0%80/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Sat, 14 Jun 2025 14:16:21 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=914</guid>

					<description><![CDATA[<p>리액트(React)는 페이스북이 만든 사용자 인터페이스(UI)를 만들기 위한 자바스크립트 라이브러리입니다.하지만 이렇게 말해도 아직 감이 안 올 수 있어요. 그래서 차근차근 풀어볼게요. 👀 웹사이트는 어떻게 동작할까? 웹사이트는 기본적으로 아래와 같은 흐름으로 동작해요: 여기서 문제가 생깁니다. 😓 전통적인 방식 🎉 그래서 나온 게 리액트! 리액트는 이걸 훨씬 깔끔하고 효율적으로 처리할 수 있게 해줘요. “데이터 중심”으로 UI를 만드는 방식이라고 [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8%eb%9e%80-%eb%ac%b4%ec%97%87%ec%9d%b8%ea%b0%80/">[React] 🧠 리액트란 무엇인가?</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>리액트(React)는 페이스북이 만든 <strong>사용자 인터페이스(UI)를 만들기 위한 자바스크립트 라이브러리</strong>입니다.<br>하지만 이렇게 말해도 아직 감이 안 올 수 있어요. 그래서 차근차근 풀어볼게요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f440.png" alt="👀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 웹사이트는 어떻게 동작할까?</h3>



<p>웹사이트는 기본적으로 아래와 같은 흐름으로 동작해요:</p>



<ol class="wp-block-list">
<li>사용자가 버튼을 누른다</li>



<li>화면의 어떤 내용이 바뀐다</li>



<li>이걸 위해 HTML/CSS/JavaScript가 협력한다</li>
</ol>



<p>여기서 문제가 생깁니다.</p>



<ul class="wp-block-list">
<li>버튼을 누를 때마다 화면을 <strong>직접 조작(DOM 조작)</strong> 해야 해요.</li>



<li>상태가 많아질수록 코드가 복잡해지고 실수하기 쉬워요.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f613.png" alt="😓" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 전통적인 방식</h3>



<ul class="wp-block-list">
<li>사용자가 버튼을 누름</li>



<li>JavaScript가 직접 <code>&lt;div&gt;</code>의 텍스트를 바꿔줌</li>



<li>여러 개의 상태를 일일이 추적해야 함</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f389.png" alt="🎉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 그래서 나온 게 리액트!</h3>



<p>리액트는 이걸 훨씬 <strong>깔끔하고 효율적으로 처리</strong>할 수 있게 해줘요.</p>



<ul class="wp-block-list">
<li>데이터(state)가 바뀌면</li>



<li>리액트가 자동으로 UI를 다시 그려줘요</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>“데이터 중심”으로 UI를 만드는 방식이라고 생각하면 돼요.</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f501.png" alt="🔁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 비유로 이해해보자</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>리액트를 처음 배우는 사람에게 가장 좋은 비유는 ‘자동 계산기’예요.</p>
</blockquote>



<ul class="wp-block-list">
<li>계산기에 숫자를 입력하면 자동으로 결과가 갱신되죠?</li>



<li>우리가 버튼을 누를 때마다 결과를 다시 계산할 필요는 없어요.</li>



<li><strong>리액트는 화면도 이렇게 자동으로 다시 계산해주는 도구</strong>예요.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f9e9.png" alt="🧩" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 리액트의 핵심 요소 3가지</h3>



<p>리액트는 크게 아래 3가지로 구성돼요:</p>



<figure class="wp-block-table"><table><thead><tr><th>요소</th><th>설명</th></tr></thead><tbody><tr><td>컴포넌트 (Component)</td><td>재사용 가능한 UI 조각</td></tr><tr><td>상태 (State)</td><td>변할 수 있는 데이터</td></tr><tr><td>렌더링 (Rendering)</td><td>데이터를 기반으로 화면을 그리는 일</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 간단한 예제 코드</h3>



<pre class="wp-block-code"><code class=""><code>function Welcome() {
  return &lt;h1&gt;안녕하세요, React!&lt;/h1&gt;;
}
</code></code></pre>



<p>이건 “Welcome”이라는 이름의 컴포넌트를 정의한 거예요.<br><code>&lt;Welcome /&gt;</code>이라고 쓰면 화면에 “안녕하세요, React!”가 나타나죠.</p>



<p><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 마치 내가 HTML 태그를 새로 만든 것처럼 쓸 수 있어요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<ol class="wp-block-list">
<li>사용자 입력 →</li>



<li>상태(state)가 바뀜 →</li>



<li>리액트가 새로운 UI를 계산 →</li>



<li>화면이 자동으로 업데이트됨</li>
</ol>



<p>이 모든 걸 리액트가 <strong>자동으로</strong> 해주는 게 핵심이에요.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/15.1.0/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 정리</h3>



<ul class="wp-block-list">
<li>리액트는 <strong>데이터 중심으로 UI를 만드는 도구</strong>예요.</li>



<li>복잡한 화면도 더 <strong>예측 가능하고 효율적</strong>으로 만들 수 있어요.</li>



<li>컴포넌트와 상태를 기반으로 작동하며, 변화에 따라 UI를 다시 그려줘요.</li>
</ul><p>The post <a href="https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8%eb%9e%80-%eb%ac%b4%ec%97%87%ec%9d%b8%ea%b0%80/">[React] 🧠 리액트란 무엇인가?</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/%f0%9f%a7%a0-%eb%a6%ac%ec%95%a1%ed%8a%b8%eb%9e%80-%eb%ac%b4%ec%97%87%ec%9d%b8%ea%b0%80/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[react-query] 리렌더링 시 useMutation 의 동작과 주의사항</title>
		<link>https://nangchang.nes.or.kr/react-query-%eb%a6%ac%eb%a0%8c%eb%8d%94%eb%a7%81-%ec%8b%9c-usemutation-%ec%9d%98-%eb%8f%99%ec%9e%91%ea%b3%bc-%ec%a3%bc%ec%9d%98%ec%82%ac%ed%95%ad/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=react-query-%25eb%25a6%25ac%25eb%25a0%258c%25eb%258d%2594%25eb%25a7%2581-%25ec%258b%259c-usemutation-%25ec%259d%2598-%25eb%258f%2599%25ec%259e%2591%25ea%25b3%25bc-%25ec%25a3%25bc%25ec%259d%2598%25ec%2582%25ac%25ed%2595%25ad</link>
					<comments>https://nangchang.nes.or.kr/react-query-%eb%a6%ac%eb%a0%8c%eb%8d%94%eb%a7%81-%ec%8b%9c-usemutation-%ec%9d%98-%eb%8f%99%ec%9e%91%ea%b3%bc-%ec%a3%bc%ec%9d%98%ec%82%ac%ed%95%ad/#respond</comments>
		
		<dc:creator><![CDATA[낭창]]></dc:creator>
		<pubDate>Sat, 14 Oct 2023 04:20:08 +0000</pubDate>
				<category><![CDATA[프로그래밍 이야기]]></category>
		<category><![CDATA[react]]></category>
		<category><![CDATA[react-query]]></category>
		<category><![CDATA[useMutation]]></category>
		<guid isPermaLink="false">https://nangchang.nes.or.kr/?p=879</guid>

					<description><![CDATA[<p>useMutation 은 useEffect, useCallback 같은 hook 과는 다르게 의존성을 설정할 수 없다. 그럼, 리렌더링 시에 useMutation에서 반환되는 mutate() 는 항상 새로 만들어 지는 걸까? useMutation 에 파라메터로 넘기는 mutaionFn, onMutate, onSettled, onSuccess 등이 리렌더링 시 변경될 경우, mutate() 를 호출 하면 각 상황에서 변경된 함수가 호출되는 것으로 봐서 그럴 수도 있어 보인다. 그렇다면 mutate() 를 [&#8230;]</p>
<p>The post <a href="https://nangchang.nes.or.kr/react-query-%eb%a6%ac%eb%a0%8c%eb%8d%94%eb%a7%81-%ec%8b%9c-usemutation-%ec%9d%98-%eb%8f%99%ec%9e%91%ea%b3%bc-%ec%a3%bc%ec%9d%98%ec%82%ac%ed%95%ad/">[react-query] 리렌더링 시 useMutation 의 동작과 주의사항</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>useMutation 은 useEffect, useCallback 같은 hook 과는 다르게 의존성을 설정할 수 없다. 그럼, 리렌더링 시에 useMutation에서 반환되는 mutate() 는 항상 새로 만들어 지는 걸까?</p>



<p>useMutation 에 파라메터로 넘기는 mutaionFn, onMutate, onSettled, onSuccess 등이 리렌더링 시 변경될 경우, mutate() 를 호출 하면 각 상황에서 변경된 함수가 호출되는 것으로 봐서 그럴 수도 있어 보인다.</p>



<p>그렇다면 mutate() 를 호출 해서 mutationFn 이 이미 실행 중인 상황에서 리렌더링이 일어나 onSuccess 등이 변경 되고, 그 후 mutationFn 의 실행이 완료된다면 어떻게 될까? mutationFn 이 성공적으로 수행된 후 호출 되는 onSuccess 는 앞서 mutate() 가 호출 되었을 당시의 onSuccess 함수가 아니라 리렌더링 중 변경된 onSuccess 함수가 호출된다.</p>



<div class="salesEvent"></div>



<p>실제 react-query 가 어떻게 구현되어 있는지 살펴보자.</p>



<pre title="query/packages/react-query/src /useMutation.ts" class="wp-block-code"><code lang="typescript" class="language-typescript">  const [observer] = React.useState(
    () =&gt;
      new MutationObserver&lt;TData, TError, TVariables, TContext&gt;(
        queryClient,
        options,
      ),
  )</code></pre>



<p>useMutation 의 구현을 보면 observer 라는 state 를 만들어 쓰는 것을 볼 수 있다.</p>



<pre title="query/packages/react-query/src /useMutation.ts" class="wp-block-code"><code lang="typescript" class="language-typescript">  React.useEffect(() =&gt; {
    observer.setOptions(options)
  }, [observer, options])</code></pre>



<p>useMutation 에 파라메터로 넘어가는 옵션이 변경될 경우, 이 observer state 의 setOptions() 를 호출 하여 변경해 주게되며,</p>



<pre title="query/packages/react-query/src /useMutation.ts" class="wp-block-code"><code lang="typescript" class="language-typescript">  const mutate = React.useCallback&lt;
    UseMutateFunction&lt;TData, TError, TVariables, TContext&gt;
  &gt;(
    (variables, mutateOptions) =&gt; {
      observer.mutate(variables, mutateOptions).catch(noop)
    },
    [observer],
  )
</code></pre>



<p>우리가 useMutation() 의 결과로 반환받는 mutate 는 useCallback() 을 사용하여 만드는데, 의존성 목록에는 observer 만 들어가 있어 mutate 는 새로 만들어지지 않는다.</p>



<p>좀 더 안 쪽을 살펴 보자. observer 의 mutate() 를 호출 했을때, 즉, 우리가 useMutation()에서 반환 받은 mutate() 함수를 호출 했을 때 무슨일이 일어나는걸까?</p>



<pre title="query/packages/query-core/src /mutationObserver.ts" class="wp-block-code"><code lang="typescript" class="language-typescript">  mutate(
    variables?: TVariables,
    options?: MutateOptions&lt;TData, TError, TVariables, TContext&gt;,
  ): Promise&lt;TData&gt; {
    this.mutateOptions = options

    if (this.currentMutation) {
      this.currentMutation.removeObserver(this)
    }

    this.currentMutation = this.client.getMutationCache().build(this.client, {
      ...this.options,
      variables:
        typeof variables !== 'undefined' ? variables : this.options.variables,
    })

    this.currentMutation.addObserver(this)

    return this.currentMutation.execute()
  }</code></pre>



<p>mutate() 가 호출 되는 시점에 현재의 옵션을 넘겨서 Mutation 객체를 새로 만들고, 마지막에 Mutation.execute() 함수를 호출해 준다.</p>



<pre title="query/packages/query-core/src /mutation.ts" class="wp-block-code"><code lang="typescript" class="language-typescript">async execute(): Promise&lt;TData&gt; {
    const executeMutation = () =&gt; {
      this.retryer = createRetryer({
        fn: () =&gt; {
          if (!this.options.mutationFn) {
            return Promise.reject('No mutationFn found')
          }
          return this.options.mutationFn(this.state.variables!)
        },
...
      })

      return this.retryer.promise
    }

...
      const data = await executeMutation()

      // Notify cache callback
      await this.mutationCache.config.onSuccess?.(
        data,
        this.state.variables,
        this.state.context,
        this as Mutation&lt;unknown, unknown, unknown, unknown&gt;,
      )
...
  }</code></pre>



<p>Mutation.execute() 는 생성 시 넘겨 받았던 options의 mutationFn 을 호출 하고, 그 결과에 따라 onSuccess 등을 호출 해 준다.</p>



<p>여기까지 봤을때는, mutate() 호출 시 객체를 생성하고, 필요한 정보는 해당 객체가 다 가지고 있는 형태이므로 이후, useMutation() 이 새로 호출되고 옵션이 바뀌더라도, 현재 실행중인 mutate 에는 영향을 미치지 않을 것으로 보인다.</p>



<p>그런데 아직 보지 못한 곳이 있다. observer의 setOptons().</p>



<pre title="query/packages/query-core/src /mutationObserver.ts" class="wp-block-code"><code lang="typescript" class="language-typescript">  setOptions(
    options?: MutationObserverOptions&lt;TData, TError, TVariables, TContext&gt;,
  ) {
    const prevOptions = this.options
    this.options = this.client.defaultMutationOptions(options)
    if (!shallowEqualObjects(prevOptions, this.options)) {
      this.client.getMutationCache().notify({
        type: 'observerOptionsUpdated',
        mutation: this.currentMutation,
        observer: this,
      })
    }
    this.currentMutation?.setOptions(this.options)
  }</code></pre>



<p>뭔가 이유가 있겠지만, 개인적으로는 좀 의아한데&#8230; 마지막에 현재 mutation, 즉, 마지막으로 mutate() 호출될 당시의 mutation 객체의 옵션을 같이 바꿔준다.</p>



<p>이로인해, mutaionFn 이 실행 중 useMutation의 옵션이 바뀌게 되면, mutationFn 이 끝난 후 처리는 바뀐 옵션대로 하게되는 것이다.</p>



<p>여기서 useMutation() 사용할때 한 가지 주의 사항이 생긴다. mutate()를 호출한 후 useMutation()의 옵션이 변하는 경우에 대해 고려하라는 것.</p>



<p>의도한게 아니라면, mutate() 호출이 완료되기 전에 useMutation() 의 옵션이 변경된는 상황은 막아야 한다. 보통 react-query 를 사용하는 목적을 생각해보면, mutationFn 을 API 호출 작업일 것이고, 해당 작업은 서버나 네트워크 상황 등에 따라 매우 느리게 끝날 가능성이 있다. 그리고, 그 사이 useMutation()의 옵션에 영향을 주는 state 가 변경되어 리렌더링이 일어나면, mutationFn 이 완료되었을 때는 의도치 않은 작업이 수행될 수 있다.</p><p>The post <a href="https://nangchang.nes.or.kr/react-query-%eb%a6%ac%eb%a0%8c%eb%8d%94%eb%a7%81-%ec%8b%9c-usemutation-%ec%9d%98-%eb%8f%99%ec%9e%91%ea%b3%bc-%ec%a3%bc%ec%9d%98%ec%82%ac%ed%95%ad/">[react-query] 리렌더링 시 useMutation 의 동작과 주의사항</a> first appeared on <a href="https://nangchang.nes.or.kr">Naver Ending Study</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://nangchang.nes.or.kr/react-query-%eb%a6%ac%eb%a0%8c%eb%8d%94%eb%a7%81-%ec%8b%9c-usemutation-%ec%9d%98-%eb%8f%99%ec%9e%91%ea%b3%bc-%ec%a3%bc%ec%9d%98%ec%82%ac%ed%95%ad/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
