0419 - 0425
0419 ~ 0423
중간고사 기간
0424
중간고사를 마무리 하고 다시 프로젝트를 이어서 진행하였다. api를 사용하는 영역을 모듈화 하고 인터셉터로 처리하였다.
인터셉터
// interceptors.js
import store from "@/store/index";
export function setInterceptors(axiosService) {
axiosService.interceptors.request.use(
function (config) {
// 요청을 보내기 전에 어떤 처리를 할 수 있다.
config.headers.Authorization = `Bearer ${store.state.member.token}`;
console.log(config);
return config;
},
function (error) {
// 요청이 잘못되었을 때, 에러가 컴포넌트 단으로 오기 전에 어떤 처리를 할 수 있다.
return Promise.reject(error);
}
);
axiosService.interceptors.response.use(
function (response) {
// 요청을 보내고 나서 응답을 받기 전에 어떤 처리를 할 수 있다.
console.log(response);
return response;
},
function (error) {
// 응답이 에러인 경우 미리 처리할 수 있다.
return Promise.reject(error);
}
);
return axiosService;
}
- 인터셉터를 이용하면 HTTP 요청과 응답을 컴포넌트 단에서 처리하기 전에 추가 로직을 넣을 수 있다.
- 요청하기 전에 헤더의 권한에 스토어에 저장된 토큰 값을 설정하였다.
- 요청과 응답 모두 결과를 확인하기 위해 console.log로 찍어보았다.
모듈화
// index.js
import axios from "axios";
import { setInterceptors } from "./common/interceptors";
function createAxiosService() {
return axios.create({
baseURL: process.env.VUE_APP_API_URL,
});
}
function createAxiosServiceWithAuth() {
const axiosService = axios.create({
baseURL: process.env.VUE_APP_API_URL,
});
return setInterceptors(axiosService);
}
export const axiosService = createAxiosService();
export const axiosServiceWithAuth = createAxiosServiceWithAuth();
- 모듈화를 하기 위해 공통으로 설정할 index.js를 작성하였다.
- axiosService는 기본 api 호출을 위한 것이고, axiosServiceWithAuth는 인터셉터를 거쳐서 토큰을 권한에 설정하여 로그인이 필요한 api를 호출하기 위해 구분한 것이다.
// member.js
import { axiosService } from "./index";
const register = data => {
return axiosService.post("members/new", data);
};
const login = data => {
return axiosService.post("members/login", data, { withCredentials: true });
};
export default { register, login };
// board.js
import { axiosServiceWithAuth } from "./index";
const getBoardList = data => {
return axiosServiceWithAuth.get("boards/lists", data);
};
export default { getBoardList };
- 위와 같이 index.js만 import하여 코드가 훨씬 간결해지고 깔끔해졌다.
0425
로그인, 로그아웃
vuex만 사용하면 새로고침 시 저장된 state가 초기화 되기 때문에 쿠키를 사용해서 기능을 구현하였다.
// utils/cookies.js
const getAuthFromCookie = () => {
return document.cookie.replace(
/(?:(?:^|.*;\s*)jwt\s*=\s*([^;]*).*$)|^.*$/,
"$1"
);
};
const getMemberNameFromCookie = () => {
return document.cookie.replace(
/(?:(?:^|.*;\s*)memberName\s*=\s*([^;]*).*$)|^.*$/,
"$1"
);
};
function deleteCookie(value) {
document.cookie = `${value}=; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
}
export { getAuthFromCookie, getMemberNameFromCookie, deleteCookie };
- utils에 쿠키와 관련된 함수를 작성하였다.
- get 관련 함수는 백엔드 서버단에서 생성해준 쿠키를 반환하는 함수이다.
- deleteCookie는 값을 매개변수로 받아서 해당하는 쿠키를 삭제한다.
// store/module/member.js
import memberService from "@/api/member";
import {
getAuthFromCookie,
getMemberNameFromCookie,
deleteCookie,
} from "@/utils/cookies";
export const member = {
state: {
token: getAuthFromCookie() || "",
memberName: getMemberNameFromCookie() || "",
},
getters: {
isLogin(state) {
return state.memberName !== "";
},
},
actions: {
async register({ commit }, member) {
const result = await memberService.register(member);
console.log(result);
},
async login({ commit }, member) {
const result = await memberService.login(member);
commit("setToken", getAuthFromCookie());
commit("setMemberName", getMemberNameFromCookie());
return result;
},
},
mutations: {
setToken(state, token) {
state.token = token;
},
setMemberName(state, memberName) {
state.memberName = memberName;
},
logout(state) {
(state.token = ""), (state.memberName = "");
deleteCookie("jwt");
deleteCookie("memberName");
},
},
};
- 회원과 관련된 store이다.
- 로그인 시 login api를 호출하여 백엔드 서버 단에서 쿠키에 토큰 값과 회원 이름을 저장해준다.
- setToken과 setMemberName을 호출하여 쿠키에서 값을 꺼내와 state에 저장해준다.
- 새로고침을 해도 token과 memberName은 쿠키에서 값을 꺼내오기 때문에 값이 초기화되지 않아서 상태를 유지한다.
- 로그아웃 시에는 state와 쿠키 값을 삭제하고 login 페이지로 이동한다.
비로그인 시 url로 접근 제한
권한이 없는 경우에도 url로 페이지에 접근하는 것을 막기 위해 router에서 설정할 수 있다.
// router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import store from "@/store/index";
Vue.use(VueRouter);
const routes = [
{
path: "/",
redirect: "/login",
},
{
path: "/login",
name: "Login",
component: () => import("@/views/Login.vue"),
},
{
path: "/signup",
name: "Signup",
component: () => import("@/views/Signup.vue"),
},
{
path: "/main",
name: "Main",
component: () => import("@/views/Main.vue"),
meta: { auth: true },
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
router.beforeEach((to, from, next) => {
if (to.meta.auth && !store.getters.isLogin) {
alert("로그인 페이지로 이동합니다.");
next("/login");
return;
}
next();
});
export default router;
- beforeEach는 라우터 네비게이션 가드로 라우팅이 발생하기 전에 실행되는 코드이다.
- to는 이동하려는 페이지, from은 현재 페이지, next는 다음 페이지로 이동할 수 있도록 호출하는 API이다.
- 접근 권한이 필요한 페이지에 meta 속성을 사용해 정의한다.
- meta 속성과 실제로 권한이 있는지를 확인해서 접근 권한이 필요한 페이지에 권한이 없다면 alert창으로 오류 메시지를 띄우고 login 창으로 이동하는 코드이다.