[Vue.js] Vue ํ๋ก์ ํธ ๊ตฌ์กฐ ์ดํดํ๊ธฐ
Vue3์์๋ ์ปดํฌ๋ํธ๋ฅผ ๋์ฑ ์ง๊ด์ ์ด๊ณ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋ค๊ธฐ ์ํด <script setup> ๋ฌธ๋ฒ์ด ๋์ ๋์์ต๋๋ค.
์ด ๊ธ์์๋ Vue 3์์ <script setup> ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ ํ๋ก์ ํธ ๊ตฌ์กฐ์ ๊ฐ ํ์ผ์ ์ญํ ์ ์ค๋ช ํ๊ฒ ์ต๋๋ค๐
1. Vue ํ๋ก์ ํธ ํ์ผ ๊ตฌ์กฐ ( Vite ๊ธฐ๋ฐ )
Vite๋ฅผ ์ฌ์ฉํ์ฌ Vue 3 ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ฉด ์๋์ ๊ฐ์ ํด๋ ๋ฐ ํ์ผ ๊ตฌ์กฐ๊ฐ ๋ง๋ค์ด์ง๋๋ค.
my-vue-app/
โโโ node_modules/
โโโ public/
โโโ src/
โ โโโ assets/
โ โโโ components/
โ โโโ App.vue
โ โโโ main.js
โโโ index.html
โโโ package.json
โโโ vite.config.js
๊ธฐ๋ณธ์ ์ผ๋ก๋ ์์ ๊ฐ์ ํด๋๊ตฌ์กฐ๊ฐ ๋์ค์ง๋ง, ์ด์ ๊ธ์์ vue๋ฅผ ์์ฑํ์ จ๋๋ผ๋ฉด, ์๋์ ๊ฐ์ด ๋์ฌ ๊ฒ์ ๋๋ค.
my-vue-app/
โโโ node_modules/
โโโ public/
โโโ src/
โ โโโ assets/
โ โโโ components/
โ โโโ router/
โ โโโ stores/
โ โโโ views/
โ โโโ App.vue
โ โโโ main.js
โโโ .eslintrc.cjs
โโโ .prettierrc.json
โโโ index.html
โโโ package.json
โโโ vite.config.js

