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

[홍재훈] Week16, Week20 #1088

Merged

Conversation

hoj0806
Copy link
Collaborator

@hoj0806 hoj0806 commented May 14, 2024

요구사항

기본

  • 링크 공유 페이지의 url path를 ‘/shared’서‘/shared/{folderId}’로 변경해 주세요.
  • 폴더의 정보는 ‘/api/folders/{folderId}’, 폴더 소유자의 정보는 ‘/api/users/{userId}’를 활용해 주세요.
  • 링크 공유 페이지에서 폴더의 링크 데이터는 ‘/api/users/{userId}/links?folderId={folderId}’를 사용해 주세요.
  • 폴더 페이지의 url path가 ‘/folder’일 경우 폴더 목록에서 “전체” 가 선택되어 있고, ‘/folder/{folderId}’일 경우 폴더 목록에서 {folderId} 에 해당하는 폴더가 선택되어 있고 폴더에 있는 링크들을 볼 수 있게 해주세요.
  • 폴더 페이지에서 현재 유저의 폴더 목록 데이터를 받아올 때 ‘/api/folders’를 활용해 주세요.
  • 폴더 페이지에서 전체 링크 데이터를 받아올 때 ‘/api/links’, 특정 폴더의 링크를 받아올 때 ‘/api/links?folderId={folderId}’를 활용해 주세요.
  • 유효한 access token이 있는 경우 ‘/api/users’로 현재 로그인한 유저 정보를 받아 상단 네비게이션 유저 프로필을 보이게 해주세요.
  • 폴더 이름 변경은 ‘PUT /folders/{folderId}’를 활용해 주세요.
  • 폴더 생성은 ‘POST /folders’를 활용해 주세요.
  • 링크 생성은 ‘POST /links’를 활용해 주세요.
  • 링크 삭제는 ‘DELETE /links/{linkId}’를 활용해 주세요.
  • 폴더 삭제는 ‘DELETE /folders/{folderId}’를 활용해 주세요.
  • https://bootcamp-api.codeit.kr/docs/linkbrary/v1 문서를 참고해 https://bootcamp-api.codeit.kr/api/linkbrary/v1 api를 활용해 주세요. (주의: 응답 데이터 양식 일부 변경이 있어요!)
  • api 요청에 TanStack React Query를 활용해 주세요.
  • 로그인은 POST ‘/auth/sign-in’ 을 활용해 주세요.
  • 회원가입은 POST ‘/auth/sign-up’ 을
이메일 중복확인은 POST ‘/users/check-email’을
활용해 주세요.
  • 폴더의 정보는 GET ‘/folders/{folderId}’,
폴더 소유자의 정보는 GET ‘/users/{userId}’를 활용해 주세요.
  • 링크 공유 페이지에서 폴더의 링크 데이터는 GET ‘/folders/{folderId}/links’를 활용해 주세요.
  • 유효한 access token이 있는 경우 GET ‘/users’로 현재 로그인한 유저 정보를 받아 상단 네비게이션 유저 프로필을 보여 주세요.
  • 유효한 access token이 없는 경우 “로그인” 버튼을 보여 주세요.
  • 폴더 페이지에서 현재 유저의 폴더 목록 데이터는 GET ‘/folders’를 활용해 주세요.
  • 폴더 페이지에서 전체 링크 데이터를 받아올 때 GET ‘/links’, 특정 폴더의 링크를 받아올 때 GET ‘/folders/{folderId}/links’를 활용해 주세요.
  • 폴더 페이지에서 유저가 access token이 없는 경우 ‘/signin’페이지로 이동하게 해주세요.

심화

  • 리퀘스트 헤더에 인증 토큰을 첨부할 때 axios interceptors 또는 이와 유사한 기능을 활용해 주세요.

주요 변경사항

  • 16주차를 진행하지 않아 15주차 코드로 한번에 16주차와 20주차를 진행했습니다
  • 로그인, 회원가입을 제외한 api요청 코드에 tanstackquery를 사용했습니다
  • vercel로 배포를 하려고 했으나 오류가 많이나 배포는 하지 못했습니다 npm run dev로 개발서버를 열어 사이트 확인해주시면 감사하겠습니다!
  • 링크 검색기능을 제외하고 모든 기능을 구현했습니다(추가 예정)
  • 타입에러로 인해 카카오 공유기능 미완성(추가 예정)

추후 변경사항

  • 전체적인 코드 리팩토링
  • 타입오류 해결
  • 링크 검색기능
  • axios interceptors를 이용해 리프레쉬 토큰 사용
  • 폴더 페이지에 접속시 유효한 엑세스토큰이 없으면 /singin 페이지로 이동

스크린샷

Folder _ Linkbrary - Chrome 2024-05-14 15-09-22
폴더 추가, 이름 변경, 삭제 기능

