[BueaFit] - Auth 인증 관리 3
저번 포스팅에서는 쿠키 보안 정책 때문에 쿠키를 사용 할 수 없어서 세션 스토리지를 사용했었다.
하지만 이번에 SSL(HTTPS)이 추가 되면서 요청과 도메인이 같은 url이 아니어도 쿠키를 전달 할 수 있게 되어 다시 쿠키로 인증 관리를 하는 방법으로 전환했다.
const login = async () => {
try{
const response = await fetch(`${process.env.NEXT_PUBLIC_BUEAFIT_API}/auth/login`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
"username" : email,
"password" : pw,
"grant_type" : "password"
}),
});
const data = response.json();
if(response.status === 200) {
// zustand 메모리에 액세스 토큰 저장
const access_token = jsonData.access_token;
setToken(access_token);
// 리프레시 토큰 저장 안되는 것 방지
await new Promise((res) => setTimeout(res, 0));
route.push('/store/main');
}
if(response.status === 401) {
alert('이메일이나 비밀번호가 틀렸습니다.')
}
}catch(error){
console.error(error)
}
}
로그인 할 때 액세스 토큰을 메모리에 담고, 이걸로 api 인증 요청을 할거다.
// 중복 리프레시 방지: 이미 요청 중이면 기존 Promise 반환받아 기다림
if (!refreshTokenPromise) {
refreshTokenPromise = fetch(`${process.env.NEXT_PUBLIC_BUEAFIT_API}/auth/refresh`, {
method: "POST",
credentials: "include",
})
.then(async (res) => {
if (!res.ok) throw new Error("리프레시 실패");
const data = await res.json();
setToken(data.access_token);
return data;
})
.finally(() => {
refreshTokenPromise = null; // 끝난 후 초기화
});
}
기존에는 세션 스토리지나 로컬 스토리지에 저장된 토큰을 꺼내서 헤더에 넣는 방식이었지만, 이제는 모든 인증 흐름을 `쿠키` 기반으로 전환하면서 스토리지를 사용할 필요가 없어졌다.
이에 따라 fetch 인터셉터에서도 관련 코드를 모두 제거하고, 쿠키를 통한 자동 인증 방식으로 통일했다.
확실히 스토리지를 이용하지 않으니까 로그인 됐을 때 로그인 페이지 가는 것을 방지하기 쉬워졌다.
// 로그인 됐을 때 페이지 못오게 이동
if (typeof window !== "undefined") {
// 리프레시 토큰 재발급
const fetchRefresh = async () => {
const res = await fetchInterceptors(`${process.env.NEXT_PUBLIC_BUEAFIT_API}/auth/refresh`, {
method: "POST",
credentials: "include",
})
const data = await res.json()
if(res.status === 200) {
setToken(data.access_token)
route.push('/store/main')
}
}
fetchRefresh();
}
리프레시 토큰이 쿠키에 존재하면 자동으로 액세스 토큰을 재발급받아 로그인 처리하고, 그 후 /store/main으로 이동하도록 설정했다.
저기 위에 보면 /store/main으로 이동하는데, 사실 원래 로직은 로그인 후 숍 선택 페이지로 이동했는데 이것보다 플로우 측면에서 main 페이지로 이동 후 선택된 숍이 없으면 숍 선택 페이지로 이동 하는 것이 더 자연스러운 것 같아 수정했다.
넥스트가 이런 점이 정말 편한게, /store 폴더의 layout.tsx에서 숍 선택 여부를 검사하면, 하위 모든 페이지에서 일관되게 이 로직을 적용할 수 있다. 덕분에 중복 코드 없이 인증 흐름과 초기 진입 제어를 깔끔하게 관리할 수 있다.