Skip to content

refact: ticket api 리팩토링#109

Merged
Yejiin21 merged 1 commit intodevelopfrom
refactor/#105/api-hook-refactor
Apr 29, 2025
Merged

refact: ticket api 리팩토링#109
Yejiin21 merged 1 commit intodevelopfrom
refactor/#105/api-hook-refactor

Conversation

@hyeeuncho
Copy link
Copy Markdown
Member

@hyeeuncho hyeeuncho commented Apr 29, 2025

Summary by CodeRabbit

  • New Features

    • 티켓 관련 API 연동을 위한 커스텀 훅(useTickets, useCreateTicket, useDeleteTicket)이 추가되었습니다.
  • Refactor

    • 티켓 목록, 생성, 삭제 기능이 커스텀 훅 기반으로 리팩터링되어 코드가 간결해지고 유지보수가 용이해졌습니다.
    • 티켓 정보 관리 인터페이스가 하나의 파일로 통합되었습니다.
  • Bug Fixes

    • 티켓 생성 시 이벤트 ID가 URL 파라미터 기반으로 동적으로 반영됩니다.
  • Style

    • 로딩 및 에러 상태에 대한 안내 메시지가 추가되어 사용자 경험이 향상되었습니다.

@hyeeuncho hyeeuncho added the 🪄 Refactoring 코드 리팩토링 label Apr 29, 2025
@hyeeuncho hyeeuncho self-assigned this Apr 29, 2025
@hyeeuncho hyeeuncho linked an issue Apr 29, 2025 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 29, 2025

Walkthrough

이번 변경 사항은 티켓 관련 API와 React 컴포넌트의 데이터 흐름을 전반적으로 리팩토링한 것입니다. API 함수들은 객체 내 메서드에서 독립적인 async 함수로 변경되었고, 타입 선언 파일이 통합 및 재구성되었습니다. 새로운 React Query 기반 커스텀 훅들이 도입되어 티켓 조회, 생성, 삭제 로직이 각 컴포넌트에서 분리되어 재사용 가능하게 되었습니다. 여러 컴포넌트가 이 훅을 활용하도록 리팩토링되어 데이터 상태 관리와 에러/로딩 처리 방식이 일관적으로 개선되었습니다.

Changes

파일/경로 변경 요약
src/features/ticket/api/ticket.ts readTicket, deleteTicket을 객체 메서드에서 독립 async 함수로 변경, 타입 및 import 경로 수정
src/features/ticket/hooks/useTicketHook.ts 티켓 조회, 생성, 삭제용 React Query 기반 커스텀 훅 3종 신규 추가
src/features/ticket/model/TicketContext.tsx CreateTicketRequest import 경로를 ticketCreation에서 ticketInformation으로 변경
src/features/ticket/model/ticketCreation.ts CreateTicketRequest 인터페이스 삭제
src/features/ticket/model/ticketInformation.ts CreateTicketRequest, TicketResponse, ReadTicketResponse 인터페이스 신규 정의
src/pages/dashboard/ui/ticket/TicketCreatePage.tsx API 직접 호출에서 useCreateTicket 훅 사용으로 변경, eventId 동적 추출, 네비게이션 로직 단순화
src/pages/dashboard/ui/ticket/TicketListPage.tsx useTickets 훅 도입, 수동 상태 관리/데이터 패칭 제거, 동적 라우팅 적용, 로딩/에러 처리 추가
src/widgets/dashboard/ui/TicketItem.tsx useDeleteTicket 훅 사용, 삭제 핸들러 로직 단순화, prop 타입 ReadTicketResponse로 변경
src/widgets/event/ui/TicketInfo.tsx useTickets 훅 도입, 수동 데이터 패칭/상태 관리 제거, 로딩/에러 처리 추가

Sequence Diagram(s)