Folder _ Linkbrary - Chrome 2024-05-14 15-23-50
폴더에 원하는 링크 추가, 기존폴더에 있는 링크 다른 폴더에 추가, 즐겨찾기 추가 , 링크 삭제 기능

Folder _ Linkbrary - Chrome 2024-05-14 15-27-40
폴더 링크 공유시 /shared/folderId url 클립보드에 복사, 공유용 shared 페이지 구현

멘토에게

  • 테스트 계정은 이메일:[email protected] 패스워드 :as650103 입니다

  • 오래전에 짯던 코드이기도 하고 갑자기 리액트 쿼리로 모두 바꿔야해서 정리를 못한 부분도 많고 여러모로 리팩토링이 많이 필요한 코드 같습니다 솔직히 말해서 처음부터 다시 만들고 싶은데 그러진 못했습니다 리액트 쿼리를 사용한 부분 위주로 피드백 해주시면 감사하겠습니다, 특히 tanstackquery를 공부할때 다른 부분에서 안가는 부분은 없었는데 queryKey를 어떻게 올바르게 작성하는지 궁금합니다 제 개인적으로는 리액트쿼리를 너무 막쓰고 있는 느낌이 듭니다

  • 엑세스 토큰이 없거나 있을때 페이지를 이동시키는 기능을 구현해야 했는데 올바르기 구현하는 방법이 무엇인지 궁금합니다

  • next js의 app router를 사용했는데 적절하게 사용하고 있는건지 궁금합니다

  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

Copy link

vercel bot commented May 14, 2024

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

Name Status Preview Comments Updated (UTC)
4-weekly-mission ❌ Failed (Inspect) May 14, 2024 6:42am
4-weekly-mission-ursd ❌ Failed (Inspect) May 14, 2024 6:42am

@hoj0806 hoj0806 requested a review from kiJu2 May 14, 2024 06:34
@hoj0806 hoj0806 added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label May 14, 2024
@hoj0806 hoj0806 changed the title Part3 홍재훈 week20 [홍재훈] week16, week20 May 14, 2024
@hoj0806 hoj0806 changed the title [홍재훈] week16, week20 [홍재훈] Week16, Week20 May 14, 2024
@kiJu2
Copy link
Collaborator

kiJu2 commented May 15, 2024

크으으으 깔끔한 PR입니다 !!

@kiJu2
Copy link
Collaborator

kiJu2 commented May 15, 2024

테스트 계정은 이메일:[email protected] 패스워드 :as650103 입니다

넵 ! 감사합니다 :)

@kiJu2
Copy link
Collaborator

kiJu2 commented May 15, 2024

오래전에 짯던 코드이기도 하고 갑자기 리액트 쿼리로 모두 바꿔야해서 정리를 못한 부분도 많고 여러모로 리팩토링이 많이 필요한 코드 같습니다 솔직히 말해서 처음부터 다시 만들고 싶은데 그러진 못했습니다 리액트 쿼리를 사용한 부분 위주로 피드백 해주시면 감사하겠습니다, 특히 tanstackquery를 공부할때 다른 부분에서 안가는 부분은 없었는데 queryKey를 어떻게 올바르게 작성하는지 궁금합니다 제 개인적으로는 리액트쿼리를 너무 막쓰고 있는 느낌이 듭니다

리액트 쿼리 키... 리뷰 하다가 조언드릴게 있으면 답변드릴게요 !
쿼리키와 관련되어 다음 재훈님께 문서가 도움될 것 같아요 !

효과적인 리액트 쿼리 키

@kiJu2
Copy link
Collaborator

kiJu2 commented May 15, 2024

엑세스 토큰이 없거나 있을때 페이지를 이동시키는 기능을 구현해야 했는데 올바르기 구현하는 방법이 무엇인지 궁금합니다

미들웨어로 서버사이드에서 첫 request을 받을 때 헤더를 파싱해서 쿠키로 판단하여 리다이렉트를 시켜주는게 가장 확실한 방법입니다 !

NextJs 미들웨어

NextJs의 미들웨어 활용해보기

@kiJu2
Copy link
Collaborator

kiJu2 commented May 15, 2024

next js의 app router를 사용했는데 적절하게 사용하고 있는건지 궁금합니다

저는 App routes를 즐겨사용합니다 ! 재훈님께 도움드릴 수 있는 내용이 있는지 꼼꼼히 살펴볼게요 😊

Comment on lines +3 to +7
export const instance = axios.create({
baseURL: "https://bootcamp-api.codeit.kr/api/linkbrary/v1",
});

axios.defaults.withCredentials = true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

인스턴스에 설정하시는게 어떨까요?

Suggested change
export const instance = axios.create({
baseURL: "https://bootcamp-api.codeit.kr/api/linkbrary/v1",
});
axios.defaults.withCredentials = true;
export const instance = axios.create({
baseURL: "https://bootcamp-api.codeit.kr/api/linkbrary/v1",
withCredentials: true,
});

