Skip to content

Commit 07609bf

Browse files
authored
Merge pull request #384 from boostcampwm-2024/Feat/383
[Feat] 서버 상태 관리를 위한 Tanstack Query 도입
2 parents 6206aef + a480e91 commit 07609bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+718
-356
lines changed

apps/client/.eslintrc

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
"parserOptions": {
55
"project": ["./tsconfig.json"],
6+
"tsconfigRootDir": "./apps/client",
67
"ecmaVersion": 12,
78
"sourceType": "module",
89
"ecmaFeatures": {
@@ -15,16 +16,20 @@
1516
"es2021": true
1617
},
1718

18-
"extends": ["airbnb", "airbnb/hooks", "plugin:@typescript-eslint/recommended", "prettier"],
19+
"extends": [
20+
"airbnb",
21+
"airbnb/hooks",
22+
"plugin:@typescript-eslint/recommended",
23+
"plugin:@tanstack/query/recommended",
24+
"prettier"
25+
],
1926

2027
"settings": {
2128
"react": {
2229
"version": "detect"
2330
}
2431
},
2532

26-
"plugins": ["prettier"],
27-
2833
"rules": {
2934
// React 관련 규칙
3035
"react/react-in-jsx-scope": "off",
@@ -59,6 +64,10 @@
5964
// 접근성 관련 규칙
6065
"jsx-a11y/media-has-caption": "off",
6166

67+
// tanstack query 관련 규칙
68+
"@tanstack/query/exhaustive-deps": "error",
69+
"@tanstack/query/stable-query-client": "error",
70+
6271
// 기타 규칙
6372
"no-param-reassign": [
6473
"warn",

apps/client/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
"@radix-ui/react-select": "^2.1.2",
1717
"@radix-ui/react-slot": "^1.1.0",
1818
"@radix-ui/react-toast": "^1.2.2",
19+
"@tanstack/react-query": "^5.66.0",
20+
"@tanstack/react-query-devtools": "^5.66.0",
1921
"axios": "^1.7.7",
2022
"class-variance-authority": "^0.7.0",
2123
"clsx": "^2.1.1",
@@ -31,6 +33,7 @@
3133
"tailwindcss-animate": "^1.0.7"
3234
},
3335
"devDependencies": {
36+
"@tanstack/eslint-plugin-query": "^5.66.1",
3437
"@types/node": "^20.3.1",
3538
"@types/react": "^18.3.12",
3639
"@types/react-dom": "^18.3.1",

apps/client/src/app/App.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2+
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
3+
import { RouterProvider } from 'react-router-dom';
4+
import { router } from './routes';
5+
6+
const queryClient = new QueryClient();
7+
8+
export function App() {
9+
return (
10+
<QueryClientProvider client={queryClient}>
11+
<RouterProvider router={router} />
12+
<ReactQueryDevtools initialIsOpen={false} buttonPosition="bottom-left" position="right" />
13+
</QueryClientProvider>
14+
);
15+
}

apps/client/src/app/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { App } from './App';
2+
export { Providers } from './providers';
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { axiosInstance } from '@/shared/api';
2+
import { AttendanceData, AttendanceResponse } from '../model/types';
3+
4+
export const fetchAttendance = async (): Promise<AttendanceData[]> => {
5+
const { data } = await axiosInstance.get<AttendanceResponse>('/v1/members/attendance');
6+
if (!data.success) {
7+
throw new Error(data.message || '출석부 조회에 실패했습니다.');
8+
}
9+
return data.data.attendances;
10+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type { AttendanceData, AttendanceResponse } from './model/types';
2+
export { useAttendanceList } from './model/queries';
3+
export { fetchAttendance } from './api/attendanceApi';
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { useQuery } from '@tanstack/react-query';
2+
import { fetchAttendance } from '@/entities/attendance/api/attendanceApi';
3+
import { AttendanceData } from './types';
4+
5+
export const useAttendanceList = () => {
6+
const {
7+
data: attendanceList,
8+
error,
9+
isLoading,
10+
} = useQuery<AttendanceData[], Error>({
11+
queryKey: ['attendance'],
12+
queryFn: fetchAttendance,
13+
staleTime: 1000 * 60,
14+
});
15+
16+
return {
17+
attendanceList,
18+
error,
19+
isLoading,
20+
};
21+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export type AttendanceData = {
2+
attendanceId: number;
3+
date: string;
4+
startTime: string;
5+
endTime: string;
6+
isAttendance: boolean;
7+
};
8+
9+
export type AttendanceResponse = {
10+
success: boolean;
11+
status: string;
12+
message: string;
13+
data: {
14+
memberId: number;
15+
attendances: AttendanceData[];
16+
};
17+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { axiosInstance } from '@/shared/api';
2+
3+
export const getRecordList = async (attendanceId: string | undefined) => {
4+
if (!attendanceId) {
5+
throw new Error('attendanceId가 없습니다.');
6+
}
7+
8+
const response = await axiosInstance.get(`/v1/records/${attendanceId}`);
9+
10+
if (!response.data.success) {
11+
throw new Error(response.data.message);
12+
}
13+
return response.data.data;
14+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export type { RecordData } from './model/types';
2+
export { useRecordList } from './model/useRecordList';

0 commit comments

Comments
 (0)