{"id":9386,"date":"2026-09-03T10:29:23","date_gmt":"2026-09-03T01:29:23","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=9386"},"modified":"2026-09-04T12:54:19","modified_gmt":"2026-09-04T03:54:19","slug":"nextjs-sns-server-31","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/09\/03\/nextjs-sns-server-31\/","title":{"rendered":"[nextjs]SNS Server-21(myapp31)\u00a0"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \ud68c\uc6d0\uac00\uc785 \ubc0f \ub85c\uadf8\uc778 \uae30\ub2a5\uc744 \uc2dc\uc791\ud569\ub2c8\ub2e4.<br>We are launching the sign-up and login functions.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb publick key \uac80\uc99d\ub85c\uc9c1\uc744 \ucd94\uac00\ud588\uc2b5\ub2c8\ub2e4.(\uae30\uc874\uc740 \uac80\uc99d \uc5c6\uc774 \ud328\uc2a4)<br>Added public key verification logic (previously, it proceeded without verification).<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb User\ud14c\uc774\ube14 \uad6c\uc870\ub97c \ubcc0\uacbd \ud588\uc2b5\ub2c8\ub2e4.<br>The User table structure has been modified.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc804\uccb4 \ucf54\ub4dc\ub294 \uae43\ud5c8\ube0c\uc5d0\uc11c \ud655\uc778 \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<br>You can find the full code on GitHub.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/gideonslife01\/flm-nextjs\">https:\/\/github.com\/gideonslife01\/flm-nextjs<\/a><\/p>\n\n\n\n<p>\ud83d\udcc1 \uc804\uccb4 \ud504\ub85c\uc81d\ud2b8 \uad6c\uc870 \/ Overall Project Structure<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myapp project\/  \n\u251c\u2500\u2500 app\/  (Next.js App Router)\n\u2502   \u251c\u2500\u2500 .well-known\/webfinger\/route.ts  -&gt; webfinger\n\u2502   \u251c\u2500\u2500 api\/follow\/route.ts    -&gt; Follow API(temporary)\n\u2502   \u251c\u2500\u2500 api\/announce\/route.ts  -&gt; Boost(Announcement)\n\u2502   \u251c\u2500\u2500 api\/like\/route.ts.     -&gt; Like API\n\u2502   \u251c\u2500\u2500 api\/posts\/route.ts     -&gt; Writing API\n\u2502   \u251c\u2500\u2500 api\/timeline\/route.ts  -&gt; Timeline API\n\u2502   \u251c\u2500\u2500 users\/&#91;username]\/\n\u2502   \u2502   \u251c\u2500\u2500 statuses\/&#91;id]\/route.ts -&gt; Indivisual Post\n\u2502   \u2502   \u251c\u2500\u2500 route.ts               -&gt; Acotr Information\n\u2502   \u2502   \u251c\u2500\u2500 followers\/route.ts     -&gt; Followers List\n\u2502   \u2502   \u251c\u2500\u2500 following\/route.ts     -&gt; Following List\n\u2502   \u2502   \u251c\u2500\u2500 inbox\/route.ts         -&gt; Inbox\n\u2502   \u2502   \u2514\u2500\u2500 outbox\/route.ts        -&gt; outbox\n\u2502   \u251c\u2500\u2500 usersui\/&#91;username]\/\n\u2502   \u2502   \u251c\u2500\u2500 page.tsx               -&gt; Timeline UI\n\u2502   \u2502   \u2514\u2500\u2500 _components\/themes\/\n\u2502   \u2502       \u251c\u2500\u2500 themeex\/ThemeexTheme.tsx   -&gt; Example Theme\n\u2502   \u2502       \u251c\u2500\u2500 pinafore\/PinaforeTheme.tsx -&gt; Theme 1\n\u2502   \u2502       \u251c\u2500\u2500 mastodon\/MastodonTheme.tsx -&gt; Theme 2\n\u2502   \u2502       \u2514\u2500\u2500 minimal\/MinimaltTheme.tsx  -&gt; Theme 3\n\u2502   \u251c\u2500\u2500 layout.tsx, page.tsx, globals.css\n\u2502   \u2514\u2500\u2500 favicon.ico\n\u251c\u2500\u2500 lib\/\n\u2502   \u251c\u2500\u2500 theme.tsx              -&gt; Theme Provider\n\u2502   \u251c\u2500\u2500<strong> <\/strong>watchThemes.ts         -&gt; Check real-time theme changes\n\u2502   \u251c\u2500\u2500<strong> auth.ts                -&gt; Authentication, User Management<\/strong>\n\u2502   \u251c\u2500\u2500 <strong>ap.ts                  -&gt; Follow,Undo,Create,Likes,Announce<\/strong>\n\u2502   \u2514\u2500\u2500 <strong>db.ts                  -&gt; DB connection<\/strong>\n\u251c\u2500\u2500 data\/\n\u2502   \u251c\u2500\u2500 <strong>keys\/userIDs\/          -&gt; private.pem, public.pem(New)<\/strong>\n\u2502   \u2514\u2500\u2500 keys\/                  -&gt; private.pem, public.pem(legacy)\n\u251c\u2500\u2500 data.sqlite                -&gt; Database(1\/3)\n\u251c\u2500\u2500 data.sqlite-wal            -&gt; Database(2\/3)\n\u251c\u2500\u2500 data.sqlite-shm            -&gt; Database(3\/3)\n\u251c\u2500\u2500 Caddyfile                  -&gt; https \n\u251c\u2500\u2500 instrumentation.ts         -&gt; Background Server\n\u2514\u2500\u2500 package.json<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ud504\ub85c\uc81d\ud2b8 \uc2dc\uc791<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-freelifemakers-org wp-block-embed-freelifemakers-org\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"kmeZdQfEq2\"><a href=\"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/09\/03\/nextjs-project-summary\/\">[nextjs]\ud504\ub85c\uc81d\ud2b8\uc694\uc57d\/project summary(myapp30+)<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; visibility: hidden;\" title=\"&#8220;[nextjs]\ud504\ub85c\uc81d\ud2b8\uc694\uc57d\/project summary(myapp30+)&#8221; &#8212; freelifemakers.org\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/09\/03\/nextjs-project-summary\/embed\/#?secret=tPWQ3hlj6D#?secret=kmeZdQfEq2\" data-secret=\"kmeZdQfEq2\" width=\"560\" height=\"315\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>\ud83d\udcc1 \ubaa8\ub4c8 \uc124\uce58 \/ Module install<\/p>\n\n\n\n<p>&#8212; \ube44\ubc00\ubc88\ud638 \uc554\ud638\ud654 \/ Password encryption<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install bcrypt jsonwebtoken\nnpm install -D @types\/bcrypt @types\/jsonwebtoken<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 DB \ub9c8\uc774\uadf8\ub808\uc774\uc158 \/ DB Migration<\/p>\n\n\n\n<p>\u2714\ufe0f \uae30\uc874 Users\ud14c\uc774\ube14\uc5d0\uc11c User1\uc744 \uc720\uc9c0\ud558\uace0 \uc815\ubcf4\ub97c \uc5c5\ub370\uc774\ud2b8\ud569\ub2c8\ub2e4.<br>Retain User1 in the existing Users table and update its information.<\/p>\n\n\n\n<p>\u2714\ufe0f Users \ud14c\uc774\ube14 \/ User Table<\/p>\n\n\n\n<p>&#8212; email,password_hash,email_verified,vaerification_token \ud544\ub4dc\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4.<br>Add the email, password_hash, email_verified, and verification_token fields.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE users (\n  username TEXT PRIMARY KEY,\n  display_name TEXT DEFAULT '',\n  summary TEXT DEFAULT '',\n  private_key TEXT,\n  public_key TEXT,\n<strong>  email TEXT UNIQUE,\n  password_hash TEXT,\n  email_verified INTEGER DEFAULT 0,\n  verification_token TEXT,<\/strong>\n  created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n);<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f SQLITE<\/p>\n\n\n\n<p>&#8212; ALTER\uba85\ub839\uc5b4\ub85c\ub294 UNIQUE\ub97c \ucd94\uac00\ud560 \uc218 \uc5c6\uc5b4\uc11c \ud14c\uc774\ube14\uc744 \uc0c8\ub85c\ub9cc\ub4ed\ub2c8\ub2e4.<br>Since a UNIQUE constraint cannot be added using the ALTER command, I am creating a new table.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># - \ud14c\uc774\ube14 \uc2e0\uaddc \uc0dd\uc131 \/ Create New Table -\n \nsqlite3 data.sqlite\n\n# - \uae30\uc874 \ud14c\uc774\ube14 \uc0ad\uc81c(UNIQUE\ub294 ALTER\ub85c \uc785\ub825 \ubd88\uac00\ub2a5) -\n# Delete existing table (UNIQUE constraint cannot be added via ALTER)\nDROP TABLE IF EXISTS users;\n\n# - \ud14c\uc774\ube14 \uc0dd\uc131 \/ Create Table --\n\nCREATE TABLE users (\n  username TEXT PRIMARY KEY,\n  display_name TEXT DEFAULT '',\n  summary TEXT DEFAULT '',\n  private_key TEXT,\n  public_key TEXT,\n  email TEXT UNIQUE,\n  password_hash TEXT,\n  email_verified INTEGER DEFAULT 0,\n  verification_token TEXT,\n  created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n);\n\n# - \uc0ac\uc6a9\uc790 \uc785\ub825(\ud328\uc2a4\uc6cc\ub4dc 1111) --\n# User input (password 1111\n\nINSERT INTO users (username, display_name, summary, email, password_hash, email_verified)\nVALUES ('user1','user1','My Fediverse account on aloy-horizon','freelifemakers@gmail.com','$2b$10$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW',1);\n\nSELECT * FROM users;\n<\/code><\/pre>\n\n\n\n<p>&#8212; Private ,Public \ud0a4 \uc0dd\uc131 \ubc0f DB\uc5c5\ub370\uc774\ud2b8(\ub610\ub294 \uae30\uc874 \ud0a4 \ud65c\uc6a9)<br>Generate private and public keys and update the database (or utilize existing keys)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud0a4 \uc0dd\uc131 \/ Key Generation\ncd ~\/myapp31\nnode -e \"\nconst crypto = require('crypto');\nconst fs = require('fs');\nconst { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {\n  modulusLength: 2048,\n  publicKeyEncoding: {type: 'spki', format: 'pem'},\n  privateKeyEncoding: {type: 'pkcs8', format: 'pem'}\n});\nfs.writeFileSync('pri.pem', privateKey);\nfs.writeFileSync('pub.pem', publicKey);\nconsole.log('\uc0dd\uc131\ub428!');\nconsole.log('private length:', privateKey.length);\nconsole.log('public length:', publicKey.length);\n\"\n\n# cat \uba85\ub839\uc5b4\ub85c \ud0a4 \ud655\uc778\ud6c4 DB\uc5d0 \uc5c5\ub370\uc774\ud2b8 \ud558\uae30\nCheck the key using the `cat` command and update the database.\n\n# DB Update \/ DB Update\nUPDATE users SET \n  private_key = '-----BEGIN PRIVATE KEY-----',\n  public_key = '-----BEGIN PUBLIC KEY-----'\nWHERE username = 'user1';\n\nSELECT username, length(private_key) as pri_len, length(public_key) as pub_len FROM users;<\/code><\/pre>\n\n\n\n<p>&#8212; \uc0ac\uc6a9\uc790 \ub514\ub809\ud1a0\ub9ac \ub9cc\ub4e4\uace0 \ud0a4 \ud30c\uc77c \ubcf5\uc0ac(db.ts\ub85c\uc9c1\uc774\ub791 \ub9de\ucd94\uae30 \uc704\ud574\uc11c)<br>Create the user directory and copy the key file (to align with the db.ts logic).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \uae30\uc874\ud30c\uc77c\uc720\uc9c0\n# Keep existing files\n# \/myapp31\/data\/keys\/\n\nuser1 % ls\nprivate.pem     public.pem\n\n# \uc2e0\uaddc\ud30c\uc77c\n# New File\n#\/myapp31\/data\/keys\/user1\n\nuser1 % ls\nprivate.pem     public.pem<\/code><\/pre>\n\n\n\n<p>1) \ud68c\uc6d0\uac00\uc785\uc2dc \ud0a4\ub294 data\/keys\/userid\/private_key.pem or public_key.pem \uc73c\ub85c \uc800\uc7a5 \ub428. <\/p>\n\n\n\n<p>\ud83d\udcc1 \ucf54\ub4dc\ucd94\uac00 \/ Add code<\/p>\n\n\n\n<p>\u2714\ufe0f \ud68c\uc6d0\uac00\uc785\ucc98\ub9ac\ub098 \ub85c\uadf8\uc778\uad00\ub828 \ud568\uc218\uc785\ub2c8\ub2e4.<br>These are functions related to user registration and login processing.<\/p>\n\n\n\n<p>&#8212; lib\/auth.ts<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>... ...\nexport async function hashPassword(password: string) {\n  ... ...\n}\n\nexport async function verifyPassword(password: string, hash: string) {\n  ... ...\n}\n\nexport function createToken(username: string) {\n  ... ...\n}\n\nexport function verifyToken(token: string) {\n... ...\n}\n\nexport function getUser(username: string) {\n  ... ...\n}\n\nexport function getUserByEmail(email: string) {\n ... ...\n}\n\n\/\/  \u2705 myapp31 - \uc2e0\uaddc \uc720\uc800 \uc0dd\uc131 (\ud0a4\ub3c4 \uac19\uc774 \uc0dd\uc131!) \/ Create a new user (with keys!)\nexport function createUser(username: string, email: string, passwordHash: string, displayName: string = '') {\n... ...\n\n}\n\n\/\/  \u2705 myapp31 -\uae30\uc874 DB -&gt; \ud30c\uc77c\ub85c \ub9c8\uc774\uadf8\ub808\uc774\uc158! \/ Migrate existing DB keys to files!\nexport function migrateKeysToFiles() {\n  ... ...\n}\n... ...<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ucf54\ub4dc \uc218\uc815 \/ Code Modification<\/p>\n\n\n\n<p>\u2714\ufe0f lib\/db.ts<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ lib\/db.ts\n\/\/ keys \ud3f4\ub354 \uc0dd\uc131! \/ Create keys folder!\nconst keysDir = path.join(process.cwd(), 'data\/keys');\nif (!fs.existsSync(keysDir)) {\n  fs.mkdirSync(keysDir, { recursive: true });\n  console.log('\u2705 keys \ud3f4\ub354 \uc0dd\uc131\/ keys folder created:', keysDir);\n}\n\n... ...\n\ndb.exec(`\nCREATE TABLE IF NOT EXISTS users (\n  username TEXT PRIMARY KEY,\n  display_name TEXT DEFAULT '',\n  summary TEXT DEFAULT '',\n  private_key TEXT,\n  public_key TEXT,\n  email TEXT UNIQUE,\n  password_hash TEXT,\n  email_verified INTEGER DEFAULT 0,\n  verification_token TEXT,\n  created_at DATETIME DEFAULT CURRENT_TIMESTAMP);\n`);<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f publick key \uac80\uc99d\ub85c\uc9c1 \ubd80\ubd84 \uc218\uc815<br>Modified the public key verification logic.<\/p>\n\n\n\n<p>&#8212; lib\/ap.ts<\/p>\n\n\n\n<p>1) Publick Key \uac80\uc99d\ub85c\uc9c1 \ucd94\uac00<br>Added public key verification logic.<\/p>\n\n\n\n<p>2)getPublicKey, verifyHttpSignature, fetchActorPublicKey \ud568\uc218 \ucd94\uac00<br>Added getPublicKey, verifyHttpSignature, and fetchActorPublicKey functions.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nfunction getPublicKey(username: string): string {\n  ... ...\n}\n\n... ... \n\nexport async function verifyHttpSignature(\n  req: Request,\n  publicKeyPem: string\n): Promise&lt;boolean&gt; { ... ...}\n\nexport async function fetchActorPublicKey(actorUrl: string): Promise&lt;string&gt; { ... ...\n}<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ub0b4 \uc11c\ubc84\ub85c \ud314\ub85c\uc6b0 \uc694\uccad\uc2dc Public Key\ub85c \uac80\uc99d<br>Verify using the public key when a follow request is sent to my server.<\/p>\n\n\n\n<p>&#8212; <code>app\/api\/inbox\/route.ts<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export async function POST(req: Request, { params }: { params: Promise&lt;{ username: string }&gt; }) {\n\n  const { username } = await params;\n  let body: any;\n  let rawBody = '';  \n\n<strong>  try {\n    \/\/ rawBody\ub97c \uba3c\uc800 \uc77d\uae30 \/ Read rawBody first\n     rawBody = await req.text(); \n    try {\n      body = JSON.parse(rawBody);\n    } catch {\n      console.log('\u26a0\ufe0f JSON \ud30c\uc2f1 \uc2e4\ud328! \ube48 \ubc14\ub514? \/ Failed to parse JSON! Empty body?', rawBody.slice(0,200));\n      return new Response('', { status: 202 });\n    }\n\n   \/\/ const body = await req.json();\n    console.log(`\ud83d\udce9 &#91;${username}] INBOX:`, body.type, body.actor, body.id);\n\n   ... ...\n\n   } <\/strong>\n... ...\n}<\/code><\/pre>\n\n\n\n<p>1) \ud314\ub85c\uc6b0,\uc5b8\ud314\ub85c\uc6b0,\uae00 \ubc1b\uae30,\uc88b\uc544\uc694,\ubd80\uc2a4\ud2b8 \ubaa8\ub450 publick key\ub85c \uac80\uc99d<br>Follow, undo, receive posts, like, and boost(announce) actions are all verified using public keys.<\/p>\n\n\n\n<p>\ud83d\udcc1 \ud14c\uc2a4\ud2b8 \/ Test<\/p>\n\n\n\n<p>\u2714\ufe0f \ub9c8\uc2a4\ud1a0\ub3c8 \uc11c\ubc84\uc5d0\uc11c aloy-horizon-duckdns.org\ub97c \uc5b8\ud314\ub85c\uc6b0\ud558\uace0 \ub2e4\uc2dc \ud314\ub85c\uc6b0 \ud558\uae30<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"437\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-unfollow-jpg.jpg\" alt=\"\" class=\"wp-image-9538\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-unfollow-jpg.jpg 800w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-unfollow-jpg-300x164.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-unfollow-jpg-768x420.jpg 768w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-unfollow-jpg-400x219.jpg 400w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Mastodon<\/figcaption><\/figure>\n\n\n\n<p>\u2714\ufe0f \ud0a4 \uac80\uc99d \ub85c\uadf8 \ud655\uc778\ud558\uae30 \/ Checking Key Verification Logs<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"372\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-serverlog-jpg.jpg\" alt=\"\" class=\"wp-image-9541\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-serverlog-jpg.jpg 800w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-serverlog-jpg-300x140.jpg 300w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-serverlog-jpg-768x357.jpg 768w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2026\/09\/myapp31-serverlog-jpg-400x186.jpg 400w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Server Log<\/figcaption><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\uc694\ud55c\ubcf5\uc74c 8\uc7a5 32\uc808 \/ John 8:32<\/p>\n\n\n\n<p>&#8220;\uadf8\ub9ac\uace0 \ub108\ud76c\ub294 \uc9c4\ub9ac\ub97c \uc54c\uac8c \ub420 \uac83\uc774\uba70, \uc9c4\ub9ac\uac00 \ub108\ud76c\ub97c \uc790\uc720\ub86d\uac8c \ud560 \uac83\uc774\ub2e4.&#8221;<\/p>\n\n\n\n<p>&#8220;Then you will know the truth ,and the truth will set you free&#8221;<\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb \ud68c\uc6d0\uac00\uc785 \ubc0f \ub85c\uadf8\uc778 \uae30\ub2a5\uc744 \uc2dc\uc791\ud569\ub2c8\ub2e4.We are launching the sign-up and login functions. \ud83d\udc49\ud83c\udffb publick key \uac80\uc99d\ub85c\uc9c1\uc744 \ucd94\uac00\ud588\uc2b5\ub2c8\ub2e4.(\uae30\uc874\uc740 \uac80\uc99d \uc5c6\uc774 \ud328\uc2a4)Added public key verification logic (previously, it proceeded without verification). \ud83d\udc49\ud83c\udffb User\ud14c\uc774\ube14 \uad6c\uc870\ub97c \ubcc0\uacbd \ud588\uc2b5\ub2c8\ub2e4.The User table structure has been modified. \ud83d\udc49\ud83c\udffb \uc804\uccb4 \ucf54\ub4dc\ub294 \uae43\ud5c8\ube0c\uc5d0\uc11c \ud655\uc778 \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.You can find the full code on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":9538,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,27,1,7],"tags":[],"class_list":["post-9386","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\/9386","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=9386"}],"version-history":[{"count":107,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/9386\/revisions"}],"predecessor-version":[{"id":9544,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/9386\/revisions\/9544"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media\/9538"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=9386"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=9386"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=9386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}