현재 전역으로 설정되어 있습니다. withCredentialinstance에 설정해두시는게 어떨까요?
다른 axios 인스턴스를 추가로 생성하실 때에 혼동될 수 있을 것 같아서 제안드립니다 !

Comment on lines +19 to +22
} catch (error) {
console.error("Error fetching links:", error);
throw error;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

굳굳 ! 해당 api 파일에서는 로그만 기록하고 throw를 던지는 군요.

계츨의 책임 분배가 확실하군요 😊👍


try {
const response = await instance.get(
"https://bootcamp-api.codeit.kr/api/linkbrary/v1/links",
Copy link
Collaborator

Choose a reason for hiding this comment

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

이미 baseUrl을 설정한 것으로 보입니다 !:

export const instance = axios.create({
  baseURL: "https://bootcamp-api.codeit.kr/api/linkbrary/v1",
});

Comment on lines +7 to +16
const response = await instance.get(
"https://bootcamp-api.codeit.kr/api/linkbrary/v1/folders",
{
headers: {
Authorization: `Bearer ${accessToken}`, // Bearer 토큰 추가
},
}
);

return response.data;
Copy link
Collaborator

Choose a reason for hiding this comment

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

다음과 같이 구조 분해 할당을 해보는건 어떨까요?:

Suggested change
const response = await instance.get(
"https://bootcamp-api.codeit.kr/api/linkbrary/v1/folders",
{
headers: {
Authorization: `Bearer ${accessToken}`, // Bearer 토큰 추가
},
}
);
return response.data;
const { data } = await instance.get(
"https://bootcamp-api.codeit.kr/api/linkbrary/v1/folders",
{
headers: {
Authorization: `Bearer ${accessToken}`, // Bearer 토큰 추가
},
}
);
return data;

response 내에 있는 속성들을 사용하지 않는 것 같아서 제안드립니다 😊

throw error;
}
};
axios.defaults.withCredentials = true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

해당 코드는 불필요해보입니다 !

instance에 설정해두시면 해당 코드는 지우셔도 됩니다 !

Comment on lines +31 to +33
if (isLoading) {
return <div>로딩중입니다</div>;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

굳굳 ! loading 중일 때는 로직을 실행하지 않고 바로 반환하는군요 !

Guard Clause 패턴을 적절히 사용하고 있습니다 ! 👍

Guard Clause ?

다음과 같이 조기에 함수를 끝내는 기법을 의미합니다:

function calculateDiscount(price, discountRate) {
  // Guard Clause: 가격이나 할인율이 유효하지 않으면 함수 종료
  if (price <= 0 || discountRate <= 0 || discountRate > 1) {
    console.error("Invalid price or discount rate");
    return;
  }

  // 할인된 가격 계산
  const discountedPrice = price * (1 - discountRate);
  return discountedPrice;
}

return <div>로딩중입니다</div>;
}

if (error) return <div>{error.message}</div>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

에러도 마찬가지로 로직이 실행되기 전 반환시키고 있군요 ! 👍

},

onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["links"] });
Copy link
Collaborator

Choose a reason for hiding this comment

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

쿼리 키로 적절히 캐싱을 무효화 시켰군요 👍👍👍

@@ -16,13 +17,21 @@ const LinkList = ({
setSharedUrl,
linkData,
}: LinkListProps) => {
const { data, isLoading, error } = useQuery({
queryKey: ["links"],
Copy link
Collaborator

Choose a reason for hiding this comment

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

쿼리 키

쿼리키는 한 곳에서 관리되는게 일반적입니다. 상수로 관리를 하거나, 쿼리키 팩토리를 만들어서 동적인 쿼리키를 보관하기도 합니다.
다음 문서를 보면 많이 도움되실 것 같습니다 😊

쿼리키 관리

},
});

console.log(selectFolderId);
Copy link
Collaborator

Choose a reason for hiding this comment

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

콘솔 로그를 남기게 될 경우 추 후 디버깅에 어려움이 있을 수 있습니다 !

git add .하실 때에 git add . -p를 사용하게 되면 변경사항을 스테이징에 올릴 때 파일 내 코드 단위로 잘라서 올릴 수 있습니다 ! 스테이징에 올릴 때 한번 더 검토하여 console.log를 검토해보실 수 있어요.
상당히 유용하므로 히스토리를 신경쓰신다면 꼭 사용해보세요 😊

어떻게 사용하지?

git add . -p

@kiJu2
Copy link
Collaborator

kiJu2 commented May 15, 2024

굳굳 ! 리액트 쿼리 처음 하시지만 정말 정말 빠르게 적응하시는게 느껴져요 재훈님 !
디렉토리 스트럭쳐랑 쿼리 키 관리하는거 한 번 고려해보시면 더욱 좋은 아키텍쳐가 될 것이라고 확신합니다 ! 😊👍👍👍

@kiJu2 kiJu2 merged commit 5fef711 into codeit-bootcamp-frontend:part3-홍재훈 May 15, 2024
1 of 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