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

[김강우] sprint11 #312

Conversation

hvrain
Copy link
Collaborator

@hvrain hvrain commented Aug 23, 2024

요구사항

  • Github에 PR(Pull Request)을 만들어서 미션을 제출합니다.
  • 피그마 디자인에 맞게 페이지를 만들어 주세요.
  • 기존의 스프린트 미션 8에 이어서 React, Typescript를 사용합니다.

기본

회원가입

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

로그인

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

메인

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

심화 (추가 구현 사항)

  • 페이지를 새로고침 했을 때도 로그인이 유지되도록 구현
  • 로그인, 회원가입을 submit 했을 때, 서버에서 보내주는 중복 에러를 브라우저에 표시
  • access token이 만료되었을 때, refresh token을 이용하여 서버로부터 새로운 access token을 받음

주요 변경사항

  • sprint10, 11을 한 번에 적용했습니다. 저번 주에 10 안해서 죄송합니다.

스크린샷

멘토에게

  • axios, react-hook-form 등 다양한 라이브러리를 사용하니 중복코드를 함수로 따로 빼는 작업이 너무 힘들었습니다. 좋은 방법이 있을까요? 아니면 해당 라이브러리에 익숙해질 수 밖에 없을까요?
  • 요구사항에는 react로 구현하라도 되어있으나, 저는 next로 구현을 하였습니다.
  • 저는 페이지가 이동될 때만 AuthProvider 안의 useEffect가 실행되어 access token을 갱신하도록 했습니다. 하지만 한 페이지에 오래 머물러 있다가 token이 필요한 작업을 한다면 만료된 token을 그대로 사용하게 되서 오류가 납니다. 혹시 인증이 필요한 모든 요청에서 accesstoken의 만료를 판단하고 refresh 후에 적용하는 로직을 간편하게 적용할 수 있을 방법이 있을까요?

@hvrain hvrain requested a review from Taero-Kim August 23, 2024 13:11
@hvrain hvrain self-assigned this Aug 23, 2024
@hvrain hvrain added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label Aug 23, 2024
@Taero-Kim Taero-Kim self-assigned this Aug 26, 2024
const fileInputRef = useRef<HTMLInputElement>(null);

const handleFileInputChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

p4.
e.target.files 가 없는 경우 함수를 종료해버리는 것도 괜찮을 것 같아요!

  const handleFileInputChange = (e: ChangeEvent<HTMLInputElement>) => {
    if (!e.target.files) return;

    const nextFile = e.target.files[0];
    onChange(name, nextFile);
    }
  };

}
}, [isLoading, keyword, orderBy, handleLoad]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [keyword, orderBy]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

p3;
deps에서 isLoading 상태를 제거한 이유가 있으신가요?

제 생각에 fetchArticles를 할 때,
loading 상태를 true로 변경시켰다가
fetch 후 loading 상태를 false로 다시 변경시키는 것은 조건에 상관 없이 일어나야 맞는 것 같습니다.

  const fetchArticles = useCallback(async () => {
    const query = {
      page: 1,
      pageSize: 6,
      orderBy,
      keyword,
    };
    setIsLoading(true);
    const { list } = await getArticles(query);

    setIsLoading(false);
    setBoards(list);
  }, [keyword, orderBy]);

