본문 바로가기

boilerplate/Jhon-Ahn boilerplate frontend

Auth

홈페이지를 사용할 때 보면 인증이 이뤄져야만 들어갈 수 있는 페이지가 있다.

예를 들어, 댓글을 작성한다던지, 마이페이지를 이용해야한다던지 등등.. 

그리고 또 로그인한 유저 중에서도 관리자 권한이 있는 유저만 들어갈 수 있는 페이지도 존재한다.

이러한 페이지들을 통제할 수 있는 것이 바로 Auth(hoc)이다.

 

"HOC(HIGHER ORDER COMPONENT) 란?"

고차 컴포넌트라고도 하는데, 컴포넌트 로직을 재사용하기 위해 사용되고 컴포넌트를 가져와 새 컴포넌트를 반환하는 함수이다.

즉, 컴포넌트를 인자로 받거나 반환하는 함수이다. 

https://jiyoon-park.tistory.com/entry/React-HOC%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

 

React HOC에 대해 알아보자

HOC(Higher-Order-Components)은 컴포넌트를 개발하는 하나의 패턴으로, 컴포넌트를 인자로 받아 새로운 컴포넌트로 변환해 반환하는 함수이다. HOC은 같은 로직을 다수의 컴포넌트에 동일 적용해야할

jiyoon-park.tistory.com

 

강사님께서도 유지보수를 위해서 auth를 hoc로 구현하셨다. 

일일이 코드에서 if(isAuth === true), if(isAdmin === true) 이런 코드들을 남발할 필요 없이

컴포넌트를 auth로 묶어주고 매개변수 몇 개 넣어주면 해당 컴포넌트의 페이지 인증 부분을 구현할 수 있다. 

 

과정은 이렇다.

1. Auth라는 hoc에서 백엔드에 request를 보낸다.

2. 현재 LandingPage에 들어와있는 사람의 상태 정보(로그인이 되어있는 유저인지, 어드민인지 등등)를 hoc에 가지고 온다.

3. Auth에서 이제 분류를 한다. 현재 들어와있는 page가 만약 LandingPage일 경우 조건없이 모든 사람이 접속할 수 있기 때문에 이 사람은 들어올 수 있고, 다른 케이스로 adminPage일 경우 접속한 사람이 로그인한 유저면서 어드민 권한까지 갖고 있는 사람만 접속할 수 있기 때문에 조건에 맞지 않는다면 들어올 수 없게 한다(다른 페이지로 보낼 수도 있다).

 

 

처음에 폴더 구조 생성할 때 hoc라는 폴더를 만들었었다.

이 폴더에 auth.js 라는 파일을 하나 만들어주자.

 

user_action.js

export function auth() {
    const request = Axios.get('/api/users/auth')
        .then(response => response.data)

    return {
        type: 'AUTH_USER',
        payload: request //옵션
    }
}

 

 

types.js

export const LOGIN_USER = 'login_user';
export const REGISTER_USER = 'register_user';
export const AUTH_USER = 'auth_user';

 

 

user_reducer.js

import {
    LOGIN_USER,
    REGISTER_USER,
    AUTH_USER
} from "../_actions/types";

export default function (state = {}, action) {
    switch (action.type) {
        case LOGIN_USER:
            return { ...state, loginSuccess: action.payload }
        case REGISTER_USER:
            return { ...state, registerSuccess: action.payload }
        case AUTH_USER:
            return { ...state, userData: action.payload }
        default:
            return state;
    }
}

위 코드에서 Success가 아닌 userData로 넣어준 이유는 

auth 액션이 axios로 서버에 get 데이터 요청을 하면 현재 상태의 유저 정보들을 갖고오기 때문이다. 

 

index.js
server/middleware/auth.js

 

 

auth.js

import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { auth } from "../_actions/user_action";
import {withRouter} from "react-router-dom";

export default function (SpecificComponent, option, adminRoute = null) {
    
    /*
        option
        null -> 아무나 출입이 가능
        true -> 로그인한 유저만 출입이 가능
        false -> 로그인한 유저는 출입이 불가능
    */

    // auth에서 백엔드에 request를 했을 때 그 사람의 상태를 갖고옴 
    function AuthenticationCheck(props) {
        const dispatch = useDispatch();

        useEffect(() => {
            dispatch(auth()).then(response => {
                console.log(response)

                // 조건에 따라 유저를 분류해주는 작업 

                // 로그인 하지 않은 상태
                if (!response.payload.isAuth) {
                    if (option) {
                        props.history.push('/login')
                    }
                } 
                // 로그인 한 상태 
                else {
                    // 어드민 페이지인데, 어드민이 아닐 경우 
                    if (adminRoute && !response.payload.isAdmin) {
                        props.history.push('/')
                    }
                    // 일반 로그인한 유저 페이지일 때 
                    else {
                        // option이 false라는 것은 로그인한 유저는 접속 불가능한 페이지이다. (ex loginPage, registerPage)
                        // 로그인한 유저인데 option이 false인 페이지에 접속하려 할 때 
                        if (!option) {
                            props.history.push('/')
                        }
                    }
                }

            })
        },[])

        return <SpecificComponent />
    }

    return withRouter(AuthenticationCheck)
}

 

App.js

redux 과정이랑 hoc에 관해서는 앞에서 계속 나온 내용이라 설명은 생략한다. 

복습할 땐 앞의 내용을 참고하자.

 

boilerplate 기초 끝!