현재 진행중인 프로젝트는 비로그인 상태의 유저도 애플리케이션을 이용할 수 있도록 설계되었는데, 특정 페이지는 로그인한 유저만 접근하도록 비로그인 유저에 한해서 페이지 접근 제한을 구현해야 했다. 해당 로직을 구현하면서 어려움을 겪었던 과정과 채택하게 된 로직에 대해서 포스팅을 진행해보고자 한다.
1. axios interceptor
가장 처음엔, 비로그인 유저를 접근 제한해야 하는 페이지 내에서는 페이지 접속 시 api를 통해 유저의 정보를 가져오도록 되어있어서, 해당 axios interceptor에서 로직을 구현하려 했다. 기본적으로 api 요청시 헤더에 토큰을 담아 요청하기 때문에, 비로그인 유저로 해당 페이지에 접속하게 되면 401 에러를 만나고, interceptor 내에서 해당 에러를 만났을 때, 알럿과 함께 로그인 창으로 이동시키는 방법이다.
import axios from 'axios';
import { CONFIG } from '@config';
import { getToken, setToken } from '@utils/token';
import authApi from '@apis/auth/authApi';
...
const instance = axios.create({
baseURL: CONFIG.BASE_URL,
});
instance.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
const { config: originalRequest, response } = error;
const { data } = response;
const UnAuthorizeError = data.error_code === '100';
if (UnAuthorizeError) {
alert('세션이 만료되었습니다. 다시 로그인해 주시기 바랍니다.');
window.location.href = `${CONFIG.LOCAL}/auth/login`;
}
},
);
export default instance;
하지만, 비로그인 유저가 해당 페이지에 접속 시에 불필요하게 api 요청이 이루어진다는 점과 특정 모달 창을 띄워야 한다는 점을 고려했을 때 위의 로직은 적합하지 않다고 판단했다.
2. _app
가장 먼저 실행되는 최상위 컴포넌트로 모든 페이지는 _app.tsx 파일을 거쳐 렌더링 되기 때문에, 해당 파일 내에서 비로그인 접근제한을 구현하게 된다면, 모든 페이지에서 접근제한이 구현되고, 각 페이지마다 접근제한에 관한 로직을 구현하지 않아도 되기 때문에, 유지보수와 코드 중복 방지에 장점을 가지게 된다. 또한 해당 페이지 내에서 api 요청이 이루어 지기 전에 접근 제한에 대한 로직이 실행되기 때문에, 불필요한 api 요청을 제거할 수 있다.
...
export default function App({ Component, pageProps }: AppPropsWithLayout) {
const router = useRouter();
const loginRequiredPages = ['/my', '/wish'];
if (
loginRequiredPages.includes(router.pathname) &&
!getLocalStorage('@token')
) {
return (
<Layout>
<Modal
isModal={true}
isKakao={true}
title="로그인 상태가 아니에요!"
message="해당 페이지는 카카오톡 로그인을 하셔야 이용가능한 페이지에요. 로그인 하시겠어요?"
left="아니요"
leftEvent={() => router.back()}
/>
</Layout>
);
}
...
}
접근 페이지가 로그인 유저만 접근이 가능한 페이지 목록에 해당하고, 현재 토큰이 존재하지 않는다면 비로그인 유저로 판단하고 모달을 띄우게 된다.
이렇게 오늘은 비로그인 사용자에 대한 접근제한을 다루는 방법에 대해서 알아보았다. 모든 페이지의 공통적인 설정을 담당하는 _app.tsx의 중요성을 다시 한 번 상기 시키는 계기가 되었던 것 같다. 이 포스팅을 보는 다른 개발자 분들에게도 도움이 되었으면 한다.
'개발' 카테고리의 다른 글
[개발] Nextjs Link 컴포넌트와 <a> 태그 (feat. 이메일 링크걸기) (0) | 2023.05.28 |
---|---|
[개발] nextjs에서 모달 관리하기 (feat. recoil) (0) | 2023.05.08 |
[React] Debounce 훅 구현하기 (0) | 2023.04.13 |
[개발] Nextjs Script 컴포넌트 사용 방법 (feat. 카카오맵) (0) | 2023.04.05 |
[개발] 카카오 로그인 구현하기 (0) | 2023.03.27 |