sequenceDiagram
    participant UI as 컴포넌트
    participant Hook as useTickets / useCreateTicket / useDeleteTicket
    participant API as API 함수
    participant Server as 서버

    UI->>Hook: 데이터 요청 (예: useTickets(eventId))
    Hook->>API: readTicket(eventId)
    API->>Server: GET /tickets?eventId
    Server-->>API: 티켓 데이터 반환
    API-->>Hook: { isSuccess, result }
    Hook-->>UI: 데이터, 로딩/에러 상태 제공

    UI->>Hook: 티켓 생성 요청 (useCreateTicket)
    Hook->>API: createTicket(data)
    API->>Server: POST /tickets
    Server-->>API: 생성 결과 반환
    API-->>Hook: TicketResponse
    Hook-->>UI: 성공/실패 처리, 알림, 새로고침

    UI->>Hook: 티켓 삭제 요청 (useDeleteTicket)
    Hook->>API: deleteTicket(ticketId)
    API->>Server: DELETE /tickets/{ticketId}
    Server-->>API: 삭제 결과 반환
    API-->>Hook: TicketResponse
    Hook-->>UI: 성공/실패 처리, 알림, 새로고침
Loading

Suggested labels

🔧 Feature

Suggested reviewers

  • Yejiin21

Poem

🐰
티켓 훅이 생겼어요,
데이터 흐름이 쉬워졌죠!
API도 깔끔하게,
타입도 딱 맞게,
에러도 로딩도 걱정 마세요,
토끼는 오늘도 코드를 춤추게 해요!
🎟️✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
src/features/ticket/model/TicketContext.tsx (1)

26-28: ⚠️ Potential issue

ticketChannelId 속성이 CreateTicketRequest 인터페이스에 정의되어 있지 않습니다.

setTicketChannelId 함수에서 ticketChannelId 속성을 사용하고 있지만, CreateTicketRequest 인터페이스에는 이 속성이 정의되어 있지 않습니다. 이로 인해 타입 오류가 발생할 수 있습니다.

다음 두 가지 방법 중 하나로 해결할 수 있습니다:

  1. CreateTicketRequest 인터페이스에 ticketChannelId 속성 추가:
export interface CreateTicketRequest {
    eventId: number;
    ticketType: string;
    ticketName: string;
    ticketDescription: string;
    ticketPrice: number;
    availableQuantity: number;
    startDate: string;
    endDate: string;
    startTime: string;
    endTime: string;
+    ticketChannelId?: number;
}
  1. 타입 단언 사용:
- setTicketState(prev => ({ ...prev, ticketChannelId }));
+ setTicketState(prev => ({ ...prev, ticketChannelId } as CreateTicketRequest));
🧹 Nitpick comments (5)
src/features/ticket/model/ticketInformation.ts (1)

14-19: result 필드의 타입을 개선하는 것이 좋겠습니다.

result 필드가 문자열 타입으로 정의되어 있고, 주석으로 "ticketId: 2"와 같은 형식임을 설명하고 있습니다. 이는 프로그래밍적으로 활용하기 어려울 수 있습니다.

다음과 같이 더 명확한 구조로 변경하는 것을 고려해보세요:

export interface TicketResponse {
    isSuccess: boolean;
    code: string;
    message: string;
-    result: string; // "ticketId: 2"
+    result: { ticketId: number };
}
src/features/ticket/api/ticket.ts (1)

16-19: deleteTicket 함수의 반환 타입을 명시하는 것이 좋겠습니다.

readTicket 함수처럼 deleteTicket 함수도 명시적인 반환 타입을 지정하는 것이 일관성 있고 타입 안전성을 높일 수 있습니다.

