보라코딩
Vue, 스프링부트 REST API (3) 본문
vue router 추가
vue 터미널에 입력해서 라우터 설치
npm i vue-router
main.js
import {createApp} from 'vue'
import App from './App.vue'
import {createRouter, createWebHistory} from 'vue-router'
import Home from "@/pages/Home.vue";
import Login from "@/pages/Login.vue";
const routes = [
{path: '/', component: Home},
{path: '/login', component: Login}
]
const router = createRouter({
history: createWebHistory(), routes: routes
})
createApp(App).use(router).mount('#app')
App.vue
RouterView로 변경!
<template>
<Header/>
<RouterView/>
<Footer/>
</template>
<script>
import Header from "@/components/Header.vue";
import Footer from "@/components/Footer.vue";
export default {
name: 'App',
components: {
Footer,
Header
}
}
</script>
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
.b-example-divider {
width: 100%;
height: 3rem;
background-color: rgba(0, 0, 0, .1);
border: solid rgba(0, 0, 0, .15);
border-width: 1px 0;
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
}
.b-example-vr {
flex-shrink: 0;
width: 1.5rem;
height: 100vh;
}
.bi {
vertical-align: -.125em;
fill: currentColor;
}
.nav-scroller {
position: relative;
z-index: 2;
height: 2.75rem;
overflow-y: hidden;
}
.nav-scroller .nav {
display: flex;
flex-wrap: nowrap;
padding-bottom: 1rem;
margin-top: -1px;
overflow-x: auto;
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
.btn-bd-primary {
--bd-violet-bg: #712cf9;
--bd-violet-rgb: 112.520718, 44.062154, 249.437846;
--bs-btn-font-weight: 600;
--bs-btn-color: var(--bs-white);
--bs-btn-bg: var(--bd-violet-bg);
--bs-btn-border-color: var(--bd-violet-bg);
--bs-btn-hover-color: var(--bs-white);
--bs-btn-hover-bg: #6528e0;
--bs-btn-hover-border-color: #6528e0;
--bs-btn-focus-shadow-rgb: var(--bd-violet-rgb);
--bs-btn-active-color: var(--bs-btn-hover-color);
--bs-btn-active-bg: #5a23c8;
--bs-btn-active-border-color: #5a23c8;
}
.bd-mode-toggle {
z-index: 1500;
}
</style>
Login.vue
부트스트랩으로 로그인화면 만들기
<template>
<div class="form-signin w-100 m-auto">
<form>
<h1 class="h3 mb-3 fw-normal">Please sign in</h1>
<div class="form-floating">
<input type="email" class="form-control" id="floatingInput" placeholder="name@example.com">
<label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">Password</label>
</div>
<div class="form-check text-start my-3">
<input class="form-check-input" type="checkbox" value="remember-me" id="flexCheckDefault">
<label class="form-check-label" for="flexCheckDefault">
Remember me
</label>
</div>
<button class="btn btn-primary w-100 py-2" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-body-secondary">© 2017–2023</p>
</form>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.form-signin {
max-width: 330px;
padding: 1rem;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
</style>

backend 로그인 기능 구현
DB에 members 테이블 생성

Member(entity)
package com.example.backend.entity;
import lombok.Getter;
import javax.persistence.*;
@Table(name="members")
@Entity
@Getter
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //자동증가
private int id;
@Column(length = 50, nullable = false, unique = true)
private String email;
@Column(length = 100, nullable = false)
private String password;
}
MemberRepository
package com.example.backend.repository;
import com.example.backend.entity.Item;
import com.example.backend.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MemberRepository extends JpaRepository<Member, Integer> {
Member findByEmailAndPassword(String email, String password);
}
AccountController (로그인 컨트롤러)
package com.example.backend.controller;
import com.example.backend.entity.Item;
import com.example.backend.entity.Member;
import com.example.backend.repository.ItemRepository;
import com.example.backend.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@CrossOrigin("http://localhost:3001/")
public class AccountController {
@Autowired
MemberRepository memberRepository;
@PostMapping("/api/account/login")
public int login(@RequestBody Map<String, String> params) {
Member member = memberRepository.findByEmailAndPassword(params.get("email"), params.get("password"));
if (member != null) {
return member.getId();
}
return 0;
}
}
return 0은 추후에 바꿔줌
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
frontend 로그인
이미 화면은 만들어둔 상태이고
Card.vue
input email에 v-model로 바인
<input type="email" class="form-control" id="floatingInput" placeholder="name@example.com"
v-model="state.form.email">
password도 바인딩
<input type="password" class="form-control" id="floatingPassword" placeholder="Password"
v-model="state.form.password">
버튼에 submit 함수
<button class="btn btn-primary w-100 py-2" type="submit" @click="submit()">Sign in</button>
setup에 state 입력하고 submit 함수도 입력
export default {
setup() {
const state = reactive({
form: {
email: "",
password: ""
}
})
const submit = () => {
axios.post("/api/account/login", state.form)
.then((res) => {
console.log(res);
window.alert("로그인 완료!!");
})
}
return {state, submit}
}
}
DB에 데이터 임의로 넣어두고
http://localhost:3001/login 에서 로그인하면 로그인 제대로 되는 것 확인 가능
Vuex로 로그인 보완
Header.vue 수정
<li>
<router-link to="/" class="text-white">메인화면</router-link>
</li>
<li>
<router-link to="/login" class="text-white">로그인</router-link>
</li>
터미널에서 vuex 설치하기
npm install vuex@next --save
store.js 생성하기 (scripts 폴더 밑에)
import { createStore } from 'vuex'
// Create a new store instance.
const store = createStore({
state () {
return {
account: {
id : 0
}
}
},
mutations: {
setAccount(state, payload){
state.account.id = payload;
}
}
})
export default store;
main.js
사용하기 위해 main.js에 추가
import store from "@/scripts/store";
createApp(App).use(store).use(router).mount('#app')
Login.vue
submit 함수 내용을 변경
store 포함하게
const submit = () => {
axios.post("/api/account/login", state.form)
.then((res) => {
store.commit('setAccount', res.data);
window.alert("로그인 완료!!");
})
}
Header.vue
v-if 사용해서 아이디가 없으면 로그인 뜨고
아니면 로그아웃 뜨게 변경
<li>
<router-link to="/login" class="text-white" v-if="!$store.state.account.id">로그인</router-link>
<router-link to="/login" class="text-white" v-else>로그아웃</router-link>
</li>
다시 로그아웃 부분 변경
<a to="/login" class="text-white" @click="logout()" v-else>로그아웃</a>
router.js (새로 생성)
기존 main.js에 있는 router를 따로 생성
import Home from "@/pages/Home.vue";
import Login from "@/pages/Login.vue";
import {createRouter, createWebHistory} from "vue-router";
const routes = [
{path: '/', component: Home},
{path: '/login', component: Login}
]
const router = createRouter({
history: createWebHistory(), routes: routes
})
export default router;
Header.vue
import해서 router을 사용 가능
export default {
name: 'Header',
setup(){
const logout = () => {
store.commit('setAccount',0);
router.push({path:"/"});
}
return {logout}
}
}
Login.vue
session에 저장시킴!
router도 지정해줌!
catch로 예외처리도!
const submit = () => {
axios.post("/api/account/login", state.form)
.then((res) => {
store.commit('setAccount', res.data);
sessionStorage.setItem("id", res.data);
router.push({path:"/"});
window.alert("로그인 완료!!");
})
.catch(() => {
window.alert("로그인 정보가 존재하지 않아요!")
})
}
Header.vue
로그아웃시에는 session remove
export default {
name: 'Header',
setup(){
const logout = () => {
store.commit('setAccount',0);
sessionStorage.removeItem("id");
router.push({path:"/"});
}
return {logout}
}
}
App.vue
sessionStorage로 id 받아와서
상태변경 해줌
export default {
name: 'App',
components: {
Footer,
Header
},
setup(){
const id = sessionStorage.getItem("id");
if (id){
store.commit("setAccount", id);
}
}
}
'코딩 > Vue' 카테고리의 다른 글
Vue, 스프링부트 REST API (2) (0) | 2023.09.12 |
---|---|
Vue, 스프링부트 REST API (1) (0) | 2023.09.10 |
vue 설치 및 기초 (0) | 2023.08.29 |