{"id":12227,"date":"2026-10-14T09:16:31","date_gmt":"2026-10-14T00:16:31","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=12227"},"modified":"2026-10-14T18:01:20","modified_gmt":"2026-10-14T09:01:20","slug":"nextjs-sns-server-51-4","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/10\/14\/nextjs-sns-server-51-4\/","title":{"rendered":"[nextjs]SNS Server-51(myapp61+)[Pagination+API]\u00a0"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \uc5ec\uae30\uc11c\ub294 \ud398\uc774\uc9c0\ub124\uc774\uc158\uc744 \uad6c\ud604\ud560\ub54c \ud638\ucd9c\ub418\ub294 API\uc640 \ud568\uaed8 \ud398\uc774\uc9c0\ub124\uc774\uc158 \uad6c\uc870\ub97c \uc0b4\ud3b4 \ubd05\ub2c8\ub2e4.<br>Here, we examine the pagination structure along with the API called when implementing pagination.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc774\uc804 \ud3ec\uc2a4\ud2b8\uc5d0\uc11c ClientList.tsx\uc5d0\uc11c TimelineList.tsx\ub85c \ucd08\uae30\ub370\uc774\ud130\ub97c \uc804\ub2ec\ud558\uba74 \uc774 \ub370\uc774\ud130\uac00 useCursonPagination\ud6c5\uc5d0 \ub4e4\uc5b4\uac14\ub2e4\uac00 \ub098\uc635\ub2c8\ub2e4.<br>As mentioned in the previous post, when initial data is passed from <code>ClientList.tsx<\/code> to <code>TimelineList.tsx<\/code>, it is processed by the <code>useCursorPagination<\/code> hook.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb TimlineList.tsx\ub97c \ud1b5\ud574 \ud6c5\ub0b4\ubd80\uc5d0 \uc804\ub2ec\ud55c \ucf5c\ubc31\ud568\uc218\uc778 fetcher\uac00 \ud6c5 \ub0b4\ubd80\uc5d0\uc11c \uc2e4\ud589\ub418\uace0 API\uc640 \ud1b5\uc2e0\ud558\uace0 \ub370\uc774\ud130\ub97c \ubc1b\uc544\uc640\uc11c \uae30\uc874 \ub370\uc774\ud130 \ub4a4\uc5d0 \ubd99\uc5ec\uc90d\ub2c8\ub2e4.<br>The <code>fetcher<\/code> callback function, passed into the hook via <code>TimelineList.tsx<\/code>, executes within the hook, communicates with the API, retrieves data, and appends it to the existing data.<\/p>\n\n\n\n<p>\ud83d\udcc1 \ucf5c\ubc31\ud568\uc218 fetcher\uc640 API \ud1b5\uc2e0 \/ API communication using the <code>fetcher<\/code> callback function<\/p>\n\n\n\n<p>\u2714\ufe0f app\/api\/v1\/timelines\/[type]\/route.ts<\/p>\n\n\n\n<p>\u2714\ufe0f API\uc640 \ud1b5\uc2e0\ud560\ub54c \uc0ac\uc6a9\ub418\ub294 URL \ud615\uc2dd  \/ URL format used when communicating with an API<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>GET \/api\/v1\/timelines\/home?limit=20&amp;max_id=59d38066-6cc2-4c2b-b06e-710f7293fda6\nGET \/api\/v1\/timelines\/home?limit=20&amp;max_id=41b5b137-d56c-4e36-a995-3dbed5ef061c\nGET \/api\/v1\/timelines\/home?limit=20&amp;max_id=a864ab3b-a090-4575-a7b1-0bf5c075f73b<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f TimelineList.tsx\uc758 fetcher\ucf5c\ubc31\ud568\uc218\ub294 \uc544\ub798\uc544 \uac19\uc774 API\uc640 \ud1b5\uc2e0\uc744 \ud569\ub2c8\ub2e4.<br>The <code>fetcher<\/code> callback function in <code>TimelineList.tsx<\/code> communicates with the API as follows.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>      if (tab === 'home') {\n        if (effectiveUser) {\n          url = `\/api\/v1\/timelines\/<strong>home<\/strong>?${params.toString()}`;\n        } else {\n          params.set('local', 'true');\n          url = `\/api\/v1\/timelines\/<strong>public<\/strong>?${params.toString()}`;\n        }\n      } else if (tab === 'local') {\n        params.set('local', 'true');\n        url = `\/api\/v1\/timelines\/public?${params.toString()}`;\n      } else {\n        url = `\/api\/v1\/timelines\/public?${params.toString()}`;\n      }<\/code><\/pre>\n\n\n\n<p>1)\uc774 params.toString()\uc774 &#8216;limit=20&amp;max_id=a864ab3b-a&#8230;&#8217; \uc774 \ubd80\ubd84\uc785\ub2c8\ub2e4.<br>This <code>params.toString()<\/code> corresponds to the part that looks like <code>'limit=20&amp;max_id=a864ab3b-a...'<\/code>.<\/p>\n\n\n\n<p>\u2714\ufe0f API\ub0b4\ubd80\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \uacfc\uc815\uc73c\ub85c \uc804\ub2ec \ubc1b\uc740 \ud30c\ub77c\uba54\ud130\ub97c \ucc98\ub9ac\ud569\ub2c8\ub2e4.<br>The API processes the received parameters internally through the following steps.<\/p>\n\n\n\n<p>1)\ub370\uc774\ud130 \uac80\uc0c9 \/ Data Retrieval<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>  let filteredRows: any&#91;] = &#91;];\n\n  if (type === 'home') {\n    \/\/ \u2705 myapp61+ - LIMIT 200 \ucd94\uac00 \/ Add LIMIT 200\n    const myPosts = db.prepare(`SELECT * FROM posts WHERE username =? LIMIT 200`).all(viewer) as any&#91;];\n    const inboxPosts = db.prepare(`SELECT * FROM inbox_posts WHERE username =? LIMIT 200`).all(viewer) as any&#91;];as any&#91;];\n... ...\n  } else if (type === 'public') {\n... ...\n  } else { ... ...}<\/code><\/pre>\n\n\n\n<p>A. \uac01 \ud0ed\uc5d0 \ub530\ub77c\uc11c \ud544\uc694\ud55c \ub370\uc774\ud130\ub97c \uac80\uc0c9\ud569\ub2c8\ub2e4<br>Search for the necessary data based on each tab.<\/p>\n\n\n\n<p>B. API\uc5d0\uc11c \ud0ed\uc740 URL\uc5d0\uc11c &#8230; timelines\/public.. ,&#8230;timeline\/home&#8230;\uc5d0\uc11c public,home \ubd80\ubd84\uc785\ub2c8\ub2e4.<br>In the API, the &#8220;tabs&#8221; refer to the <code>public<\/code> and <code>home<\/code> segments found in URL paths like <code>...\/timelines\/public...<\/code> and <code>...\/timeline\/home...<\/code>.<\/p>\n\n\n\n<p>2)max_id,limit<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>  if (<strong>max_id<\/strong>) {\n    \/\/ \ud604\uc7ac\ub294 \ud0c0\uc784\uc2a4\ud0ec\ud504\uac00 \uc544\ub2cc UUID\ub4e4\uc5b4\uac00\ub294 \uad6c\uc870\ub77c maxTime\uc740 \ud56d\uc0c1 0.\n    \/\/ Currently, since the structure uses a UUID instead of a timestamp, maxTime is always 0.\n    let maxTime = parseDate(max_id);\n    \n    \/\/ max_id\uac00 UUID\uc778 \uacbd\uc6b0 created_at\uac80\uc0c9 \/ Search created_at when max_id is a UUID\n    if (maxTime === 0) {\n      const refRow = filteredRows.find((r: any) => String(r.id) === String(max_id));\n      if (refRow) {\n        \/\/ maxTime\uc5d0 \ub0a0\uc9dc \uac12 \uc800\uc7a5 \uc774\uc81c 0\uc774 \uc544\ub2d8 \/ Storing the date value in maxTime; it is no longer zero.\n        maxTime = parseDate(refRow.created_at);\n      } else {\n        \/\/ filteredRows\uc5d0 \uc5c6\uc73c\uba74 DB\uc5d0\uc11c \uc9c1\uc811 \uc870\ud68c \/ If not found in filteredRows, query the database directly.\n        try {\n          const refDb = db.prepare(`SELECT created_at FROM posts WHERE id=?`).get(max_id) as any;\n          if (refDb) maxTime = parseDate(refDb.created_at);\n          else {\n            const refInbox = db.prepare(`SELECT created_at FROM inbox_posts WHERE id=?`).get(max_id) as any;\n            if (refInbox) maxTime = parseDate(refInbox.created_at);\n          }\n        } catch {}\n      }\n    }\n\n    \/\/ \uc774\uc804\uae00 \uac80\uc0c9\ub85c\uc9c1 \/ Previous Post Search Logic\n    \/\/ \uc804\ub2ec\ubc1b\uc740 max_id\uc640 \uc77c\uce58\ud558\ub294 \uae00\ubcf4\ub2e4 \uc774\uc804\uae00\uc744 \ubc30\uc5f4\uc5d0\uc11c \uac80\uc0c9 \/ Search the array for posts preceding the post matching the provided max_id.\n    if (maxTime > 0) {\n      filteredRows = filteredRows.filter((r) => parseDate(r.created_at) &lt; maxTime);\n    }\n  }\n\n  \/\/ \ud30c\ub77c\uba54\ud130\ub85c \uc804\ub2ec\ubc1b\uc740 limit=20\ub85c \ub370\uc774\ud130 20\uac1c\ub9cc \uc120\ud0dd \n  \/\/ Select only 20 items using the limit=20 parameter\n  const hasMore = filteredRows.length > <strong>limit<\/strong>;\n  const sliced = filteredRows.slice(0, <strong>limit<\/strong>);\n\n\n  const statuses = sliced.map((row: any) => { ... ... \n    return {  ... ...\n    });\n  }\n<\/code><\/pre>\n\n\n\n<p>A.max_id\uc640 \uac19\uc740 \uae00\uc758 created_at(\uae00 \uc791\uc131\ud55c \ub0a0\uc790)\ub97c \uac80\uc0c9\ud574\uc11c \uc774 created_at\ubcf4\ub2e4 \uc774\uc804 \ub370\uc774\ud130\ub9cc \ucd94\ucd9c\ud569\ub2c8\ub2e4.<br>Retrieve the <code>created_at<\/code> (post creation date) associated with the <code>max_id<\/code>, and extract only the data from before that timestamp.<\/p>\n\n\n\n<p>B. \ud398\uc774\uc9c0\ub124\uc774\uc158\uc774 \uc801\uc6a9\ub418\uae30 \uc804\uc5d0 \uccab \uac8c\uc2dc\ubb3c 20\uac1c\ub294 order by desc\ub85c \uac00\uc838\uc624\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc2e0\ub370\uc774\ud130\ubd80\ud130 \uc774\uc804\ub370\uc774\ud130 20\uac1c\ub97c \uac00\uc838\uc635\ub2c8\ub2e4.<br>Before pagination is applied, the first 20 posts are retrieved using <code>ORDER BY DESC<\/code>, so the 20 most recent items are fetched.<\/p>\n\n\n\n<p>C.\uc5ec\uae30\uc11c \ub9c8\uc9c0\ub9c9\uc5d0 \ubcf8 \uae00\uc758 \uc544\uc774\ub514\uac00 max_id\uac00 \ub418\uace0 \uc774 max_id\uc640 \uac19\uc740 \uae00\uc758 id\ud544\ub4dc\uc5d0 \uc788\ub294 crated_at(\uae00\uc774 \uc791\uc131\ub41c \ub0a0\uc9dc)\uc774\uc804\uc758 \ub370\uc774\ud130 20\uac1c\ub97c \uac00\uc838\uc640\uc11c \ub9ac\ud134\ud569\ub2c8\ub2e4.<br>Here, the ID of the last post viewed becomes the <code>max_id<\/code>; the system then retrieves and returns 20 records that precede the <code>created_at<\/code> timestamp associated with that <code>max_id<\/code>.<\/p>\n\n\n\n<p>\ud83d\udcc1 \ub370\uc774\ud130 \ucc98\ub9ac\uacfc\uc815 \uc694\uc57d \/ Summary of the Data Processing Workflow<\/p>\n\n\n\n<p>\u2714\ufe0f API\ubd80\ubd84\uc758 \ub370\uc774\ud130 \ucc98\ub9ac \uacfc\uc815\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4.<br>The data processing flow for the API component is as follows.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>1)\ucd5c\uc2e0\ub370\uc774\ud130 \uac80\uc0c9\nSearch for the latest data\n\n2)max_id\uac00 \uc788\uc73c\uba74 max_id\uac19\uc740 id\uac00 \uc788\ub294 \ud544\ub4dc\uc758 created_at\uc744 \uac80\uc0c9\nIf max_id exists, search for the created_at of fields with an ID matching max_id.\n\n3)limit\uc218\ub7c9(20\uac1c) \ub9cc\ud07c\ub9cc \ub370\uc774\ud130\ub97c \uc798\ub77c\uc11c \ub9ac\ud134 \nSlice the data up to the specified limit (20 items) and return it.<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\ud83d\udcc1\ubd80\uc2a4\ud2b8 \uce74\uc6b4\ud130(\ucf54\ub4dc\uc218\uc815) \/ Boost Counter (Code Modification)<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>  const allAnnounces = viewer ? (db.prepare(`SELECT * FROM announces WHERE username =?`).all(viewer) as any&#91;]) : &#91;];\n... ...\n\n  const announcesByObject = new Map&lt;string, number>();\n\n  for (const a of allAnnounces) {\n    \/* \n    announces \uac2f\uc218 \uc138\uae30\n    - &#91;fullurl,'\/' \uae30\uc900\uc73c\ub85c \uc804\uccb4 \ubd84\ub9ac\ud6c4 \ub9c8\uc9c0\ub9c9 \uc694\uc18c\ub9cc \uc120\ud0dd] => &#91;https:\/\/fllurl\/adc.abc]\n    - allAnnounces\uac00 10\uac1c\uba74 for\uac00 20\ubc88 \ub3cc\uac8c \ub418\uc5b4 \uc788\uc74c k\uac00 \ubb38\uc790\uc5f4\uc774\ub77c a.object1\ud68c,a.object.split\uac00 2\ud68c \uc774\ub807\uac8c for\uac00 \uc2e4\ud589\ub428.\n    *\/\n    for (const k of &#91;a.object, a.object.split('\/').pop() || '']) { if (k) announcesByObject.set(k, (announcesByObject.get(k) || 0) + 1); }\n  }<\/code><\/pre>\n\n\n\n<p>A.\uae30\ubcf8\uc801\uc73c\ub85c \uc804\uccb4 \ubd80\uc2a4\ud2b8(allAnnounces)\uc5d0\uc11c announcedByObject Map\uc5d0 fullURL\uacfc &#8216;\/&#8217;\uae30\uc900\uc73c\ub85c \ubd84\ub9ac\ub41c \ub9c8\uc9c0\ub9c9url\uac12(split(&#8216;\/&#8217;).pop())\uc744 \ubaa8\ub450 \uc800\uc7a5<br>Basically, for all boosts (<code>allAnnounces<\/code>), store both the <code>fullURL<\/code> and the last URL segment (obtained via <code>split('\/').pop()<\/code>) in the <code>announcedByObject<\/code> map.<\/p>\n\n\n\n<p>B. cont k of [a.object, a.object.split(&#8216;\/&#8217;).pop()]\uc740 k\uc5d0 \ubc30\uc5f4 \uac12\uc774 \ubb38\uc790\uc5f4\ub85c \uac01\uac01 \ub530\ub85c \ud560\ub2f9\ub418\uc5b4 \ub370\uc774\ud130\uac00 10\uac1c\uba74 for\uac00 20\ubc88 \uc2e4\ud589\ub418\uac8c \ub418\uc5b4 \uc788\uc74c.<br>In <code>cont k of [a.object, a.object.split('\/').pop()]<\/code>, the array values \u200b\u200bare assigned to <code>k<\/code> individually as strings; consequently, if there are 10 data items, the <code>for<\/code> loop executes 20 times.<\/p>\n\n\n\n<p>C.announcesByObject.set(k, (announcesByObject.get(k) || 0) + 1); } \uc5ec\uae30\uc11c URL\uacfc \uc22b\uc790\ub97c Map\uc5d0 \uc785\ub825\ud568<br>announcesByObject.set(k, (announcesByObject.get(k) || 0) + 1); } Here, the URL and the number are stored in the Map.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code># \uc804\uccb4 \ub370\uc774\ud130\uac00 \uc544\ub798\uc640 \uac19\ub2e4\uba74... \/ If the entire dataset is as follows...\nallAnnounces = &#91;\n  {object: \"https:\/\/server.com\/posts\/abc123\"},\n  {object: \"https:\/\/server.com\/posts\/abc123\"},\n  {object: \"abc123\"}\n]\n\n# \uccab\ub370\uc774\ud130 \uc608\uc2dc \/ Example of initial data\n1. a.object\n   = \"https:\/\/myserver.com\/posts\/abc123\" (\uc804\uccb4 URL \/ Full URL)\n\n2. a.object.split('\/').pop()\n   = \"https:\/\/server.com\/posts\/abc123\".split('\/')\n   = &#91;\"https:\", \"\", \"server.com\", \"posts\", \"abc123\"]\n   .pop() = \ub9c8\uc9c0\ub9c9 \uc694\uc18c\/Last element, ID only = \"abc123\" (id\ub9cc\/ID only)\n\n3.\uadf8\ub7ec\uba74 \uc544\ub798\uc640 \uac19\uc774 \ubc30\uc5f4\uc5d0 \uc800\uc7a5\ub428 \/ Then, it is stored in an array as shown below.\n&#91; a.object, a.object.split('\/').pop() || '' ]\n= &#91; \"https:\/\/myserver.com\/posts\/abc123\", \"abc123\" ]\n\n4.for \ubb38\uc774 \uc2e4\ud589\ub418\uba74\uc11c const k\ub294 \ubb38\uc790\uc5f4\uc774\uae30 \ub54c\ubb38\uc5d0 k = \"https:\/\/myserver.com\/posts\/abc123\" \uc774\ub807\uac8c \ud55c\ubc88\uc2e4\ud589\ud558\uace0 \ub450\ubc88\uc9f8\ub85c k = \"abc123\" \uc774\ub807\uac8c \ud560\ub2f9\ub418\uc5b4 \uc2e4\ud589\ub428\nAs the `for` loop executes, since `k` is a string, it first runs with `k = \"https:\/\/myserver.com\/posts\/abc123\"`, and then, in the second iteration, it runs with `k = \"abc123\"` assigned to it.\n\n5.announcesByObject.set(k, (announcesByObject.get(k) || 0) + 1); \n- \uc5ec\uae30\uc11c announcesByObject\ub9f5\uc5d0 k(\"https:\/\/myserver.com\/posts\/abc123\") \uac12\uc774 Map\uc5d0 \uc14b\ud305\ub428\nHere, the key \"https:\/\/myserver.com\/posts\/abc123\" is set in the `announcesByObject` map.\n\n- Map\uc758 \ub450\ubc88\uc9f8 \uc778\uc790\uac00 \uc22b\uc790\uc774\uace0 \uc9c0\uae08 \uc544\ubb34\uac83\ub3c4 \uc800\uc7a5\ud558\uc9c0 \uc54a\uc558\uc73c\ub2c8 announcesByObject.get(k) \uc774\uac74 \uae30\ubcf8\uac12\uc774 0\uc774\ub428\nSince the second argument of the Map is a number and nothing has been stored yet, `announcesByObject.get(k)` defaults to 0.\n\n- 0\uc5d0 + 1\ud558\uba74 \uac12\uc774 1 \uadf8\ub798\uc11c \ub9f5\uc5d0\ub294 &#91;\"https:\/\/myserver.com\/posts\/abc123\",1] \uc774\ub807\uac8c \uc800\uc7a5\ub428.\nAdding 1 to 0 results in a value of 1, so it is stored in the map like this: `&#91;\"https:\/\/myserver.com\/posts\/abc123\", 1]`.\n\n- \uadf8\ub9ac\uace0 \ub450\ubc88\uc9f8 \uc694\uc18c \"abc123\"\ub3c4 &#91;\"abc123\",1] \uc774\ub807\uac8c \uc800\uc7a5\ub428\nAnd the second element, \"abc123\", is also stored as `&#91;\"abc123\", 1]`.\n\n\n\n\n# \ub450\ubc88\uc9f8 \ub370\uc774\ud130 \uc608\uc2dc \/ Second data example\n1.\uccab\ub370\uc774\ud130 \uc608\uc2dc\uc758 1,2\ubc88\uc758 \uacfc\uc815\uc774 \ub3d9\uc77c\ud558\uac8c \uc2e4\ud589\ub428.\nSteps 1 and 2 from the first data example are executed in the same way.\n\n2.announcesByObject.set(k, (announcesByObject.get(k) || 0) + 1); \n- \uc5ec\uae30\uc11c \ub9f5\uc5d0 \uae30\uc874\uc5d0 \uc800\uc7a5\ud588\ub358 \ub3d9\uc77c\ud55c \ud0a4\uac00 \"https:\/\/myserver.com\/posts\/abc123\"\uc774\uac70\uace0 \uae30\uc874\uac12\uc740 1\nHere, the identical key previously saved in the map is \"https:\/\/myserver.com\/posts\/abc123\", and the existing value is 1.\n\n- \uadf8\ub798\uc11c \uae30\uc874\ud0a4\uc758 \ub450\ubc88\uc9f8 \uc778\uc790\ub294 2\uac00 \ub41c\ub2e4.\nTherefore, the second argument of the existing key becomes 2.\n\n- &#91;\"https:\/\/myserver.com\/posts\/abc123\",2] , &#91;\"abc123\",2] \n\n\n\n\n# \uc138\ubc88\uc9f8 \ub370\uc774\ud130 \uc608\uc2dc \/ Third data example\n1.\uc138\ubc88\uc9f8 \ub370\uc774\ud130\ub294 \"abc123\"\uc774 \uac12\ub9cc \uc788\uae30\ub54c\ubb38\uc5d0 \uc911\ubcf5 \uc81c\uac70\ud558\uba74 \uae30\uc874\uc5d0 \"abc123\"\uc758 \ud0a4\uc5d0 +1\uc774 \ub429\ub2c8\ub2e4.\nSince the third data item consists only of the value \"abc123,\" removing duplicates results in the count for the existing \"abc123\" key increasing by 1.\n\n2.\uadf8\ub7ec\uba74 &#91;\"https:\/\/myserver.com\/posts\/abc123\",2] ,&#91;\"abc123\",3] \uc774\ub807\uac8c \ub429\ub2c8\ub2e4.\nThen it becomes `&#91;\"https:\/\/myserver.com\/posts\/abc123\", 2], &#91;\"abc123\", 3]`.\n\n3.\uc9c0\uae08 \ud638\ucd9c\ubc29\uc2dd\uc774 \uc804\uccb4 URL\ub85c \ud638\ucd9c\ud558\ubbc0\ub85c &#91;\"https:\/\/myserver.com\/posts\/abc123\",2]  \uc774\uac78 \uae30\uc900\uc73c\ub85c \uc0ac\uc6a9\ud558\uba74\ub429\ub2c8\ub2e4.\nSince the current invocation method uses the full URL, you can use `&#91;\"https:\/\/myserver.com\/posts\/abc123\", 2]` as the basis.\n\n\n# \uacb0\uad6d\uc740 \uc804\uccb4 url\ub85c \ud638\ucd9c\ud558\ub358\uc9c0 \uc9e7\uc740 id\ub85c \ud638\ucd9c\ud558\ub358\uc9c0 \ub458\ub2e4 \ub300\uc751\ud558\uae30 \uc704\ud55c \ub85c\uc9c1\uc774\uba70 \uc0ac\uc6a9\ud560\ub54c \ub458\uc911 \ud558\ub098\ub9cc \uc0ac\uc6a9\ud560\uac83.\n# Ultimately, the logic is designed to handle calls made using either the full URL or the short ID; however, you should use only one of the two methods.\n<\/code><\/pre>\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 \uc5ec\uae30\uc11c\ub294 \ud398\uc774\uc9c0\ub124\uc774\uc158\uc744 \uad6c\ud604\ud560\ub54c \ud638\ucd9c\ub418\ub294 API\uc640 \ud568\uaed8 \ud398\uc774\uc9c0\ub124\uc774\uc158 \uad6c\uc870\ub97c \uc0b4\ud3b4 \ubd05\ub2c8\ub2e4.Here, we examine the pagination structure along with the API called when implementing pagination. \ud83d\udc49\ud83c\udffb \uc774\uc804 \ud3ec\uc2a4\ud2b8\uc5d0\uc11c ClientList.tsx\uc5d0\uc11c TimelineList.tsx\ub85c \ucd08\uae30\ub370\uc774\ud130\ub97c \uc804\ub2ec\ud558\uba74 \uc774 \ub370\uc774\ud130\uac00 useCursonPagination\ud6c5\uc5d0 \ub4e4\uc5b4\uac14\ub2e4\uac00 \ub098\uc635\ub2c8\ub2e4.As mentioned in the previous post, when initial data is passed from ClientList.tsx to TimelineList.tsx, it is processed by the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,27,1,7],"tags":[],"class_list":["post-12227","post","type-post","status-publish","format-standard","hentry","category-news","category-nextjs","category-uncategorized","category-website","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12227","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=12227"}],"version-history":[{"count":47,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12227\/revisions"}],"predecessor-version":[{"id":12278,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/12227\/revisions\/12278"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=12227"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=12227"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=12227"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}