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

Refactor/#511 프론트의 토큰 만료 검증로직을 삭제하고 Axios를 도입한다. #554

Merged
merged 24 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3ec2b5f
config: axios 설치
Creative-Lee Nov 10, 2023
895be60
feat: axios 인스턴스 및 인터셉터 구현
Creative-Lee Nov 12, 2023
69605c1
refactor: 엑세스 토큰 refresh remote 함수 분리
Creative-Lee Nov 12, 2023
89bdb5f
refactor: 분리되지 않은 type, remote 함수 분리
Creative-Lee Nov 12, 2023
e10bfbe
refactor: remote 함수의 fetcher 의존성 제거 및 인스턴스 적용
Creative-Lee Nov 13, 2023
f2c79ee
refactor: 로그인 remote 함수 분리
Creative-Lee Nov 13, 2023
3ecd234
feat: 메인 페이지 장르별 fetch msw 구현
Creative-Lee Nov 13, 2023
db04ff0
chore: 불필요한 파일 제거
Creative-Lee Nov 13, 2023
a2bbcee
chore: remote 함수 중복 래핑 hook 삭제 및 코드 이동
Creative-Lee Nov 13, 2023
c287cfe
refactor: remote 함수 query parameter 처리 방식 통일
Creative-Lee Nov 13, 2023
d06887a
chore: import 방식 변경
Creative-Lee Nov 13, 2023
a4a83df
chore: auth 관련 remote함수 auth/하위로 이동
Creative-Lee Nov 13, 2023
4f858e9
fix: refresh 요청 API 명세에 맞게 로직 수정
Creative-Lee Nov 13, 2023
09cf9f3
refactor: 최종 만료시 로그인 페이지 리다이렉트 처리
Creative-Lee Nov 14, 2023
e6bfcfe
refactor: 타입 분리
Creative-Lee Nov 14, 2023
744fbff
refactor: 인터셉터 refresh 중복 요청 방지 기능 추가
Creative-Lee Nov 14, 2023
2166a72
refactor: 에러응답 타입 분리
Creative-Lee Nov 14, 2023
8e0a22f
chore: fetcher 및 토큰 만료 검증 파일 제거
Creative-Lee Nov 14, 2023
0fbcfde
refactor: 함수 네이밍 개선
Creative-Lee Nov 15, 2023
6755702
chore: 주석 수정
Creative-Lee Nov 15, 2023
0f87b75
refactor: promise 변수 null 초기화 코드 위치 이동
Creative-Lee Nov 28, 2023
dbf9655
style: promise 변수 라인 변경
Creative-Lee Nov 28, 2023
500cae1
refactor: config type 변경 및 린트 주석 제거
Creative-Lee Dec 9, 2023
ea5e89b
Merge branch 'main' into refactor/#511
Creative-Lee Dec 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions frontend/src/features/comments/remotes/comments.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';
import type { Comment } from '../types/comment.type';

export const postComment = async (songId: number, partId: number, content: string) => {
await fetcher(`/songs/${songId}/parts/${partId}/comments`, 'POST', { content });
await client.post(`/songs/${songId}/parts/${partId}/comments`, { content });
};

