주요 내용 출처 : ( https://www.daleseo.com/js-web-storage/ )
1인 프론트 프로젝트를 하다보니 새로운 문제가 계속 발생하는 것 같다.
웹 사이트의 가장 기본인 로그인 페이지를 구현하고 싶었는데 생각해보니 로그인을 하려면 그 정보를 어딘가에 저장해야 했다….!
우선 recoil을 최대한 활용해볼 예정이라 관련해서 구글링 중 웹 로컬 스토리지를 발견했다.
웹 스토리지는 로컬 스토리지 vs 세션 스토리지로 나뉜다.
세션 스토리지는 각 창이나 탭이 생기면 데이터가 생생되고 창이나 탭이 닫히면 데이터가 없어진다.
하지만 로컬 스토리지는 동일한 컴퓨터 동일한 브라우저를 쓴다는 요건만 충족되면, 데이터 영속성(persistence)에 의해 그 정보를 계속 활용할 수 있게 된다.
localStorage 기본 code
// 키에 데이터 쓰기
localStorage.setItem("key", value);
// 키로 부터 데이터 읽기
localStorage.getItem("key");
// 키의 데이터 삭제
localStorage.removeItem("key");
// 모든 키의 데이터 삭제
localStorage.clear();
// 저장된 키/값 쌍의 개수
localStorage.length;
사용 예시
> localStorage.getItem('name')
null
> localStorage.getItem('email')
null
> localStorage.setItem('email', 'test@user.com')
undefined
> localStorage.getItem('email')
"test@user.com"
> localStorage.setItem('email', 'test@admin.com')
undefined
> localStorage.getItem('email')
"test@admin.com"
> localStorage.removeItem('email')
undefined
> localStorage.getItem('email')
null
주의사항 → 문자열만 저장
일반 object 저장시 다음과 같이 나오게 된다.
> localStorage.setItem('obj', {a: 1, b: 2})
undefined
> localStorage.getItem('obj')
"[object Object]"
해결방법
> localStorage.setItem('json', JSON.stringify({a: 1, b: 2}))
undefined
> JSON.parse(localStorage.getItem('json'))
{a: 1, b: 2}
stringify는 JSON 형태로 직렬화(serialization)를 해주고
parse 라는 역직렬화(deserialization)로 데이터를 그대로 얻을 수 있다.
구현 code
import React, { useEffect, useState } from 'react';
import { useRecoilState } from 'recoil';
import { loginState } from '../../state/userNameState';
export default function LoginForm() {
// const setUserName = useSetRecoilState(userNameState);
//useSetRecoilState : 상태를 업데이트 하는 setter 함수.
// 현재 로그인한 userName을 전역으로 관리
const [loginInfo, setLoginInfo] = useRecoilState(loginState);
const [input, setInput] = useState('');
// const [loginState, setLoginState] = useState({
// isLogin: false,
// userName: '',
// });
const loginText = loginState.isLogin ? 'LOGOUT' : 'LOGIN';
const onChangeInputHandler = (e) => {
const text = e.target.value;
setInput(text);
};
// const inputText = <input type="text" onChange={onChangeInputHandler} />;
// const getUserName = window.localStorage.getItem('userName');
// 로컬 스토리지에 유저 data 저장
// useEffect(() => {
// // const storedUserName = window.localStorage.getItem('userName');
// // if (storedUserName) {
// // setLoginInfo({
// // isLogin: true,
// // userName: storedUserName,
// // });
// // }
// // console.log()
// }, [setLoginInfo]); // 의존성 배열 설정 [state.userName] 의존성 배열과의 차이?
// console.log('loginstate >>', loginState);
const onClickSubmitHandler = (e) => {
e.preventDefault();
if (!loginInfo.isLogin) {
// false 시 실행
setLoginInfo({
isLogin: true,
userName: input,
});
} else {
setLoginInfo({
isLogin: false,
userName: '',
});
}
setInput('');
};
return (
<div>
<span>
{loginInfo.isLogin ? (
<h2>안녕하세요 {loginInfo.userName}</h2>
) : (
<h2>로그인 X </h2>
)}
</span>
<form>
<input type="text" value={input} onChange={onChangeInputHandler} />
<button type="button" onClick={onClickSubmitHandler}>
{loginText}
</button>
</form>
</div>
);
}
로그인 페이지 내에서 구현하고 로컬 스토리지에 넣고 활용하는 것까지는 이렇게 성공했는데, 새로 고침 시 데이터가 날라갔다. localStorage의 정보를 불러오려면 매번 useEffect를 써야 할 것 같았다…. 모든 페이지에서 그런 과정을 거치는 건 비효율적으로 보여 recoil-persist를이용했다.
recoil-persist를 사용하면 새로 고침해도 정보를 유지시켜준다.
import { atom } from 'recoil';
import { recoilPersist } from 'recoil-persist';
const { persistAtom } = recoilPersist({
key: 'localStorage',
storage: localStorage,
});
export const loginState = atom({
key: 'loginState',
default: { isLogin: false, userName: '' },
effects_UNSTABLE: [persistAtom],
});
하지만 이렇게 아이디를 구현한다 하면, email이나 비밀번호 같은 것은 localStorage에 저장되면 정보가 그대로 노출되어 보안에 문제가 생길 것 같았다. bcrypt를 이용하는 방법도 있긴 하지만,,, 불완전한 방법 같았다.
++ 리더님에게 물어보았더니 firebase라는 백엔드를 활용할 수 있는 사이트가 있었다. 이를 이용한 사용자 데이터 베이스를 구축해 볼 예정이다. 본래 계획했던 '보고 싶은 영화 찜하기', 평점 기능 등을 이를 통해 구현할 예정이다.
'SeSAC' 카테고리의 다른 글
코딩온 비전공자, 입문자도 가능한 웹 개발자 부트캠프 후기 (4) | 2024.01.18 |
---|---|
[코딩온] SeSAC 세번째 프로젝트 회고록 (0) | 2024.01.06 |
[코딩온]Image grid 형태로 Infinite scroll 기능 구현하기 (0) | 2024.01.03 |
[코딩온] TMDB API에서 genre name 대신 genreID만 나올 때 (0) | 2023.12.24 |
[코딩온] 검색 기능 구현을 위한 TMDB API의 활용 방법 (0) | 2023.12.21 |