boards.map((board, i) => (
<div className="mb-[10px] mt-4">
{boards.map((board, i) => {
const isLastArticle = i !== boards.length - 1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

이렇게 변수화하니까 더 알아보기 좋은 것 같아요👍

import BackLinkButton from '../elements/BackLinkButton';

function ArticleComments() {
const [input, setInput] = useState('');
Copy link
Collaborator

Choose a reason for hiding this comment

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

p3;
input 이라고 했을 때, input 요소와 조금 헷갈릴 여지가 있으니
inputValue 내지는 commentValue 등의 상태명이 어떨까 합니다!

const { id } = router.query;
const [comments, setComments] = useState<ArticleComment[]>([]);

const validationSubmit = input;
Copy link
Collaborator

Choose a reason for hiding this comment

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

p4;
요건 그냥 validationSubmti이라는 변수를 새로 선언하지 않고 input을 그대로 사용해도 좋을 것 같아요!

import cn from '@/lib/utils';
import React from 'react';

function HorizentalBar({ className }: { className?: string }) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

p5;
HorizontalBar 오타가 있는 것 같아요!

};

useEffect(() => {
if (runRouting === true) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

p4;
if (runRouting) 으로 작성해도 괜찮을 것 같아요!

};

function Signup() {
const {
Copy link
Collaborator

Choose a reason for hiding this comment

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

p3;
useForm + signup 과 관련된 로직을
useSignupForm 등의 커스텀훅으로 옮겨도 괜찮을 것 같아요!

placeholder="이메일을 입력해주세요"
register={register}
errors={errors}
validation={{
Copy link
Collaborator

Choose a reason for hiding this comment

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

p3l
컴포넌트와 별개의 유틸파일을 만들어서
각 입력 항목별 validation을 객체로 관리하면 더 좋을 것 같아요!
필요에 따라서 signin의 입력항목과 공통적으로 사용할 수도 있구요!

ex) validation.js

export const validationRules = {
  email: {
    required: '이메일을 입력해주세요.',
    pattern: {value: ..., message: ...}
  }, 
  ...
}

headers: {
Authorization: `Bearer ${accessToken}`,
},
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

p4;
axios 인스턴스에 인터셉터를 설정하셔서 여기 헤더는 제거해도 괜찮을 것 같아요!

@Taero-Kim
Copy link
Collaborator

axios, react-hook-form 등 다양한 라이브러리를 사용하니 중복코드를 함수로 따로 빼는 작업이 너무 힘들었습니다. 좋은 방법이 있을까요? 아니면 해당 라이브러리에 익숙해질 수 밖에 없을까요?

axios 같은 경우에는, 이번에 하신 것처럼 자신의 니즈에 맞게 커스텀화하여 중심 인스턴스를 구현하면 될 것 같습니다!
react-hook-form과 같은 리액트 전용 라이브러리는 우선 말씀대로 해당 라이브러리에 익숙해야, 모듈화가 더 편할 것 같습니다.
react-hook-form의 경우 사용하시는 form과 입력항목에 맞게 validation등을 유틸 파일로 정의해놓으시고,
필요한 form 컴포넌트에서 사용할 수 있도록 useForm을 한 번 더 래핑하여 커스텀훅을 작성하시는 것도 좋은 방법 같습니다!

저는 페이지가 이동될 때만 AuthProvider 안의 useEffect가 실행되어 access token을 갱신하도록 했습니다. 하지만 한 페이지에 오래 머물러 있다가 token이 필요한 작업을 한다면 만료된 token을 그대로 사용하게 되서 오류가 납니다. 혹시 인증이 필요한 모든 요청에서 accesstoken의 만료를 판단하고 refresh 후에 적용하는 로직을 간편하게 적용할 수 있을 방법이 있을까요?

우선, 한 페이지에 오래 머물러 있는 상태에서, 토큰이 만료되어 현재 인증이 무효화 되는건 자연스러운 동작 같긴 합니다!

하지만 만약 그걸 유지하고 싶으시다면, 아래 방법을 생각해볼 수 있을 것 같습니다.

현재 axios의 요청 인터셉터를 사용하셔서, api 요청 전에 토�큰을 설정해주고 계십니다.
한 페이지에 오래 머물러 있어 token이 만료되는 경우 응답에서 오류가 난다면
response(응답)에도 인터셉터를 사용하셔도 괜찮을 것 같습니다.

  • 토큰 만료때문에 응답 오류가 나는 경우 (401 등 에러)
  • 리프레시 토큰으로 새로운 엑세스 토큰 발급
instance.interceptors.response.use(
 response => response, // 응답 성공시 그대로 응답 객체 반환
 () => {}, // 응답 실패시 시도할 콜백
);

@Taero-Kim Taero-Kim merged commit aed5ea9 into codeit-bootcamp-frontend:Next-김강우 Aug 27, 2024
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