예약 관리 시스템 - Spring + Vue
예약 관리 시스템 (Spring Boot 3 + Vue 3) - 사용자 인증 프론트엔드 (Vue 3 + Vuetify)
그랜파 개발자
2025. 5. 26. 11:01
Spring Boot 백엔드와 연동 가능한 Vue 3 + Vuetify 기반의 간단한 홈, 회원가입, 로그인 예제입니다.
기본적인 페이지와 API 연동 코드, 라우터, Vuetify UI를 포함합니다.
1. 프로젝트
npm init vue@latest
Project name (target directory):
│ reservation
cd reservation
npm install
npm install vue-router@4 vuetify@3 axios
2. main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import 'vuetify/styles';
import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';
const vuetify = createVuetify({
components,
directives,
});
createApp(App).use(router).use(vuetify).mount('#app');
3. router.js
import { createRouter, createWebHistory } from 'vue-router';
import Home from '@/views/HomeView.vue' //./HomeView.vue';
import SignUp from '@/views/SignUp.vue';
import Login from '@/views/Login.vue';
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/signup', name: 'SignUp', component: SignUp },
{ path: '/login', name: 'Login', component: Login },
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
4. api/auth.js (Axios로 Spring Boot API 호출)
import axios from 'axios';
const API_URL = 'http://localhost:8080/api/auth'; // Spring Boot 백엔드 주소
export function signUp(user) {
// user = { username, email, password }
return axios.post(`${API_URL}/register`, user);
}
export function login(credentials) {
// credentials = { username, password }
return axios.post(`${API_URL}/login`, credentials);
}
5. App.vue
<template>
<v-app>
<v-app-bar app color="primary" dark>
<v-toolbar-title>예약관리 시스템</v-toolbar-title>
<v-spacer />
<v-btn text to="/">홈</v-btn>
<v-btn text to="/login">로그인</v-btn>
<v-btn text to="/signup">회원가입</v-btn>
</v-app-bar>
<v-main>
<v-container class="mt-5">
<router-view />
</v-container>
</v-main>
</v-app>
</template>
<script setup>
</script>
6. views/Home.vue
<template>
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" md="6">
<v-card>
<v-card-title>홈 페이지</v-card-title>
<v-card-text>
<p>Spring Boot + Vue 3 + Vuetify 예제 홈 화면입니다.</p>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
7. views/SignUp.vue
<template>
<v-container>
<v-row justify="center">
<v-col cols="12" md="6">
<v-card>
<v-card-title>회원가입</v-card-title>
<v-card-text>
<v-form @submit.prevent="submitSignUp" ref="form">
<v-text-field v-model="user.email" label="이메일" type="email" required />
<v-text-field v-model="user.password" label="비밀번호" type="password" required />
<v-text-field v-model="user.username" label="사용자 이름" required />
<v-btn type="submit" color="primary" :loading="loading" block>가입하기</v-btn>
</v-form>
<v-alert v-if="error" type="error" class="mt-4">{{ error }}</v-alert>
<v-alert v-if="success" type="success" class="mt-4">{{ success }}</v-alert>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script setup>
import { ref } from 'vue'
import { signUp } from '../api/auth'
const user = ref({
name: '',
email: '',
password: '',
})
const loading = ref(false)
const error = ref('')
const success = ref('')
const submitSignUp = async () => {
loading.value = true
error.value = ''
success.value = ''
try {
const response = await signUp(user.value)
success.value = response.data.message || '회원가입 성공! 로그인 페이지로 이동합니다.'
setTimeout(() => {
window.location.href = '/login'
}, 1500)
} catch (e) {
error.value = e.response?.data?.message || '회원가입 실패'
} finally {
loading.value = false
}
}
</script>
8. views/Login.vue
<template>
<v-container>
<v-row justify="center">
<v-col cols="12" md="6">
<v-card>
<v-card-title>로그인</v-card-title>
<v-card-text>
<v-form @submit.prevent="submitLogin">
<v-text-field v-model="email" label="이메일" type="email" required />
<v-text-field v-model="password" label="비밀번호" type="password" required />
<v-btn type="submit" color="primary" :loading="loading" block>로그인</v-btn>
</v-form>
<v-alert v-if="error" type="error" class="mt-4">{{ error }}</v-alert>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { login } from '../api/auth'
const email = ref('')
const password = ref('')
const loading = ref(false)
const error = ref('')
const router = useRouter()
const submitLogin = async () => {
loading.value = true
error.value = ''
try {
const response = await login({ email: email.value, password: password.value })
// 로그인 성공 시 토큰 저장 및 이동
const token = response.token
localStorage.setItem('token', token)
router.push('/')
} catch (e) {
error.value = e.response?.data?.message || '로그인 실패'
} finally {
loading.value = false
}
}
</script>
✅ 개발 서버 실행
npm run dev
브라우저에서 http://localhost:5173 열어 확인하세요.