내가 원하는 조건 ->
- 로그인 상태가 아닐 경우 접근 제한: /signin 이외의 모든 route ('/today, /calendar')
- 로그인 상태일 경우 접근 제한: /signin
- 실제 페이지에 접근 후 리다이렉트되는 게 아니라 그 이전에 서버에서 체크
그런데 클라이언트 쪽에서 인증 페이지를 구분하고 로그인 페이지로 리다이렉트할 경우 인증되지 않은 사용자가 페이지를 방문했을 때 일시적으로 화면이 표시된 후 페이지가 리다이렉트되면서 깜박거린다 !
루트에 있는 middleware.ts를 많이 사용하시길래 방법을 찾아봤는데, middleware.ts 파일에서 요청하면 API 라우트 또는 페이지 요청 전에 실행되기 때문에 보호해야 할 경로에 대한 초기 접근 제어가 가능하다고 한다.
나는 세션을 가져와서 사전 체크를 진행했는데, (세션 써본적없어서 ... 궁금해서) 구글링 해보니까 쿠키에 담긴 토큰을 확인하는 사례가 많더라.?? 이 부분은 나중에 보안 관련해서 더 찾아보고 수정할 것 같다.
// 로그인해야 접근할 수 있는 루트[]
const protectedRoutes = ['/today', '/calendar']
export async function middleware(request: NextRequest) {
const response = await updateSession(request)
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
/* 쿠키 get/set/remove 설정 */
},
},
)
// session 값 여부에 따라 리다이렉션
const { data: { session }, error} = await supabase.auth.getSession()
if (request.nextUrl.pathname === '/signin' && session) {
url.pathname = '/'
return NextResponse.redirect(url)
}
if (protectedRoutes.includes(request.nextUrl.pathname)) {
if (!session) {
url.pathname = '/signin'
return NextResponse.redirect(url)
}
}
if(error) {
console.error(error)
}
return response
}
(하단은 추가 구현 내용)
로그인 없이 접근하면 안되는 페이지에 접근하면, 그때 유저의 세션 확인으로 접근 제한했으면 좋겠는데 로그인하지 않은 상태로 웹페이지에 들어가기만 해도 세션없다는 에러가 뜬다. 먼가 좋은 방법이 없을까....
위 문제 방법을 찾고 수정했다. (글의 3차 시도 부분)
+ 사용자 정보 전역 관리
문제 하나 더 찾았다.
- 일반 로그인 성공 -> '/'로 이동하는데, fetchUser로 데이터 들어오기 전에 서버에서 session 먼저 체크해서 '/'로 이동하기 때문에 로그인 상태가 아닌 상태로 페이지 이동을 하는 상황으로 보인다. (task create하려고 하면 user.id가 null, 새로고침을 하면 데이터가 들어온다.)
- oauth 로그인 성공 -> '/signin'에 그대로 있는데, fetchUser가 먼저 작동되었는지 사이드바에 유저 데이터가 들어와 있다.
일반 로그인 버그는 로그인 버튼 함수끝에 이걸로 해결함
if (response && response.error) {
alert('일치하는 계정이 없습니다. 다시 작성해주세요. ')
} else {
await checkisLogin() // 요거
}
const handleGoogleLogin = async () => {
const supabase = createClient()
const { error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: 'http://localhost:3000/auth/callback', // 이 부분을 안 쓰고 있었음 그리고 기존에 내가 위에서 작성한 액션 함수는 경로가 잘못되어서 적용이 안되고 잇엇음!!!
queryParams: {
access_type: 'offline',
prompt: 'consent',
},
},
})

이렇게 옳은 경로로 수정해주니 원하던 대로 oauth 성공하면 /로 이동된다. 황당하다. 공식문서를 잘 읽자.