Skip to content

Conversation

cksrlcks
Copy link
Collaborator

@cksrlcks cksrlcks commented Jan 24, 2025

요구사항

기본

회원가입

  • 유효한 정보를 입력하고 스웨거 명세된 “/auth/signUp”으로 POST 요청해서 성공 응답을 받으면 회원가입이 완료됩니다.
  • 회원가입이 완료되면 “/login”로 이동합니다.
  • 회원가입 페이지에 접근시 로컬 스토리지에 accessToken이 있는 경우 ‘/’ 페이지로 이동합니다.

로그인

  • 회원가입을 성공한 정보를 입력하고 스웨거 명세된 “/auth/signIp”으로 POST 요청을 하면 로그인이 완료됩니다.
  • 로그인이 완료되면 로컬 스토리지에 accessToken을 저장하고 “/” 로 이동합니다.
  • 로그인/회원가입 페이지에 접근시 로컬 스토리지에 accessToken이 있는 경우 ‘/’ 페이지로 이동합니다.

메인

  • 로컬 스토리지에 accessToken이 있는 경우 상단바 ‘로그인’ 버튼이 판다 이미지로 바뀝니다.

주요 변경사항

  • 이전 react 스프린트 미션 진행당시에, 토큰을 localstorage에 저장해서 사용하는 방법으로 실습을 해보아서, 이번에는 auth.js를 한번 도입해서 공부해보았습니다.
  • 세션이 있을시
  • api가 제공되고 있는것 같아서 로그인한후에 내정보 페이지도 한번 간략하게 만들어보았습니다. (프로필 수정, 비밀번호 수정페이지)

스크린샷

image

멘토에게

  • 배포링크 : https://sprint-mission-chanki-next.vercel.app/
  • ssr시 유저 세션을 체크할 필요가 있는 페이지가 있어서, axios interceptor를 서버와 공유해야하는 경우가 있어서 고민을 많이 해보았습니다.
  • auth.js 각종 콜백이 실행되는 조건(타이밍)을 이해하는데 시간을 좀 투자했습니다.
    • nextauth에서 제공하는 user, session, token의 타입을 연장해서 작업했습니다. (로그인 성공시 토큰들과 전달된 유저정보를 추가로 넣음)
    • jwt콜백에서 가지고 있는 accesstoken이 유효한지 체크후 필요시 refresh토큰으로 재발급받는 로직도 넣었습니다.
    • jwt,session콜백이 실행될때, 따로 유저정보를 조회하는 api는 사용하지 않고 필요한 페이지에서 유저정보를 가져오는 api를 사용하도록 했습니다. (로그인 성공시에만 백엔드서 받은 유저정보를 세션에 넣었습니다.)

- 중복관리를 set을 사용해보기
- 공식문서 nextjs 예제 참고
- server action에서 interceptor가 동작하지 않아서 수정
- 이미지를 유저정보를 조회해서 가져오도록 변경(프로필 이미지 변경시 재조회 가능하도록)
- 서버와 클라이언트에서 함께 쓰도록 개선
- (방법1) session provider에 key 설정 (선택)
- (방법2) 서버액션 종료후 useSession의 update호출
@cksrlcks cksrlcks requested a review from Lanace January 24, 2025 11:22
@cksrlcks cksrlcks added the 순한맛🐑 마음이 많이 여립니다.. label Jan 24, 2025
Copy link
Collaborator

@Lanace Lanace 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 +38 to +41
<Form
isLoading={isSubmitting}
error={formError}
onSubmit={handleSubmit(onSubmit)}
Copy link
Collaborator

Choose a reason for hiding this comment

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

오.... Form 공통화를 이렇게 해두니 사용하기 편하게 잘 하셨네요ㅎㅎ!

Comment on lines +19 to +29
interface ArticleAddFormProps {
mode: "add";
onFormSubmit: (data: ArticleFormType) => Promise<Article | undefined>;
}
interface ArticleModifyFormProps {
initialData: Article;
mode: "edit";
onFormSubmit: (data: ArticleFormType) => Promise<Article | undefined>;
}

type ArticleFormProps = ArticleAddFormProps | ArticleModifyFormProps;
Copy link
Collaborator

Choose a reason for hiding this comment

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

타입스크립트가 잘 추론해서 사용할 수 있도록 해주셨네요ㅎㅎ!

<div className={styles.info}>
<h2 className={styles.name}>{nickname}</h2>
<div className={styles.date}>
가입일 : {dayjs(createdAt).format("YYYY-MM-DD")}
Copy link
Collaborator

Choose a reason for hiding this comment

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

createdAt가 알수없는 문자열이나 dayjs가 파싱하지 못하는 값이 오는걸 대비해서 예외처리해주면 좀더 좋을것같네요!

const createdDay = dayjs(createdAt)

return (
  ...
  가입일: {createdDay.isValid() ? createdDay.format("YYYY-MM-DD") : "-"}
  ...
)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

전에 이 부분 코드리뷰해주셔서, 날짜검증후에 포맷팅하는 유틸함수를 만들어 두었는데 사용안하고 그냥 써버렸네요... 수정해두겠습니다!

};
} catch (error) {
if (isAxiosError(error)) {
console.log(error);
Copy link
Collaborator

Choose a reason for hiding this comment

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

error 인 경우엔 console.error 가 좀더 좋을것같아요ㅎㅎ

Comment on lines +7 to +12
const session = await auth();
if (!session) {
redirect("/login");
}

const { nickname, image } = await getUser();
Copy link
Collaborator

Choose a reason for hiding this comment

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

getUser 에서 값을 정상적으로 가져오지 못한경우에도 login 페이지로 redirect 시켜주면 좀더 좋을것같아요

Comment on lines +27 to +29
<Dropdown.Item onClick={() => router.push("/mypage")}>
내정보
</Dropdown.Item>
Copy link
Collaborator

Choose a reason for hiding this comment

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

router로 이동하는것보단 Link를 사용하는게 좀더 좋긴 해요ㅎㅎ

onClick으로 하면 prefetch도 안되기도 하고, 브라우저 스팩에 따라서 휠클릭도 안먹을 수 있어서요ㅠ

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

드롭다운을 버튼으로 만들어두어서 버튼으로 해결했는데, 이번 기회에 원하는 엘레멘트로 설정할 수 있게 수정하겠습니다. ㅎㅎ

Comment on lines +64 to +67
export const COMMENT_EMPTY: Record<
BoardName,
{ image: string; message: string }
> = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

타입처리 👍

Comment on lines +12 to +13
const session =
typeof window === "undefined" ? await auth() : await getSession();
Copy link
Collaborator

Choose a reason for hiding this comment

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

엇? 이렇게 되어있으면 axios로 요청 날릴떄마다 auth정보나 session 정보를 가져오지 않나요...?

차라리 메모리에 들고있다가 있으면 있는거 쓰고, 없을떄 가져오게 처리하면 어떨까요??

@Lanace Lanace merged commit 173c715 into codeit-bootcamp-frontend:Next-김찬기 Jan 28, 2025
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