์ฃผ์ด์ง API๋ฅผ ํ์ฉํด '์์ฑ ์์' ์ฒ๋ผ ํ ์ผ(Todo) ๊ด๋ฆฌ ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค.
Vue Composition API + TypeScript๋ฅผ ์ฌ์ฉํด ๊ตฌํํฉ๋๋ค.
- Options API: ๊ฐ์ ํ๋ ์ต์ ์ฌ์ฉ์ผ๋ก ๋ฎ์ ์ง์ ์ฅ๋ฒฝ ์ ๊ณต, ๊ธฐ์กด ์ฝ๋(>=@2)์ ํธํ์ฑ ์ ์ง
- Composition API: ์ ์ฐํ ๊ตฌ์กฐ๋ก ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ ํฅ์ ๊ฐ๋ฅ, ํ์ ์คํฌ๋ฆฝํธ ํธํ์ฑ ํฅ์
- Vue.js ํต์ฌ ํ ๋ฉค๋ฒ๊ฐ ๊ฐ๋ฐํ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ๊ณต์ Vuex์ ์ ์ฌํ์ง๋ง, ๋ ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ API ์ ๊ณต
- Vue.js ์ธก์์ ๊ณต์์ ์ผ๋ก ์ฌ์ฉ์ ์ถ์ฒ
- ๋ค์ ๋ฒ์ ์ ๊ณต์ Vuex์์ ์ฐจ์ฉํ๊ฑฐ๋ ์์ Pinia๋ก ์ ํ ์์
Vue Router์ HTML5 ๋ชจ๋์์ ๋จ์ผ ํ์ด์ง ์ฑ(SPA)์ ์ ๊ณตํ ๋๋ ์ ์ ํ ์๋ฒ ๊ตฌ์ฑ์ด ํ์ํฉ๋๋ค.
์ฐ๋ฆฌ๋ Vercel ํธ์คํ
์ ์ฌ์ฉํ๋ฏ๋ก, ๋ชจ๋ ๊ฒฝ๋ก์ ๋ํด index.html
ํ์ผ์ ์ ๊ณตํ ์ ์๊ฒ ๋ค์๊ณผ ๊ฐ์ด ์ต์
์ ์ ๊ณตํฉ๋๋ค.
https://vercel.com/docs/concepts/projects/project-configuration#legacy-spa-fallback
/ vercel.json
{
"routes": [
{ "handle": "filesystem" },
{ "src": "/(.*)", "dest": "/index.html" }
]
}
ํ์
์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ ๋, ์ง์ ์ค์นํ ๋ฒ์ ๊ณผ Vercel(@vercel/node
) ๋ด๋ถ์์ ์ฌ์ฉํ๋ ๋ฒ์ ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ์ผ์น์ํฌ ์ ์์ต๋๋ค.
Vercel ์๋ฒ๋ฆฌ์ค ํจ์๋ฅผ ์ฌ์ฉํ ๋, ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
/package.json
{
"devDependencies": {
"typescript": "^5.0.2",
"vercel": "^30.2.1"
},
"overrides": {
"@vercel/node": {
"ts-node": "10.9.1",
"typescript": "5.0.2"
}
}
}
/.eslintrc.json
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-recommended",
"plugin:prettier/recommended"
],
"parserOptions": {
"parser": "@typescript-eslint/parser"
}
}
parser
: ESLint ์ ๋ฐ์ ๊ฑธ์ณ ์ฌ์ฉํ๋ ๊ธฐ๋ณธ ํ์๋ฅผ ์ค์ parserOptions.parser
: ํน์ ํ๋ฌ๊ทธ์ธ(Vue)์์ ์ฌ์ฉํ๋ ํ์๋ฅผ ์ค์
๋ชจ๋ ์์ฒญ์ ๋ค์ Headers ์ ๋ณด๊ฐ ํ์๋ก ํฌํจ๋ผ์ผ ํฉ๋๋ค.
<APIKEY>
์ <USERNAME>
์ ๋ณด๋ ๋ณ๋ ์ ๊ณตํฉ๋๋ค.
curl <ENDPOINT>
\ -X <METHOD>
\ -H 'content-type: application/json'
\ -H 'apikey: <APIKEY>'
\ -H 'username: <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 // ์ ์ ์๋ต