[React] Cookie에 정보저장하기
Cookie란?
- 클라이언트(웹 브라우저)에 저장되는 작은 데이터 조각이다.
- 서버 > 웹 브라우저로 데이터를 보내면, 웹 브라우저는 해당 데이터를 로컬에 저장한다.
- 그리고 다음에 같은 서버로부터 요청이 있을 때마다, 브라우저는 이전에 저장된 데이터를 서버로 보내주어 서버는 해당 정보를 활용하여 사용자에 맞는 웹페이지를 제공하게 된다.
- 보안 문제로 브라우저에서는 쿠키에 접근하는 것이 제한되어 있으며, 쿠키에 저장된 데이터도 중요한 정보는 암호화되어 저장되어야 한다.
- 웹 개발에서 쿠키는 사용자가 로그인을 했는지 여부, 사용자 설정 등을 저장하기 위해 사용된다.
Cookie 어디에 저장되었는지 확인하기
1. [F12]로 개발자 도구를 연다.
2. [Application]을 클릭한다.
3. [Cookies]를 클릭한다.
적용하기
1. 터미널에 아래 코드 입력해서 설치한다.
npm i react-cookie
2. import 해준다.
import { useCookies } from 'react-cookie';
3. useState Hook 작성
const [userId, setUserId] = useState('');
const [userPw, setUserPw] = useState('');
const [cookies, setCookie, removeCookie] = useCookies(["rememberUserId", "autoUserId", "autoUserPw"]);
const [isRemember, setIsRemember] = useState(false);
4. useEffect Hook 작성
useEffect(() => {
if (cookies.rememberUserId !== undefined) {
setUserId(cookies.rememberUserId);
// setUserId 함수를 호출하여 state 변수인 userId의 값을 cookies.rememberUserId로 설정
setIsRemember(true);
// state 변수인 setIsRemember 값을 true로 설정
}
}, [cookies.rememberUserId]);
// rememberUserId 값이 변경될 때만 useEffect 함수가 실행되도록 설정한다.
// 이렇게 하면 불필요한 state 업데이트를 방지할 수 있음
5. id저장 handler 작성
const handleRemember = (e) => {
setIsRemember(e.target.checked); // isRemember의 상태를 체크박스의 체크 여부와 일치시킴
if (!e.target.checked) { // 체크박스가 체크되어 있지 않다면,
removeCookie('rememberUserId'); // 쿠키 삭제
} else if(isRemember){ // 체크박스가 체크되어있고, isRemember이 true라면
setCookie("rememberUserId", userId, { path: '/', expires: new Date(Date.now() + 604800000) });
}
};
6. login handler 작성
const handleLogin = () => {
if(userId === "") {
alert("아이디를 입력해주세요.");
} else if (userPw === "") {
alert("비밀번호를 입력해주세요.")
} else {
axios.post('/auth/login', {
userId: userId,
userPw: userPw,
})
.then(function(obj) {
localStorage.setItem("refresh_token", obj.data.data.authToken);
const config = {
headers: {
Authorization: `${localStorage.getItem("refresh_token")}`,
},
};
axios.get('/try', config)
.then(function (response) {
console.log("refresh_token 값 : " + response.data);
alert(userId + "님 환영합니다.");
setIsRemember(true); // 체크박스에 체크가 되어있다면
setCookie("rememberUserId", userId, { path: '/', expires: new Date(Date.now() + 604800000) });
setAutoLogin(true);
window.location.href = "/";
})
.catch(function (error) {
console.log("오류 " + error);
});
})
.catch(() => {
alert("아이디 또는 비밀번호를 잘못 입력했습니다. 입력하신 내용을 다시 확인해주세요.")
})
}
};
- 여기서 5번과 6번에 setCookie를 왜 두번해주는지 이해가 되지 않아 찾아보니..
- 먼저 handlerRemeber함수에서 실행되고, isRemember(체크박스가)가 true면 쿠키에 rememberUSerId가 저장되어야하기 때문
- 그러나 이거는 첫 번째 페이지 로드시에만 실행되므로, 이후 새로고침되거나 페이지가 이동될 때 유지되지가 않음
- 그래서 handlerLogin에서 (로그인이 완료된 시점에서) 실행 되는 setCookie를 해줘야 한다.
- 이거는 새로고침이나 페이지 이동후에도 로그인 정보를 유지하기 위해 사용된다.
7. js 작성
<Box>
<TextField
type="text"
label="아이디"
value={userId}
onChange={(e) => setUserId(e.target.value)}
variant="standard"
/>
<TextField
type="password"
label="패스워드"
value={userPw}
onChange={(e) => setUserPw(e.target.value)}
variant="standard"
/>
<LoginButton />
<FormControlLabel
control={<Checkbox />}
label="ID 저장"
checked={isRemember}
onChange={handleRemember}
/>
</Box>
■ 최종코드
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import Div from './api/reactive.js'
import { useCookies } from 'react-cookie';
// mui
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Box from '@mui/material/Box';
import theme from "./api/theme";
import styled, { ThemeProvider } from "styled-components";
import PersonIcon from '@mui/icons-material/Person';
import VpnKeyIcon from '@mui/icons-material/VpnKey';
import { InputAdornment, Checkbox, FormControlLabel } from '@mui/material';
// 1. 레이아웃 디자인
const StyleDivText = styled.p`
color: rgb(117, 117, 117);
font-size: 20px;
font-weight: 500;
text-align: center;
`;
const StyleDiv = styled.div`
margin: 15% 0 25% 0;
`;
const StyleButton = styled(Button)`
background: rgb(62, 128, 234) !important;
color: white !important;
border-radius: 15px !important;
height: 50px;
margin: 30px 0 10px 0 !important;
`;
function Login() {
// 1. useState
const [userId, setUserId] = useState('');
const [userPw, setUserPw] = useState('');
const [cookies, setCookie, removeCookie] = useCookies(["rememberUserId", "autoUserId", "autoUserPw"]);
const [isRemember, setIsRemember] = useState(false);
useEffect(() => {
if (cookies.rememberUserId !== undefined) {
setUserId(cookies.rememberUserId);
setIsRemember(true);
}
}, [cookies.rememberUserId]);
// 2. Id 기억하기
const handleRemember = (e) => {
setIsRemember(e.target.checked);
if (!e.target.checked) {
removeCookie('rememberUserId');
} else if(isRemember){
setCookie("rememberUserId", userId, { path: '/', expires: new Date(Date.now() + 604800000) });
}
};
// 3. handle Login
const handleLogin = () => {
if(userId === "") {
alert("아이디를 입력해주세요.");
} else if (userPw === "") {
alert("비밀번호를 입력해주세요.")
} else {
axios.post('/auth/login', {
userId: userId,
userPw: userPw,
})
.then(function(obj) {
localStorage.setItem("refresh_token", obj.data.data.authToken);
const config = {
headers: {
Authorization: `${localStorage.getItem("refresh_token")}`,
},
};
axios.get('/try', config)
.then(function (response) {
console.log("refresh_token 값 : " + response.data);
alert(userId + "님 환영합니다.");
setIsRemember(true);
setCookie("rememberUserId", userId, { path: '/', expires: new Date(Date.now() + 604800000) });
setAutoLogin(true);
window.location.href = "/";
})
.catch(function (error) {
console.log("오류 " + error);
});
})
.catch(() => {
alert("아이디 또는 비밀번호를 잘못 입력했습니다. 입력하신 내용을 다시 확인해주세요.")
})
}
};
// 4. Login Button
function LoginButton() {
return <StyleButton
onClick={handleLogin}
fullWidth
>로그인</StyleButton>
}
return (
<Box>
<ThemeProvider theme={theme}>
<Div>
<form>
<TextField
type="text"
label="아이디"
margin="normal"
value={userId}
onChange={(e) => setUserId(e.target.value)}
fullWidth
variant="standard"
InputProps={{
startAdornment: (
<InputAdornment position="start" >
<PersonIcon />
</InputAdornment>
),
}}
/>
<TextField
type="password"
label="패스워드"
margin="normal"
value={userPw}
onChange={(e) => setUserPw(e.target.value)}
autoComplete="on"
fullWidth
variant="standard"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<VpnKeyIcon />
</InputAdornment>
),
}}
/>
<LoginButton />
<FormControlLabel
control={<Checkbox />}
label="ID 저장"
checked={isRemember}
onChange={handleRemember}
/>
<FormControlLabel
control={<Checkbox />}
label="자동 로그인"
checked={autoLogin}
onChange={handleAutoLogin}
/>
</form>
</Div>
</ThemeProvider>
</Box>
);
}
export default Login;