{"id":12813,"date":"2026-10-24T08:00:19","date_gmt":"2026-10-23T23:00:19","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=12813"},"modified":"2026-10-24T16:17:13","modified_gmt":"2026-10-24T07:17:13","slug":"nextjs-sns-server-51-8","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/10\/24\/nextjs-sns-server-51-8\/","title":{"rendered":"[nextjs]SNS Server-51(myapp61+)[Website Login]\u00a0"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \uc774 \ubd80\ubd84\uc5d0\uc11c\ub294 \uc6f9\uc0ac\uc774\ud2b8 \ub85c\uadf8\uc778 \ubd80\ubd84\uc758 \uad6c\uc870\ub97c \uc0b4\ud3b4\ubd05\ub2c8\ub2e4.<br>In this section, we examine the structure of the website&#8217;s login area.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc774\ubc88 \ud30c\ud2b8\uc5d0\uc11c\ub294 \uc6f9\uc0ac\uc774\ud2b8 \ubd80\ubd84\uc758 \ub85c\uadf8\uc778 \uad6c\uc870\ub9cc \uc0b4\ud3b4\ubcf4\uace0 \uc678\ubd80\uc571 \ubd80\ubd84\uc758 \ub85c\uadf8\uc778\uc740 \ub2e4\uc74c \ud3ec\uc2a4\ud2b8\uc5d0\uc11c \uc0b4\ud3b4\ubd05\ub2c8\ub2e4.<br>In this part, we will look only at the login structure for the website; the login process for external apps will be covered in the next post.<\/p>\n\n\n\n<p>\ud83d\udcc1 \uc678\ubd80 \uc571 \ubc0f \ub85c\uceec UI\ubd80\ubd84 \uc778\uc99d \ubd80\ubd84 \uad6c\uc870<br>Authentication-related structure for external apps and the local UI<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>app\/api\/auth\/\n  \u251c\u2500\u2500 signup\/route.ts      -&gt; \uc6f9\uc0ac\uc774\ud2b8 \ud68c\uc6d0\uac00\uc785 \/ website signup\n  \u251c\u2500\u2500 login\/route.ts       -&gt; \uc6f9\uc0ac\uc774\ud2b8 \ub85c\uadf8\uc778 \/ website login\n  \u251c\u2500\u2500 logout\/route.ts      -&gt; \ub85c\uadf8\uc544\uc6c3 \/ logout\n  \u251c\u2500\u2500 refresh\/route.ts     -&gt; refresh_token\uc73c\ub85c access token\uc7ac\ubc1c\uae09\n  |                        -&gt; Reissuing an access token using a refresh token\n  \u2514\u2500\u2500 me\/route.ts          -&gt; \ub85c\uadf8\uc778 \uccb4\ud06c \/ Login check\n\napp\/auth\/\n  \u251c\u2500\u2500 signup\/page.tsx      -&gt; \ud68c\uc6d0\uac00\uc785 UI \/ Sign-up UI\n  \u2514\u2500\u2500 login\/page.tsx       -&gt; \ub85c\uadf8\uc778 UI \/ Login UI\n\noauth\/authorize\/route.ts   -&gt; OAuth \ub3d9\uc758 \ud654\uba74 \/ OAuth consent screen\noauth\/token\/route.ts       -&gt; access_token \ubc1c\uae09 \/ Issuance of an access token\n\nlib\/auth.ts                -&gt; \uc2e4\uc81c \uc720\uc800 \uac80\uc99d \ub85c\uc9c1 (getUser, \uc138\uc158 \ud655\uc778)\n                           -&gt; Actual user verification logic (getUser, session check)<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \uc6f9\uc0ac\uc774\ud2b8 \ub85c\uadf8\uc778 \/ Website Login<\/p>\n\n\n\n<p>\u2714\ufe0f \ub77c\uc6b0\ud2b8 \/ route<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>https:&#47;&#47;aloy-horizon.duckdns.org\/auth\/login<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ub85c\uadf8\uc778 \uccb4\ud06c \ud568\uc218 \/ Login check function<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>  useEffect(() =&gt; {\n    async function checkLogin() {\n      try {\n        const res = await fetch('\/api\/auth\/me', { credentials: 'include' });\n        if (res.ok) {\n          const data = await res.json();\n          if (data.username) {\n            setCurrentUser(data.username);\n          }\n        }\n      } catch {}\n      setLoading(false);\n    }\n    checkLogin();\n  }, &#91;]);<\/code><\/pre>\n\n\n\n<p>1)\ub77c\uc6b0\ud2b8 \uc2e4\ud589\uc2dc \ud55c\ubc88 \uc2e4\ud589\ub429\ub2c8\ub2e4.<br>It is executed once when the route is triggered.<\/p>\n\n\n\n<p>2)\/api\/auth\/me \ub77c\uc6b0\ud2b8\ub97c \uc2e4\ud589\ud574\uc11c(\ucfe0\ud0a4\ud3ec\ud568 \uc804\uc1a1 -> credentials :&#8217;include&#8217;) \uc5d1\uc138\uc2a4 \ud1a0\ud070\uc744 \uc5c5\ub370\uc774\ud2b8\ud569\ub2c8\ub2e4.<br>Execute the \/api\/auth\/me route (sending it with cookies\u2014i.e., <code>credentials: 'include'<\/code>) to update the access token.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>const res = await fetch('\/api\/auth\/me', { credentials: 'include' });<\/code><\/pre>\n\n\n\n<p>3)\/api\/auth\/me \ub77c\uc6b0\ud2b8\uc5d0\uc11c \ub9ac\ud134\ub418\ub294 username\uc744 currentUser\ubcc0\uc218\uc5d0 \uc124\uc815\ud569\ub2c8\ub2e4.<br>Set the <code>username<\/code> returned from the <code>\/api\/auth\/me<\/code> route to the <code>currentUser<\/code> variable.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>... ...\n const &#91;currentUser, setCurrentUser] = useState('');\n... ...        \n       if (res.ok) {\n          const data = await res.json();\n          if (data.username) {\n            setCurrentUser(data.username);\n          }\n        }<\/code><\/pre>\n\n\n\n<p>4)currentUser\uac00 \uc5c6\uc73c\uba74 \uc989 \uae30\uc874\uc5d0 \ub85c\uadf8\uc778\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc740 \uacbd\uc6b0 \uc544\ub798 UI\uc5d0\uc11c \ub85c\uadf8\uc778 \ud3fc\uc744 \ubcf4\uc5ec\uc90d\ub2c8\ub2e4.<br>If <code>currentUser<\/code> is absent\u2014meaning no user is currently logged in\u2014the UI below displays a login form.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>      {currentUser ? (\n        &lt;&gt;\n          &lt;p style={{ color: 'green', fontSize: 18 }}&gt;\ud604\uc7ac \ub85c\uadf8\uc778: &lt;strong&gt;{currentUser}&lt;\/strong&gt;&lt;\/p&gt;\n          {next &amp;&amp; next !== '\/' ? (\n            &lt;&gt;\n              &lt;p&gt;\uc2b9\uc778 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud574\uc57c \ud569\ub2c8\ub2e4 \/ You need to go to the approval page.&lt;\/p&gt;\n              &lt;button\n                onClick={() =&gt; { window.location.href = next; }}\n                style={{ marginTop: 20, padding: 12, width: '100%', background: '#6364ff', color: 'white', border: 0, borderRadius: 8, fontSize: 16 }}\n              &gt;\n                \ud83d\udd10 \uc2b9\uc778 \ud398\uc774\uc9c0\ub85c \uac00\uae30 \/ Go to Approval Page\n              &lt;\/button&gt;\n            &lt;\/&gt;\n          ) : (\n            &lt;p&gt;\uc774\ubbf8 \ub85c\uadf8\uc778\ub428 \/ Already logged in&lt;\/p&gt;\n          )}\n          &lt;button\n            onClick={handleLogout}\n            style={{ marginTop: 20, padding: 12, width: '100%', background: '#ff4444', color: 'white', border: 0, borderRadius: 8, fontSize: 16 }}\n          &gt;\n            \ub85c\uadf8\uc544\uc6c3 \/ Log out\n          &lt;\/button&gt;\n          &lt;p style={{ marginTop: 20 }}&gt;&lt;a href=\"\/\"&gt;\ud648\uc73c\ub85c \uac00\uae30 \/ Go to Home&lt;\/a&gt;&lt;\/p&gt;\n        &lt;\/&gt;\n      ) : ( ... )}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"769\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/login-form-jpg.jpg\" alt=\"\" class=\"wp-image-12863\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/login-form-jpg.jpg 600w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/login-form-jpg-234x300.jpg 234w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/login-form-jpg-400x513.jpg 400w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">Login Form<\/figcaption><\/figure>\n\n\n\n<p>\u2714\ufe0f \ub85c\uadf8\uc778 \ud568\uc218 \/ Login function<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>async function handleLogin(e: React.FormEvent) {\n    e.preventDefault();\n    setError('');\n\n    try {\n      const res = await fetch('\/api\/auth\/login', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application\/json' },\n        credentials: 'include',\n        body: JSON.stringify({ email: loginId, username: loginId, password })\n      });\n\n      const data = await res.json();\n      if (!res.ok) {\n        setError(data.error || '\ub85c\uadf8\uc778 \uc2e4\ud328\/Login failed');\n        return;\n      }\n\n      localStorage.setItem('username', data.username || loginId);\n\n      console.log('\u2705 \ub85c\uadf8\uc778 \uc131\uacf5 \/ login success next:', next);\n\n      \/\/ - router.push \ub300\uc2e0 window.location.href\uc0ac\uc6a9(\ub80c\ub354\ub9c1 \ub51c\ub808\uc774 \ub54c\ubb38\uc5d0) \n      \/\/  Use window.location.href instead of router.push (due to rendering delays).\n      if (next &amp;&amp; next !== '\/') {\n        if (next.startsWith('http')) {\n          window.location.href = next;\n        } else {\n          window.location.href = next;\n        }\n      } else {\n        window.location.href = '\/';\n      }\n    } catch (err) {\n      setError('\ub124\ud2b8\uc6cc\ud06c \uc624\ub958 \/ Network error');\n    }\n  }<\/code><\/pre>\n\n\n\n<p>1)\/api\/auth\/login \ub77c\uc6b0\ud2b8\ub85c \ub85c\uadf8\uc778 \ud3fc\uc5d0\uc11c \uc785\ub825\ub41c \uac12\uc744 \uc804\uc1a1\ud574\uc11c \ub85c\uadf8\uc778\uc744 \uc9c4\ud589\ud569\ub2c8\ub2e4.<br>Log in by sending the values \u200b\u200bentered in the login form to the \/api\/auth\/login route.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>      const res = await fetch('\/api\/auth\/login', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application\/json' },\n        credentials: 'include',\n        body: JSON.stringify({ email: loginId, username: loginId, password })\n      });<\/code><\/pre>\n\n\n\n<p>A.app\/api\/auth\/login\/route.ts \ub77c\uc6b0\ud2b8\uc5d0\uc11c \ub85c\uadf8\uc778 \uc815\ubcf4\uac00 \uc77c\uce58\ud558\uba74\ucfe0\ud0a4\uc5d0 \ud1a0\ud070\uc744 \uc800\uc7a5\ud569\ub2c8\ub2e4.<br>In the <code>app\/api\/auth\/login\/route.ts<\/code> route, if the login credentials match, the token is stored in a cookie.<\/p>\n\n\n\n<p>&#8212; \ucfe0\ud0a4\uc5d0 \uc800\uc7a5\ub420 \ud1a0\ud070\uc740 \uc5d1\uc138\uc2a4\ud1a0\ud070\uacfc \ub9ac\ud504\ub808\uc2dc\ud1a0\ud070\uc785\ub2c8\ub2e4.<br>The tokens to be stored in the cookie are the access token and the refresh token.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>   \/\/ \u2705 Access Token - 15\ubd84 - \ubaa8\ub4e0 \uacbd\ub85c\uc5d0\uc11c \uc0ac\uc6a9 \/ Use for all routes\n    res.cookies.set('token', accessToken, {\n      httpOnly: true, \/\/ \u2705 true - JS\uc5d0\uc11c \ubabb \uc77d\uc74c XSS \ubc29\uc5b4 \/ XSS protection: Unreadable by JS\n      secure: IS_PROD, \/\/ only https \n      sameSite: 'lax',\/\/'lax', \/\/ \ub2e4\ub978 \uc0ac\uc774\ud2b8\uc5d0\uc11c POST\uc694\uccad\uc2dc \ucfe0\ud0a4 \uc548\ubcf4\ub0c4 \/ Cookies are not sent during POST requests from other sites.\n      maxAge: 60*15, \/\/ 15\ubd84 \/ 15minute\n      path: '\/'\n    });\n\n    \/\/ \u2705 Refresh Token - 7\uc77c! - \/api\/auth\/refresh \uc5d0\uc11c\ub9cc \uc0ac\uc6a9\n    \/\/ Refresh Token - 7 days! - Used only at \/api\/auth\/refresh\n    res.cookies.set('refresh_token', refreshToken, {\n      httpOnly: true,\n      secure: IS_PROD, \/\/ only https \n      sameSite: 'lax',\/\/'lax', \/\/ \ub2e4\ub978 \uc0ac\uc774\ud2b8\uc5d0\uc11c POST\uc694\uccad\uc2dc \ucfe0\ud0a4 \uc548\ubcf4\ub0c4 \/ Cookies are not sent during POST requests from other sites.\n      maxAge: 60*60*24*7, \/\/ 7\uc77c \/ 7days\n      path: '\/'\n    });<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"550\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/cookies-jpg.jpg\" alt=\"\" class=\"wp-image-12868\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/cookies-jpg.jpg 800w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/cookies-jpg-300x206.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/cookies-jpg-768x528.jpg 768w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/cookies-jpg-400x275.jpg 400w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Refresh Token,Access Token<\/figcaption><\/figure>\n\n\n\n<p>2)\ub85c\uadf8\uc778\uc774 \uc131\uacf5\ud558\uba74 \uc0ac\uc6a9\uc790 \uc774\ub984\uc744 \ube0c\ub77c\uc6b0\uc800 \ub85c\uceec \uc2a4\ud1a0\ub9ac\uc9c0\uc5d0 \uc800\uc7a5\ud569\ub2c8\ub2e4.<br>Upon successful login, the username is saved to the browser&#8217;s local storage.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>const data = await res.json();\n... ...\nlocalStorage.setItem('username', data.username || loginId);<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"642\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/localstorage-jpg.png\" alt=\"\" class=\"wp-image-12866\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/localstorage-jpg.png 800w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/localstorage-jpg-300x241.png 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/localstorage-jpg-768x616.png 768w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/localstorage-jpg-400x321.png 400w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<p>\u2714\ufe0f \ub85c\uadf8\uc544\uc6c3 \ud568\uc218 \/ Logout function<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>  async function handleLogout() {\n    await fetch('\/api\/auth\/logout', { method: 'POST', credentials: 'include' });\n    localStorage.removeItem('token');\n    localStorage.removeItem('username');\n    setCurrentUser('');\n    window.location.href = '\/auth\/login';\n  }<\/code><\/pre>\n\n\n\n<p>1)\/api\/auth\/logout\ub77c\uc6b0\ud2b8\ub97c \uc2e4\ud589\uc2dc\ucf1c\uc11c \ucfe0\ud0a4\uc640 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ud14c\uc774\ube14\uc5d0\uc11c \ub85c\uadf8\uc778\ud55c \uc815\ubcf4\ub97c \uc0ad\uc81c\ud569\ub2c8\ub2e4.<br>Execute the \/api\/auth\/logout route to remove login information from both the cookies and the database table.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>1.\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc0ad\uc81c \/ Delete from database\n- app\/api\/auth\/logout\/route.ts\ndeleteSessionByRefreshToken(refreshToken); \n\n- lib\/auth.ts\nexport function deleteSessionByRefreshToken(refreshToken: string) {\n  return db.prepare('DELETE FROM <strong>sessions<\/strong> WHERE refresh_token =?').run(refreshToken);\n}\n\n- app\/api\/auth\/logout\/route.ts\n db.prepare('DELETE FROM <strong>oauth_tokens<\/strong> WHERE access_token =?').run(decodeURIComponent(tokenMatch&#91;1]));\n\n2.\ud1a0\ud070 \ucd08\uae30\ud654 \/ Token Initialization\n- app\/api\/auth\/logout\/route.ts\n  res.cookies.set('token', '', { maxAge: 0, path: '\/' });\n  res.cookies.set('refresh_token', '', { maxAge: 0, path: '\/' });<\/code><\/pre>\n\n\n\n<p>A.sessions\ud14c\uc774\ube14\uc740 \ub85c\uceec UI\uc6a9\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0 oauth_tokens\ub294 \uc678\ubd80\uc571 \uc6a9\uc73c\ub85c \uc0ac\uc6a9\ub429\ub2c8\ub2e4.<br>The <code>sessions<\/code> table is used for the local UI, while <code>oauth_tokens<\/code> is used for external apps.<\/p>\n\n\n\n<p>2)fetch\uac00 \ub05d\ub098\uba74 \ub85c\uceec\uc2a4\ud1a0\ub9ac\uc9c0\uc5d0\uc11c username\uc744 \uc0ad\uc81c\ud558\uace0 currentUser\ubcc0\uc218\ub97c \ucd08\uae30\ud654 \ud569\ub2c8\ub2e4.<br>Once the fetch operation is complete, remove the username from local storage and reset the currentUser variable.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>    localStorage.removeItem('token');\n    localStorage.removeItem('username');\n    setCurrentUser('');<\/code><\/pre>\n\n\n\n<p>3)\ub85c\uadf8\uc544\uc6c3\uc774 \uc644\ub8cc\ub418\uba74 \/auth\/login(https:\/\/aloy-horizon.duckdns.org\/auth\/login) \ub77c\uc6b0\ud2b8\ub97c \uc2e4\ud589 \uc2dc\ucf1c\uc11c \ub85c\uadf8\uc778\uc815\ubcf4 \uc785\ub825\ud3fc UI\ub97c \ubcf4\uc5ec\uc90d\ub2c8\ub2e4.<br>Once logout is complete, the \/auth\/login (https:\/\/aloy-horizon.duckdns.org\/auth\/login) route is triggered to display the login form UI.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>{currentUser ? (\n... ...\n) : (\n        &lt;&gt;\n          {next &amp;&amp; next !== '\/' &amp;&amp; (\n            &lt;p style={{ background: '#f5f5ff', padding: 10, borderRadius: 5, fontSize: 13 }}&gt;\n              \ub85c\uadf8\uc778 \ud6c4 &lt;code&gt;{next.substring(0, 60)}...&lt;\/code&gt;\ub85c \uc774\ub3d9!\n            &lt;\/p&gt;\n          )}\n          &lt;form onSubmit={handleLogin} style={{ display: 'flex', flexDirection: 'column', gap: 12, marginTop: 20 }}&gt;\n            &lt;input placeholder=\"email or username\" value={loginId} onChange={e =&gt; setLoginId(e.target.value)} style={{ padding: 10, fontSize: 16 }} required \/&gt;\n            &lt;input type=\"password\" placeholder=\"password\" value={password} onChange={e =&gt; setPassword(e.target.value)} style={{ padding: 10, fontSize: 16 }} required \/&gt;\n            {error &amp;&amp; &lt;p style={{ color: 'red' }}&gt;{error}&lt;\/p&gt;}\n            &lt;button type=\"submit\" style={{ padding: 12, fontSize: 16, background: '#6364ff', color: 'white', border: 0, borderRadius: 8 }}&gt;\n              \ub85c\uadf8\uc778 \/ Login\n            &lt;\/button&gt;\n          &lt;\/form&gt;\n          &lt;p style={{ marginTop: 20 }}&gt;&lt;a href=\"\/auth\/signup\"&gt;\ud68c\uc6d0\uac00\uc785\/Signup&lt;\/a&gt;&lt;\/p&gt;\n        &lt;\/&gt;\n      )}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"762\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/logout-jpg.jpg\" alt=\"\" class=\"wp-image-12861\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/logout-jpg.jpg 600w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/logout-jpg-236x300.jpg 236w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/10\/logout-jpg-400x508.jpg 400w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">Logout<\/figcaption><\/figure>\n\n\n\n<p>\u2714\ufe0f \ud398\uc774\uc9c0\uc774\ub3d9  \/ Navigate to page<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>... ...\nconst next = searchParams.get('next') || '\/';\n... ... \n     if (next &amp;&amp; next !== '\/') {\n        if (next.startsWith('http')) {\n          window.location.href = next;\n        } else {\n          window.location.href = next;\n        }\n      } else {\n        \/\/ \u2705 myapp61+ \n        \/\/ \uc9c0\uae08\uc740 proxy.ts\uc5d0 next\uc124\uc815\uc774 \uc5c5\uc5b4\uc11c \ubb34\uc870\uac74 '\/'\ub77c\uc6b0\ud2b8 \uc2e4\ud589\ub428\n        \/\/ Currently, there is no 'next' configuration in proxy.ts, so the '\/' route is always executed.\n        window.location.href = '\/';\n      }<\/code><\/pre>\n\n\n\n<p>1)\uc9c0\uae08\uc740 proxy.ts\ubd80\ubd84\uc5d0 next\uc124\uc815\uc774 \uc5c6\uc5b4\uc11c \ub85c\uadf8\uc778 \uc644\ub8cc\ud6c4 \ubb34\uc870\uac74 &#8216;\/&#8217;\ub77c\uc6b0\ud2b8\uac00 \uc2e4\ud589\ub429\ub2c8\ub2e4. <br>Currently, there is no <code>next<\/code> configuration in <code>proxy.ts<\/code>, so the <code>\/<\/code> route is always executed after a successful login.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\ub9c8\ud0dc\ubcf5\uc74c 21\uc7a5 22\uc808 \/ Matthew 21: 22<\/p>\n\n\n\n<p>&#8220;\ub108\ud76c\uac00 \uae30\ub3c4\ud560 \ub54c\uc5d0 \ubb34\uc5c7\uc774\ub4e0\uc9c0 \ubbff\uace0 \uad6c\ud558\ub294 \uac83\uc740 \ub2e4 \ubc1b\uc73c\ub9ac\ub77c \ud558\uc2dc\ub2c8\ub77c&#8221;<\/p>\n\n\n\n<p>&#8220;And everything you ask in prayer, believing, you will receive.&#8221;<\/p>\n<\/blockquote>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb \uc774 \ubd80\ubd84\uc5d0\uc11c\ub294 \uc6f9\uc0ac\uc774\ud2b8 \ub85c\uadf8\uc778 \ubd80\ubd84\uc758 \uad6c\uc870\ub97c \uc0b4\ud3b4\ubd05\ub2c8\ub2e4.In this section, we examine the structure of the website&#8217;s login area. \ud83d\udc49\ud83c\udffb \uc774\ubc88 \ud30c\ud2b8\uc5d0\uc11c\ub294 \uc6f9\uc0ac\uc774\ud2b8 \ubd80\ubd84\uc758 \ub85c\uadf8\uc778 \uad6c\uc870\ub9cc \uc0b4\ud3b4\ubcf4\uace0 \uc678\ubd80\uc571 \ubd80\ubd84\uc758 \ub85c\uadf8\uc778\uc740 \ub2e4\uc74c \ud3ec\uc2a4\ud2b8\uc5d0\uc11c \uc0b4\ud3b4\ubd05\ub2c8\ub2e4.In this part, we will look only at the login structure for the website; the login process for external apps will be covered [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":12863,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,27,1,7],"tags":[],"class_list":["post-12813","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","category-nextjs","category-uncategorized","category-website","has-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12813","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=12813"}],"version-history":[{"count":50,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12813\/revisions"}],"predecessor-version":[{"id":12870,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12813\/revisions\/12870"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media\/12863"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=12813"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=12813"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=12813"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}