export const getComments = async (songId: number, partId: number): Promise<Comment[]> => {
return await fetcher(`/songs/${songId}/parts/${partId}/comments`, 'GET');
export const getComments = async (songId: number, partId: number) => {
const { data } = await client.get<Comment[]>(`/songs/${songId}/parts/${partId}/comments`);

return data;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
import { useAuthContext } from '@/features/auth/components/AuthProvider';
import useCollectingPartContext from '@/features/killingParts/hooks/useCollectingPartContext';
import { usePostKillingPart } from '@/features/killingParts/remotes/usePostKillingPart';
import useVideoPlayerContext from '@/features/youtube/hooks/useVideoPlayerContext';
import useModal from '@/shared/components/Modal/hooks/useModal';
import Modal from '@/shared/components/Modal/Modal';
import Spacing from '@/shared/components/Spacing';
import { useMutation } from '@/shared/hooks/useMutation';
import { toPlayingTimeText } from '@/shared/utils/convertTime';
import { postKillingPart } from '../hooks/killingPart';

const RegisterPart = () => {
const { isOpen, openModal, closeModal } = useModal();
const { user } = useAuthContext();
const { interval, partStartTime, songId } = useCollectingPartContext();
const video = useVideoPlayerContext();
const { createKillingPart } = usePostKillingPart();
const { mutateData: createKillingPart } = useMutation(postKillingPart);
const navigate = useNavigate();

// 현재 useMutation 훅이 response 객체를 리턴하지 않고 내부적으로 처리합니다.
Expand Down Expand Up @@ -75,7 +76,6 @@ const RegisterButton = styled.button`

@media (min-width: ${({ theme }) => theme.breakPoints.md}) {
padding: 11px 15px;

font-size: 18px;
}
`;
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/features/killingParts/hooks/killingPart.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';
import type { KillingPartPostRequest } from '@/shared/types/killingPart';

export const postKillingPart = async (songId: number, body: KillingPartPostRequest) => {
return await fetcher(`/songs/${songId}/member-parts`, 'POST', body);
await client.post(`/songs/${songId}/member-parts`, body);
};
9 changes: 6 additions & 3 deletions frontend/src/features/killingParts/remotes/killingPart.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';
import type { SongInfo } from '@/shared/types/song';

// PartCollectingPage에 존재하던 remote 함수입니다.
// useFetch<SongInfo>(() => fetcher(`/songs/${songId}`, 'GET')) 로직에서 분리하였습니다.
// SongInfo type에는 killingPart[] 필드가 있는데, 마이파트 수집용 `노래 1개` 조회에서 해당 타입이 사용되고 있습니다.
// 추후 수정되어야 합니다.
export const getSong = async (songId: number): Promise<SongInfo> => {
return await fetcher(`/songs/${songId}`, 'GET');

export const getSong = async (songId: number) => {
const { data } = await client.get<SongInfo>(`/songs/${songId}`);

return data;
};
4 changes: 2 additions & 2 deletions frontend/src/features/member/components/MyPartList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export type LikeKillingPart = Pick<
const MyPartList = () => {
const [tab, setTab] = useState<MyPageTab>('Like');

const { data: likes } = useFetch<LikeKillingPart[]>(getLikeParts);
const { data: myParts } = useFetch<LikeKillingPart[]>(getMyParts);
const { data: likes } = useFetch(getLikeParts);
const { data: myParts } = useFetch(getMyParts);
Comment on lines -22 to +23
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 제네릭이 필요 없어졌다면 useFetch도 수정해야되지 않을까요?

Copy link
Collaborator Author

@Creative-Lee Creative-Lee Dec 4, 2023

Choose a reason for hiding this comment

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

어떤 식으로 수정이 되어야할까요? 생각나는 방향이 있으시면 같이 알려주세용
제네릭 없이도 useFetch data 타입이 추론 될지 모르겠네용


if (!likes || !myParts) {
return null;
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/features/member/remotes/member.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';

export const deleteMember = (memberId: number | undefined) => () => {
return fetcher(`/members/${memberId}`, 'DELETE');
export const deleteMember = async (memberId: number) => {
await client.delete(`/members/${memberId}`);
};
Comment on lines +3 to 5
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 async/await여야 하는 이유가 있나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

useMutaion의 타입을 맞추려다보니 그렇습니다~
useMutaion의 타입을 어떻게 수정해볼 수 있을까요?

6 changes: 4 additions & 2 deletions frontend/src/features/member/remotes/memberParts.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';

export const deleteMemberParts = (partId: number) => fetcher(`/member-parts/${partId}`, 'DELETE');
export const deleteMemberParts = async (partId: number) => {
await client.delete(`/member-parts/${partId}`);
};
15 changes: 12 additions & 3 deletions frontend/src/features/member/remotes/myPage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';
import type { LikeKillingPart } from '../components/MyPartList';

export const getLikeParts = () => fetcher('/my-page/like-parts', 'GET');
export const getLikeParts = async () => {
const { data } = await client.get<LikeKillingPart[]>('/my-page/like-parts');

export const getMyParts = () => fetcher('/my-page/my-parts', 'GET');
return data;
};

export const getMyParts = async () => {
const { data } = await client.get<LikeKillingPart[]>('/my-page/my-parts');

return data;
};
18 changes: 13 additions & 5 deletions frontend/src/features/search/remotes/search.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';
import type { SingerDetail } from '../../singer/types/singer.type';
import type { SingerSearchPreview } from '../types/search.type';

export const getSingerSearchPreview = async (query: string): Promise<SingerSearchPreview[]> => {
export const getSingerSearchPreview = async (query: string) => {
const encodedQuery = encodeURIComponent(query);
return await fetcher(`/search?keyword=${encodedQuery}&type=singer`, 'GET');
const { data } = await client.get<SingerSearchPreview[]>(
`/search?keyword=${encodedQuery}&type=singer`
);

return data;
};

export const getSingerSearch = async (query: string): Promise<SingerDetail[]> => {
export const getSingerSearch = async (query: string) => {
const encodedQuery = encodeURIComponent(query);
return await fetcher(`/search?keyword=${encodedQuery}&type=singer&type=song`, 'GET');
const { data } = await client.get<SingerDetail[]>(
`/search?keyword=${encodedQuery}&type=singer&type=song`
);

return data;
};
8 changes: 5 additions & 3 deletions frontend/src/features/singer/remotes/singer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';
import type { SingerDetail } from '../types/singer.type';

export const getSingerDetail = async (singerId: number): Promise<SingerDetail> => {
return await fetcher(`/singers/${singerId}`, 'GET');
export const getSingerDetail = async (singerId: number) => {
const { data } = await client.get<SingerDetail>(`/singers/${singerId}`);

return data;
};
4 changes: 2 additions & 2 deletions frontend/src/features/songs/remotes/likes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';

export const putKillingPartLikes = async (songId: number, partId: number, likeStatus: boolean) => {
return await fetcher(`/songs/${songId}/parts/${partId}/likes`, 'PUT', { likeStatus });
await client.put(`/songs/${songId}/parts/${partId}/likes`, { likeStatus });
};
Comment on lines 3 to 5
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 mutation 함수를 확인해보니 타입이 (...params: P) => Promise<T>인데, promise를 반환 안해도 되는건가요?

export const useMutation = <T, P extends any[]>(mutateFn: (...params: P) => Promise<T>) => {
  const [data, setData] = useState<T | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  // ...

14 changes: 9 additions & 5 deletions frontend/src/features/songs/remotes/song.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';
import type { Genre, Song } from '../types/Song.type';
import type { RecentSong } from '@/shared/types/song';

// 메인 케러셀 최신순 노래 n개 조회 api - 쿼리파람 없는경우, 응답 기본값은 5개입니다.
export const getRecentSongs = async (songCount?: number): Promise<RecentSong[]> => {
export const getRecentSongs = async (songCount?: number) => {
const query = songCount ? `?size=${songCount}` : '';

return await fetcher(`/songs/recent${query}`, 'GET');
const { data } = await client.get<RecentSong[]>(`/songs/recent${query}`);

return data;
};

export const getHighLikedSongs = async (genre: Genre): Promise<Song[]> => {
export const getHighLikedSongs = async (genre: Genre) => {
const query = genre === 'ALL' ? '' : `?genre=${genre}`;

return await fetcher(`/songs/high-liked${query}`, 'GET');
const { data } = await client.get<Song[]>(`/songs/high-liked${query}`);

return data;
};
29 changes: 13 additions & 16 deletions frontend/src/features/songs/remotes/songs.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
import fetcher from '@/shared/remotes';
import client from '@/shared/remotes/axios';
import type { Genre } from '../types/Song.type';
import type { SongDetail, SongDetailEntries } from '@/shared/types/song';

export const getSongDetailEntries = async (
songId: number,
genre: Genre
): Promise<SongDetailEntries> => {
export const getSongDetailEntries = async (songId: number, genre: Genre) => {
const query = genre === 'ALL' ? '' : `?genre=${genre}`;
return await fetcher(`/songs/high-liked/${songId}${query}`, 'GET');
const { data } = await client.get<SongDetailEntries>(`/songs/high-liked/${songId}${query}`);

return data;
};

export const getExtraPrevSongDetails = async (
songId: number,
genre: Genre
): Promise<SongDetail[]> => {
export const getExtraPrevSongDetails = async (songId: number, genre: Genre) => {
const query = genre === 'ALL' ? '' : `?genre=${genre}`;
return await fetcher(`/songs/high-liked/${songId}/prev${query}`, 'GET');
const { data } = await client.get<SongDetail[]>(`/songs/high-liked/${songId}/prev${query}`);

return data;
};

export const getExtraNextSongDetails = async (
songId: number,
genre: Genre
): Promise<SongDetail[]> => {
export const getExtraNextSongDetails = async (songId: number, genre: Genre) => {
const query = genre === 'ALL' ? '' : `?genre=${genre}`;
return await fetcher(`/songs/high-liked/${songId}/next${query}`, 'GET');
const { data } = await client.get<SongDetail[]>(`/songs/high-liked/${songId}/next${query}`);

return data;
};
6 changes: 3 additions & 3 deletions frontend/src/pages/EditProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import { useMutation } from '@/shared/hooks/useMutation';
const EditProfilePage = () => {
const { user, logout } = useAuthContext();
const { isOpen, openModal, closeModal } = useModal();
const { mutateData } = useMutation(deleteMember(user?.memberId));
const { mutateData: withdrawal } = useMutation(deleteMember);
const navigate = useNavigate();

if (!user) {
navigate(ROUTE_PATH.LOGIN);
return;
return null;
}

const handleWithdrawal = async () => {
await mutateData();
await withdrawal(user.memberId);
logout();
navigate(ROUTE_PATH.ROOT);
};
Expand Down