웹 브라우저에서 새로고침(F5)을 하면 Vue가 초기화되면서 Vuex store의 state가 초기화됩니다.
페이지 새로고침 후 Vuex store의 state 초기화
1. Node.js 레스트 API 서버를 먼저 실행시킵니다.
콘솔을 실행하고 Node.js 레스트 API 서버 프로젝트가 있는 C:\workspaces\nodeserver\testrestapi 폴더로 이동합니다. 그리고 npm run 명령어를 실행합니다.
npm run start
2. Vue를 실행시킵니다.
콘솔을 실행하고 Vue 프로젝트가 있는 C:\workspaces\nodeserver\testvue 폴더로 이동합니다. 그리고 콘솔에서 npm run 명령어를 실행합니다.
npm run serve
그리고 로그인을 합니다.
3. F5 나 마우스 오른쪽 컨텍스트 메뉴에서 새로고침을 클릭합니다. 그러면 로그인이 해제됩니다.
그래서 Vuex store의 state에 있는 정보를 유지하기 위해서는 state의 정보를 저장하고 초기화되면 다시 읽어 들어 유지하게 하면 됩니다.
state의 정보를 저장하고 유지하기 위해 다음과 같이 세 가지 방법이 있습니다.
1. Storage(스토리지)를 사용하는 방법
2. Cookie(쿠키)를 사용하는 방법
3. Vuex PersistedState를 사용하는 방법
첫 번째로 추가 라이브러리 설치 없이 바로 사용할 수 있는 Storage(스토리지)를 사용하는 방법을 알아보도록 하겠습니다.
Storage(스토리지)를 사용하는 방법
웹 브라우저에서 F12 키를 누르면 개발자 툴이 나타납니다.
여기서 Application를 클릭하고 Storage를 클릭합니다.
HTML5에서는 데이터를 클라이언트에 저장할 수 있게 Storage를 지원합니다.
Storage는 키(key)와 값(value)으로 구성되어 저장되고 키(key)로 조회됩니다.
Storage는 Local Storage(로컬 스토리지)와 Session Storage(섹션 스토리지)가 있습니다.
Local Storage(로컬 스토리지)는 영구적으로 저장되고 Session Storage(섹션 스토리지)는 임시적으로 저장됩니다. Local Storage(로컬 스토리지)는 삭제하지 않는 한 계속 유지됩니다. 그러나 Session Storage(섹션 스토리지)는 웹 브라우저가 종료되면 사라집니다.
그래서 Vuex store의 state를 유지하기 위해서 Local Storage(로컬 스토리지)를 사용합니다.
Storage(스토리지)에 state 저장하고 읽기
1. C:\workspaces\nodeserver\testvue\src\store\modules\login.js 파일을 오픈합니다.
Local Storage(로컬 스토리지)에 state를 저장하기 위해서 mutations에 saveStateToStorage() 함수를 추가합니다. state에 있는 memberId, accessToken, refreshToken를 localStorage의 setItem() 메서드로 저장합니다.
mutations: {
// memberId를 설정합니다.
setMmemberId(state, memberId) {
state.memberId = memberId;
},
// Access-Token를 설정합니다.
setAccessToken(state, accessToken) {
state.accessToken = accessToken;
},
// Refresh-Token를 설정합니다.
setRefreshToken(state, refreshToken) {
state.refreshToken = refreshToken;
},
// 초기화시킵니다.
reset(state) {
state.memberId = '';
state.accessToken = '';
state.refreshToken = '';
},
// Storage에 state를 저장합니다.
saveStateToStorage(state) {
localStorage.setItem("testvue.login.memberId", state.memberId);
localStorage.setItem("testvue.login.accessToken", state.accessToken);
localStorage.setItem("testvue.login.refreshToken", state.refreshToken);
}
}
2. actions의 doLogin() 함수에서 state를 저장하기 위해 store의 commit() 메서드로 saveStateToStorage() 함수를 호출합니다.
// 로그인합니다.
async doLogin({ commit }, memberInfo) {
let result = false;
let resultErr = null;
try {
let res = await axios.post("http://localhost:9000/members/login", memberInfo);
if (res.data.success == true) {
console.log("로그인되었습니다.");
commit('setMmemberId', memberInfo.id);
commit('setAccessToken', res.data.accessToken);
commit('setRefreshToken', res.data.refreshToken);
// Storage에 state를 저장합니다.
commit('saveStateToStorage');
axios.defaults.headers.common['Access-Token'] = res.data.accessToken;
result = true;
} else {
console.log("로그인되지 않았습니다.");
let err = new Error("Request failed with status code 401");
err.status = 401;
err.response = {data:{"success":false, "errormessage":"로그인되지 않았습니다."}};
resultErr = err;
}
} catch(err) {
if (!err.response) {
err.response = {data:{"success":false, "errormessage":err.message}};
}
resultErr = err;
}
return new Promise((resolve, reject) => {
if (result) {
resolve();
} else {
reject(resultErr);
}
});
}
3. 로그인을 합니다. 그러면 Application의 Local Storage(로컬 스토리지)에 state가 저장되어 있는 것을 확인할 수 있습니다.
그러나 웹 브라우저에서 새로고침(F5)을 하면 Vue는 여전히 초기화됩니다.
4. Local Storage(로컬 스토리지)에서 저장된 state를 읽기 위해서 mutations에 readStateFromStorage() 함수를 추가합니다. 저장된 정보를 localStorage의 getItem() 메서드로 읽어 들어 state에 적용합니다.
mutations: {
// memberId를 설정합니다.
setMmemberId(state, memberId) {
state.memberId = memberId;
},
// Access-Token를 설정합니다.
setAccessToken(state, accessToken) {
state.accessToken = accessToken;
},
// Refresh-Token를 설정합니다.
setRefreshToken(state, refreshToken) {
state.refreshToken = refreshToken;
},
// 초기화시킵니다.
reset(state) {
state.memberId = '';
state.accessToken = '';
state.refreshToken = '';
},
// Storage에 state를 저장합니다.
saveStateToStorage(state) {
localStorage.setItem("testvue.login.memberId", state.memberId);
localStorage.setItem("testvue.login.accessToken", state.accessToken);
localStorage.setItem("testvue.login.refreshToken", state.refreshToken);
},
// Storage에서 state를 읽어옵니다.
readStateFromStorage(state) {
if (localStorage.getItem("testvue.login.memberId") != null) {
state.memberId = localStorage.getItem("testvue.login.memberId");
}
if (localStorage.getItem("testvue.login.accessToken") != null) {
state.accessToken = localStorage.getItem("testvue.login.accessToken");
}
if (localStorage.getItem("testvue.login.refreshToken") != null) {
state.refreshToken = localStorage.getItem("testvue.login.refreshToken");
}
}
}
5. actions에 doReadStateFromStorage() 함수를 추가하여 store의 commit() 메서드로 readStateFromStorage() 함수를 호출합니다.
doReadStateFromStorage({commit}) {
commit('readStateFromStorage');
}
6. C:\workspaces\nodeserver\testvue\src 폴더에서 App.vue 파일을 오픈하여 <script>에 mounted() 함수를 추가하고 store의 dispatch() 메서드를 사용하여 호출합니다.
mounted() {
this.$store.dispatch("loginStore/doReadStateFromStorage");
}
7. 웹 브라우저에서 새로고침(F5)을 하면 로그인이 유지되는 것을 확인할 수 있습니다.
8. 로그아웃되면 Local Storage(로컬 스토리지)에서 저장된 state를 삭제시키기 위해 reset() 함수에 추가합니다. localStorage의 removeItem() 메서드로 삭제합니다.
mutations: {
// memberId를 설정합니다.
setMmemberId(state, memberId) {
state.memberId = memberId;
},
// Access-Token를 설정합니다.
setAccessToken(state, accessToken) {
state.accessToken = accessToken;
},
// Refresh-Token를 설정합니다.
setRefreshToken(state, refreshToken) {
state.refreshToken = refreshToken;
},
// 초기화시킵니다.
reset(state) {
state.memberId = '';
state.accessToken = '';
state.refreshToken = '';
localStorage.removeItem("testvue.login");
},
// Storage에 state를 저장합니다.
saveStateToStorage(state) {
localStorage.setItem("testvue.login.memberId", state.memberId);
localStorage.setItem("testvue.login.accessToken", state.accessToken);
localStorage.setItem("testvue.login.refreshToken", state.refreshToken);
},
// Storage에서 state를 읽어옵니다.
readStateFromStorage(state) {
if (localStorage.getItem("testvue.login.memberId") != null) {
state.memberId = localStorage.getItem("testvue.login.memberId");
}
if (localStorage.getItem("testvue.login.accessToken") != null) {
state.accessToken = localStorage.getItem("testvue.login.accessToken");
}
if (localStorage.getItem("testvue.login.refreshToken") != null) {
state.refreshToken = localStorage.getItem("testvue.login.refreshToken");
}
}
}
Storage(스토리지)에 state 삭제
1. Local Storage(로컬 스토리지)에서 저장된 state를 삭제하기 위해서 Local Storage의 http://localhost:8080에서 마우스 오른쪽 컨텍스트 메뉴의 Clear를 클릭합니다.
또는 Local Storage의 Key에서 마우스 오른쪽 컨텍스트 메뉴의 Delete를 클릭합니다.
2. 웹 브라우저에서 새로고침(F5)을 하면 초기화된 것을 확인할 수 있습니다.
Local Storage(로컬 스토리지)에 state에 있는 memberId, accessToken, refreshToken를 저장하면 여러 개로 저장하게 되어 키(key)가 많아집니다. 그래서 JSON 객체로 저장하면 관리가 용이해집니다.
Storage(스토리지)에 state이 JSON 객체로 저장하고 읽기
1. mutations에서 saveStateToStorage() 함수와 readStateFromStorage() 함수를 JSON 객체로 저장하고 읽게 수정합니다.
mutations: {
// memberId를 설정합니다.
setMmemberId(state, memberId) {
state.memberId = memberId;
},
// Access-Token를 설정합니다.
setAccessToken(state, accessToken) {
state.accessToken = accessToken;
},
// Refresh-Token를 설정합니다.
setRefreshToken(state, refreshToken) {
state.refreshToken = refreshToken;
},
// 초기화시킵니다.
reset(state) {
state.memberId = '';
state.accessToken = '';
state.refreshToken = '';
localStorage.removeItem("testvue.login");
},
// Storage에 state를 저장합니다.
saveStateToStorage(state) {
//localStorage.setItem("testvue.login.memberId", state.memberId);
//localStorage.setItem("testvue.login.accessToken", state.accessToken);
//localStorage.setItem("testvue.login.refreshToken", state.refreshToken);
localStorage.setItem("testvue.login", JSON.stringify(state));
},
// Storage에서 state를 읽어옵니다.
readStateFromStorage(state) {
//if (localStorage.getItem("testvue.login.memberId") != null) {
// state.memberId = localStorage.getItem("testvue.login.memberId");
//}
//if (localStorage.getItem("testvue.login.accessToken") != null) {
// state.accessToken = localStorage.getItem("testvue.login.accessToken");
//}
//if (localStorage.getItem("testvue.login.refreshToken") != null) {
// state.refreshToken = localStorage.getItem("testvue.login.refreshToken");
//}
if (localStorage.getItem("testvue.login") != null) {
let storage = JSON.parse(localStorage.getItem("testvue.login"));
if (storage.memberId != null) {
state.memberId = storage.memberId;
}
if (storage.accessToken != null) {
state.accessToken = storage.accessToken;
}
if (storage.memberId != null) {
state.refreshToken = storage.refreshToken;
}
}
}
}
2. 로그인을 합니다. 그러면 Application의 Local Storage(로컬 스토리지)에 state가 객체로 저장되어 있는 것을 확인할 수 있습니다.
이제 페이지가 새로고침 되어도 로그인을 유지할 수 있고 state 정보를 JSON 객체로 관리할 수 있게 되었습니다.