- node_modules ํด๋: ํด๋๋ ํ๋ก์ ํธ์์ ์ฌ์ฉํ๋ ๋ชจ๋ npm ํจํค์ง์ ๊ทธ ์์กด์ฑ๋ค์ด ์ ์ฅ๋๋ ํด๋์ ๋๋ค.
- src ํด๋: ์ฃผ์ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋๊ฐ ์ ์ฅ๋๋ ๊ณณ์ ๋๋ค.
- public ํด๋: ์ ์ ํ์ผ์ด ์์นํ๋ ๊ณณ์ผ๋ก, ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ธฐ๋ณธ HTML์ด๋ ์ด๋ฏธ์ง, ํฐํธ ํ์ผ ๋ฑ์ ์ฌ๊ธฐ์ ๋ฃ์ต๋๋ค.
- vite.config.js: Vite์ ์ค์ ํ์ผ๋ก, ํ๋ก์ ํธ์ ๋น๋ ๋ฐ ๊ฐ๋ฐ ์๋ฒ ๊ตฌ์ฑ์ ๊ด๋ฆฌํฉ๋๋ค.
- eslintrc.cjs: eslintrc.cjs ํ์ผ์ ESLint์ ์ค์ ํ์ผ๋ก, JavaScript ๋ฐ Vue ํ์ผ์์ ์ฝ๋ ํ์ง์ ์ ์งํ๊ณ ์ผ๊ด์ฑ์ ๋์ด๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
- prettierrc.json: prettierrc.json ํ์ผ์ Prettier์ ์ค์ ํ์ผ๋ก, ์ฝ๋ ํฌ๋งคํ ๊ท์น์ ์ ์ํฉ๋๋ค.
- package.json: package.json ํ์ผ์ ํ๋ก์ ํธ์ ๊ธฐ๋ณธ ์ ๋ณด๋ฅผ ์ ์ํ๋ฉฐ, npm ํจํค์ง ๊ด๋ฆฌ ์์คํ ๊ณผ ์ํธ์์ฉํ๋ ๋ฐ ํ์ํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ต๋๋ค.
2. main.js ํ์ผ
main.js๋ Vue.js ์ ํ๋ฆฌ์ผ์ด์ ์ ์ง์ ์ ( entry point ) ์ญํ ์ ํ๋ ํ์ผ์ ๋๋ค. Vue ์ ํ๋ฆฌ์ผ์ด์ ์ด ์คํ๋ ๋ ๊ฐ์ฅ ๋จผ์ ์ด ํ์ผ์ด ์คํ๋๋ฉฐ, ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๊ธฐ ์ค์ ์ด ์ด๋ฃจ์ด์ง๋ ๊ณณ์ ๋๋ค. Vue ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ ํน์ DOM ์์์ ๋ง์ดํธ( Mount )ํ๋ ์ญํ ์ ํฉ๋๋ค.
3. App.vue ํ์ผ
App.vue๋ ํ๋ก์ ํธ์ ๋ฃจํธ ์ปดํฌ๋ํธ๋ก, ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์ ๋ ์ด์์์ด๋ ์ฃผ์ ๊ตฌ์กฐ๋ฅผ ๋ด๋นํฉ๋๋ค.
Vue 3์ <script setup>์ ์ฌ์ฉํ๋ฉด ์ฝ๋๊ฐ ๋์ฑ ๊ฐ๊ฒฐํด์ง๋๋ค.
<template>
<div id="app">
<h1>{{ title }}</h1>
<MyComponent />
</div>
</template>
<script setup>
import { ref } from 'vue';
import MyComponent from './components/MyComponent.vue';
const title = ref('Hello Vite + Vue 3!');
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
text-align: center;
margin-top: 60px;
}
</style>
- <template>: ์ปดํฌ๋ํธ์ HTML ๊ตฌ์กฐ๋ฅผ ์ ์ํฉ๋๋ค.
- <script setup>: ์ปดํฌ๋ํธ ๋ก์ง์ ์์ฑํ๋ ๋ถ๋ถ์ผ๋ก, Vue์ ref, reactive ๊ฐ์ ์ํ ๊ด๋ฆฌ ๊ธฐ๋ฅ์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- <style>: ์ปดํฌ๋ํธ์ ๋ํ ์คํ์ผ์ ์ง์ ํ๋ ๋ถ๋ถ์ ๋๋ค.
ref, reactive๋?
ref : ๊ธฐ๋ณธ ๋ฐ์ดํฐ ํ์ (๋ฌธ์์ด, ์ซ์ ๋ฑ)์ด๋ ๊ฐ์ฒด๋ฅผ ๋ฐ์ํ์ผ๋ก ๋ง๋ค๊ธฐ ์ํด ์ฌ์ฉํ๋ API์ ๋๋ค.
reactive : ๊ฐ์ฒด๋ฅผ ๋ฐ์ํ์ผ๋ก ๋ง๋ค๊ธฐ ์ํด ์ฌ์ฉํ๋ API์ ๋๋ค. reactive๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ์์ฑ์ด ๋ฐ์ํ์ด ๋ฉ๋๋ค.
// ref
import { ref } from 'vue';
const count = ref(0); // count๋ณ์๋ฅผ ๋ฐ์ํ ๋ณ์๋ก ๋ง๋ญ๋๋ค.
function increment() {
count.value++; // ๊ฐ์ ๋ณ๊ฒฝ ํ๋ฉด UI์ ์๋ ๋ฐ์๋ฉ๋๋ค.
}
// reactive
import { reactive } from 'vue';
const state = reactive({
count: 0,
message: 'Hello, Vue!'
});
function increment() {
state.count++; // ๊ฐ์ ๋ณ๊ฒฝ ํ๋ฉด UI์ ์๋ ๋ฐ์๋ฉ๋๋ค.
}
4. Vite์ ์ญํ
Vite๋ ๋น ๋ฅธ ๊ฐ๋ฐ ํ๊ฒฝ์ ์ ๊ณตํ๋ ๋น๋ ๋๊ตฌ๋ก, ํ๋ก์ ํธ๋ฅผ ์์ฑํ ๋ ๊ธฐ๋ณธ์ ์ธ ์ค์ ์ ์ต์ํํ๋ฉด์ ๋น ๋ฅธ ๋ฒ๋ค๋ง๊ณผ HMR(Hot Module Replacement) ๋ฑ์ ์ง์ํฉ๋๋ค.
- ๋น ๋ฅธ ๋น๋: Vite๋ ๋ค์ดํฐ๋ธ ES ๋ชจ๋์ ๊ธฐ๋ฐ์ผ๋ก ํ์ฌ ๋น ๋ฅธ ๋น๋ ์๋๋ฅผ ์๋ํฉ๋๋ค.
- HMR ์ง์: ๋ณ๊ฒฝ๋ ํ์ผ๋ง์ ๋น ๋ฅด๊ฒ ๋ฆฌ๋ก๋ํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํด ๊ฐ๋ฐ ์๋๋ฅผ ํฅ์์ํต๋๋ค.
HMR์ด๋?
๋ชจ๋ ๊ต์ฒด๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ฅผ ์ ์งํ๋ฉด์ ๋ณ๊ฒฝ๋ ๋ชจ๋์ ์ฆ์ ์ ๋ฐ์ดํธ ํ ์ ์๋ ๊ฐ๋ฐ ๋๊ตฌ์ ๋๋ค.
์ฃผ๋ก ์น ๊ฐ๋ฐ์์ ์ฌ์ฉ๋๋ฉฐ, ํนํ Vue.js์ Vite์ ๊ฐ์ JavaScript ํ๋ ์์ํฌ ๋ฐ ๋น๋ ๋๊ตฌ์์ ์ง์ํฉ๋๋ค.