Next.js
React에서 페이지 전환 후 로그인이 풀리는 이유
페이지네이션 같은 URL 변경에서 인증 상태가 초기화되는 건 전역 상태 관리 방식 때문이다. 재렌더링 시에도 상태를 유지해야 한다.
페이지 네이션으로 페이지를 바꾸면 로그인이 풀린다. 새로운 페이지를 로드할 때 인증 토큰을 확인하지 않기 때문이다.
상태 초기화 문제
React에서 라우트가 바뀔 때 전역 상태가 초기화되는 경우가 있다:
const [isAuthenticated, setIsAuthenticated] = useState(false);
// 이렇게 하면 페이지 이동할 때마다 false로 초기화된다
로컬 스토리지나 세션 스토리지에 저장된 값을 읽지 않으면 매번 초기화된다는 뜻이다.
해결법: 초기값 복원
컴포넌트가 마운트될 때 저장된 인증 상태를 복원해야 한다:
const [isAuthenticated, setIsAuthenticated] = useState(() => {
const stored = localStorage.getItem('auth_token');
return !!stored;
});
useEffect(() => {
localStorage.setItem('auth_token', token);
}, [token]);
초기값으로 함수를 전달하면 한 번만 실행되고, 이후 페이지 이동에서도 상태가 유지된다.
컨텍스트를 활용한 방식
여러 컴포넌트에서 인증 상태를 공유해야 한다면 Context가 좋다:
const AuthContext = createContext<AuthContextType | null>(null);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState(() => {
const stored = sessionStorage.getItem('user');
return stored ? JSON.parse(stored) : null;
});
useEffect(() => {
if (user) {
sessionStorage.setItem('user', JSON.stringify(user));
}
}, [user]);
return (
<AuthContext.Provider value={{ user, setUser }}>
{children}
</AuthContext.Provider>
);
}
렌더링 조건 확인
페이지 전환 후에도 조건부 렌더링이 제대로 되는지 확인해야 한다:
if (!isAuthenticated) {
return <div>로그인하세요</div>;
}
return (
// 페이지 콘텐츠
);
라우트 보호를 위해서는 라우터 레벨에서도 처리하는 게 좋다.
토큰 만료 시간 확인
토큰이 만료되었을 수도 있다. 토큰에 만료 시간이 있다면 주기적으로 확인해야 한다:
useEffect(() => {
const checkToken = () => {
const token = localStorage.getItem('auth_token');
const expiresAt = localStorage.getItem('auth_expires');
if (expiresAt && new Date().getTime() > parseInt(expiresAt)) {
// 토큰 만료됨
localStorage.removeItem('auth_token');
setIsAuthenticated(false);
}
};
checkToken();
const interval = setInterval(checkToken, 60000); // 1분마다 확인
return () => clearInterval(interval);
}, []);
빌드 후 테스트
npm run build
# 브라우저에서 직접 페이지 전환을 여러 번 해본다
개발 서버와 프로덕션 빌드에서 동작이 다를 수 있으니 꼭 확인해야 한다.
안전한 수정 순서
- 현재 인증 상태를 localStorage에서 읽도록 수정
- 페이지 이동 후에도 상태가 유지되는지 테스트
- 토큰 만료 로직 추가
- 라우트 보호 추가
한 번에 여러 개를 바꾸면 뭐가 원인인지 알 수 없다. 하나씩 테스트하며 진행하자.