Front-End/React

[React] React-router-dom을 이용한 Private Route 설정 시 인증/인가 처리 오류

Olivia Kim 2023. 6. 3. 19:58
반응형

 

오류 내역

반복되는 인증/인가 처리를 효율적으로 진행하기 위해 라우팅을 진행하는 App.jsx에서 Private Route를 이용해 일괄 인증/인가 처리를 진행했다. 이때, 로컬 환경에서는 제대로 인증/인가 처리가 진행되지만 배포 서버에서는 동일한 코드임에도 불구하고 제대로 진행되지 않는 오류가 발생했다.

 

 

 


오류가 발생한 경로

  • 배포 서버에서 로그인 성공 후 마이페이지 진입 시 로그인이 유효하지 않아 재로그인 처리를 할 때와 같이 로그인 페이지로 navigate됨
  • 로그인 관련 데이터가 없는 경우가 아니라서 localStorage에 로그인 token, userFlag는 그대로 남아있고 마이페이지로 route만 되지 않는 상태

 

 

 


오류를 해결하기 위해 시도해 본 것들

1. 모든 인증/인가 if문에 console.log를 찍어서 어느 부분에서 넘어가지 않는 건지 확인을 진행했다.

 

▼ 해당 코드

더보기
// App.jsx

const isAuthenticated = () => {
  const authorization = localStorage.getItem('authorization');
  const refreshToken = localStorage.getItem('refreshToken');
  const user = localStorage.getItem('user');
  const store = localStorage.getItem('store_id');
  const result = {
    userFlag: '',
    msg: '',
  };

  if (!user && store) {
    result.userFlag = 'store';
  } else if (user && !store) {
    result.userFlag = 'user';
  }

  // 로그인 관련 모든 데이터가 존재할 경우
  if (result.userFlag && authorization && refreshToken) {
    console.log('[isAuthenticated] 모든 데이터가 존재 함', result);
    return { ...result };
  }

  // 로그인 관련 데이터가 하나라도 없을 경우 기존 로그인 정보 삭제, 재로그인 진행
  if ((!result.userFlag && authorization && refreshToken) || (result.userFlag && (!authorization || !refreshToken))) {
    localStorage.removeItem('authorization');
    localStorage.removeItem('refreshToken');
    localStorage.removeItem('user');
    localStorage.removeItem('store_id');
    const updatedResult = { ...result };
    updatedResult.msg = '로그인 정보가 유효하지 않습니다. \n다시 로그인을 진행해주세요.';
    console.log('[isAuthenticated] 데이터가 하나라도 없음', updatedResult);
    return updatedResult;
  }

  console.log('[isAuthenticated] 마지막으로 출력되는 result', result);
  return { ...result };
};

// * PrivateRoute 검증
const PrivateRoute = ({ category, element }) => {
  const { userFlag, msg } = isAuthenticated();
  console.log('userFlag와 msg', userFlag, msg);

  // ManagePage 진입할 경우
  if (userFlag !== '' && msg === '' && element.type.name === 'ManagePage') {
    console.log('ManagePage 진입할 경우');
    return element;
  }

  // 로그인 정보는 있으나 해당 정보가 유효하지 않을 경우
  if (msg !== '') {
    console.log('로그인 정보는 있으나 해당 정보가 유효하지 않을 경우');
    toast.error(msg);
    return <Navigate to={'/Login'} replace />;
  }

  // 로그인 정보와 해당 페이지 진입 조건이 일치할 경우
  if (userFlag !== '' && category === userFlag) {
    console.log('로그인 정보와 해당 페이지 진입 조건이 일치할 경우');
    return element;
  }

  // 로그인 정보와 해당 페이지 진입 조건이 불일치할 경우
  if (userFlag !== '' && category && category !== userFlag) {
    toast.error(`접근 권한이 없습니다. \n메인페이지로 이동합니다.`);
    return <Navigate to={'/'} replace />;
  }

  console.log('PrivateRoute 마지막 출력!🤔');
  return <Navigate to={'/Login'} replace />;
};

 

 

 

2. isAuthenticated(0에서 로그인 데이터가 모두 있는 부분은 확인했고, PrivateRoute()에서 userFlag만 있다는 것을 감지했으나(msg값이 있을 경우 로그인 정상 인증 X) 기존에 넘어가야 할 페이지로 route되지 않고 있었다.

// 👇🏼 원래 route 되어야 할 부분의 함수
// ManagePage 진입할 경우
  if (userFlag !== '' && msg === '' && element.type.name === 'ManagePage') {
    console.log('ManagePage 진입할 경우');
    return element;

// 👇🏼 콘솔에 출력된 부분의 함수
console.log('PrivateRoute 마지막 출력!🤔');
return <Navigate to={'/Login'} replace />;

 

 

 

3. 넘어오는 element값을 console.log로 출력하여 다시 확인해 보았다.

*로컬 환경에서의 element console.log

로컬에서는 element.type.name이 설정해 둔 'ManagePage'로 잘 출력되고 있다.

 

 

*배포 환경에서의 element console.log

하지만 배포 환경에서는 element.type이 'jw'라는 이름으로 출력되는 것을 확인할 수 있었다.

 

 

 


오류 해결 방법

React로 앱을 만들고 빌드를 하게 되면, 빌드 과정에서 JS 파일을 압축하기 위해 파일 명을 유동적으로 임의의 이름으로 바꾸는데, 이때 발생한 문제임을 확인했다. 따라서 element의 type.name으로 구분하지 않고 props를 추가적으로 부여하여 인증/인가 구분자를 설정했다.

// App.jsx
{/* PrivateRoute */}
<Route path={'/ManagePage/*'} element={<PrivateRoute element={<ManagePage />} isManagePage={'true'} />}>
  <Route path={'user'} element={<PrivateRoute category={'user'} element={<UserManagePage />} />} />
  <Route path={'store'} element={<PrivateRoute category={'store'} element={<StoreManagePage />} />} />
</Route>

// * PrivateRoute 검증
const PrivateRoute = ({ category, element, isManagePage }) => {
	const { userFlag, msg } = isAuthenticated();

	// ManagePage 진입할 경우
  if (userFlag !== '' && msg === '' && isManagePage === 'true') {
    return element;
  }
}

 

 

 


[해당 코드 전체 보기]

https://github.com/dawhisky/dawhisky-FE/blob/develop/src/App.jsx

 


[참고 자료]

https://cotak.tistory.com/108

 

[React.js] 라우터를 이용한 접근 제한 구현 (Access Control & Authentication)

사용자의 로그인 상태나 권한에 따라 접근할 수 있는 경로가 다르다. 물론 서버쪽에서 체크를 해주긴 하지만, 해당 URL로 넘어간다는 것 자체를 프론트측에서 막아주는 것이 바람직하다. 이를 그

cotak.tistory.com

 

 

 

반응형