프로젝트를 진행하면서 리액트와 DRF간의 통신을 진행하게 되었는데, 이 때 백엔드에서 보내준 id값과 token값을 이용하여 로그인 상태 유지 및 token 값을 가지고 있지 않다면 화면에 접근할 수 없도록 설정을 해야했다. 이 때 새로고침시에도 로그인에 대한 정보를 가지고 있어야 했기 때문에 localStorage를 이용하여 로그인 정보를 유지할 수 있도록 token을 기억시켰다.
이처럼 오늘의 velog 게시글은 react에서 localStorage를 왜 사용하고 이를 로그인에 적용시키면 어떻게 사용해볼 수 있을지 기억하고자 한다!!
👉 localStorage의 사용법 이동하기
localStorage는 자바스크립트의 Web Storage를 이용한 것이다. 우리가 웹 개발을 하다보면 임시적으로 이 데이터를 저장해야하는 필요성을 느낄 것이며 이에 따라서 웹 스토리지를 이용하여 데이터를 저장하고 활용할 수 있을 것이다!!
웹 스토리지에는 두 종류, localStorage와 sessionStorage가 있다. 두 개의 차이점은 간단히 무엇일까?? 이는 데이터 저장이 어떤 범위로 계속 보존되어 있는지에 차이가 있다.
localStorage는 어떠한 세션에 들어와있어서 그것이 끝나더라도 데이터가 지워지지않고 보존된다. 이는 같은 페이지에 대해 여러 페이지가 탭으로 열려있어서 사용하더라도 데이터가 지워지지 않고 localStorage의 내용을 삭제하지 않는다면 데이터가 유지된다!!
하지만 sessionStorage는 각 탭들이 별개의 데이터들을 저장하게 되고 탭이나 창이 닫힐 때마다 데이터는 소멸하게 된다.
따라서 자신의 브라우저에서 데이터를 계속 보존시키면서 사용한다면 localStorage를, 여러 페이지 마다 다른 데이터를 보존시키고 싶다면 sessionStorage를 사용하면 되겠다!!
유의해야할 점은 localStorage를 사용할 때 유지되는 데이터는 자신의 컴퓨터, 자신의 브라우저에만 저장되어 있고 동일한 링크의 다른 컴퓨터에는 당연히 데이터가 저장되어 있지 않다는 것이다. 자신의 브라우저에 데이터가 자신의 localStorage에 남는 다는 것을 기억하도록 하자!!
localStorage의 사용 방법은 다음과 같다.
// 데이터 저장하기
localStorage.setItem("key", value);
// 데이터 읽기
localStorage.getItem("key");
// 데이터 삭제
localStorage.removeItem("key");
// 모든 데이터 삭제
localStorage.clear();
// 저장된 키/값 쌍의 개수
localStorage.length;
우리가 만약 어떠한 token의 값을 백엔드로 부터 전달받았다면 이를 setItem과 같이 API를 사용하여 key값을 정하여 value인 token 값을 저장할 수 있는 것이다!!
위의 API를 적절히 사용하여 다음과 같이 내가 React에서 localStorage를 이용한 로그인을 구현해보았다!!
먼저 로그인이 이루어지고 다른 화면으로 이동되었을 때 어떻게 이 정보들을 활용할 수 있는지를 고민해보자. 로그인을 위해 아이디와 비밀번호를 작성했다면, 이를 서버쪽에 보내어 아이디와 비밀번호가 일치하는 저장된 db를 확인하고 이에 대한 response를 받을 것이다. 그렇게 되면 이 response 객체에 담긴 정보들을 localStorage에 저장한 후 이를 다른 화면에서 사용할 수 있도록, 또는 로그인 상태가 유지될 수 있도록 진행시킬 수 있을 것이다!!
초기 상태를 보자!!
위 사진과 같이 만약 로그인 환경에서 아이디와 비밀번호와 함께 로그인 시도를 하려고하였을 때는 빈 localStorage를 볼 수 있다. (localStorage는 크롬 개발자 환경의 애플리케이션 탭에서 볼 수 있다.) 이 후 만약 내가 로그인 버튼을 누르고 다른 화면으로 이동했을 때에는 localStorage의 로그인 정보에 대한 token 값과 pk 값을 받아 이를 다른 화면에서 데이터를 보내는 과정에서 사용할 수 있도록 하고자할 것이다.
따라서 localStorage에 key와 value를 지정하여 데이터를 저장해 놓는 과정이 로그인 과정에서 필요할 것이다!!
const onClickLogin = () => {
axios.post("http://127.0.0.1:8000/accounts/login/"
,{
classnetid : inputId,
classnetpw : inputPw
}
)
.then(res => {
console.log(res.data)
localStorage.clear()
localStorage.setItem('id', res.data.id)
localStorage.setItem('token', res.data.token)
window.location.replace('http://localhost:3000/main')
})
.catch((err) => {
console.log(err)
setErrorMessage(false)
})
}
위는 로그인 버튼을 눌렀을 때 발생하는 동작으로 axios를 이용하여 통신하였다. 이를 통해 나는 적절한 요청을 서버로부터 응답을 받은 후 이에 응답에 담긴 정보를 localStorage에 저장하면 되겠다!!
아래는 장고의 DRF에서 구현한 로그인 확인 과정이다. token은 jwt를 이용하여 클래스넷아이디와 비밀번호가 일치하면 발급해주는 것을 이용하여 Response에 담아서 주었다. bcrypt를 이용하여 비밀번호를 암호화 했기 때문에 이에 대한 모듈을 사용하여 인코딩 과정을 거쳐 비밀번호를 검사해주었다!!
def post(self, request):
data = request.data
try:
if User.objects.filter(classnetid = data['classnetid']).exists():
user = User.objects.get(classnetid = data['classnetid'])
if bcrypt.checkpw(data['classnetpw'].encode('utf-8'), user.classnetpw.encode('utf-8')):
token = jwt.encode({'classnetid' : data['classnetid']}, SECRET_KEY, algorithm = "HS256")
token = token.decode('utf-8') # 유니코드 문자열로 디코딩
#-----------------------------#
# return JsonResponse({"token" : token }, status=200) # 토큰을 담아서 응답
return Response({"id" : user.id, "token" : token}, status=200)
else :
return HttpResponse(status=401)
return HttpResponse(status=400)
except KeyError:
return JsonResponse({"message":"INVALID_KEYS"}, status = 400)
이렇게 되면 적절하게 응답을 받고 위 사진 처럼 localStorage에도 저장할 수 있다!! 그렇다면 다른 화면에서 이러한 localStorage에 저장된 정보를 이용할 수 있는 방법은 무엇이고 어떻게 로그인이 유지되는 것을 확인할 수 있을까?? 그 방법은 이번에는 getItem을 이용하여 token 또는 다른 데이터들의 유무를 통해 활용하면 된다!!
앞서 저장한 정보를 key 값을 통해 있는지 확인하고 데이터를 이용하면 되는 것이다!! react의 useEffect를 활용한다면 화면이 첫 렌더링 되었을 때 localStorage안의 token의 유무를 확인하고 만약 없다면 그냥 로그인 화면으로 이동시켜버려서 자동로그인, 또는 로그인이 필요한 상태임을 확인할 수 있는 것이다!!!
아래는 다른 화면에서 로그인 상태를 확인하거나 localStorage의 정보를 활용하는 코드의 내용이다.
.
.
.
useEffect(() => {
if (localStorage.getItem('token') === null) {
window.location.replace('http://localhost:3000/')
}
}, []);
.
.
.
<p style={{fontSize: 30 , fontFamily : 'KyoboHand'}}>야자수 {localStorage.getItem('id')} 님 어서오세요!</p>
<p style={{fontSize: 30 , fontFamily : 'KyoboHand'}}>토큰 값 : {localStorage.getItem('token')}</p>
.
.
.
자 그렇다면 마지막으로 로그아웃을 시도하려면 어떤 방법을 이용해야할까?? localStorage를 이용하여 로그인을 유지하거나 로그인이 필요한 상태임을 확인하였을테니 이번에는 이 안의 내용을 다 지워서 다시 로그인이 필요한 상태를 만들어주는 것이다. 그렇기 위해서는 clear()를 이용하여 localStorage를 빈 상태로 만들고 아까의 다른 화면에 접속하였을 때 로그인이 필요하여 login 화면으로 이동시켜버릴 수 있게 만들 수 있을 것이다!!
const logout = () => {
let token = localStorage.getItem('token')
localStorage.clear()
window.location.replace('http://localhost:3000/')
}
export default logout
위에서 설명한 내용들을 총 정리해보면
로 정리할 수 있겠다!!
(아직 다른 화면 비율을 못맞춰놨지만,,, localStorage에 정보가 저장되고 로그인이 잘되면서 token값도 넘어오는 것을 확인할 수 있었다!!)
React를 이용한 회원가입, 인증, 로그인 단계를 거치면서 Django의 DRF를 이용하여 구현해볼 수 있었을 뿐만아니라 통신과정을 더 깊이 알 수 있었다. 특히 이번에 사용한 localStorage를 이용하여 어떻게 자동로그인과 로그인이 필요한 상태임을 나타내는지도 알 수 있게 되었다!!
로그인 로직을 더 이해함으로써 서버와의 통신과정을 보다 더 잘 이해할 수 있는게 도움이 많이 되었던 것 같다. 하나 구현했을 때 뿌듯함이 더 다가왔던 것 같다!! 특히 이번에는 직접 장고를 구현하고 DRF와의 통신을 내가 진행해봤던 점이 서버를 이용하여 처음 직접 백엔드와 프론트엔드 둘다 구현해본 것이기 때문에 특히 새로웠다.
다음에는 백엔드도 찍먹해볼까,,,? ㅠㅠ 너무 어렵다 백엔드는,,, 그래도 기회가 있었으면 좋겠다!!
화팅~~!