인프런 커뮤니티 질문&답변

호갱님의 프로필 이미지

작성한 질문수

맛집 지도앱 만들기 (React Native + NestJS)

[3-8] React Query 도입(2) - 로그인 연동하기

로그인 구현 에러 (nest 에러?)

해결된 질문

24.09.18 21:06 작성

·

96

0

안녕하세요 강사님

수준높은 강의 정말 감사합니다.

 

회원가입, 로그인 구현중 에러가 나서 질문드립니다.

 

제가

섹션4 인증 기능 구현하기

[3-8] React Query 도입(2) - 로그인 연동하기

구현중에 있습니다.

 

회원가입시 db 까지는 insert가 등록은 잘됩니다.

select 해보니깐 user 테이블에 회원가입이 잘되었더라구요

 

하지만

로그인후 페이지 이동? 이되지가 않는데

front 에서는 에러가 나지 않고

 

server 에서만

image.png

 

이렇게 에러가 나더라구요

그래서 제가 uploads 폴더에 제대로 복사를 하지 않은줄 알았는데

server 에서는 uploads 폴더가 없더라구요?

 

그래서 이게

front 에서 잡아야하는 문제인지

server 에서 잡아야하는 문제인지 좀 헷갈리는데

제가 혹시 server 설정중 빠트린부분이 있어서 에러가 나는걸까요?

 

답변 1

0

Kyo님의 프로필 이미지
Kyo
지식공유자

2024. 09. 18. 21:09

로그인은 상관없이 되어야합니다. 회원가입도 잘되었고 db에 들어갔다면 설정에도 문제가 없는것입니다. 프론트 코드 로그인 로직에 문제가없나 살펴보시겠어요? 저 에러메세지는 무시하셔도됩니다.

호갱님의 프로필 이미지
호갱
질문자

2024. 09. 18. 21:25

아 server 쪽 에러는 무시해도되는군요

login api 에서

log 를 찍어보니

accessToken 과 refreshToken 이 잘찍히는걸보면

제가 아무래도

페이지 전환? MapHomeScreen 으로 연결하는쪽에서 무언가 빼먹은것 같습니다.

차근차근 살펴보겠습니다.

 

빠른답변 감사드립니다!!

Kyo님의 프로필 이미지
Kyo
지식공유자

2024. 09. 18. 21:26

네 네비게이션, 로그인이나 리프레시 로직 살펴보시겠어요?

또한 3-8 수업노트도 확인해보셨나요? 안드로이드의경우 설정해주셔야하는 부분이 있습니다.

3-8수업 화면에서 모바일이라면 [수업자료]를 누르고, pc라면 수업노트 보기를 누르거나 아래로 스크롤하면 됩니다.

호갱님의 프로필 이미지
호갱
질문자

2024. 09. 18. 21:50

아 넵

이제보니 isLogin 이 무조건 false 로 떨어져서

login 페이지로 못가는거였네요

function RootNavigator() {
  const {isLogin} = useAuth();
  console.log(`isLogin : ${isLogin}`);
  return <>{isLogin ? <MainDrawerNavigator /> : <AuthStackNavigator />}</>;
}

 

에고 git 을 봤더니 완료된 소스라서그런지

에러를 못찾겠는데

혹시 아래 소스에서 어디가 잘못되었는지 알수 있을까요? ㅜㅜ

import {useMutation, useQuery} from '@tanstack/react-query';
import {
  getAccessToken,
  getProfile,
  logout,
  postLogin,
  postSignup,
} from '../../api/auth';
import {
  UseMutationCustomOptions,
  UseQueryCustomOptions,
} from '../../types/common';
import {removeEncryptStorage, setEncryptStorage} from '../../utils';
import {removeHeader, setHeader} from '../../utils/header';
import {useEffect} from 'react';
import queryClient from '../../api/queryClient';

function useSignup(mutationOptions?: UseMutationCustomOptions) {
  return useMutation({
    mutationFn: postSignup,
    ...mutationOptions,
  });
}

function useLogin(mutationOptions?: UseMutationCustomOptions) {
  return useMutation({
    mutationFn: postLogin,
    onSuccess: ({accessToken, refreshToken}) => {
      setEncryptStorage('refreshToken', refreshToken);
      setHeader('Authorization', `Bearer ${accessToken}`);
    },
    onSettled: () => {
      queryClient.refetchQueries({queryKey: ['auth', 'getAccessToken']});
      queryClient.invalidateQueries({queryKey: ['auth', 'getProfile']});
    },
    ...mutationOptions,
  });
}

function useGetRefreshToken() {
  const {isSuccess, data, isError} = useQuery({
    queryKey: ['auth', 'getAccessToken'],
    queryFn: getAccessToken,
    staleTime: 1000 * 60 * 30 - 1000 * 60 * 3,
    refetchInterval: 1000 * 60 * 30 - 1000 * 60 * 3,
    refetchOnMount: true,
    refetchIntervalInBackground: true,
  });

  useEffect(() => {
    if (isSuccess) {
      setHeader('Authorization', `Bearer ${data.accessToken}`);
      setEncryptStorage('refreshToken', data.refreshToken);
    }
  }, [isSuccess]);

  useEffect(() => {
    if (isError) {
      removeHeader('Authorization');
      removeEncryptStorage('refreshToken');
    }
  }, [isError]);

  return {isSuccess, isError};
}

function useGetProfile(queryOptions?: UseQueryCustomOptions) {
  return useQuery({
    queryKey: ['auth', 'getProfile'],
    queryFn: getProfile,
    ...queryOptions,
  });
}

function useLogout(mutationOptions?: UseMutationCustomOptions) {
  return useMutation({
    mutationFn: logout,
    onSuccess: () => {
      removeHeader('Authorization');
      removeEncryptStorage('refreshToken');
    },
    onSettled: () => {
      queryClient.invalidateQueries({queryKey: ['auth']});
    },
    ...mutationOptions,
  });
}

function useAuth() {
  const signupMutation = useSignup();
  const refreshTokenQuery = useGetRefreshToken();
  const getProfileQuery = useGetProfile({
    enabled: refreshTokenQuery.isSuccess,
  });
  const isLogin = getProfileQuery.isSuccess;

  const loginMutation = useLogin();
  const logoutMutation = useLogout();

  return {
    signupMutation,
    loginMutation,
    isLogin,
    getProfileQuery,
    logoutMutation,
  };
}

export default useAuth;

 

 

호갱님의 프로필 이미지
호갱
질문자

2024. 09. 19. 00:20

아이고 죄송합니다.

const getProfile = async (): Promise<ResponseProfile> => {
  const {data} = await axiosInstance.get('/auth/profile');
  console.log(`getProfile data : ${JSON.stringify(data)}`);
  return data;
};

 

해당로그가 안찍혀서

api server 에 가서 /auth/profile 을 찾았는데 없어서보니깐

/auth/me 였네요 ㅜㅜ

죄송합니다 오타? 로 강사님의 시간을 뺏었습니다 ㅜㅜ

Kyo님의 프로필 이미지
Kyo
지식공유자

2024. 09. 19. 00:33

찾아서 다행입니다!

호갱님의 프로필 이미지

작성한 질문수

질문하기