
Vue.js๋ ๋ฌด์์ธ๊ฐ
Vue.js๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ถํ๊ธฐ ์ํ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ ์์ํฌ์ด๋ค.
ํ์ค HTML, CSS, JavaScript ์์ ๊ตฌ์ถ๋ Vue๋ ์ ์ธ์ ์ด๊ณ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ์ ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ์ ์ ๊ณตํ์ฌ ๋ณต์กํ UI๋ ํจ์จ์ ์ผ๋ก ๊ฐ๋ฐํ ์ ์๊ฒ ํ๋ค. Vue๋ React๋ Angular์ ๋ฌ๋ฆฌ, ํ๋ก๊ทธ๋ ์๋ธ ํ๋ ์์ํฌ๋ฅผ ์งํฅํ๋ค.
ํ์ํ ๊ธฐ๋ฅ๋ง ์ ์ง์ ์ผ๋ก ์ฑํํ ์ ์์ด ๊ธฐ์กด ํ๋ก์ ํธ์ ๋ฌด๋ฆฌ ์์ด ๋์ ํ๊ธฐ ์ฝ๋ค.
Vue 3 ๋ฒ์ ์์๋ ์ปดํฌ์ง์ API (Composition API)๋ฅผ ๋์ ํ์ฌ ์ํ์ ๋ก์ง์ ๋ณด๋ค ์ ์ฐํ๊ฒ ๊ตฌ์ฑํ ์ ์๊ฒ ๋์๊ณ ,
์ฑ๋ฅ๊ณผ ๊ฐ๋ฐ์ ๊ฒฝํ ๋ฉด์์๋ ์ฌ๋ฌ ๊ฐ์ ์ด ์ด๋ฃจ์ด์ก๋ค.
์ฆ, Vue.js๋ ๊ฐ๋ณ์ง๋ง ๊ฐ๋ ฅํ ํ๋ก ํธ์๋ ํ๋ ์์ํฌ๋ก, ๋ทฐ(View) ๋ ์ด์ด๋ฅผ ์ค์ฌ์ผ๋ก ํ ๋น ๋ฅธ ๊ฐ๋ฐ์ ๋๋๋ค.
ํ๋ก ํธ์๋ ํ๋ก์ ํธ ๋๋ ํฐ๋ฆฌ ๊ตฌ์กฐ
Vue.js๋ก ํ๋ก์ ํธ๋ฅผ ์์ํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก frontend ๋๋ ํฐ๋ฆฌ์ ์๋์ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ถ๊ฒ ๋๋ค.
๊ฐ ํด๋์ ํ์ผ์ ์ญํ ์ ๋ฐ๋ผ ๋๋์ด ์์ด, ํ๋ก์ ํธ ๊ท๋ชจ๊ฐ ์ปค์ ธ๋ ์ฝ๋๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๊ฒ ํ๋ค.
frontend/ (ํ๋ก์ ํธ ๋ฃจํธ)
โโ public/ # ์ ์ ํ์ผ ๋ฐ HTML ํ
ํ๋ฆฟ ์์น
โ โโ index.html # ์ ํ๋ฆฌ์ผ์ด์
์ง์
์ ์ด ๋๋ ๊ธฐ๋ณธ HTML
โโ src/ # ์์ค ์ฝ๋ ๋๋ ํฐ๋ฆฌ
โโ main.js # ์ ํ๋ฆฌ์ผ์ด์
์ง์
JS ํ์ผ (Vue ์ฑ ์์ฑ ๋ฐ ํ๋ฌ๊ทธ์ธ ๋ฑ๋ก)
โโ App.vue # ์ต์์ Root ์ปดํฌ๋ํธ
โโ components/ # ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ Vue ์ปดํฌ๋ํธ๋ค
โโ views/ # ํ๋ฉด ๋จ์ ์ปดํฌ๋ํธ (ํ์ด์ง ์ปดํฌ๋ํธ)
โโ router/ # Vue Router ์ค์ (๋ผ์ฐํธ ๋งคํ ์ ์)
โโ store/ # ์ํ ๊ด๋ฆฌ ์คํ ์ด (Pinia ๋ฑ ์ํ ๊ด๋ฆฌ ๋ชจ๋๋ค)
โโ composables/ # ์ปดํฌ์ง์
API๋ก ์์ฑํ ์ฌ์ฌ์ฉ ๋ก์ง (ํ
/์ ํธ ํจ์)
โโ assets/ # ์ ์ ์์ฐ (์ด๋ฏธ์ง, CSS, ํฐํธ ๋ฑ)
โโ ... ๊ธฐํ ํ๊ฒฝ์ค์ ํ์ผ (.env ๋ฑ) ๋ฐ ํด๋ (์: utils/, plugins/, tests/)
- public/: ๋น๋๋์ง ์์ ์ ์ ์์์ ๋๋ ๊ณณ์ด๋ค. index.html ํ์ผ์ ๋จ์ผ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ธฐ๋ณธ HTML ํ๋ก์, Vue๋ก ์์ฑํ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ด HTML ๋ด #app ๋ฑ์ DOM ์๋ฆฌ๋จผํธ์ ๋ง์ดํธ๋๋ค. ์ด ํด๋๋ ์ฃผ๋ก ํ๋น์ฝ์ด๋ ํน์ ์ ์ ํ์ผ์ ๋ ๋ ์ฌ์ฉํ๋ฉฐ, Vue CLI๋ Vite ๊ธฐ๋ฐ ํ๋ก์ ํธ์์ ๊ธฐ๋ณธ ์ ๊ณต๋๋ค.
- src/main.js: ์ ํ๋ฆฌ์ผ์ด์ ์ง์ ์คํฌ๋ฆฝํธ ํ์ผ์ด๋ค. ์ฌ๊ธฐ์ Vue ์ดํ๋ฆฌ์ผ์ด์ ์ ์์ฑ(createApp)ํ๊ณ , ๋ผ์ฐํฐ์ ์คํ ์ด(Pinia) ๋ฑ์ ํ๋ฌ๊ทธ์ธ์ ๋ฑ๋กํ ๋ค #app ์๋ฆฌ๋จผํธ์ ๋ง์ดํธํ๋ค. ์๋ฅผ ๋ค์ด, Pinia๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ import { createPinia } from 'pinia'๋ก Pinia ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ app.use(createPinia())๋ก ์ฑ์ ์ฃผ์ ํ๋ฉฐ, ๋ผ์ฐํฐ๋ app.use(router)๋ก ๋ฑ๋กํ ๋ค app.mount('#app')์ผ๋ก ์ด๊ธฐํํ๋ค.
- src/App.vue: ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฃจํธ ์ปดํฌ๋ํธ์ด๋ค. ๋ณดํต ์ต์์ ๋ ์ด์์ ์ญํ ์ ํ๋ฉฐ, <router-view>๋ฅผ ํฌํจํ์ฌ ๋ผ์ฐํธ์ ๋ฐ๋ผ ๋ณํ๋ ํ๋ฉด์ ํ์ํ๋ค. ๋ชจ๋ ์ปดํฌ๋ํธ์ ๊ณตํต ์กฐ์์ด๋ฏ๋ก ์ ์ญ ์คํ์ผ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ๋ ์ด์์์ ์ฌ๊ธฐ์ ์ ์ํ๋ค.
- src/components/: ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ Vue ์ปดํฌ๋ํธ๋ฅผ ๋ชจ์๋๋ ๋๋ ํฐ๋ฆฌ์ด๋ค. ์๋ฅผ ๋ค์ด ๋ฒํผ, ์นด๋, ๋ชจ๋ฌ ์ฐฝ ๊ฐ์ UI ์์๋ค์ ์ปดํฌ๋ํธ๋ก ๋ง๋ค์ด ์ด ํด๋์ ๋ฃ๋๋ค. ์ปดํฌ๋ํธ๋ ํ์ํ ๋๋ง๋ค ์ํฌํธํ์ฌ ์ฌ์ฉํ๋ฉฐ, ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ ๋ทฐ์์ ์กฐํฉ๋์ด ํ๋ฉด์ ๊ตฌ์ฑํ๋ค. ์ผ๋ฐ์ ์ผ๋ก ํ๋์ .vue ํ์ผ์ด ํ๋์ ์ปดํฌ๋ํธ๋ฅผ ํํํ๋ค.
- src/views/ (ํน์ pages/): ํ๋ฉด ๋จ์ ์ปดํฌ๋ํธ๋ฅผ ์ํ ๋๋ ํฐ๋ฆฌ์ด๋ค. ๋ทฐ ์ปดํฌ๋ํธ๋ ๋ผ์ฐํฐ์ ๋งคํ๋์ด ํ๋์ ํ์ด์ง(ํ๋ฉด)์ ๊ตฌ์ฑํ๋ค. ์๋ฅผ ๋ค์ด Home.vue, Login.vue, Dashboard.vue ๊ฐ์ ํ์ผ์ด ์ฌ๊ธฐ์ ์์นํ๋ฉฐ, ๊ฐ๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ผ์ฐํธ(route)์ ์ฐ๊ฒฐ๋์ด ์๋ค. ๋ทฐ ์ปดํฌ๋ํธ ๋ด๋ถ์์๋ ์ฌ๋ฌ ์ฌ์ฌ์ฉ ์ปดํฌ๋ํธ(components/ ํด๋์ ๋ด์ฉ)๋ฅผ ์กฐํฉํ์ฌ ํ๋์ ์์ฑ๋ ํ๋ฉด์ ๊ตฌํํ๋ค.
- src/router/: Vue Router ์ค์ ํ์ผ๋ค์ ํฌํจํ๋ค. ์ผ๋ฐ์ ์ผ๋ก index.js ํน์ index.ts ํ์ผ์ ๊ฒฝ๋ก๋ณ ์ปดํฌ๋ํธ ๋งคํ์ ์ ์ํ๋ค. ์๋ฅผ ๋ค์ด '/login' ๊ฒฝ๋ก์ Login.vue ์ปดํฌ๋ํธ๋ฅผ ํ์ํ๋๋ก ๋ผ์ฐํธ๋ฅผ ์ค์ ํ๊ณ , ํ์คํ ๋ฆฌ ๋ชจ๋ ์ฌ๋ถ, ๊ธ๋ก๋ฒ ๋ค๋น๊ฒ์ด์ ๊ฐ๋ ๋ฑ์ ์ฌ๊ธฐ์ ์ค์ ํ๋ค. main.js์์ ์ด ๋ผ์ฐํฐ ์ธ์คํด์ค๋ฅผ ๋ถ๋ฌ์ ์ฑ์ ๋ฑ๋กํ์ฌ ์ฌ์ฉํ๋ค.
- src/store/: ์ ์ญ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํ ์คํ ์ด ๋ชจ๋๋ค์ ๋ชจ์๋์ ํด๋์ด๋ค. Vue 3 ๊ธฐ์ค์ผ๋ก๋ ๊ณต์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Pinia๋ฅผ ์ฃผ๋ก ์ฌ์ฉํ๋ฉฐ, ๊ฐ ์คํ ์ด๋ฅผ ๋ณ๋์ ํ์ผ๋ก ์ ์ํ๋ค. (Vue 2์ Vuex๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ ์ฌํ ๊ตฌ์กฐ๋ก store/index.js์์ ์คํ ์ด๋ฅผ ์์ฑํ๊ฒ ์ง๋ง, Pinia์์๋ ๋ณดํต ๊ฐ ์คํ ์ด ํ์ผ๋ณ๋ก defineStore๋ฅผ ์ฌ์ฉํ๊ณ main.js์์ Pinia๋ฅผ ํ๋ฌ๊ทธ์ธ์ผ๋ก ๋ฑ๋กํ๋ค.) ์ด ๋๋ ํฐ๋ฆฌ์๋ ์๋ฅผ ๋ค์ด auth.js (์ธ์ฆ ๊ด๋ จ ์ํ), todo.js (ํ ์ผ ๋ชฉ๋ก ์ํ) ๋ฑ ์ฌ๋ฌ ๊ฐ์ ์ํ ๋ชจ๋์ ํ์ผ๋ณ๋ก ์ ์ํ ์ ์๋ค. ์คํ ์ด๋ฅผ ํ์ฉํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ญ์์ ๊ณต์ ๋๋ ์ํ๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค.
- src/composables/: Vue 3 ์ปดํฌ์ง์ API๋ก ์์ฑ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ก์ง์ ๋ชจ์ ํด๋์ด๋ค. ์ปดํฌ๋ํธ ๊ฐ์ ๊ณตํต์ผ๋ก ์ฐ์ด๋ ์ฝ๋(์: ๋ฐ์ดํฐ ํ์นญ, ํผ ํธ๋ค๋ง ๋ฑ)๋ฅผ ํ (hook) ํํ๋ก ์ถ์ํํ ์ปดํฌ์ ๋ธ(composable) ํจ์๋ฅผ ์ฌ๊ธฐ์ ์์ฑํ๋ค. ๊ด๋ก์ useSomething.js์ฒ๋ผ ํ์ผ๋ช ์ ์ง๋๋ค (์: useAuth.js๋ ์ธ์ฆ ๊ด๋ จ ์ํ๋ ํจ์๋ฅผ ์ ๊ณต). ์ด๋ ๊ฒ ๋ถ๋ฆฌํ๋ฉด ๋ก์ง์ ์ฝ๊ฒ ๊ณต์ ํ ์ ์๊ณ , ์ปดํฌ๋ํธ์ ๊ฐ๋ ์ฑ๋ ๋์์ง๋ค.
- src/assets/: ์ด๋ฏธ์ง, ํฐํธ, ๊ธ๋ก๋ฒ CSS ๋ฑ ์ ์ ์์์ ์ ์ฅํ๋ ํด๋์ด๋ค. Webpack์ด๋ Vite ๋ฑ ๋น๋ ๋๊ตฌ์ ์ํด ์ฒ๋ฆฌ๋๋ ์์ฐ ๊ฒฝ๋ก์ด๋ฏ๋ก, ์ด ํด๋์ ๋ฃ์ ํ์ผ๋ค์ ๋น๋์ ๋ฒ๋ค์ ํฌํจ๋๊ฑฐ๋ ๋ณต์ฌ๋๋ค. ์์ปจ๋ ๋ก๊ณ ์ด๋ฏธ์ง logo.png๋ ๊ณตํต ์คํ์ผ์ํธ styles.css ๋ฑ์ ์ด๊ณณ์ ๋ ์ ์๋ค. .vue ํ์ผ ์์์ @/assets/... ๊ฒฝ๋ก๋ ์๋๊ฒฝ๋ก๋ก ์ฐธ์กฐํ๋ฉด ๋น๋ ์ ์ ์ ํ ์ฒ๋ฆฌ๋๋ค.
- ๊ธฐํ ํด๋: ๊ท๋ชจ์ ๋ฐ๋ผ ์ถ๊ฐ์ ์ธ ํด๋๋ฅผ ๊ตฌ์ฑํ๊ธฐ๋ ํ๋ค. ์๋ฅผ ๋ค์ด plugins/ ํด๋๋ ์ ์ญ์ผ๋ก ์ฌ์ฉํ๋ Vue ํ๋ฌ๊ทธ์ธ ์ด๊ธฐํ ์ฝ๋ (์: axios ์ธ์คํด์ค ์ค์ , i18n ๊ตญ์ ํ ์ค์ ๋ฑ)๋ฅผ ๋ฃ๋ ๊ณณ์ด๋คv. utils/ ํด๋๋ ๋ฒ์ฉ ์ ํธ๋ฆฌํฐ ํจ์๋ ํฌํผ๋ฅผ ๋ชจ์๋๋ ๊ณณ์ผ๋ก ์ฌ์ฉ๋๋ค. ํ ์คํธ๋ฅผ ์์ฑํ๋ค๋ฉด tests/ ํด๋ ์๋์ unit ๋๋ e2e ํด๋๋ฅผ ๋์ด ๋จ์ ํ ์คํธ์ ์ข ๋จ๊ฐ ํ ์คํธ ์ฝ๋๋ฅผ ๊ด๋ฆฌํ๋ค. ํ๋ก์ ํธ๊ฐ ๋งค์ฐ ์ปค์ง ๊ฒฝ์ฐ Atomic Design ๋ฐฉ์์ด๋ ๋๋ฉ์ธ ๋ณ ๋ชจ๋ ํด๋๋ก ์ธ๋ถํํ๊ธฐ๋ ํ์ง๋ง, ๊ธฐ๋ณธ์ ์ผ๋ก๋ ์์ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ํ ๋๋ก ํ์์ ๋ฐ๋ผ ํด๋๋ฅผ ์ถ๊ฐ/์ ๋ฆฌํ๋ค.
RESTful API ์ฐ๋๊ณผ ๋น๋๊ธฐ ์์ฒญ ์ฒ๋ฆฌ (axios)
ํ๋์ ์ธ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์์ Vue ์ ํ๋ฆฌ์ผ์ด์ ์ RESTful API๋ฅผ ํตํด ๋ฐฑ์๋ ์๋ฒ์ ๋ฐ์ดํฐ ํต์ ์ ํ๋ค.
RESTful API๋ HTTP ํ๋กํ ์ฝ์ ํ์ฉํ์ฌ ์์์ CRUDํ ์ ์๋ ์๋ํฌ์ธํธ๋ฅผ ์ ๊ณตํ๋ ์น API ๋ฐฉ์์ด๋ค.
Vue์์๋ ์ด๋ฌํ API ํธ์ถ์ ์ํด ์ฃผ๋ก axios ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค.
axios๋ ๋ธ๋ผ์ฐ์ ์ Node.js ๋ชจ๋์์ ๋์ํ๋ Promise ๊ธฐ๋ฐ HTTP ํด๋ผ์ด์ธํธ๋ก,
ํ๋ก ํธ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ฐํธํ๊ฒ AJAX ์์ฒญ์ ๋ณด๋ผ ์ ์๊ฒ ํด์ค๋ค.
axios๋ฅผ ์ด์ฉํ๋ฉด GET, POST ๊ฐ์ HTTP ๋ฉ์๋๋ก ๋ฐฑ์๋ REST ์๋ํฌ์ธํธ์ ์์ฒญ์ ๋ณด๋ด๊ณ ,
์๋ต ๋ฐ์ดํฐ๋ฅผ Promise ํํ๋ก ๋ฐ์์ฌ ์ ์๋ค.
์ฆ, axios๋ฅผ ํตํด ํด๋ผ์ด์ธํธ์์ CRUD ์์ ์ ๋์ํ๋ HTTP ์์ฒญ์ ๋ณด๋ด๊ณ
RESTful ์๋ํฌ์ธํธ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์๋ค.
Vue 3 ์ปดํฌ์ง์ API ํ๊ฒฝ์์๋ axios๋ฅผ ํตํฉํ๊ธฐ๊ฐ ๋งค์ฐ ์์ํ๋ค.
์ปดํฌ๋ํธ์ <script setup> ์์ญ์ด๋ setup ํจ์ ๋ด์์ ํ์ํ ๊ณณ์ ๋จ์ํ import axios from 'axios'๋ก ๋ถ๋ฌ์ ์ฌ์ฉํ ์ ์๋ค. axios์ ํธ์ถ์ ๋น๋๊ธฐ๋ก ์ด๋ฃจ์ด์ง๋ฏ๋ก Promise๋ฅผ ๋ฐํํ๋ฉฐ,
async/await ๊ตฌ๋ฌธ์ ํ์ฉํ๋ฉด ๋๊ธฐ ์ฝ๋์ฒ๋ผ ์์ฑํ ์ ์์ด ๊ฐ๋ ์ฑ์ด ์ข๋ค.
๋ํ API ํธ์ถ ์ค ์๋ฌ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ try...catch๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค.
์๋ฅผ ๋ค์ด, ์ปดํฌ์ง์ API ๊ธฐ๋ฐ ์ปดํฌ๋ํธ์์ onMounted ํ ์ ์ฌ์ฉํด ์ด๊ธฐ ๋ฐ์ดํฐ ๋ก๋๋ฅผ ์ํํ๊ณ ,
๋ฒํผ ํด๋ฆญ ๋ฑ ์ด๋ฒคํธ์ ๋ฐ๋ผ ์ถ๊ฐ ์์ฒญ์ ๋ณด๋ด๋ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค.
์๋๋ axios๋ฅผ ์ด์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ์ ์ธ ์์์ด๋ค:
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const items = ref([]) // ๊ฐ์ ธ์จ ๋ฐ์ดํฐ ๋ฐฐ์ด
const error = ref(null) // ์๋ฌ ์ํ ์ ์ฅ
// ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ ํจ์
const fetchItems = async () => {
try {
// REST API GET ์์ฒญ (์์ URL)
const response = await axios.get('/api/items')
items.value = response.data // ์๋ต ๋ฐ์ดํฐ๋ฅผ ์ํ์ ์ ์ฅ
} catch (err) {
error.value = err // ์๋ฌ ๋ฐ์ ์ ์๋ฌ ์ ๋ณด ์ ์ฅ
}
}
// ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋ API ํธ์ถ ์คํ
onMounted(() => {
fetchItems()
})
</script>
<template>
<div v-if="error">
์๋ฌ ๋ฐ์: {{ error.message }}
</div>
<ul v-else>
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
</template>
์ ์ฝ๋์์๋ onMounted ํ ๋ด๋ถ์์ fetchItems() ํจ์๋ฅผ ํธ์ถํ์ฌ
์ปดํฌ๋ํธ๊ฐ ํ๋ฉด์ ๋ํ๋ ๋ ์๋์ผ๋ก GET ์์ฒญ์ ๋ณด๋ด๋๋ก ํ๋ค.
axios.get์ผ๋ก ๋ฐ์ ์๋ต ๋ฐ์ดํฐ(response.data)๋ฅผ items ์ํ์ ๋ฃ๊ณ , ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด error ์ํ์ ์๋ฌ ์ ๋ณด๋ฅผ ๊ธฐ๋กํ๋ค.
์ด๋ ๊ฒ ๋ถ๋ฌ์จ items๋ <template>์์ ๋ฆฌ์คํธ ๋ ๋๋ง(v-for)์ ํตํด ํ๋ฉด์ ์ถ๋ ฅ๋๊ณ ,
error ์ํ๊ฐ ์์ผ๋ฉด ์๋ฌ ๋ฉ์์ง๋ฅผ ํ์ํ๋๋ก ํ๋ค.
์ด์ฒ๋ผ axios๋ฅผ ์ปดํฌ๋ํธ ๋ด์์ ์ง์ ์ฌ์ฉํ๋ฉด ํ์ํ ๋๋ง๋ค ์์ฝ๊ฒ ๋ฐฑ์๋์ ํต์ ํ ์ ์๋ค.
ํ๋ก์ ํธ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด API ํธ์ถ ๋ก์ง์ ๋ชจ๋ํํ๋ ๊ฒ๋ ๊ณ ๋ คํ๋ค.
์๋ฅผ ๋ค์ด src/plugins/axios.js ํ์ผ์ ๋ง๋ค์ด axios ๊ธฐ๋ณธ ์ค์ (๊ธฐ๋ณธ URL, ๊ณตํต ํค๋ ๋ฑ)์ ์ ์ํ๊ณ
์ ํ๋ฆฌ์ผ์ด์ ์ ํ๋ฌ๊ทธ์ธ์ผ๋ก ๋ฑ๋กํ ์ ์๋ค.
ํน์ src/composables/useApi.js ๊ฐ์ ์ปดํฌ์ ๋ธ์ axios ํธ์ถ ํจ์๋ฅผ ๋ชจ์๋ ์๋ ์๋ค.
ํ์ง๋ง ์๊ท๋ชจ ํ๋ก์ ํธ๋ ๊ฐ๋ณ ์ปดํฌ๋ํธ ์์ค์์๋ ์ ์์์ฒ๋ผ ์ปดํฌ๋ํธ์์ ๋ฐ๋ก axios๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํ๋ค.
Vue์์์ ์ํ ๊ด๋ฆฌ (Pinia)์ ์ํ ๊ณต์ ๊ตฌ์กฐ
์ ํ๋ฆฌ์ผ์ด์ ๊ท๋ชจ๊ฐ ์ปค์ง์ ๋ฐ๋ผ ์ปดํฌ๋ํธ ๊ฐ์ ๊ณต์ ํด์ผ ํ๋ ์ํ(state)๊ฐ ๋ง์์ง๋ฉด,
ํจ์จ์ ์ธ ์ํ ๊ด๋ฆฌ(state management)๊ฐ ํ์ํ๋ค. Vue 3์์๋ ๊ณต์ ๊ถ์ฅ ์ํ ๊ด๋ฆฌ ๋๊ตฌ๋ก Pinia๋ฅผ ์ฌ์ฉํ๋ค.
Pinia๋ Vue์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, ์ฌ๋ฌ ์ปดํฌ๋ํธ๋ ํ์ด์ง ๊ฐ์ ์ ์ญ ์ํ๋ฅผ ๊ณต์ ํ ์ ์๋๋ก ๋์์ค๋ค.
์ฝ๊ฒ ๋งํด, ๊ฐ๋ณ ์ปดํฌ๋ํธ์ ์ง์ญ ์ํ(data)๋ง์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์ด
์ฌ์ฉ์ ์ ๋ณด, ์ธ์ฆ ์ํ, ์ฅ๋ฐ๊ตฌ๋ ๋ด์ฉ ๋ฑ ์ ์ญ์ ์ธ ๋ฐ์ดํฐ๋ฅผ ํ ๊ณณ์์ ๊ด๋ฆฌํ๊ณ ์ด๋ ๊ณณ์์๋ ์ ๊ทผํ ์ ์๊ฒ ํ๋ ๊ฒ์ด๋ค.
Pinia์ ์คํ ์ด(store)๋ ์ปดํฌ๋ํธ ํธ๋ฆฌ์ ์ํ์ง ์๋ ๋ ๋ฆฝ์ ์ธ ๊ฐ์ฒด๋ก, ์ ์ญ ์ํ์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๊ณ ์๋ค.
์ด๋ฅผ ์ผ์ข ์ ํญ์ ์กด์ฌํ๋ ์จ์ ์ปดํฌ๋ํธ๋ผ๊ณ ๋ณผ ์๋ ์๋๋ฐ, ๋ชจ๋ ์ปดํฌ๋ํธ๊ฐ ์ด ์คํ ์ด์ ์ ๊ทผํ์ฌ ์ํ๋ฅผ ์ฝ๊ฑฐ๋ ์ธ ์ ์๋ค.
์คํ ์ด์๋ ์ธ ๊ฐ์ง ์ฃผ์ ๊ฐ๋ ์ด ์๋ค:
state(์ํ ๋ฐ์ดํฐ), getters(์ํ๋ก๋ถํฐ ๊ณ์ฐ๋ ๊ฐ, ์ฆ ํ์ ์ํ), actions(์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ํจ์, ๋น์ฆ๋์ค ๋ก์ง).
์ด๋ค์ ๊ฐ๊ฐ Vue ์ปดํฌ๋ํธ์ data, computed, methods์ ๋์๋๋ฉฐ ์๋ ๋ฐฉ์๋ ์ ์ฌํ๋ค.
์ ๋ฆฌํ๋ฉด, Pinia ์คํ ์ด๋ ์ ์ญ ๊ณตํต ์ํ๋ฅผ ๋ณด๊ดํ๊ณ ๊ด๋ฆฌํ๋ ํ๋์ ๋ชจ๋์ด๋ฉฐ,
์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ๊ทธ ์ํ๋ฅผ ์ ๋ขฐ์(source of truth)์ผ๋ก ์ผ์ ๊ณต์ ํ๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ๋๋ค.
Pinia๋ฅผ ํ๋ก์ ํธ์ ๋์ ํ๋ ค๋ฉด, ๋จผ์ pinia ํจํค์ง๋ฅผ ์ค์นํ ํ ์ง์ ํ์ผ(main.js)์์ Pinia๋ฅผ ์์ฑํ์ฌ ์ฑ์ ๋ฑ๋กํด์ผ ํ๋ค.
Vue ์ฑ ์์ฑ ์ createPinia()๋ก ์คํ ์ด ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ app.use(pinia)๋ก ์ ์ฉํ๋ฉด ์ค์ ์๋ฃ์ด๋ค.
์ด๋ ๊ฒ ํ๋ฉด ์ฑ ์ ์ญ์์ Pinia๋ฅผ ์ฌ์ฉํ ์ค๋น๊ฐ ๋๋ค.
์ด์ ๊ตฌ์ฒด์ ์ธ ์ํ ๊ด๋ฆฌ๋ ์คํ ์ด ๋ชจ๋์ ์ ์ํจ์ผ๋ก์จ ์ด๋ฃจ์ด์ง๋ค.
Pinia์์๋ ๊ฐ๋ณ ์คํ ์ด๋ฅผ ์ ์ํ๊ธฐ ์ํด defineStore ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
ํ ์คํ ์ด๋ ํ๋์ ์ํ ๋ชจ๋์ ํด๋นํ๋ฉฐ, ๊ณ ์ ํ ID(์ด๋ฆ)์ ๊ฐ์ ธ์ผ ํ๋ค.
๋ค์์ Pinia๋ฅผ ์ฌ์ฉํด ๊ฐ๋จํ ์นด์ดํฐ(counter) ์คํ ์ด๋ฅผ ์ ์ํ๋ ์ฝ๋ ์์ ์ด๋ค:
// src/store/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
// state: ์ ์ญ์์ ๊ณต์ ํ ์ํ๋ฅผ ์ ์ธ
state: () => ({
count: 0,
name: 'default'
}),
// getters: ์ํ๋ฅผ ํ์ฉํ์ฌ ๊ณ์ฐ๋ ๊ฐ์ ๊ฐ์ ธ์ค๋ ์์ฑ
getters: {
doubleCount: (state) => state.count * 2, // count์ 2๋ฐฐ ๊ฐ์ ๋ฐํ
welcomeMessage: (state) => `Hello, ${state.name}` // ์ํ name์ ํ์ฉํ ๋ฌธ์์ด
},
// actions: ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฉ์๋ (๋น์ฆ๋์ค ๋ก์ง ํฌํจ ๊ฐ๋ฅ)
actions: {
increment() {
this.count++ // this๋ฅผ ํตํด state์ ์ ๊ทผํ์ฌ ๋ณ๊ฒฝ
},
setName(newName) {
this.name = newName // ์ํ ์์ฑ ์
๋ฐ์ดํธ
}
}
})
์ ์ฝ๋์์๋ 'counter'๋ผ๋ ID๋ฅผ ๊ฐ์ง ์คํ ์ด๋ฅผ ์ ์ํ๋ค.
state๋ ํจ์ ํํ๋ก ์ด๊ธฐ ์ํ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ฉฐ, ์ฌ๊ธฐ์๋ count์ name ๋ ๊ฐ์ ์์ฑ์ ๊ฐ์ง๊ณ ์๋ค.
getters๋ ํ์ฌ ์ํ๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ๊ณ์ฐ๋ ๊ฐ์ ๋ฐํํ๋ ์์ฑ๋ค์ ์ ์ํ๋ค.
์๋ฅผ ๋ค์ด doubleCount๋ ํ์ฌ count์ 2๋ฐฐ ๊ฐ์ ๊ณ์ฐํ๊ณ , welcomeMessage๋ name์ ์ด์ฉํด ํ์ ๋ฉ์์ง๋ฅผ ๋ง๋ ๋ค.
actions์๋ ์ํ๋ฅผ ๋ณํ์ํค๋ ํจ์๋ค์ ์ ์ํ๋๋ฐ,
increment()๋ count๋ฅผ 1 ์ฆ๊ฐ์ํค๊ณ , setName(newName)์ name ์ํ๋ฅผ ์ฃผ์ด์ง ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๋ค.
Pinia์ actions ์์์๋ this๋ฅผ ํตํด ํด๋น ์คํ ์ด์ ์ํ์ ์ ๊ทผํ๋ฉฐ,
๋น๋๊ธฐ ์์ ์ด๋ ์ฌ๋ฌ ์ํ ๋ณ๊ฒฝ์ ํฌํจํ ๋ณต์กํ ๋ก์ง๋ ๋ฃ์ ์ ์๋ค.
์ด๋ ๊ฒ ์ ์๋ Pinia ์คํ ์ด๋ ์ปดํฌ๋ํธ์์ ์์ ๋กญ๊ฒ ํ์ฉํ ์ ์๋ค.
์ฌ์ฉํ๊ณ ์ ํ๋ ์ปดํฌ๋ํธ์ <script setup>์์ ํด๋น ์คํ ์ด๋ฅผ ์ํฌํธํ๊ณ (useCounterStore ํจ์ ์์ฒด๋ฅผ ๊ฐ์ ธ์ด),
ํธ์ถํ์ฌ ์คํ ์ด ์ธ์คํด์ค๋ฅผ ๋ฐ๋๋ค. ์๋ฅผ ๋ค๋ฉด:
<script setup>
import { useCounterStore } from '@/store/counter'
const counterStore = useCounterStore() // ์คํ ์ด ์ธ์คํด์ค ์์ฑ (์ ์ญ์์ ํ๋ ๊ณต์ ๋จ)
// ์คํ ์ด ์ํ ํ์ฉ
console.log(counterStore.count) // ํ์ฌ count ์ถ๋ ฅ
counterStore.increment() // ์ก์
ํธ์ถ๋ก ์ํ ๋ณ๊ฒฝ
counterStore.setName('Vue') // name ์ํ๋ฅผ 'Vue'๋ก ๋ณ๊ฒฝ
</script>
<template>
<p>Count: {{ counterStore.count }}</p>
<p>Double: {{ counterStore.doubleCount }}</p>
<p>{{ counterStore.welcomeMessage }}</p>
</template>
์์ ๊ฐ์ด useCounterStore()๋ฅผ ํธ์ถํ๋ฉด ํด๋น ์คํ ์ด์ ๋ ๋ฆฝ์ ์ธ ์ธ์คํด์ค๋ฅผ ๋ฐ๋๋ค.
Pinia์์๋ ์ด ์ธ์คํด์ค๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ญ์์ ์ฑ๊ธํค(singleton)์ผ๋ก ๊ด๋ฆฌ๋๋ฏ๋ก,
์ด๋ค ์ปดํฌ๋ํธ์์ ๋ถ๋ฌ๋ ๋ชจ๋ ๋์ผํ ํ๋์ ์ ์ญ ์ํ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๊ฒ ๋๋ค.
๋ฐ๋ผ์ ํ ์ปดํฌ๋ํธ์์ counterStore.increment()๋ก count๋ฅผ ์ฆ๊ฐ์ํค๋ฉด,
๋ค๋ฅธ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ๋ counterStore.count ๊ฐ๋ ์ฆ์ ์ฆ๊ฐํ ๊ฐ์ผ๋ก ๋ฐ์๋๋ค.
์ด์ฒ๋ผ Pinia๋ฅผ ์ด์ฉํ๋ฉด ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ๋์ผํ ์ํ๋ฅผ ๊ณต์ ํ๊ณ ์ค์๊ฐ์ผ๋ก ๋ฐ์ํ ์ ์์ผ๋ฉฐ,
์ํ ๋ณ๊ฒฝ ์ถ์ ์ด๋ ๋๋ฒ๊น ๋ Vue DevTools์ ์ฐ๋๋์ด ์์ํด์ง๋ค (Pinia๋ ์๊ฐ ์ฌํ ๋๋ฒ๊น , ํซ ๋ฆฌ๋ก๋ฉ ๋ฑ๋ ์ง์ํ๋ค).
์ ๋ฆฌํ๋ฉด, Vue 3 ์ปดํฌ์ง์ API ๊ธฐ๋ฐ ํ๋ก์ ํธ์์ Pinia๋ก ์ ์ญ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ฉด ๊ตฌ์กฐ์ ์ธ ์ํ ๊ณต์ ๊ฐ ๊ฐ๋ฅํ๋ค.
์ปดํฌ๋ํธ๋ค์ ํ์ํ ๋ ๊ฐ์ ์คํ ์ด๋ฅผ ๋ถ๋ฌ์ ์ํ๋ฅผ ์ฝ๊ฑฐ๋ ๊ฐฑ์ ํ๊ณ ,
์ด๋ฌํ ์ํธ ์์ฉ์ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์ ์ผ๊ด๋ ๋ฐ์ดํฐ ํ๋ฆ์ ์ ์งํ๋ค.
์ด๋ ๊ท๋ชจ๊ฐ ์ปค์ก์ ๋ ๋ฐ์ดํฐ ๋๊ธฐํ ๋ฌธ์ ๋ฅผ ์ค์ด๊ณ , ์ฝ๋์ ์ ์ง๋ณด์์ฑ์ ๋์ฌ์ค๋ค.
Pinia์ ๋ํ ๋ ์์ธํ ์ ๋ณด๋ ๋ค์ ๊ฒ์๊ธ์ธ 'Vue.js์ ์ํ ๊ด๋ฆฌ ๋๊ตฌ : Pinia'๋ฅผ ํ์ธํ๋ฉด ๋๋ค.
Vue.js์ ์ํ ๊ด๋ฆฌ ๋๊ตฌ : Pinia
Pinia๋ ๋ฌด์์ธ๊ฐPinia๋ Vue 3์์ ๊ณต์์ ์ผ๋ก ๊ถ์ฅํ๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.์ด์ ๊น์ง Vue์ ์ํ ๊ด๋ฆฌ๋ Vuex๊ฐ ์ฌ์ค์ ํ์ค์ด์์ง๋ง, Vue 3 ์ดํ๋ก๋ Pinia๊ฐ ์๋ก์ด ๊ณต์ ๋์์ด ๋์๋ค.Vuex์ ๋ณต
pids.tistory.com
์ปดํฌ์ง์ API ๊ธฐ๋ฐ ์ฝ๋ ๊ตฌํ ์์ ์ ๋ฆฌ
๋ง์ง๋ง์ผ๋ก, ์์ ์ค๋ช ํ ๊ฐ๋ ๋ค์ ์ปดํฌ์ง์ API ๊ด์ ์์ ์์ฝํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
Vue 3์์๋ Options API ๋์ Composition API๋ฅผ ํ์ฉํ์ฌ ์ํ์ ๋ก์ง์ ๊ตฌ์ฑํ๋ฉฐ,
์ด๋ ์ฝ๋์ ๋ชจ๋ํ์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ฌ์ค๋ค. ์ปดํฌ์ง์ API ํ๊ฒฝ์์ REST API ์ฐ๋๊ณผ ์ํ ๊ด๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ก ๊ตฌํ๋๋ค:
- Axios๋ฅผ ์ด์ฉํ API ํธ์ถ: ์ปดํฌ๋ํธ์ setup() ํจ์ ๋ด(ํน์ <script setup> ๋ธ๋ก)์์ axios๋ฅผ ์ํฌํธํ์ฌ ๋ฐ๋ก ์ฌ์ฉํ๋ค. onMounted ํ ์ ํตํด ์ด๊ธฐ ๋ฐ์ดํฐ ๋ก๋๋ฅผ ์ํํ๊ณ , ํ์์ ๋ฐ๋ผ methods๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด๋ถ์์ axios.get/post ๋ฑ์ ํธ์ถํ์ฌ ๋น๋๊ธฐ ์์ฒญ์ ๋ณด๋ธ๋ค. Promise ๊ธฐ๋ฐ ํธ์ถ์ด๋ฏ๋ก async/await์ ์ฌ์ฉํด ์๋ต์ ์ฒ๋ฆฌํ๊ณ , ์๋ฌ๋ try-catch๋ก ์ก๋๋ค. ์ด๋ฌํ API ํต์ ๋ก์ง์ ์ปดํฌ๋ํธ์ ์ง์ ์์ฑํ๊ฑฐ๋, ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ์ฐ์ธ๋ค๋ฉด composables/ ํด๋์ ๊ณตํต ํ ์ผ๋ก ๋ถ๋ฆฌํ ์ ์๋ค. (์: useFetch.js์ fetchItems ํจ์๋ฅผ ์์ฑํ๊ณ ๊ฐ ์ปดํฌ๋ํธ์์ ์ด๋ฅผ ํธ์ถ).
- Pinia๋ฅผ ์ด์ฉํ ์ ์ญ ์ํ ๊ด๋ฆฌ: ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ main.js์์ Pinia๋ฅผ ๋ฑ๋กํ๊ณ , ๊ฐ ์คํ ์ด๋ src/store/ ๋๋ ํฐ๋ฆฌ์ ๊ฐ๋ณ ํ์ผ๋ก ์ ์ํ๋ค. defineStore๋ก ์ ์ธ๋ ์คํ ์ด๋ ํ์ํ ์ปดํฌ๋ํธ์์ useStore() ํํ๋ก ๋ถ๋ฌ์ ์ฌ์ฉํ๋ค. ์ปดํฌ๋ํธ ๋ด์์ Pinia ์คํ ์ด๋ฅผ ์ฌ์ฉํ ๋๋ Composition API ๋ฌธ๋ฒ์ ๊ทธ๋๋ก ํ์ฉํ๋ค. ์๋ฅผ ๋ค์ด <script setup>์์ const userStore = useUserStore()๋ก ์คํ ์ด๋ฅผ ๊ฐ์ ธ์ค๊ณ , ๊ทธ ์์ state๋ getters๋ฅผ ๋ฐ๋ก ์ฐธ์กฐํ๊ฑฐ๋ actions๋ฅผ ํธ์ถํ๋ฉด ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ํ๋์ userStore ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ๋ฏ๋ก, ํ์ชฝ์์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ฉด ๋ค๋ฅธ ์ปดํฌ๋ํธ์๋ ๋ณ๊ฒฝ์ฌํญ์ด ๋ฐ์๋๋ค. Pinia๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ๊ฑธ์น ์ผ๊ด์ฑ ์๋ ์ํ ๊ณต์ ๊ฐ ์ด๋ฃจ์ด์ง๋ฉฐ, ์ปดํฌ๋ํธ ๊ฐ prop ์ ๋ฌ์ด๋ ์ด๋ฒคํธ ๋ฒ์ค ์์ด๋ ํธ๋ฆฌํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์๋ค.
์์์ ์ดํด๋ณธ ๊ตฌ์กฐ์ ์์ ์ฝ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก,
Vue.js 3 ํ๋ก์ ํธ๋ฅผ ๊ตฌ์ฑํ๋ฉด ์ด๋ณด ๊ฐ๋ฐ์๋ ์ค๋ฌด ์์ค์ ํ๋ก์ ํธ ๊ตฌ์กฐ๋ฅผ ์ดํดํ๊ณ ๊ตฌํํ ์ ์๋ค.
ํ๋ก ํธ์๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ๊ธฐ๋ฅ๋ณ๋ก ๋๋๊ณ ,
์ปดํฌ์ง์ API์ ์ฅ์ ์ ํ์ฉํด ํด๋ฆฐํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ํต์ฌ์ด๋ค.
Vue.js์ ์ ์ฐํ ์ปดํฌ๋ํธ ์์คํ , axios๋ฅผ ํตํ ์์ฌ์ด API ์ฐ๋, Pinia์ ํจ์จ์ ์ธ ์ํ ๊ณต์ ๋ฅผ ์กฐํฉํ๋ฉด,
์์ ์ธํฐํ์ด์ค๋ถํฐ ๋ณต์กํ SPA์ ์ด๋ฅด๊ธฐ๊น์ง ๊ฒฌ๊ณ ํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ถ ํ๋ก ํธ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค์ด๋ผ ์ ์๋ค.
์์ฝ
Vue.js๋ ๊ฐ๋ณ๊ณ ์ ์ฐํ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ํ๋ ์์ํฌ์ด๋ฉฐ,
Vue 3์์๋ ์ปดํฌ์ง์ API ๋์ ์ผ๋ก ๋ก์ง ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ํ ๊ด๋ฆฌ์ ์ ์ฐ์ฑ์ด ๊ฐํ๋์๋ค.
ํ๋ก์ ํธ ๊ตฌ์กฐ๋ src/ ๋๋ ํฐ๋ฆฌ๋ฅผ ์ค์ฌ์ผ๋ก
components, views, router, store, composables, assets ๋ฑ์ผ๋ก
๋ถ๋ฆฌํ์ฌ ์ ์ง๋ณด์์ฑ์ ๋์ด๋ ๊ฒ์ด ํต์ฌ์ด๋ค.
RESTful API ํต์ ์ axios๋ฅผ ์ฌ์ฉํด ๊ฐ๋จํ๊ฒ ๋น๋๊ธฐ ์์ฒญ์ ์ฒ๋ฆฌํ ์ ์์ผ๋ฉฐ,
Pinia๋ฅผ ํ์ฉํ๋ฉด ์ ์ญ ์ํ๋ฅผ ์์ ํ๊ณ ์ผ๊ด๋๊ฒ ๊ณต์ ํ ์ ์๋ค.
์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Vue ํ๋ก์ ํธ๋ฅผ ์ค๊ณํ๋ฉด ์์ ์ฑ๋ถํฐ ๋๊ท๋ชจ SPA๊น์ง
ํ์ฅ ๊ฐ๋ฅํ ํ๋ก ํธ์๋ ์ํคํ ์ฒ๋ฅผ ๊ตฌํํ ์ ์๋ค.
์ฐธ๊ณ ์๋ฃ
- Vue.js ๊ณต์ ๋ฌธ์ : ko.vuejs.org
- Vue FAQ ์๋ฃ : vue-faq.orgvue-faq.org
- LogRocket ๋ธ๋ก๊ทธ : blog.logrocket.comblog.logrocket.com
- Pinia ๊ณต์ ๋ฌธ์ : pinia.vuejs.orgpinia.vuejs.org ๋ฑ.
'๐ป Frontend > Vue.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Vue 3 + Vite์์ Axios API ๊ตฌ์กฐ ์๋ฒฝ ๊ฐ์ด๋ (4) | 2025.06.05 |
|---|---|
| Vue.js์ ์ํ ๊ด๋ฆฌ ๋๊ตฌ : Pinia (0) | 2025.06.02 |