본문 바로가기

React를 시작해보자

5) React - JWT를 이용한 로그인 인증 - 1부

반응형

이전까지 Route를 이용한 페이지 전환에 대해 공부해 봤다.

이제 페이지 전환을 할때 로그인된 사용자만 볼 수 있는 Page와 그렇지 않도 되는 Page에 대한 구분을 하려고 한다.

 

그러면 먼저 로그인에 대한 처리를 해야 한다. 로그인에 대한 처리 방식은 

1) BackEnd 서버에 Session 관리 방식.

- 서버에서 session을 관리하여 session 시간이 만료 되면 다시 로그인 하는 방식.

  다중 서버일경우 각 서버사이의 sesison clustring을 생각해야함.

2) JWT ( Json Web Token) 방식

- Token 방식으로 로그인을 하게 되면 인증서버에서 Access Token과 Refresh Token을 받아와 사용하는 방식

- 다소 복잡한 처리 Front에서 해야함. 

3) OAuth 방식

- 외부서비스의 인증 시스템을 이용해 다른 서비스의 회원 정보를 안전하게 이용하기 위한것 이라고 알고 넘어간다.

- 이부분의 테스트는 차후 구글 OAuth2.0 API 를 테스트해 보도록 한다.

 

여기서는 2번 방법인 JWT 방식으로 BackEnd 인증 서버를 java SpringBoot 를 이용해 개발하도록 한다. 

 

앞에서 만들어놓은 LoginPage.jsx 파일을 아래 처럼 joinHandler 를 부분에 axios를 이용한 서버 호출을 추가한다.

 

// src/App.jsx

import './App.css';
import { BrowserRouter, Route } from 'react-router-dom';
import LoginPage from './pages/LoginPage';
import HomePage from './pages/HomePage';
import AuthRoute from './component/AuthRoute';
import Counnter from './component/Counter';
import { useEffect, useState } from 'react';
import axios from "axios";

function App() {
  const [isLogin , setIsLogin] = useState(false);

  useEffect(()=>{
     
  },[]);

  function loginCallBack(login){
    setIsLogin(login);
  }

  return (
    <div className="App">
      <BrowserRouter>
        <AuthRoute exact isLogin={isLogin} path="/" component={HomePage} />
        <Route path="/login"  render={(props)=> <LoginPage {...props} loginCallBack={loginCallBack}/>} />
        <AuthRoute path="/counter" isLogin={isLogin} component={Counnter} />
      </BrowserRouter>
    </div>
  );
}

export default App;

 

// src/pages/LoginPage.jsx

import { useEffect } from "react";
import axios from "axios";

function LoginPage(props){
    
    function joinHandler(){
        try{
            let data = {email: "devracoon@naver.com"};
            axios.post("/auth/login" ,JSON.stringify(data), {
                headers: {
                  "Content-Type": `application/json`,
                }})
            .then(res =>{
                console.log("res.data.accessToken : " + res.data);
                axios.defaults.headers.common['Authorization'] = 'Bearer ' + res.data;
                props.loginCallBack(true);
                props.history.push("/");
            })
            .catch(ex=>{
                console.log("login requset fail : " + ex);
            })
            .finally(()=>{console.log("login request end")});
        }catch(e){
            console.log(e);
        }
        
        
    }

    useEffect(()=>{
        console.log("LoginPage render ... ");
    })
    return(
        <div>
            <span>Login Page</span>
            
            <button type="button" onClick={joinHandler}>Join</button>
        </div>
    )
}

export default LoginPage;

위 코드로 수정하고 Join 버튼을 클릭하면 아래와 같은 에러가 나온다.

Access to XMLHttpRequest at 'http://localhost:8080/devracoon/auth/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

이 에러는 CORS (Cross-Origin Resource Sharing) 즉 Front 를 띄운 서버는 localhost:3000 인데 backEnd 서버는 

localhost:8080 이라서 브라우저 CORS 규칙에 위반된다. 이런 내용이다. 

 

이것을 해결하기위해 react axios 호출시에 proxy 호출을 하도록해서 회피하도록하자.

 

아래 package를 설치한다.

npm install http-proxy-middleware --save

그리고 src 폴더 바로 밑에 setupProxy.js 파일 생성.

//setupProxy.js

const createProxyMiddleware = require('http-proxy-middleware');

// src/setupProxy.js
module.exports = function(app) {
    app.use(
        '/auth',
        createProxyMiddleware({
            target :"http://localhost:8080/devracoon/",
            changeOrigin: true
        })
    );
};

 

이제 Join 버튼을 클릭하면 정상적으로 api가 호출이 되고 access Token을 받아오는것을 확인 할 수 있다.

res.data.accessToken : eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhYWFhYSIsImlhdCI6MTYwNTk3NDE5MiwiZXhwIjoxNjA1OTc0NDkyfQ.pV9EjTLj4fmuNf6flYYu0s_80jSM2o3OzGUxAw1nxkg

 

이제 정상적으로 받아온 token을 가지고 Login 한 후에 어떻게 사용하는지에 대해 2부에서 공부하자.

너무 늦은 시간이라 오늘은 이만 자야겠다.. 

 

참고 : https://github.com/devraccon/React