마지막으로 인증 체크 기능을 구현한다!
여러가지 페이지들은 아래 등으로 구성될 수 있다.
이런 페이지 접근에 대한 인증 부분들도 컨트롤 해주어야 한다.
물론 이것보다 user의 role에 따라 이것보다 더 많은 페이지가 있을 수 있고, 페이지 뿐만 아니라 댓글 작성, 파일 전송, 파일 업로드 등등에도 끊임없이 인증 체크 부분이 필요하다.
해당 글에서는 위의 기능들을 인증하기 위해 인증체크 기능을 구현하고, 들어갈 수 있는 페이지들에 대한 통제는 HOC 에서 진행한다.
HOC의 정의에 대해서는 앞의 글에서 짧게 설명한 적이 있으므로 넘어가고 어떻게 구성되어있는지에 대해 설명하겠다.
HOC는 function으로 다른 컴포넌트를 받은 다음 새로운 컴포넌트를 return한다.
const EnhancedComponent = higherOrderComponent(WrappedComponent);
위의 코드를 보면 hoc에 다른 컴포넌트를 넣어서 새로운 컴포넌트를 return 하는 것을 볼 수 있다.
우리는 인증 체크를 구현하려 하므로 Auth Component(HOC)를 만든다. 해당 Component에는 다른 Component를 집어넣어 새로운 Component를 만들어준다.
우리는 만들어둔 LoginPage, LandingPage, RegisterPage 들을 모두 Auth Component에 넣는다!
이렇게 HOC에 넣으면 어떤 일이 벌어지는지 흐름을 알기 위해 예시를 들어보자.
LandingPage를 Auth Component에 넣었다고 가정한다.
1. Auth 라는 HOC Component에서 백엔드에 request를 날린다.
2. 현재 LandingPage에 들어와있는 사람의 상태 정보(로그인이 되어있는지에 대한 여부, admin인지 등)을 가져온다.
3. 가지고 온 정보를 토대로 페이지에 접근할 수 있는지의 여부를 결정한다.
import Auth from "./hoc/auth";
function App() {
const AuthLandingPage = Auth(LandingPage, null);
const AuthLoginPage = Auth(LoginPage, false);
const AuthRegisterPage = Auth(RegisterPage, false);
return (
<Router>
<div>
<Routes>
<Route path="/" element={<AuthLandingPage />} />
<Route path="/login" element={<AuthLoginPage />} />
<Route path="/register" element={<AuthRegisterPage />} />
</Routes>
</div>
</Router>
);
}
모든 페이지 컴포넌트를 Auth로 감싸줌.
Auth의 parameter 설명
LandingPage는 아무나 들어갈 수 있기 때문에 option에 null 할당
LoginPage와 RegisterPage는 로그인 한 유저는 출입 불가하기 때문에 option에 false 할당
function(SpecificComponent, option, adminRoute = null){
}
import React, { useEffect } from "react";
import { useDispatch } from "react-redux";
import { auth } from "../_actions/user_action";
import { useNavigate } from "react-router-dom";
function Auth(SpecificComponent, option, adminRoute = null) {
function AuthenticationCheck(props) {
const dispatch = useDispatch();
const navigate = useNavigate();
useEffect(() => {
dispatch(auth()).then((response) => {
console.log(response);
// 로그인 하지 않은 상태
if (!response.payload.isAuth) {
if (option) {
navigate("/login");
}
} else {
// 로그인 한 상태
if (adminRoute && !response.payload.isAdmin) {
navigate("/");
} else {
if (!option) {
navigate("/");
}
}
}
});
}, []);
return <SpecificComponent />;
}
return AuthenticationCheck;
}
export default Auth;
Auth function 생성 후 parameter로 SpecificComponent, option, adminRoute = null 를 받음
AuthenticationCheck function 생성
3-1. 로그인 하지 않은 상태인 경우
response.payload.isAuth가 false이면 로그인 하지 않은 상태
3-2. 로그인 한 상태인 경우
response.payload.isAuth가 true이면 로그인 한 상태
export function auth() {
const request = axios.get("/api/users/auth").then((response) => response.data);
return {
type: AUTH_USER,
payload: request,
};
}
auth function 생성
axios를 통해 request 진행
서버에서 받은 data를 request 변수에 저장
return을 시켜 reducer로 보냄
type 이름은 AUTH_USER
export const AUTH_USER = "auth_user";
AUTH_USER을 추가해준다.
import { LOGIN_USER, REGISTER_USER } from "../_actions/types";
const userReducer = (state = {}, action) => {
switch (action.type) {
case AUTH_USER:
return { ...state, userData: action.payload };
default:
return state;
}
};
export default userReducer;
오늘도 어김없이 문제가 발생한다.
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
react-router-dom v6부터 component가 아닌 element를 사용해야하는데, auth로 감쌀 때 문제가 발생한다.
import Auth from "./hoc/auth";
function App() {
return (
<Router>
<div>
<Routes>
<Route path="/" element={ Auth(LandingPage, null) } />
<Route path="/login" element={ Auth(LoginPage, false) } />
<Route path="/register" element={ Auth(RegisterPage, false) } />
</Routes>
</div>
</Router>
);
}
hoc는 function이고 함수는 element에는 컴포넌트만 들어갈 수 있기 때문에 함수는 들어갈 수 없어 발생하는 에러이다.
import Auth from "./hoc/auth";
function App() {
const AuthLandingPage = Auth(LandingPage, null);
const AuthLoginPage = Auth(LoginPage, false);
const AuthRegisterPage = Auth(RegisterPage, false);
return (
<Router>
<div>
<Routes>
<Route path="/" element={<AuthLandingPage />} />
<Route path="/login" element={<AuthLoginPage />} />
<Route path="/register" element={<AuthRegisterPage />} />
</Routes>
</div>
</Router>
);
}
그래서 이렇게 변수를 선언한 뒤 컴포넌트와 option들을 auth로 감싸 할당해준다. auth로 감싼 이후 나오는 값은 specificComponent이므로 해당 변수는 Component이고 요 변수를 그대로 element에 넣어주어 해결한다!
대장정이 끝이 났다면 오산이고.. 그냥 기본 기능을 배워보자! 인 기초 강의라 쇼핑몰 사이트 만들려면 다시 바닥부터 시작이다.🥲
그래도 기초 강의 들으면서 노드에 대해 조금 알게되었고, 해본적 없던 기능 구현에 대해 배우면서 아 나 정말 아무것도 모르는 우물 안 개구리였구나를 느꼈다. 배웠던 redux도 기능 구현도 기초적인 부분이라지만 가장 코어한 부분이니 잘 익혀두자.🔥
따라하며 배우는 노드, 리액트 시리즈 - 기본 강의 를 공부하며 작성한 글입니다.