이전글
https://greed-yb.tistory.com/310
로그인했을 때 유저 정보를 담아두고
페이지마다 기능 동작할 때 확인용으로 사용하려고 한다
userInfo.tsx
import React, {createContext, useState, ReactNode, useContext} from 'react';
// 권한 및 필요한게 있다면 추가하자
interface UserInfoType {
username: string;
setUserInfo: (username: string) => void;
}
const UserInfo = createContext<UserInfoType>({
username: '',
setUserInfo: () => {},
});
const UserProvider = ({ children }: { children: ReactNode }) => {
const [username, setUsername] = useState<string>('');
return (
<UserInfo.Provider value={{ username, setUserInfo: setUsername }}>
{children}
</UserInfo.Provider>
);
};
// UserInfo를 사용하는 커스텀 훅 정의
const useUserContext = () => useContext(UserInfo);
export { UserInfo, UserProvider, useUserContext };
사용자 정보를 저장하기 위한 코드
현재 로그인한 사용자 id 만 받아오게 했는데
필요에 따라서 권한이나 여러 정보를 담으면 된다
login.tsx 수정
import React, { useState} from "react";
import axios from "axios";
import {Link, useNavigate} from "react-router-dom";
import { useUserContext } from '../utils/UserInfo';
function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const { setUserInfo } = useUserContext();
const navigate = useNavigate(); // navigate 훅 사용
const handleLogin = async (e: { preventDefault: () => void; }) => {
e.preventDefault();
try {
const response = await axios.post('http://localhost:7172/api/login', {
username,
password,
}, {withCredentials: true }); // 쿠키를 자동 입력해 준다
if(response.data.message == "success"){
// 로그인이 성공했기 때문에 해당 id 를 저장한다
setUserInfo(username );
// 로그인 성공 후 홈 페이지로 이동
navigate("/");
}else {
alert("로그인 실패하였습니다.");
}
} catch (error) {
console.error('Login failed:', error);
}
};
return(
https://greed-yb.tistory.com/305
여기에서 생성했던 auth, privateRoute 에 코드를 수정한다
auth.tsx
// 유저정보 가져오기
export const userNameCheck = async (): Promise<string | null> => {
const checkToken = Cookies.get('refreshToken'); // refreshToken 가져오기
try {
const response = await axios.post("http://localhost:7172/api/username", {}, {
params: { checkToken }
});
return response.data ? response.data : null;
} catch (error) {
console.error('error');
return null; // 오류가 발생하면 null 반환
}
};
//////////////////////////////////////////////////////////
코드를 추가해 준다
privateRoute.tsx
// user 정보 저장
const { setUserInfo } = useUserContext();
React.useEffect(() => {
const fetchUsername = async () => {
const username = await userNameCheck(); // 비동기적으로 username 가져오기
if (username) {
setUserInfo(username); // username 저장
}
};
fetchUsername();
}, [setUserInfo]);
////////////////////////////////////////////
저장되어 있는 username 이 없다면 페이지 이동 시 확인하여
auth.tsx 에서 만든 userNameCheck() 를 사용하여
사용자의 username 을 저장한다
controller
@PostMapping("/username")
@ResponseBody
public String username(@RequestParam String checkToken) throws Exception {
// refreshToken 에서 사용자의 username 을 가져온다
String username = jwtTokenUtil.getUsernameFromRefreshToken(checkToken);
System.err.println("username : " + username);
return username;
}
사용자 username 을 가져오기 위해 refresh token 에서 데이터를 추출하였다
Spring Security 가 잘 설정되어 있고 오류가 없다면
// Spring Security 에서 로그인한 사용자 id 가져오기
String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
이 방식을 선호하는데, 현재 Security 가 제대로 동작하지 않아서 refresh 에서 추출하였다
App.tsx
import {BrowserRouter, Route, Routes, useLocation} from "react-router-dom";
import Header from "./components/layout/header";
import Footer from "./components/layout/footer";
import Sidebar from "./components/layout/sidebar";
import Dashboard from "./components/pages/dashboard";
import Profile from "./components/pages/profile";
import Login from "./components/pages/login";
import PrivateRoute from "./components/utils/privateRoute";
import Register from "./components/pages/register";
import Board from "./components/pages/board";
import BoardWrite from "./components/pages/boardWrite";
import BoardRead from "./components/pages/boardRead";
import {UserProvider} from "./components/utils/UserInfo";
// 페이지 layout 구분하기
function AppLayout(){
const location = useLocation();
const layoutPass = ["/signin" , "/register"]; // 로그인 , 회원가입 페이지 제외
const pageCheck = layoutPass.includes(location.pathname);
return (
<div className="App">
{!pageCheck && <Header/>}
{!pageCheck && <Sidebar/>}
<Routes>
<Route path="/signin" element={<Login />}/>
<Route path="/register" element={<Register />}/>
<Route path="/" element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
}/>
<Route path="/board" element={
<PrivateRoute>
<Board />
</PrivateRoute>
}/>
<Route path="/boardWrite" element={
<PrivateRoute>
<BoardWrite />
</PrivateRoute>
}/>
<Route path="/boardRead/:no" element={
<PrivateRoute>
<BoardRead />
</PrivateRoute>
}/>
<Route path="/profile" element={
<PrivateRoute>
<Profile />
</PrivateRoute>
}/>
</Routes>
{!pageCheck && <Footer/>}
</div>
);
}
function App() {
return (
// 저장한 유저정보를 사용하기 위해서 감싼다
<UserProvider>
<BrowserRouter>
<AppLayout />
</BrowserRouter>
</UserProvider>
);
}
export default App;
<BrowserRouter> 위에
<UserProvider> 을 감싸서 username 을 전역변수로 사용할 수 있게 한다
TEST
import {useUserContext} from "../utils/UserInfo";
function Board() {
const { username } = useUserContext();
console.log("Board 페이지 : "+ username);
어느 페이지에서든 useUserContext() 로 데이터를 가져올 수 있다
이제 username 또는 권한으로 수정, 삭제 기능을 만들면 된다
며칠간 JPA 공부한다고 React 를 안 만졌더니
그새 또 어리바리하고 있다...
공부하면서 너무 많은 난관에 부딪히다 보니
그저 회사에서 일처리 하듯이... 그저 해결하기 위해
머릿속에 남지 않는 코딩을 하고 있는 기분이다
그리고 문법이 도저히 적응이 안 된다...
현재 포스팅한 방식도 내 맘대로 개발한 방식이므로 FM 적인 방법은 아니라고 단언할 수 있다
그저 이번에도 이런 흐름으로 사용한다 정도로 참고하길 바란다
'개발 > Spring' 카테고리의 다른 글
[SpringBoot] React + TypeScript + JPA 프로젝트 (10) - 게시판 만들기(수정하기) (0) | 2024.11.21 |
---|---|
[SpringBoot] React + TypeScript + JPA 프로젝트 (9) - 게시판 만들기(상세보기) (0) | 2024.11.20 |
[SpringBoot] React + TypeScript + JPA 프로젝트 (7) - 게시판 만들기(글 작성) (1) | 2024.11.08 |
[SpringBoot] React + TypeScript + JPA 프로젝트 (6) - 게시판 만들기(페이징 처리) (1) | 2024.11.07 |
[SpringBoot] React + TypeScript + JPA 프로젝트 (5) - 게시판 만들기(목록) (0) | 2024.11.04 |
댓글