Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[윤아영] week19 & week20 #1080

Conversation

ayoung-iya
Copy link
Collaborator

요구사항

기본

  • [로그인페이지] 로그인 실패하는 경우, 이메일 input 아래에 “이메일을 확인해주세요.”, 비밀번호 input 아래에 “비밀번호를 확인해주세요.” 에러 메세지가 보이나요?
  • [로그인페이지] https://bootcamp-api.codeit.kr/docs 에 명세된 “/api/sign-in”으로 { “email”: “[email protected]”, “password”: “sprint101” } POST 요청해서 성공 응답을 받으면 “/folder”로 이동하나요?
  • [회원가입 페이지] 회원가입을 실행할 경우, 문제가 있는 경우 문제가 있는 input에 에러 메세지가 보이나요?
  • [회원가입 페이지] 이메일 중복 확인은 “/api/check-email” POST 요청해서 확인 할 수 있나요?
  • [회원가입 페이지] 유효한 회원가입 형식의 경우 “/api/sign-up” POST 요청하고 성공 응답을 받으면 “/folder”로 이동하나요?
  • [로그인, 회원가입 페이지 공통] 로그인/회원가입시 성공 응답으로 받은 accessToken을 로컬 스토리지에 저장하나요?
  • [로그인, 회원가입 페이지 공통] 로그인/회원가입 페이지에 접근시 로컬 스토리지에 accessToken이 있는 경우 ‘/folder’ 페이지로 이동하나요?
  • 모달에 필요한 api 요청을 만들어 기능을 완성해 주세요.
  • api 요청에 TanStack React Query를 활용해 주세요.

주요 변경사항

  • 로그인, 회원가입 api요청을 보내고 토큰을 로컬 스토리지에 저장했습니다.

멘토에게

  • 지난 미션에서 로그인, 회원가입 기능을 구현하지 못해 이번 주에 구현하였습니다.
  • 이후 유저의 정보를 context api로 관리할 수 있도록 할 예정이고, 모달의 기능을 구현하고 싶습니다.

Copy link

vercel bot commented May 12, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
4-weekly-mission ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 18, 2024 5:42pm
4-weekly-mission-ursd ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 18, 2024 5:42pm

Copy link
Collaborator

@arthurkimdev arthurkimdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

과제 제출하시느라 고생 많으셨습니다! 🙏

Comment on lines +31 to +32
window.localStorage.setItem('accessToken', accessToken);
window.localStorage.setItem('refreshToken', refreshToken);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보통 localStorage.setItem 사용할 땐, 그럴일이 없겠지만, characters limit & 저장공간 5MB 제한이 있어서 초과하려고 할 때, QuotaExceededError 에러가 발생할 수 있어요. 그렇기 때문에 아래처럼 try / catch를 감싸서 사용해야합니다.
혹은 보안 설정으로 인하여 localStorage 접근이 안될 때도 저렇게 하게되면 에러가 발생하겠죠?

const saveToLocalStorage = (key, value) => {
  try {
    localStorage.setItem(key, value);
  } catch (e) {
    console.error(e)
  }
}

Comment on lines +54 to +55
const token = window.localStorage.getItem('accessToken');

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 localStorage에서 getItem을 실행할 땐, try / catch로 에러 처리가 반드시 필요합니다.
일부 브라우저 (safari) 시크릿 모드 사용 시, localStorage에 접근을 제한할 수 있기 때문이에요.
즉, localStorage에 접근하려고 시도하면 스크립트 오류가 발생하거나 localStorage 객체 자체가 정의되지 않아 오류가 발생할 수 있습니다.
이를 방지하기 위해 보통 공통 util 함수를 만들어서 사용합니다.

const safeGetItem = (key) => {
  try {
    return localStorage.getItem(key);
  } catch (error) {
    console.error(error);
    return null;
  }
}

Comment on lines +46 to +53
const fetchUser = async () => {
try {
const user = await getUser();
setUser(user);
} catch (error) {
console.error((error as Error).message);
}
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런 유저정보를 가져오는 기능은 다른 곳에서도 충분히 사용 할 수 있기 때문에, util 디렉토리에 별도로 hook을 분리해서 만든 후 재사용 하는 습관이 좋을 것 같아요~

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const useFetchUser = () => {
  const [user, setUser] = useState<User | undefined>(undefined);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState<boolean>(true);

  useEffect(() => {
    const fetchUser = async () => {
      try {
        const userData = await getUser();
        setUser(userData);
      } catch (error) {
        setError((error as Error).message);
      }
    };

    fetchUser();
  }, []);

  return { user, error, loading };
};

export default useFetchUser;

그리고 실제 사용때는 아래처럼 사용하는거죠

...

const { user, error, loading } = useFetchUser();

Comment on lines +3 to +19
export const postSignIn = async ({ email, password }: { email: string; password: string }) => {
const response = await fetch(`${BASE_URL}/auth/sign-in`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password }),
});

if (!response?.ok) {
throw new Error('로그인을 실패했습니다.');
}

const token = await response.json();

return token;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 아래 코드들 보면 headers 같은 값들이 중복으로 설정되는 코드들이 보여요

보통 이럴땐 fetchApi 같은 공통 fetch 함수를 만들고, 이를 통해 중복 설정하는 로직을 개선합니다.

const fetchApi = async (url: string, options: RequestInit) => {
  const response = await fetch(`${BASE_URL}${url}`, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });

  if (!response.ok) {
    const errorBody = await response.json();
    throw new Error(errorBody.message || '요청에 실패했습니다.');
  }

  return response;
};

그리고 실제 사용때는 아래처럼 사용할 수 있어요.

export const postSignIn = async ({ email, password }: { email: string; password: string }) => {
  const response = await fetchApi('/auth/sign-in', {
    method: 'POST',
    body: JSON.stringify({ email, password }),
  });

  const token = await response.json();
  return token;
};

@arthurkimdev arthurkimdev merged commit f28a0d4 into codeit-bootcamp-frontend:part3-윤아영 May 24, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
미완성 죄송합니다.. 순한맛🐑  마음이 많이 여립니다..
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants