{"id":67,"date":"2026-06-26T13:32:24","date_gmt":"2026-06-26T13:32:24","guid":{"rendered":"https:\/\/aabbee.cafe24.com\/?p=67"},"modified":"2026-06-26T14:02:46","modified_gmt":"2026-06-26T14:02:46","slug":"hook","status":"publish","type":"post","link":"https:\/\/coalacoding.com\/?p=67","title":{"rendered":"Hook"},"content":{"rendered":"<h1>1. Hook<\/h1>\n<p>Hook\uc740 \ud568\uc218\ud615 \ucef4\ud3ec\ub10c\ud2b8\uc5d0\uc11c React \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud574\uc8fc\ub294 \ud2b9\ubcc4\ud55c \ud568\uc218\ub2e4.<br \/>\n\uc774\ub984\uc774 \ud56d\uc0c1 <code>use<\/code>\ub85c \uc2dc\uc791\ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\ub2e4.<\/p>\n<h2>1.1. Hook \uc0ac\uc6a9 \uaddc\uce59<\/h2>\n<p>Hook\uc744 \uc0ac\uc6a9\ud560 \ub54c \ubc18\ub4dc\uc2dc \uc9c0\ucf1c\uc57c \ud560 \ub450 \uac00\uc9c0 \uaddc\uce59\uc774 \uc788\ub2e4.<\/p>\n<table>\n<thead>\n<tr>\n<th>\uaddc\uce59<\/th>\n<th>\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>\ucef4\ud3ec\ub10c\ud2b8 \ucd5c\uc0c1\uc704\uc5d0\uc11c\ub9cc \ud638\ucd9c<\/strong><\/td>\n<td>if\ubb38, for\ubb38, \uc911\ucca9 \ud568\uc218 \uc548\uc5d0\uc11c \ud638\ucd9c\ud558\uba74 \uc548 \ub41c\ub2e4<\/td>\n<\/tr>\n<tr>\n<td><strong>React \ud568\uc218\uc5d0\uc11c\ub9cc \ud638\ucd9c<\/strong><\/td>\n<td>\uc77c\ubc18 JavaScript \ud568\uc218\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre><code class=\"language-jsx\">\/\/ \u274c \uc798\ubabb\ub41c \uc608\uc2dc\nfunction App() {\n  if (condition) {\n    const [count, setCount] = useState(0); \/\/ if\ubb38 \uc548\uc5d0\uc11c \ud638\ucd9c \u2192 \uc624\ub958!\n  }\n}\n\n\/\/ \u2705 \uc62c\ubc14\ub978 \uc608\uc2dc\nfunction App() {\n  const [count, setCount] = useState(0); \/\/ \ucd5c\uc0c1\uc704\uc5d0\uc11c \ud638\ucd9c\n}\n<\/code><\/pre>\n<h2>1.2. \uc790\uc8fc \uc4f0\ub294 Hook \ubaa9\ub85d<\/h2>\n<table>\n<thead>\n<tr>\n<th>Hook<\/th>\n<th>\uc6a9\ub3c4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>useState<\/code><\/td>\n<td>\uc0c1\ud0dc(\ub370\uc774\ud130) \uad00\ub9ac<\/td>\n<\/tr>\n<tr>\n<td><code>useEffect<\/code><\/td>\n<td>\ud654\uba74 \ud45c\uc2dc\/\uc0ac\ub77c\uc9d0\/\uc5c5\ub370\uc774\ud2b8 \uc2dc \uc2e4\ud589<\/td>\n<\/tr>\n<tr>\n<td><code>useRef<\/code><\/td>\n<td>DOM \uc694\uc18c \uc9c1\uc811 \uc811\uadfc, \ub80c\ub354\ub9c1 \uc5c6\uc774 \uac12 \uc800\uc7a5<\/td>\n<\/tr>\n<tr>\n<td><code>useContext<\/code><\/td>\n<td>\ucef4\ud3ec\ub10c\ud2b8 \ud2b8\ub9ac \uc804\uccb4\uc5d0 \ub370\uc774\ud130 \uc804\ub2ec<\/td>\n<\/tr>\n<tr>\n<td><code>useMemo<\/code><\/td>\n<td>\ubcf5\uc7a1\ud55c \uacc4\uc0b0 \uacb0\uacfc \uce90\uc2f1 (\uc131\ub2a5 \ucd5c\uc801\ud654)<\/td>\n<\/tr>\n<tr>\n<td><code>useCallback<\/code><\/td>\n<td>\ud568\uc218 \uce90\uc2f1 (\uc131\ub2a5 \ucd5c\uc801\ud654)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\uc774 \ucc55\ud130\uc5d0\uc11c\ub294 \uac00\uc7a5 \ub9ce\uc774 \uc4f0\ub294 <code>useState<\/code>\uc640 <code>useEffect<\/code>\ub97c \uc9d1\uc911\uc801\uc73c\ub85c \ub2e4\ub8ec\ub2e4.<\/p>\n<h1>2. UseState()<\/h1>\n<h2>2.1. State\ub780?<\/h2>\n<p>State\ub294 \ucef4\ud3ec\ub10c\ud2b8\uc758 \ub370\uc774\ud130 \uc800\uc7a5\uc18c\ub2e4. \uac12\uc774 \ubcc0\uacbd\ub418\uba74 \ud654\uba74\uc774 \uc790\ub3d9\uc73c\ub85c \ub2e4\uc2dc \uadf8\ub824\uc9c4\ub2e4.<\/p>\n<h3>2.1.1. \uae30\ubcf8 \uc0ac\uc6a9\ubc95<\/h3>\n<pre><code class=\"language-jsx\">import { useState } from &quot;react&quot;;\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  return (\n    &lt;div&gt;\n      &lt;p&gt;\ud69f\uc218: {count}&lt;\/p&gt;\n      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;\uc99d\uac00&lt;\/button&gt;\n    &lt;\/div&gt;\n  );\n}\n<\/code><\/pre>\n<h2>2.2. useState \ub3d9\uc791 \uc6d0\ub9ac<\/h2>\n<p><code>useState<\/code>\ub294 \ub450 \uac1c\uc758 \uac12\uc744 \ubc30\uc5f4\ub85c \ubc18\ud658\ud55c\ub2e4.<\/p>\n<ul>\n<li>\uccab \ubc88\uc9f8: \ud604\uc7ac \uc0c1\ud0dc \uac12<\/li>\n<li>\ub450 \ubc88\uc9f8: \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \ud568\uc218<\/li>\n<\/ul>\n<pre><code class=\"language-jsx\">const [value, setValue] = useState(\ucd08\uae30\uac12);\n<\/code><\/pre>\n<h3>2.2.1. \uc608\uc81c: \uce74\uc6b4\ud130<\/h3>\n<pre><code class=\"language-jsx\">function Counter() {\n  const [num, setNum] = useState(0);\n\n  const plus = () =&gt; setNum(num + 1);\n  const minus = () =&gt; setNum(num - 1);\n\n  return (\n    &lt;div&gt;\n      &lt;h2&gt;{num}&lt;\/h2&gt;\n      &lt;button onClick={plus}&gt;+&lt;\/button&gt;\n      &lt;button onClick={minus}&gt;-&lt;\/button&gt;\n    &lt;\/div&gt;\n  );\n}\n<\/code><\/pre>\n<h2>2.3. \uac1d\uccb4\uc640 \ubc30\uc5f4 State \uad00\ub9ac<\/h2>\n<blockquote>\n<p><strong>Warning<\/strong>: <strong>\uc8fc\uc758: \uc9c1\uc811 \uc218\uc815 \uae08\uc9c0!<\/strong><\/p>\n<p>\uc0c1\ud0dc \uac1d\uccb4\ub098 \ubc30\uc5f4\uc744 \uc9c1\uc811 \uc218\uc815\ud558\uba74 \uc548 \ub41c\ub2e4. \ubc18\ub4dc\uc2dc \uc0c8\ub85c\uc6b4 \uac1d\uccb4\/\ubc30\uc5f4\uc744 \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4.<\/p>\n<p><strong>\uc804\uac1c \uc5f0\uc0b0\uc790<\/strong> \ub97c \uc0ac\uc6a9\ud558\uba74 \ud3b8\ub9ac\ud558\ub2e4.<\/p>\n<\/blockquote>\n<p><Accordion title=\"\u2764\ufe0f \uc804\uac1c \uc5f0\uc0b0\uc790(...)\ub780?\"><br \/>\n> `&#8230;`\uc740 \uac1d\uccb4\ub098 \ubc30\uc5f4\uc758 <strong>\ub0b4\uc6a9\ubb3c\uc744 \uaebc\ub0b4\uc11c \ud3bc\uce58\ub294<\/strong> \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \ubb38\ubc95\uc774\ub2e4.<\/p>\n<h6>2.3.0.0.0.1. \uc804\uac1c\uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \uac1d\uccb4\ub97c \uc218\uc815<\/h6>\n<pre><code class=\"language-jsx\">const user = { name: &quot;\ucca0\uc218&quot;, age: 20 };\nconst newUser = { ...user, name: &quot;\uc601\ud76c&quot; };\n<\/code><\/pre>\n<h6>2.3.0.0.0.2. \uc804\uac1c\uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \uac1d\uccb4\ub97c \uc218\uc815<\/h6>\n<pre><code class=\"language-jsx\">const user = { name: &quot;\ucca0\uc218&quot;, age: 20 };\nconst newUser = { name: &quot;\uc601\ud76c&quot;, age: user.age };\n<\/code><\/pre>\n<h6>2.3.0.0.0.3. \uc804\uac1c\uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ubc30\uc5f4\uc744 \uc218\uc815<\/h6>\n<pre><code class=\"language-jsx\">const fruits = [&quot;\uc0ac\uacfc&quot;, &quot;\ubc14\ub098\ub098&quot;];\nconst newFruits = [...fruits, &quot;\uc624\ub80c\uc9c0&quot;];\n<\/code><\/pre>\n<h6>2.3.0.0.0.4. \uc804\uac1c\uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubc30\uc5f4\uc744 \uc218\uc815<\/h6>\n<pre><code class=\"language-jsx\">const fruits = [&quot;\uc0ac\uacfc&quot;, &quot;\ubc14\ub098\ub098&quot;];\nconst newFruits2 = fruits.concat(&quot;\uc624\ub80c\uc9c0&quot;);\n<\/code><\/pre>\n<p><\/Accordion><\/p>\n<h3>2.3.1. \uc608\uc81c 2: Todo<\/h3>\n<h4>Todo.css<\/h4>\n<pre><code class=\"language-css\">\/* \uc804\uccb4 \uc601\uc5ed \uc124\uc815 *\/\n.container {\n  max-width: 400px;\n  margin: 50px auto;\n  padding: 20px;\n  border: 1px solid #ddd;\n  border-radius: 8px;\n}\n\n\/* \uc785\ub825\ucc3d\uacfc \ubc84\ud2bc \uac00\ub85c \ubc30\uce58 *\/\n.input-box {\n  display: flex;\n  gap: 10px;\n  margin-bottom: 20px;\n}\n\n\/* \uc785\ub825\ucc3d \ud06c\uae30 \ud655\uc7a5 *\/\n.input-field {\n  flex: 1;\n  padding: 10px;\n}\n\n\/* \ucd94\uac00 \ubc84\ud2bc \ub514\uc790\uc778 *\/\n.add-btn {\n  padding: 10px 20px;\n  background-color: #007bff;\n  color: white;\n  border: none;\n  cursor: pointer;\n}\n\n\/* \ubaa9\ub85d \uc2a4\ud0c0\uc77c \ucd08\uae30\ud654 *\/\n.list-box {\n  list-style: none;\n  padding: 0;\n}\n\n\/* \uac1c\ubcc4 \ud56d\ubaa9 \ub514\uc790\uc778 *\/\n.list-item {\n  padding: 10px;\n  border-bottom: 1px solid #eee;\n}\n<\/code><\/pre>\n<h4>Todo.jsx(\ucd94\uac00)<\/h4>\n<pre><code>\ucd94\uac00\n\n```jsx\nimport { useState } from &quot;react&quot;;\n\nfunction Todo() {\n  const [todos, setTodos] = useState([]);\n  const [inputValue, setInputValue] = useState(&quot;&quot;);\n\n  const addTodo = () =&gt; {\n    if (inputValue.trim() === &quot;&quot;) return;\n    setTodos([...todos, inputValue]);\n    setInputValue(&quot;&quot;);\n  };\n\n  return (\n    &lt;div className=&quot;container&quot;&gt;\n      &lt;div className=&quot;input-box&quot;&gt;\n        &lt;input\n          className=&quot;input-field&quot;\n          value={inputValue}\n          onChange={(e) =&gt; setInputValue(e.target.value)}\n          placeholder=&quot;\ud560 \uc77c\uc744 \uc785\ub825\ud558\uc138\uc694&quot;\n        \/&gt;\n        &lt;button className=&quot;add-btn&quot; onClick={addTodo}&gt;\ucd94\uac00&lt;\/button&gt;\n      &lt;\/div&gt;\n      &lt;ul className=&quot;list-box&quot;&gt;\n        {todos.map((todo, index) =&gt; (\n          &lt;li key={index} className=&quot;list-item&quot;&gt;{todo}&lt;\/li&gt;\n        ))}\n      &lt;\/ul&gt;\n    &lt;\/div&gt;\n  );\n}\n```\n\n- \uc0c1\ud0dc \uad00\ub9ac \ubcc0\uc218: todos\ub294 \ud560 \uc77c \ubaa9\ub85d \ubc30\uc5f4\uc744, inputValue\ub294 \uc785\ub825\ucc3d\uc758 \ubb38\uc790\uc5f4\uc744 \uad00\ub9ac\ud55c\ub2e4.\n- \uc0c1\ud0dc \uac31\uc2e0 \ud568\uc218: addTodo \ud568\uc218 \ub0b4\ubd80\uc5d0\uc11c \uc804\uac1c \uad6c\ubb38(...todos)\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\uc874 \ubc30\uc5f4\uc744 \ubcf5\uc0ac\ud55c \ud6c4 \uc0c8 \ud56d\ubaa9\uc744 \ucd94\uac00\ud55c\ub2e4.\n<\/code><\/pre>\n<h4>Todo.jsx(\uc0ad\uc81c)<\/h4>\n<pre><code>\uc0ad\uc81c \uae30\ub2a5\uc774 \ud3ec\ud568\ub41c \ub9ac\uc2a4\ud2b8\n\n```jsx\nconst deleteTodo = (index) =&gt; {\n  setTodos(todos.filter((_, i) =&gt; i !== index));\n};\n\nreturn (\n  &lt;ul&gt;\n    {todos.map((todo, index) =&gt; (\n      &lt;li key={index}&gt;\n        {todo} &lt;button onClick={() =&gt; deleteTodo(index)}&gt;\uc0ad\uc81c&lt;\/button&gt;\n      &lt;\/li&gt;\n    ))}\n  &lt;\/ul&gt;\n);\n```\n<\/code><\/pre>\n<h1>3. useEffect()<\/h1>\n<p>\ucef4\ud3ec\ub10c\ud2b8\ub0b4\uc758 \ud568\uc218\uac00 \ud638\ucd9c\ub418\ub294 \uc2dc\uc810\uc744 \uc81c\uc5b4\ud558\ub294 \ud6c5<br \/>\n<code>useEffect<\/code>\ub294 \ucef4\ud3ec\ub10c\ud2b8\uac00 \ud654\uba74\uc5d0 \ub098\ud0c0\ub0a0 \ub54c, \uc0ac\ub77c\uc9c8 \ub54c, \ub610\ub294 \ud2b9\uc815 \uac12\uc774 \ubcc0\ud560 \ub54c \uc2e4\ud589\ud560 \ucf54\ub4dc\ub97c \uc815\uc758\ud55c\ub2e4.<\/p>\n<h2>3.1. \ubb38\ubc95\uc815\ub9ac<\/h2>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\uc0c1\ud669<\/th>\n<th align=\"left\">\uc608\uc2dc<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\">\uccab \ub80c\ub354\ub9c1 \uc2dc \uc2e4\ud589 (\ub9c8\uc6b4\ud2b8)<\/td>\n<td align=\"left\"><code>useEffect(() =&gt; {<\/code><br \/><code>  console.log(&quot;\ub9c8\uc6b4\ud2b8&quot;);<\/code><br \/><code>}, [])<\/code><\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\ub80c\ub354\ub9c1\ub420 \ub54c\ub9c8\ub2e4 \uc2e4\ud589<\/td>\n<td align=\"left\"><code>useEffect(() =&gt; {<\/code><br \/><code>  console.log(&quot;\ub80c\ub354\ub9c1&quot;);<\/code><br \/><code>})<\/code><\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\ud2b9\uc815 \uac12 \ubcc0\uacbd \uc2dc \uc2e4\ud589<\/td>\n<td align=\"left\"><code>useEffect(() =&gt; {<\/code><br \/><code>  console.log(\uac12);<\/code><br \/><code>}, [\uac12])<\/code><\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\ucef4\ud3ec\ub10c\ud2b8 \uc81c\uac70 \uc2dc \uc815\ub9ac (\uc5b8\ub9c8\uc6b4\ud2b8)<\/td>\n<td align=\"left\"><code>useEffect(() =&gt; {<\/code><br \/><code>  console.log(&quot;\ub9c8\uc6b4\ud2b8&quot;);<\/code><br \/><code>  return () =&gt; console.log(&quot;\uc5b8\ub9c8\uc6b4\ud2b8&quot;);<\/code><br \/><code>}, [])<\/code><\/td>\n<\/tr>\n<tr>\n<td align=\"left\">\uac12 \ubcc0\uacbd \uc2dc \uc2e4\ud589 + \uc774\uc804 \uac83 \uc815\ub9ac<\/td>\n<td align=\"left\"><code>useEffect(() =&gt; {<\/code><br \/><code>  console.log(\uac12);<\/code><br \/><code>  return () =&gt; console.log(&quot;\uc815\ub9ac&quot;);<\/code><br \/><code>}, [\uac12])<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>3.1.1. \ub9c8\uc6b4\ud2b8\uc2dc<\/h3>\n<p>\ucef4\ud3ec\ub10c\ud2b8\uac00 \ud654\uba74\uc5d0 \ucc98\uc74c \ub098\ud0c0\ub0a0 \ub54c <strong>\ub2e8 \ud55c \ubc88<\/strong> \uc2e4\ud589\ub41c\ub2e4.<br \/>\n\ube48 \ubc30\uc5f4 <code>[]<\/code>\uc744 \uc758\uc874\uc131 \ubc30\uc5f4\ub85c \uc804\ub2ec\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">useEffect(() =&gt; {\n  console.log(&quot;\ucef4\ud3ec\ub10c\ud2b8\uac00 \ud654\uba74\uc5d0 \ub098\ud0c0\ub0a8&quot;);\n}, []);\n<\/code><\/pre>\n<h3>3.1.2. \ub80c\ub354\ub9c1\uc2dc<\/h3>\n<p>\uc758\uc874\uc131 \ubc30\uc5f4\uc744 \uc0dd\ub7b5\ud558\uba74 <strong>\ub80c\ub354\ub9c1\ub420 \ub54c\ub9c8\ub2e4<\/strong> \uc2e4\ud589\ub41c\ub2e4.<br \/>\n\uc0c1\ud0dc\ub098 props\uac00 \ubc14\ub014 \ub54c\ub9c8\ub2e4 \ub9e4\ubc88 \ud638\ucd9c\ub418\ubbc0\ub85c \uc8fc\uc758\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">useEffect(() =&gt; {\n  console.log(&quot;\ub80c\ub354\ub9c1\ub428&quot;);\n});\n<\/code><\/pre>\n<h3>3.1.3. \ud2b9\uc815\uac12 \ubcc0\uacbd\uc2dc<\/h3>\n<p>\uc758\uc874\uc131 \ubc30\uc5f4\uc5d0 \uac12\uc744 \ub123\uc73c\uba74 <strong>\uadf8 \uac12\uc774 \ubc14\ub014 \ub54c\ub9c8\ub2e4<\/strong> \uc2e4\ud589\ub41c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">const [count, setCount] = useState(0);\n\nuseEffect(() =&gt; {\n  console.log(&quot;count\uac00 \ubc14\ub01c:&quot;, count);\n}, [count]);\n<\/code><\/pre>\n<h3>3.1.4. \uc5b8\ub9c8\uc6b4\ud2b8\uc2dc<\/h3>\n<p><code>return<\/code>\uc73c\ub85c <strong>\uc815\ub9ac \ud568\uc218(cleanup)<\/strong>\ub97c \ubc18\ud658\ud558\uba74 \ucef4\ud3ec\ub10c\ud2b8\uac00 \ud654\uba74\uc5d0\uc11c \uc0ac\ub77c\uc9c8 \ub54c \uc2e4\ud589\ub41c\ub2e4.<br \/>\n\ud0c0\uc774\uba38, \uc774\ubca4\ud2b8 \ub9ac\uc2a4\ub108 \ub4f1 \uc815\ub9ac\uac00 \ud544\uc694\ud55c \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-jsx\">useEffect(() =&gt; {\n  console.log(&quot;\ub9c8\uc6b4\ud2b8&quot;);\n\n  return () =&gt; {\n    console.log(&quot;\uc5b8\ub9c8\uc6b4\ud2b8 - \uc815\ub9ac \uc2e4\ud589&quot;);\n  };\n}, []);\n<\/code><\/pre>\n<h2>3.2. \uc2e4\uc2b5: \ub85c\uadf8\uc778<\/h2>\n<p>\uc6f9\ube0c\ub77c\uc6b0\uc800\uc758 \ub370\uc774\ud130 \uc800\uc7a5 \uacf5\uac04\uc778 \ub85c\uceec \uc2a4\ud1a0\ub9ac\uc9c0\uc5d0 \ub85c\uadf8\uc778 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ub85c\uadf8\uc778 \ud398\uc774\uc9c0\ub97c \ub9cc\ub4e4\uc5b4\ubcf4\uc790<\/p>\n<h4>App.css<\/h4>\n<pre><code class=\"language-css\">\n\n.container {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  min-height: 100vh;\n}\n\n\n.card {\n  background: white;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);\n  border-radius: 10px;\n  padding: 2rem;\n  margin: 2rem auto;\n  width: 90%;\n  max-width: 40rem;\n  text-align: center;\n}\n\n.control {\n  margin: 1rem 0;\n  display: flex;\n  flex-direction: column;\n  text-align: left;\n}\n\n.control label {\n  font-weight: bold;\n  margin-bottom: 0.5rem;\n}\n\n.control input {\n  font: inherit;\n  padding: 0.5rem;\n  border-radius: 6px;\n  border: 1px solid #ccc;\n}\n\n.actions {\n  text-align: center;\n  margin-top: 1rem;\n}\n\n.btn {\n  font: inherit;\n  background: #7a0141;\n  border: 1px solid #7a0141;\n  color: white;\n  padding: 0.75rem 2rem;\n  border-radius: 30px;\n  cursor: pointer;\n}\n\n.btn:disabled {\n  background: #ccc;\n  border-color: #ccc;\n  color: #666;\n  cursor: not-allowed;\n}\n\n.btn:hover:not(:disabled) {\n  background: #a40256;\n  border-color: #a40256;\n}\n\n<\/code><\/pre>\n<h4>App.jsx<\/h4>\n<pre><code class=\"language-jsx\">import { useState, useEffect } from &quot;react&quot;;\nimport &quot;.\/App.css&quot;;\n\nconst App = () =&gt; {\n  const [isLoggedIn, setIsLoggedIn] = useState(false);\n  const [email, setEmail] = useState(&quot;&quot;);\n  const [password, setPassword] = useState(&quot;&quot;);\n\n  useEffect(() =&gt; {\n    const storedLoginInfo = localStorage.getItem(&quot;isLoggedIn&quot;);\n    if (storedLoginInfo === &quot;1&quot;) {\n      setIsLoggedIn(true);\n    }\n  }, []);\n\n  const loginHandler = (e) =&gt; {\n    e.preventDefault();\n    localStorage.setItem(&quot;isLoggedIn&quot;, &quot;1&quot;);\n    setIsLoggedIn(true);\n  };\n\n  const logoutHandler = () =&gt; {\n    localStorage.removeItem(&quot;isLoggedIn&quot;);\n    setIsLoggedIn(false);\n    setEmail(&quot;&quot;);\n    setPassword(&quot;&quot;);\n  };\n\n  return (\n    &lt;div className=&quot;container&quot;&gt;\n      &lt;header className=&quot;main-header&quot;&gt;\n        &lt;h1&gt;React Auth Demo&lt;\/h1&gt;\n        {isLoggedIn &amp;&amp; (\n          &lt;nav className=&quot;nav&quot;&gt;\n            &lt;button className=&quot;btn&quot; onClick={logoutHandler}&gt;\n              \ub85c\uadf8\uc544\uc6c3\n            &lt;\/button&gt;\n          &lt;\/nav&gt;\n        )}\n      &lt;\/header&gt;\n      &lt;main&gt;\n        {!isLoggedIn ? (\n          &lt;div className=&quot;card login&quot;&gt;\n            &lt;form onSubmit={loginHandler}&gt;\n              &lt;div className=&quot;control&quot;&gt;\n                &lt;label htmlFor=&quot;email&quot;&gt;\uc774\uba54\uc77c&lt;\/label&gt;\n                &lt;input type=&quot;email&quot; id=&quot;email&quot; value={email} onChange={(e) =&gt; setEmail(e.target.value)} \/&gt;\n              &lt;\/div&gt;\n              &lt;div className=&quot;control&quot;&gt;\n                &lt;label htmlFor=&quot;password&quot;&gt;\ube44\ubc00\ubc88\ud638&lt;\/label&gt;\n                &lt;input type=&quot;password&quot; id=&quot;password&quot; value={password} onChange={(e) =&gt; setPassword(e.target.value)} \/&gt;\n              &lt;\/div&gt;\n              &lt;div className=&quot;actions&quot;&gt;\n                &lt;button type=&quot;submit&quot; className=&quot;btn&quot;&gt;\n                  \ub85c\uadf8\uc778\n                &lt;\/button&gt;\n              &lt;\/div&gt;\n            &lt;\/form&gt;\n          &lt;\/div&gt;\n        ) : (\n          &lt;div className=&quot;card home&quot;&gt;\n            &lt;h1&gt;\ud658\uc601\ud569\ub2c8\ub2e4!&lt;\/h1&gt;\n            &lt;p&gt;\ub85c\uadf8\uc778\uc5d0 \uc131\uacf5\ud588\uc2b5\ub2c8\ub2e4.&lt;\/p&gt;\n          &lt;\/div&gt;\n        )}\n      &lt;\/main&gt;\n    &lt;\/div&gt;\n  );\n};\n\nexport default App;\n\n<\/code><\/pre>\n<h2>3.3. \ucf54\ub4dc \ubd84\uc11d<\/h2>\n<h3>3.3.1. \uc0c1\ud0dc(State) \uc120\uc5b8<\/h3>\n<pre><code class=\"language-jsx\">const [isLoggedIn, setIsLoggedIn] = useState(false);\nconst [email, setEmail] = useState(&quot;&quot;);\nconst [password, setPassword] = useState(&quot;&quot;);\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th align=\"left\">\ubcc0\uc218<\/th>\n<th align=\"center\">\ucd08\uae30\uac12<\/th>\n<th align=\"left\">\uc5ed\ud560<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td align=\"left\"><code>isLoggedIn<\/code><\/td>\n<td align=\"center\"><code>false<\/code><\/td>\n<td align=\"left\">\ub85c\uadf8\uc778 \uc5ec\ubd80 \u2014 true\uba74 \ud648 \ud654\uba74, false\uba74 \ub85c\uadf8\uc778 \ud654\uba74<\/td>\n<\/tr>\n<tr>\n<td align=\"left\"><code>email<\/code><\/td>\n<td align=\"center\"><code>&quot;&quot;<\/code><\/td>\n<td align=\"left\">\uc774\uba54\uc77c \uc785\ub825\ucc3d\uc758 \ud604\uc7ac \uac12<\/td>\n<\/tr>\n<tr>\n<td align=\"left\"><code>password<\/code><\/td>\n<td align=\"center\"><code>&quot;&quot;<\/code><\/td>\n<td align=\"left\">\ube44\ubc00\ubc88\ud638 \uc785\ub825\ucc3d\uc758 \ud604\uc7ac \uac12<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>3.3.2. useEffect \u2014 \uc7ac\ubc29\ubb38 \uccb4\ud06c<\/h3>\n<pre><code class=\"language-jsx\">useEffect(() =&gt; {\n  const storedLoginInfo = localStorage.getItem(&quot;isLoggedIn&quot;);\n  if (storedLoginInfo === &quot;1&quot;) {\n    setIsLoggedIn(true);\n  }\n}, []);\n<\/code><\/pre>\n<ul>\n<li><code>localStorage<\/code>\ub294 \ube0c\ub77c\uc6b0\uc800\uc5d0 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uacf5\uac04\uc774\ub2e4. \uc0c8\ub85c\uace0\uce68\ud574\ub3c4 \uc0ac\ub77c\uc9c0\uc9c0 \uc54a\ub294\ub2e4.<\/li>\n<li><code>getItem(&quot;isLoggedIn&quot;)<\/code>\uc73c\ub85c \uc774\uc804\uc5d0 \uc800\uc7a5\ub41c \ub85c\uadf8\uc778 \uc815\ubcf4\ub97c \uaebc\ub0b8\ub2e4.<\/li>\n<li>\uac12\uc774 <code>&quot;1&quot;<\/code>\uc774\uba74 \uc774\ubbf8 \ub85c\uadf8\uc778\ud55c \uc0ac\uc6a9\uc790\uc774\ubbc0\ub85c <code>setIsLoggedIn(true)<\/code>\ub85c \uc0c1\ud0dc\ub97c \ubc14\uafbc\ub2e4.<\/li>\n<li>\uc758\uc874\uc131 \ubc30\uc5f4\uc774 <code>[]<\/code>\uc774\ubbc0\ub85c <strong>\ucc98\uc74c \ub9c8\uc6b4\ud2b8\ub420 \ub54c \ud55c \ubc88\ub9cc<\/strong> \uc2e4\ud589\ub41c\ub2e4 \u2192 \ubb34\ud55c \ub8e8\ud504 \uc5c6\uc74c.<\/li>\n<\/ul>\n<h3>3.3.3. loginHandler \u2014 \ub85c\uadf8\uc778 \ucc98\ub9ac<\/h3>\n<pre><code class=\"language-jsx\">const loginHandler = (e) =&gt; {\n  e.preventDefault();\n  localStorage.setItem(&quot;isLoggedIn&quot;, &quot;1&quot;);\n  setIsLoggedIn(true);\n};\n<\/code><\/pre>\n<ul>\n<li><code>e.preventDefault()<\/code>: \ud3fc \uc81c\ucd9c \uc2dc \ud398\uc774\uc9c0\uac00 \uc0c8\ub85c\uace0\uce68\ub418\ub294 \uae30\ubcf8 \ub3d9\uc791\uc744 \ub9c9\ub294\ub2e4.<\/li>\n<li><code>localStorage.setItem(&quot;isLoggedIn&quot;, &quot;1&quot;)<\/code>: \ube0c\ub77c\uc6b0\uc800\uc5d0 \ub85c\uadf8\uc778 \uc815\ubcf4\ub97c \uc800\uc7a5\ud55c\ub2e4. \uc7ac\ubc29\ubb38\ud574\ub3c4 \ub85c\uadf8\uc778 \uc0c1\ud0dc\uac00 \uc720\uc9c0\ub41c\ub2e4.<\/li>\n<li><code>setIsLoggedIn(true)<\/code>: \uc0c1\ud0dc\ub97c \ubc14\uafd4 \ud654\uba74\uc744 \ud648\uc73c\ub85c \uc804\ud658\ud55c\ub2e4.<\/li>\n<\/ul>\n<h3>3.3.4. logoutHandler \u2014 \ub85c\uadf8\uc544\uc6c3 \ucc98\ub9ac<\/h3>\n<pre><code class=\"language-jsx\">const logoutHandler = () =&gt; {\n  localStorage.removeItem(&quot;isLoggedIn&quot;);\n  setIsLoggedIn(false);\n  setEmail(&quot;&quot;);\n  setPassword(&quot;&quot;);\n};\n<\/code><\/pre>\n<ul>\n<li><code>localStorage.removeItem(&quot;isLoggedIn&quot;)<\/code>: \uc800\uc7a5\ub41c \ub85c\uadf8\uc778 \uc815\ubcf4\ub97c \uc0ad\uc81c\ud55c\ub2e4.<\/li>\n<li><code>setIsLoggedIn(false)<\/code>: \uc0c1\ud0dc\ub97c \ubc14\uafd4 \ud654\uba74\uc744 \ub85c\uadf8\uc778 \ud3fc\uc73c\ub85c \uc804\ud658\ud55c\ub2e4.<\/li>\n<li><code>setEmail(&quot;&quot;)<\/code>, <code>setPassword(&quot;&quot;)<\/code>: \uc785\ub825\ucc3d\uc744 \ube48 \uac12\uc73c\ub85c \ucd08\uae30\ud654\ud55c\ub2e4.<\/li>\n<\/ul>\n<h3>3.3.5. JSX \u2014 \ud654\uba74 \ubd84\uae30<\/h3>\n<pre><code class=\"language-jsx\">{!isLoggedIn ? (\n  &lt;\ub85c\uadf8\uc778 \ud3fc \/&gt;\n) : (\n  &lt;\ud658\uc601 \uba54\uc2dc\uc9c0 \/&gt;\n)}\n<\/code><\/pre>\n<ul>\n<li><code>isLoggedIn<\/code>\uc774 <code>false<\/code>\uc774\uba74 <code>!isLoggedIn<\/code>\uc774 <code>true<\/code>\uac00 \ub418\uc5b4 \ub85c\uadf8\uc778 \ud3fc\uc744 \ubcf4\uc5ec\uc900\ub2e4.<\/li>\n<li><code>isLoggedIn<\/code>\uc774 <code>true<\/code>\uc774\uba74 \ud658\uc601 \ud654\uba74\uc744 \ubcf4\uc5ec\uc900\ub2e4.<\/li>\n<li><code>?<\/code> <code>:<\/code> \uc740 \uc0bc\ud56d \uc5f0\uc0b0\uc790\ub85c, <code>if\/else<\/code>\ub97c \ud55c \uc904\ub85c \ud45c\ud604\ud55c \uac83\uc774\ub2e4.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>1. Hook Hook\uc740 \ud568\uc218\ud615 \ucef4\ud3ec\ub10c\ud2b8\uc5d0\uc11c React \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud574\uc8fc\ub294 \ud2b9\ubcc4\ud55c \ud568\uc218\ub2e4. \uc774\ub984\uc774 \ud56d\uc0c1 use\ub85c \uc2dc\uc791\ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\ub2e4. 1.1. Hook \uc0ac\uc6a9 \uaddc\uce59 Hook\uc744 \uc0ac\uc6a9\ud560 \ub54c \ubc18\ub4dc\uc2dc \uc9c0\ucf1c\uc57c \ud560 \ub450 \uac00\uc9c0 \uaddc\uce59\uc774 \uc788\ub2e4. \uaddc\uce59 \uc124\uba85 \ucef4\ud3ec\ub10c\ud2b8 \ucd5c\uc0c1\uc704\uc5d0\uc11c\ub9cc \ud638\ucd9c if\ubb38, for\ubb38, \uc911\ucca9 \ud568\uc218 \uc548\uc5d0\uc11c \ud638\ucd9c\ud558\uba74 \uc548 \ub41c\ub2e4 React \ud568\uc218\uc5d0\uc11c\ub9cc \ud638\ucd9c \uc77c\ubc18 JavaScript \ud568\uc218\uc5d0\uc11c\ub294 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4 &#8230; <a title=\"Hook\" class=\"read-more\" href=\"https:\/\/coalacoding.com\/?p=67\" aria-label=\"Hook\uc5d0 \ub300\ud574 \ub354 \uc790\uc138\ud788 \uc54c\uc544\ubcf4\uc138\uc694\">\ub354 \uc77d\uae30<\/a><\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-67","post","type-post","status-publish","format-standard","hentry","category-react-basics"],"_links":{"self":[{"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/posts\/67","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/coalacoding.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=67"}],"version-history":[{"count":1,"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":2247,"href":"https:\/\/coalacoding.com\/index.php?rest_route=\/wp\/v2\/posts\/67\/revisions\/2247"}],"wp:attachment":[{"href":"https:\/\/coalacoding.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coalacoding.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coalacoding.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}