์ฃผ์ด์ง API๋ฅผ ํ์ฉํด '์์ฑ ์์' ์ฒ๋ผ ํ ์ผ(Todo) ๊ด๋ฆฌ ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค.
์ด ์ฑ์์ ์ฌ์ฉํ ์ฃผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
react-router-dom
: React ์ฑ์ ๋ผ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, URL๊ณผ ์ปดํฌ๋ํธ์ ๋งคํ์ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.framer-motion
: ๋ณต์กํ ์ ๋๋ฉ์ด์ ๊ณผ ์ ์ค์ฒ๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.axios
: HTTP ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, ๋ธ๋ผ์ฐ์ ์ Node.js์์ ๋ชจ๋ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.zustand
: ์ํ ๊ด๋ฆฌ๋ฅผ ๊ฐํธํ๊ฒ ํ ์ ์๋ ์์ง๋ง ๊ฐ๋ ฅํ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.@tanstack/react-query
: ๋ฐ์ดํฐ ํจ์นญ๊ณผ ์บ์ฑ ๋ฑ์ ๊ฐํธํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.sortablejs
: ๋๋๊ทธ ์ค ๋๋กญ ๊ธฐ๋ฅ์ผ๋ก ๋ชฉ๋ก์ ์ ๋ ฌํ๊ฑฐ๋ ์ฌ๋ฐฐ์นํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.sass
: CSS ์ ์ฒ๋ฆฌ๊ธฐ๋ก CSS๋ณด๋ค ๋ ๋์ ๋ฌธ๋ฒ๊ณผ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.clsx
: ์กฐ๊ฑด๋ถ CSS ํด๋์ค๋ฅผ ๋์ ์ผ๋ก ์กฐํฉํ๋ ์ ํธ๋ฆฌํฐ์ ๋๋ค.vercel
: Vercel์์ ์ ๊ณตํ๋ ๋ฐฐํฌ ๋๊ตฌ๋ก, ์๋ ๋ฐฐํฌ, ์๋ฒ๋ฆฌ์ค ํจ์ ๋ฑ์ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค.concurrently
: ์ฌ๋ฌ ๊ฐ์ ์คํฌ๋ฆฝํธ ๋ช ๋ น์ ๋์์(๋ณ๋ ฌ) ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ์ ํธ๋ฆฌํฐ์ ๋๋ค.dotenv
: ํ๊ฒฝ ๋ณ์ ๊ด๋ฆฌ๋ฅผ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก,.env
ํ์ผ์ ์ ์๋ ๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค.
Browser Router ๋ชจ๏ฟฝ๏ฟฝ๏ฟฝ์์ ๋จ์ผ ํ์ด์ง ์ฑ(SPA)์ ์ ๊ณตํ ๋๋ ์ ์ ํ ์๋ฒ ๊ตฌ์ฑ์ด ํ์ํฉ๋๋ค.
์ฐ๋ฆฌ๋ Vercel ํธ์คํ
์ ์ฌ์ฉํ๋ฏ๋ก, ๋ชจ๋ ๊ฒฝ๋ก์ ๋ํด index.html
ํ์ผ์ ์ ๊ณตํ ์ ์๊ฒ ๋ค์๊ณผ ๊ฐ์ด ์ต์
์ ์ ๊ณตํฉ๋๋ค.
https://vercel.com/docs/concepts/projects/project-configuration#legacy-spa-fallback
/vercel.json
{
"routes": [
{ "handle": "filesystem" },
{ "src": "/(.*)", "dest": "/index.html" }
]
}
๋ชจ๋ ์์ฒญ์ ๋ค์ Headers ์ ๋ณด๊ฐ ํ์๋ก ํฌํจ๋ผ์ผ ํฉ๋๋ค.
<TODO_APIKEY>
์ <TODO_USERNAME>
์ ๋ณด๋ ๋ณ๋ ์ ๊ณตํฉ๋๋ค.
curl <API_ENDPOINT>
\ -X <REQUEST_METHOD>
\ -H 'content-type: application/json'
\ -H 'apikey: <TODO_APIKEY>'
\ -H 'username: <TODO_USERNAME>'
์ ์ฒด ํ ์ผ ๋ชฉ๋ก์ ์กฐํํฉ๋๋ค.
curl https://asia-northeast3-heropy-api.cloudfunctions.net/api/todos
\ -X 'GET'
์์ฒญ ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
- N/A
์๋ต ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
type ResponseValue = Todo[] // ํ ์ผ ๋ชฉ๋ก
interface Todo {
id: string // ํ ์ผ ID
order: number // ํ ์ผ ์์
title: string // ํ ์ผ ์ ๋ชฉ
done: boolean // ํ ์ผ ์๋ฃ ์ฌ๋ถ
createdAt: string // ํ ์ผ ์์ฑ์ผ
updatedAt: string // ํ ์ผ ์์ ์ผ
}
[
{
"id": "mnIwaAPIAE1ayQmqekiR",
"order": 0,
"title": "JS ๊ณต๋ถํ๊ธฐ",
"done": false,
"createdAt": "2021-10-28T05:18:51.868Z",
"updatedAt": "2021-10-28T05:18:51.868Z"
},
{
"id": "tMzPImGoWtRdJ6yyVv2y",
"order": 1,
"title": "๊ณผ์ PullRequest(PR) ์์ฑ",
"done": true,
"createdAt": "2021-10-28T04:16:53.980Z",
"updatedAt": "2021-10-28T09:40:17.955Z"
},
{
"id": "Rq8BebKihCgteHHhMIRS",
"order": 2,
"title": "API ์คํฐ๋",
"done": false,
"createdAt": "2021-10-28T04:17:02.510Z",
"updatedAt": "2021-10-28T04:17:02.510Z"
}
]
ํ ์ผ ํญ๋ชฉ์ ์๋กญ๊ฒ ์ถ๊ฐํฉ๋๋ค.
curl https://asia-northeast3-heropy-api.cloudfunctions.net/api/todos
\ -X 'POST'
์์ฒญ ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
interface RequestBody {
title: string // ํ ์ผ ์ ๋ชฉ
order?: number // ํ ์ผ ์์
}
{
"title": "KDT ๊ณผ์ ์ค๊ณ ๋ฏธํ
"
}
์๋ต ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
interface ResponseValue {
id: string
order: number
title: string
done: boolean
createdAt: string
updatedAt: string
}
{
"id": "7P8dOM4voAv8a8cfoeKZ",
"order": 0,
"title": "KDT ๊ณผ์ ์ค๊ณ ๋ฏธํ
",
"done": false,
"createdAt": "2021-10-29T07:20:02.749Z",
"updatedAt": "2021-10-29T07:20:02.749Z"
}
ํน์ ํ ์ผ ํญ๋ชฉ์ ์์ ํฉ๋๋ค.
curl https://asia-northeast3-heropy-api.cloudfunctions.net/api/todos/:todoId
\ -X 'PUT'
์์ฒญ ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
interface RequestBody {
title: string // ํ ์ผ ์ ๋ชฉ
done: boolean // ํ ์ผ ์๋ฃ ์ฌ๋ถ
order?: number // ํ ์ผ ์์
}
{
"title": "Bootstrap ์คํ์ผ ์ถ๊ฐ",
"done": false
}
์๋ต ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
interface ResponseValue {
id: string
order: number
title: string
done: boolean
createdAt: string
updatedAt: string
}
{
"id": "7P8dOM4voAv8a8cfoeKZ",
"title": "Bootstrap ์คํ์ผ ์ถ๊ฐ",
"done": false,
"order": 2,
"createdAt": "2021-10-29T07:20:02.749Z",
"updatedAt": "2021-10-29T07:20:02.749Z"
}
ํน์ ํ ์ผ ํญ๋ชฉ์ ์ญ์ ํฉ๋๋ค.
curl https://asia-northeast3-heropy-api.cloudfunctions.net/api/todos/:todoId
\ -X 'DELETE'
์์ฒญ ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
- N/A
์๋ต ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
type ResponseValue = true // ์ ์ ์๋ต
curl https://asia-northeast3-heropy-api.cloudfunctions.net/api/todos/deletions
\ -X 'DELETE'
์์ฒญ ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
interface RequestBody {
todoIds: string[] // ์ญ์ ํ ํ ์ผ ID ๋ชฉ๋ก
}
{
"todoIds": [
"mnIwaAPIAE1ayQmqekiR",
"tMzPImGoWtRdJ6yyVv2y",
"GHrvr3LaPx1g7y2sNuaC",
"Rq8BebKihCgteHHhMIRS"
]
}
์๋ต ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
type ResponseValue = true // ์ ์ ์๋ต
ํ ์ผ ๋ชฉ๋ก์ ์์๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค.
curl https://asia-northeast3-heropy-api.cloudfunctions.net/api/todos/reorder
\ -X 'PUT'
์์ฒญ ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
interface RequestBody {
todoIds: string[] // ์๋กญ๊ฒ ์ ๋ ฌํ ํ ์ผ ID ๋ชฉ๋ก
}
{
"todoIds": [
"mnIwaAPIAE1ayQmqekiR",
"tMzPImGoWtRdJ6yyVv2y",
"GHrvr3LaPx1g7y2sNuaC",
"Rq8BebKihCgteHHhMIRS"
]
}
์๋ต ๋ฐ์ดํฐ ํ์ ๋ฐ ์์:
type ResponseValue = true // ์ ์ ์๋ต