-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] Vite 프록시 도입을 통한 개발 환경 개선 및 API 호출 리팩터링 (#154) #155
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
Changes from all commits
8f966a9
44b730b
30083d0
aac2954
9cd631a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,30 @@ | ||
| import type { ClubDetailEdit } from '../types/clubDetailEdit'; | ||
|
|
||
| const BASE_URL = import.meta.env.VITE_API_BASE_URL; | ||
|
|
||
| export const fetchClubDetailEdit = async (clubId: string | number): Promise<ClubDetailEdit> => { | ||
| const res = await fetch(`${BASE_URL}/clubs/${clubId}`); | ||
| if (!res.ok) { | ||
| const url = `/api/clubs/${clubId}`; | ||
| const response = await fetch(url); | ||
|
|
||
| if (!response.ok) { | ||
| throw new Error('동아리 상세 수정 데이터를 가져오는데 실패했습니다.'); | ||
| } | ||
| return res.json() as Promise<ClubDetailEdit>; | ||
| return response.json() as Promise<ClubDetailEdit>; | ||
| }; | ||
|
|
||
| export const updateClubDetailEdit = async ( | ||
| clubId: string | number, | ||
| updatedData: Partial<ClubDetailEdit>, | ||
| ): Promise<ClubDetailEdit> => { | ||
| const res = await fetch(`${BASE_URL}/clubs/${clubId}`, { | ||
| const url = `/api/clubs/${clubId}`; | ||
| const response = await fetch(url, { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| body: JSON.stringify(updatedData), | ||
| }); | ||
|
|
||
| if (!res.ok) { | ||
| if (!response.ok) { | ||
| throw new Error('동아리 상세 정보를 수정하는데 실패했습니다.'); | ||
| } | ||
|
|
||
| return res.json() as Promise<ClubDetailEdit>; | ||
| return response.json() as Promise<ClubDetailEdit>; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,13 @@ | ||
| import type { | ||
| ApplicantData, | ||
| ApplicationFilterOption, | ||
| } from '@/pages/admin/Dashboard/types/dashboard'; | ||
| import type { ApplicantData } from '@/pages/admin/Dashboard/types/dashboard'; | ||
|
|
||
| export const fetchApplicants = async ( | ||
| clubId: number, | ||
| status?: ApplicationFilterOption, | ||
| ): Promise<ApplicantData[]> => { | ||
| const url = new URL( | ||
| import.meta.env.VITE_API_BASE_URL + `/clubs/${clubId}/applicants`, | ||
| window.location.origin, | ||
| ); | ||
| if (status && status !== 'ALL') { | ||
| url.searchParams.set('status', status); | ||
| export const fetchApplicants = async (clubId: number): Promise<ApplicantData[]> => { | ||
| const url = `/api/clubs/${clubId}/dashboard/applicants`; | ||
| const response = await fetch(url); | ||
|
|
||
| if (!response.ok) { | ||
| const errorText = await response.text(); | ||
| throw new Error(`HTTP ${response.status}: ${errorText}`); | ||
| } | ||
|
|
||
| const response = await fetch(url.toString()); | ||
| return await response.json(); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,11 @@ | ||
| import type { ClubDetail } from '../types/clubDetail'; | ||
|
|
||
| const BASE_URL = import.meta.env.VITE_API_BASE_URL; | ||
|
|
||
| export const fetchClubDetail = async (clubId: string | number): Promise<ClubDetail> => { | ||
| const res = await fetch(`${BASE_URL}/clubs/${clubId}`); | ||
| if (!res.ok) throw new Error('동아리 상세 정보를 가져오는데 실패했습니다.'); | ||
| return res.json() as Promise<ClubDetail>; | ||
| const url = `/api/clubs/${clubId}`; | ||
| const response = await fetch(url); | ||
|
|
||
| if (!response.ok) { | ||
| throw new Error('동아리 상세 정보를 가져오는데 실패했습니다.'); | ||
| } | ||
| return response.json() as Promise<ClubDetail>; | ||
| }; |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,8 +6,8 @@ export type ClubResponse = { | |||||||||||
| }; | ||||||||||||
|
|
||||||||||||
| export async function getClubsByCategory(filter: ClubCategoryEng): Promise<ClubResponse> { | ||||||||||||
| const response = await fetch( | ||||||||||||
| import.meta.env.VITE_API_BASE_URL + `/clubs/search/category?category=${filter}`, | ||||||||||||
| ); | ||||||||||||
| const url = `/api/clubs?category=${filter}`; | ||||||||||||
| const response = await fetch(url); | ||||||||||||
|
Comment on lines
+9
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Relative By dropping Please keep using the environment-provided base URL (and only fall back to - const url = `/api/clubs?category=${filter}`;
- const response = await fetch(url);
+ const endpoint = `/clubs?category=${filter}`;
+ const baseUrl = import.meta.env.VITE_API_BASE_URL ?? '';
+ const response = await fetch(`${baseUrl}${endpoint}`);This preserves production correctness while still letting you set 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
|
|
||||||||||||
| return await response.json(); | ||||||||||||
| } | ||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,30 @@ | ||
| import react from '@vitejs/plugin-react'; | ||
| import { defineConfig } from 'vite'; | ||
| import { defineConfig, loadEnv, type ConfigEnv } from 'vite'; | ||
|
|
||
| // https://vite.dev/config/ | ||
| export default defineConfig({ | ||
| plugins: [ | ||
| react({ | ||
| babel: { | ||
| plugins: ['@emotion/babel-plugin'], | ||
| export default ({ mode }: ConfigEnv) => { | ||
| const env = loadEnv(mode, process.cwd(), ''); | ||
| return defineConfig({ | ||
| plugins: [ | ||
| react({ | ||
| babel: { | ||
| plugins: ['@emotion/babel-plugin'], | ||
| }, | ||
| }), | ||
| ], | ||
| resolve: { | ||
| alias: { | ||
| '@': '/src', | ||
| }, | ||
| }), | ||
| ], | ||
| resolve: { | ||
| alias: { | ||
| '@': '/src', | ||
| }, | ||
| }, | ||
| }); | ||
| server: { | ||
| proxy: { | ||
| '/api': { | ||
| target: env.VITE_API_BASE_URL, | ||
| changeOrigin: true, | ||
| secure: false, | ||
| }, | ||
| }, | ||
| }, | ||
| }); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix cache key to match API call signature.
The
queryKeyat Line 14 includesstatus, but the API call at Line 15 no longer passesstatustofetchApplicants. This creates a cache key mismatch:statusvalues create separate cache entriesApply this diff to align the cache key with the API call:
const { data, isLoading, error } = useQuery({ - queryKey: ['applicants', clubId, status], + queryKey: ['applicants', clubId], queryFn: () => fetchApplicants(clubId), staleTime: 1000 * 60 * 2, });If client-side filtering by
statusis still needed, implement it in the hook's return value instead:🤖 Prompt for AI Agents