저번에 spring boot에서 로그인후 JWT토큰 생성하고 응답 Header에 토큰 전송하는것까지 완료하였다.
이번에는 react(처음써봄) 이용해서 비동기 통신 이용하여 로그인 기능 작성해볼려고한다.
우선 react에서 router-dom 설치해두었고,
페이지이동을위한 router설정을 진행하였다.
vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
// "/api" 요청시 -> "http://localhost:9000/api~~" 으로 치환됨
"/api": "http://localhost:9000",
},
},
});
main.jsx
import { createRoot } from "react-dom/client";
import App from "./App.jsx";
import { BrowserRouter } from "react-router-dom";
createRoot(document.getElementById("root")).render(
<BrowserRouter>
<App />
</BrowserRouter>
);
App.jsx
"/" = 메인페이지
"/login" = 로그인 페이지
"/*" = 그외 페이지(오류페이지)
import Home from "./pages/Home/Home";
import Login from "./pages/Login/Login";
import NotFound from "./pages/Error/NotFound";
import { Routes, Route } from "react-router-dom";
import "./styles/reset.min.css";
function App() {
return (
<>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/*" element={<NotFound />}></Route>
</Routes>
</>
);
}
export default App;
Home.jsx
const Home = () => {
return <div>Home Page</div>;
};
export default Home;
Login.jsx
아직 완성은 아니고, 계속해서 수정해나갈예정.
우선 localStorage에 저장은 해두었지만,
이런방식보다는 엑세스토큰, 리프레쉬토큰 사용해서 많이 하는것같다
아직 학습한적이없기 때문에 우선진행할지.. 엑세스,리프레쉬 토큰 학습하고 진행할지.. 고민중이다..
import "./Login.css";
import { useState, useRef } from "react";
import axios from "axios";
const Login = () => {
const idRef = useRef();
const pwRef = useRef();
const [state, setState] = useState({
userid: "",
password: "",
});
const { userid, password } = state;
const stateHandler = (e) => {
setState({
...state,
[e.target.name]: e.target.value,
});
};
/**
* 로그인 기능
* @returns
*/
const loginHandler = () => {
try {
if (!validationForm()) {
return;
}
const formData = new FormData();
formData.append("userid", state.userid);
formData.append("password", state.password);
axios
.post("/api/login", formData)
.then((res) => {
// 만약 api 통신 실패했을시
if (res.status !== 200) {
alert("API 통신에 실패 하였습니다.");
return;
}
// JWT 토큰 파싱
const token = res.headers.authorization.replace("Bearer ", "");
// localStorage에 JWT 토큰 저장
localStorage.setItem("token", token);
})
.catch((error) => {
alert("로그인 정보가 일치하지 않습니다. 다시 시도해 주세요.");
});
} catch (error) {
alert("통신중 오류가 발생하였습니다. 잠시후 시도해주세요.");
}
};
/**
* form 입력값 유효성 체크
* @returns
*/
const validationForm = () => {
if (!userid.trim()) {
alert("아이디를 입력해주세요.");
idRef.current.focus();
return false;
}
if (!password.trim()) {
alert("비밀번호를 입력해주세요.");
pwRef.current.focus();
return false;
}
return true;
};
return (
<>
<div className="login_wrap">
<div className="login">
<h3 className="login_logo"></h3>
<div className="login_input_box">
<input
type="text"
name="userid"
id="userid"
className="input"
placeholder="아이디"
value={state.userid}
onChange={stateHandler}
ref={idRef}
/>
<input
type="password"
name="password"
id="password"
className="input"
placeholder="비밀번호"
value={state.password}
onChange={stateHandler}
ref={pwRef}
/>
</div>
<div className="login_btn_wrap">
<button className="active" onClick={loginHandler}>
로그인
</button>
<button>회원가입</button>
</div>
</div>
</div>
</>
);
};
export default Login;
Login.css
.login_wrap {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.login_wrap .login {
width: 500px;
}
.login_wrap .login .login_logo {
width: 100%;
height: 50px;
text-align: center;
line-height: 50px;
background: #999;
font-weight: bold;
background: url(/src/assets//images/logo.png) no-repeat 50% 50%;
background-size: 400px;
}
.login_wrap .login .login_input_box {
padding: 3cqmin 0;
}
.login_wrap .login .login_input_box .input {
display: block;
width: 100%;
height: 40px;
box-sizing: border-box;
padding: 0 10px;
border: 1px solid #999;
border-radius: 5px;
margin-top: 20px;
}
.login_wrap .login .login_input_box .input:first-child {
margin-top: 0;
}
.login_wrap .login .login_btn_wrap {
}
.login_wrap .login .login_btn_wrap button {
display: block;
width: 100%;
height: 40px;
line-height: 20px;
text-align: center;
margin-bottom: 10px;
border-radius: 5px;
border-width: 0;
font-size: 14px;
background: rgb(232, 240, 254);
color: rgb(75, 90, 214);
font-weight: bold;
}
.login_wrap .login .login_btn_wrap .active {
background: rgb(82, 106, 240);
color: #fff;
}
로그인 테스트
1. 로그인 페이지
- 아이디, 패스워드 입력후 로그인 버튼 클릭하면
2. 응답헤더로 토큰 저장
- 아래 처럼 localStorage에 token 값을 저장해둔다.
- 만약 필요할떄 | localStorage.getItem("token") | 으로 토큰을 꺼내쓰면된다.
'프로그래밍 > 개인프로젝트' 카테고리의 다른 글
[프로젝트] 7. 오류페이지(일반) - 프론트화면(react) (0) | 2024.09.04 |
---|---|
[프로젝트] 5. 로그인(일반) (0) | 2024.08.29 |
[프로젝트] 4. 프로젝트 Entity (0) | 2024.08.29 |
[프로젝트] 3. 프로젝트 폴더 구조 (3) | 2024.08.28 |
[프로젝트] 2. ERD 및 테이블 정의서 작성하기 (1) | 2024.08.28 |