- export const deleteTicket = async (ticketId: number) => {
+ export const deleteTicket = async (ticketId: number): Promise<{ isSuccess: boolean; message: string }> => {
    const response = await axiosClient.delete(`/tickets/${ticketId}`);
    return response.data;
}
src/pages/dashboard/ui/ticket/TicketCreatePage.tsx (1)

13-16: 이벤트 ID를 URL에서 동적으로 추출하는 방식으로 개선되었습니다.

기존 하드코딩된 이벤트 ID 대신 useParams를 사용해 URL에서 동적으로 ID를 추출하는 방식이 좋습니다. 다만, 숫자가 아닌 ID에 대한 처리가 부족합니다.

다음과 같이 유효성 검사를 추가하는 것이 좋겠습니다:

  const { id } = useParams();
-  const eventId = Number(id);
+  const eventId = id ? Number(id) : 0;
+  if (!eventId) {
+    navigate('/dashboard');
+    return;
+  }
src/widgets/event/ui/TicketInfo.tsx (2)

15-22: 데이터 접근 방식이 새로운 API 응답 구조에 맞게 업데이트되었습니다.

데이터 구조가 변경되어 data.result를 사용하도록 수정된 점이 좋습니다. 하지만 여기서 null 체크를 더 안전하게 할 수 있습니다.

선택적 체이닝(optional chaining)을 사용하여 코드를 개선해보세요:

-    if (data && data.isSuccess) {
+    if (data?.isSuccess) {
      const initialQuantity: { [key: number]: number } = {};
      data.result.forEach(ticket => {
        initialQuantity[ticket.ticketId] = 1;
      });
      setQuantity(initialQuantity);
    }
🧰 Tools
🪛 Biome (1.9.4)

[error] 15-15: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


59-59: 사용하지 않는 'error' 변수가 있습니다.

catch 블록에서 'error' 변수가 선언되었지만 사용되지 않고 있습니다.

디버깅 정보 출력이나 로깅이 필요한 경우가 아니라면 다음과 같이 수정하세요:

-    } catch (error) {
+    } catch (_) {
      alert("티켓 구매 중 오류가 발생했습니다.");
    }
🧰 Tools
🪛 ESLint

[error] 59-59: 'error' is defined but never used.

(@typescript-eslint/no-unused-vars)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8f0575f and 3c3be8a.

📒 Files selected for processing (9)
  • src/features/ticket/api/ticket.ts (1 hunks)
  • src/features/ticket/hooks/useTicketHook.ts (1 hunks)
  • src/features/ticket/model/TicketContext.tsx (1 hunks)
  • src/features/ticket/model/ticketCreation.ts (0 hunks)
  • src/features/ticket/model/ticketInformation.ts (1 hunks)
  • src/pages/dashboard/ui/ticket/TicketCreatePage.tsx (2 hunks)
  • src/pages/dashboard/ui/ticket/TicketListPage.tsx (2 hunks)
  • src/widgets/dashboard/ui/TicketItem.tsx (2 hunks)
  • src/widgets/event/ui/TicketInfo.tsx (2 hunks)
💤 Files with no reviewable changes (1)
  • src/features/ticket/model/ticketCreation.ts
🧰 Additional context used
🧬 Code Graph Analysis (5)
src/pages/dashboard/ui/ticket/TicketCreatePage.tsx (3)
src/features/ticket/api/ticket.ts (1)
  • createTicket (4-7)
src/features/ticket/hooks/useTicketHook.ts (1)
  • useCreateTicket (13-24)
src/features/ticket/model/ticketInformation.ts (1)
  • CreateTicketRequest (1-12)
src/pages/dashboard/ui/ticket/TicketListPage.tsx (1)
src/features/ticket/hooks/useTicketHook.ts (1)
  • useTickets (5-11)
src/features/ticket/api/ticket.ts (2)
src/features/ticket/model/ticketInformation.ts (2)
  • CreateTicketRequest (1-12)
  • ReadTicketResponse (21-27)
src/shared/types/api/http-client.ts (1)
  • axiosClient (6-13)
src/widgets/event/ui/TicketInfo.tsx (2)
src/features/ticket/hooks/useTicketHook.ts (1)
  • useTickets (5-11)
src/features/ticket/api/order.ts (1)
  • orderTickets (22-25)
src/features/ticket/hooks/useTicketHook.ts (2)
src/features/ticket/model/ticketInformation.ts (3)
  • ReadTicketResponse (21-27)
  • TicketResponse (14-19)
  • CreateTicketRequest (1-12)
src/features/ticket/api/ticket.ts (3)
  • readTicket (9-14)
  • createTicket (4-7)
  • deleteTicket (16-19)
🪛 Biome (1.9.4)
src/widgets/event/ui/TicketInfo.tsx

[error] 15-15: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 ESLint
src/widgets/event/ui/TicketInfo.tsx

[error] 59-59: 'error' is defined but never used.

(@typescript-eslint/no-unused-vars)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: storybook
🔇 Additional comments (18)
src/features/ticket/model/ticketInformation.ts (2)

1-12: 잘 정의된 티켓 생성 인터페이스입니다.

티켓 생성에 필요한 모든 필드들이 적절한 타입으로 잘 정의되어 있습니다.


21-27: 읽기 응답 인터페이스에 시간 관련 필드가 누락되었습니다.

CreateTicketRequest에는 startDate, endDate, startTime, endTime 필드가 있지만, ReadTicketResponse에는 이 필드들이 없습니다. 의도적인 설계라면 문제가 없지만, 클라이언트 측에서 티켓의 시간 정보가 필요할 수 있습니다.

src/features/ticket/model/TicketContext.tsx (1)

2-2: 임포트 경로 업데이트가 적절히 이루어졌습니다.

ticketCreation에서 통합된 ticketInformation으로 임포트 경로를 변경한 것은 좋은 리팩토링입니다.

src/widgets/dashboard/ui/TicketItem.tsx (3)

5-6: 임포트가 잘 업데이트되었습니다.

새로운 인터페이스와 커스텀 훅을 위한 임포트가 적절히 추가되었습니다.


8-10: 컴포넌트 리팩토링이 잘 이루어졌습니다.

ReadTicketResponse 타입으로 변경하고 useDeleteTicket 훅을 활용하여 관심사를 분리한 것은 좋은 패턴입니다.


47-47: 삭제 로직이 간결하게 개선되었습니다.

복잡한 인라인 핸들러 대신 훅에서 제공하는 mutate 함수를 호출하는 방식으로 단순화되었습니다.

src/features/ticket/api/ticket.ts (2)

2-2: 적절한 타입 임포트가 추가되었습니다.

통합된 인터페이스 파일에서 필요한 타입을 가져오도록 업데이트되었습니다.


9-14: readTicket 함수가 개선되었습니다.

독립적인 비동기 함수로 리팩토링되었고, 명시적인 반환 타입을 통해 타입 안전성이 향상되었습니다.

src/pages/dashboard/ui/ticket/TicketCreatePage.tsx (2)

8-10: 모듈 가져오기 업데이트가 잘 되었습니다.

새로운 파일 구조로 import 경로가 잘 업데이트되었으며, 티켓 생성을 위한 커스텀 훅과 라우터 훅이 적절히 추가되었습니다.


19-19: 동적 이벤트 ID를 초기 상태에 적용한 점이 좋습니다.

URL에서 추출한 이벤트 ID를 초기 상태에 적용한 것은 좋은 접근입니다.

src/widgets/event/ui/TicketInfo.tsx (2)

7-7: useTickets 커스텀 훅 통합이 잘 되었습니다.

수동 데이터 페칭 로직을 React Query 기반 커스텀 훅으로 대체한 것은 좋은 개선입니다. 데이터 가져오기, 로딩 상태, 에러 처리가 모두 한 줄로 처리되어 코드가 간결해졌습니다.

Also applies to: 11-11


63-64: 로딩 및 에러 상태 처리가 추가되었습니다.

React Query의 isLoadingisError 상태를 활용하여 적절한 UI 피드백을 제공하는 것은 좋은 UX 개선입니다.

src/pages/dashboard/ui/ticket/TicketListPage.tsx (4)

4-4: 필요한 훅과 API 모듈이 잘 임포트되었습니다.

리팩토링에 필요한 라우터 관련 훅과 티켓 커스텀 훅이 적절히 임포트되었습니다.

Also applies to: 7-7


13-13: 동적 라우팅이 잘 구현되었습니다.

정적 경로 대신 URL 파라미터에서 추출한 ID를 사용하여 동적 라우팅을 구현한 것이 좋습니다.


19-20: 로딩 및 에러 상태 처리가 적절히 추가되었습니다.

React Query에서 제공하는 상태를 활용하여 로딩 중과 에러 상태에 대한 UI 처리를 추가한 것은 좋은 개선입니다.


48-49: 데이터 접근 및 조건부 렌더링이 적절히 업데이트되었습니다.

새로운 API 응답 구조에 맞게 데이터 접근 방식이 업데이트되었고, 선택적 체이닝을 사용하여 안전하게 처리된 점이 좋습니다.

src/features/ticket/hooks/useTicketHook.ts (2)

1-4: 필요한 의존성과 타입을 적절히 임포트하고 있습니다.

React Query와 티켓 관련 API 함수 및 타입들을 적절하게 임포트하고 있습니다.


5-11: useTickets 훅이 잘 구현되었습니다.

티켓 목록을 조회하는 useTickets 훅의 구현이 적절합니다. 다음 사항이 특히 좋습니다:

  1. queryKey에 eventId를 포함시켜 캐싱과 무효화를 효과적으로 관리할 수 있음
  2. enabled 옵션을 사용하여 eventId가 있을 때만 쿼리가 실행되도록 함
  3. 타입 정의가 명확함

Comment on lines +85 to +86
createTicket(ticketData);
navigate(`/dashboard/${id}/ticket`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

티켓 생성 로직이 React Query를 사용하여 개선되었습니다.

기존의 직접적인 API 호출 대신 React Query 기반 훅을 사용하여 코드가 간결해졌습니다. 하지만 다음 두 가지 개선점이 있습니다:

  1. 현재 방식은 API 호출 결과를 기다리지 않고 바로 페이지를 이동합니다.
  2. useCreateTicket 훅은 내부적으로 window.location.reload()를 호출하는데, 페이지 이동과 충돌할 수 있습니다.

성공 여부를 확인한 후 페이지를 이동하는 방식이 더 안정적일 것입니다:

-    createTicket(ticketData);
-    navigate(`/dashboard/${id}/ticket`);
+    createTicket(ticketData, {
+      onSuccess: () => {
+        navigate(`/dashboard/${id}/ticket`);
+      }
+    });

이 변경을 위해서는 useTicketHook.ts에서 useCreateTicket 훅도 함께 수정해야 합니다:

// useTicketHook.ts에서 수정 필요
export const useCreateTicket = () => {
    return useMutation<TicketResponse, Error, CreateTicketRequest>({
        mutationFn: createTicket,
        onSuccess: () => {
            alert('티켓이 성공적으로 저장되었습니다.');
            // window.location.reload(); // 제거
        },
        onError: () => {
            alert('티켓 저장에 실패했습니다. 다시 시도해주세요.');
        },
    });
};

Comment on lines +26 to +37
export const useDeleteTicket = () => {
return useMutation<TicketResponse, Error, number>({
mutationFn: deleteTicket,
onSuccess: () => {
alert("티켓이 삭제되었습니다.");
window.location.reload();
},
onError: () => {
alert('티켓 삭제 중 오류가 발생했습니다.');
}
});
}; No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

useDeleteTicket 훅에도 동일한 개선이 필요합니다.

삭제 훅도 마찬가지로 페이지 리로드 대신 쿼리 무효화를 통한 데이터 갱신 방식으로 개선이 필요합니다.

다음과 같이 개선해보세요:

export const useDeleteTicket = () => {
+   const queryClient = useQueryClient();
    return useMutation<TicketResponse, Error, number>({
        mutationFn: deleteTicket,
        onSuccess: () => {
            alert("티켓이 삭제되었습니다.");
-           window.location.reload();
+           // 모든 티켓 쿼리 무효화
+           queryClient.invalidateQueries({ queryKey: ['tickets'] });
        },
        onError: () => {
            alert('티켓 삭제 중 오류가 발생했습니다.');
        }
    });
};

또한 삭제 함수에 이벤트 ID를 함께 전달하여 특정 이벤트의 티켓 쿼리만 무효화하는 방식으로도 구현할 수 있습니다:

export const useDeleteTicket = () => {
    const queryClient = useQueryClient();
    return useMutation<TicketResponse, Error, { ticketId: number, eventId: number }>({
        mutationFn: ({ ticketId }) => deleteTicket(ticketId),
        onSuccess: (_, { eventId }) => {
            alert("티켓이 삭제되었습니다.");
            queryClient.invalidateQueries(['tickets', eventId]);
        },
        // ...
    });
};

이 방식을 사용하면 특정 이벤트의 티켓 목록만 갱신할 수 있어 더 효율적입니다.

Comment on lines +13 to +24
export const useCreateTicket = () => {
return useMutation<TicketResponse, Error, CreateTicketRequest>({
mutationFn: createTicket,
onSuccess: () => {
alert('티켓이 성공적으로 저장되었습니다.');
window.location.reload();
},
onError: () => {
alert('티켓 저장에 실패했습니다. 다시 시도해주세요.');
},
});
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

useCreateTicket 훅에 개선이 필요합니다.

티켓 생성을 위한 훅이 잘 구현되었지만, 페이지 리로드 방식에 개선이 필요합니다.

현재 방식은 window.location.reload()를 사용하여 전체 페이지를 새로고침하고 있습니다. 이는 사용자 경험을 저하시키고, React Query의 장점을 충분히 활용하지 못합니다. 다음과 같이 개선해보세요:

export const useCreateTicket = () => {
    return useMutation<TicketResponse, Error, CreateTicketRequest>({
        mutationFn: createTicket,
        onSuccess: () => {
            alert('티켓이 성공적으로 저장되었습니다.');
-           window.location.reload();
+           // 쿼리 무효화를 통해 데이터 갱신
+           // queryClient.invalidateQueries(['tickets']);
        },
        onError: () => {
            alert('티켓 저장에 실패했습니다. 다시 시도해주세요.');
        },
    });
};

이를 위해서는 QueryClient 인스턴스에 대한 접근이 필요합니다. 다음과 같이 모듈 최상단에 useQueryClient를 추가하고 훅 내부에서 사용할 수 있습니다:

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

// 훅 내부
export const useCreateTicket = () => {
    const queryClient = useQueryClient();
    return useMutation<TicketResponse, Error, CreateTicketRequest>({
        // ...
        onSuccess: (data, variables) => {
            alert('티켓이 성공적으로 저장되었습니다.');
            queryClient.invalidateQueries(['tickets', variables.eventId]);
        },
        // ...
    });
};

Copy link
Copy Markdown
Contributor

@Yejiin21 Yejiin21 left a comment

Choose a reason for hiding this comment

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

귀여우니까 승인해드릴게요❤️❤️

@Yejiin21 Yejiin21 merged commit 4694f99 into develop Apr 29, 2025
2 checks passed
@Yejiin21 Yejiin21 deleted the refactor/#105/api-hook-refactor branch April 29, 2025 13:55
@xaexunxang
Copy link
Copy Markdown
Contributor

귀여우신 분이였군요 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🪄 Refactoring 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[refactor] react-query 기반 API 커스텀 훅 리팩토링

3 participants