Skip to content

[feature] 동아리 지원서 타입 설계 및 Mock API 개발#418

Merged
seongwon030 merged 43 commits intodevelop-fefrom
feature/#383-club-application-type-mock-api-FE-107
May 31, 2025
Merged

[feature] 동아리 지원서 타입 설계 및 Mock API 개발#418
seongwon030 merged 43 commits intodevelop-fefrom
feature/#383-club-application-type-mock-api-FE-107

Conversation

@seongwon030
Copy link
Member

@seongwon030 seongwon030 commented May 16, 2025

#️⃣연관된 이슈

ex) #383

📝작업 내용

1️⃣ MSW 기반 API Mocking 및 테스트 환경 구축

msw란?

  • msw는 클라이언트가 http요청을 보내면 Service Worker가 요청을 가로채고
  • mocking된 응답 값을 반환하여 서버와의 통신을 모방합니다.

왜 사용하는가?

  1. 지원서 api가 없는 상황.
  2. 미리 api를 테스트할 수 없을까하는 생각이 들었습니다.
  3. msw로 미리 api와 유틸함수를 테스트하고자 합니다.

msw 구성에 msw 공식문서 내용을 간단하게 정리해두었습니다.

mswDevSetup

  • setUpWorker는 네트워크 요청을 가로채어 모의 응답을 반환하는 역할을 합니다.

2️⃣ 테스트 작성

단위 테스트

  • clubId가 유효한지 검사했습니다. 15e8527

API 테스트

  • 응답을 정의해놓고 맞는 응답을 반환하는지 검사했습니다.
  • 200, 400 status를 테스트했습니다.
  • get, post, put 테스트를 완료했습니다.

3️⃣ Jsdom 문제

  • 기본적으로 JSDOM은 node에서 DOM을 사용할 수 있게 하지만, 서비스 워커(Service Worker)를 완전히 지원하지 않습니다.
  • msw에서는 api 요청 가로챈 다음, 바이너리 데이터를 처리할 수 있어야 합니다.
  • 여기서 필요한 게 TextEncoder, TextDecoder인데 JSDOM에 해당 기능이 없습니다.

jest-fixed-jsdom

  • jest-fixed-jsdom은 기존 JSDOM 환경을 패치하여 Service Worker API와 같은 브라우저 API를 폴리필한다고 하네요. 폴리필
  • jest.config.js에서 environment를 jest-fixed-jsdom로 하면 에러가 나지 않습니다.

그 외 작업

  • initSDK에 sdk 실행 함수를 분리하였습니다. 96979f4
  • sentry 로컬호스트 추적 비활성화했습니다.

중점적으로 리뷰받고 싶은 부분(선택)

  • 단위테스트와 api테스트가 가독성 및 결합도 측면에서 잘 작성되었는지?
  • api 테스트가 백엔드뿐만 아니라 프론트에서도 필요할지 궁금합니다.

논의하고 싶은 부분(선택)

put, post에서 request body 검증 로직이 필요할지 의문입니다. 한 번 생각해보죵

🫡 참고사항

Summary by CodeRabbit

  • 신규 기능

    • MSW(Mock Service Worker)를 활용한 API 모킹 환경이 추가되어 개발 및 테스트 시 네트워크 요청을 시뮬레이션할 수 있습니다.
    • 클럽 지원서 관련 모킹 API 및 샘플 데이터가 제공됩니다.
  • 테스트

    • 클럽 지원서 API와 URL 생성 유틸리티에 대한 테스트가 추가되었습니다.
  • 문서화

    • 오류 메시지 및 API 상수 등 사용자 메시지와 관련된 상수 정의가 추가되었습니다.
  • 환경 설정 및 초기화

    • Sentry, Mixpanel, ChannelService 등 외부 SDK 초기화가 유틸리티로 분리되어 관리가 용이해졌습니다.
    • 개발 환경에서만 MSW가 자동으로 활성화됩니다.
  • 의존성 추가

    • Sentry, MSW 등 관련 패키지가 새롭게 추가되었습니다.

- 클라이언트 사이드 API 모킹을 위한 MSW(Mock Service Worker) 설정
- './apply'에서 클럽 핸들러를 가져와 적용
- `setupWorker`를 통해 일관된 핸들러 초기화 보장
- 클럽 지원서 조회 및 제출을 위한 Mock API 핸들러 추가
- GET /api/club/apply: 유효하지 않은 클럽 ID에 대한 400 에러 처리
- GET /api/club/:clubId/apply: 클럽 ID 유효성 검사 및 모의 데이터 반환
- POST /api/club/:clubId/apply: 클럽 ID 유효성 검사 및 성공 메시지 반환
- 클럽 지원서 API 테스트 케이스 추가 (MSW)
- 정상 요청: 클럽 지원서 조회 및 제출 테스트
- 필수 질문 항목이 비어있지 않은지 확인하는 테스트
- 에러 케이스: 잘못된 클럽 ID 및 클럽 ID 누락 시 400 에러 테스트
- 지원서 제출 성공 및 에러 케이스 확인
@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 16, 2025

Walkthrough

동아리 지원서 타입 설계, 목(mock) 데이터 정의, Mock API 및 테스트 코드가 추가되었습니다. MSW(Mock Service Worker) 기반의 API 핸들러와 유틸리티, 타입, 상수, 테스트 파일 등이 신규로 도입되었으며, 관련 의존성 패키지도 추가되었습니다. SDK 초기화 코드가 유틸리티로 분리되었습니다.

Changes

파일/경로 그룹 변경 요약
frontend/package.json, frontend/jest.config.js Sentry, MSW, jest-fixed-jsdom 등 의존성 추가 및 Jest 환경 설정 변경
frontend/public/mockServiceWorker.js MSW용 서비스 워커 스크립트 신규 추가
frontend/src/mocks/api/apply.ts, frontend/src/mocks/api/index.ts 동아리 지원서 mock API 핸들러 및 핸들러 집계 파일 신규 추가
frontend/src/mocks/data/mockData.ts 지원서 mock 데이터와 타입 정의 신규 추가
frontend/src/mocks/constants/clubApi.ts, frontend/src/mocks/constants/error.ts API base URL, clubId, 에러 메시지 상수 신규 추가
frontend/src/mocks/utils/createApiUrl.ts, frontend/src/mocks/utils/validateClubId.ts clubId 유효성 검사 및 API URL 생성 유틸리티 신규 추가
frontend/src/mocks/api/utils/request.ts 지원서 제출/수정 API 요청 유틸리티 신규 추가
frontend/src/mocks/�mswDevSetup.ts MSW 개발 환경 셋업 모듈 신규 추가
frontend/src/mocks/utils/createApiUrl.test.ts, frontend/src/mocks/api/applyHandlers.test.ts API URL 생성 및 applyHandlers에 대한 테스트 코드 신규 추가
frontend/src/index.tsx, frontend/src/utils/initSDK.ts SDK 초기화 코드 분리 및 앱 시작 로직 개선

Sequence Diagram(s)

sequenceDiagram
    participant Test as 테스트 코드
    participant MSW as Mock Service Worker
    participant Handler as applyHandlers
    participant MockData as mockData

    Test->>MSW: API 요청 (GET/POST/PUT /:clubId/apply)
    MSW->>Handler: 해당 요청 핸들러 호출
    Handler->>MockData: mockData 참조 (질문/폼 데이터)
    Handler-->>MSW: 응답 데이터 생성
    MSW-->>Test: Mock 응답 반환
Loading

Assessment against linked issues

Objective (이슈 번호) Addressed Explanation
지원서 타입 설계, mock data 정의, TDD 기반 API 테스트 구현 (FE-107)

Assessment against linked issues: Out-of-scope changes

(해당 사항 없음)

Suggested labels

✨ Feature, 🔨 Refactor

Suggested reviewers

  • oesnuj
✨ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.

@netlify
Copy link

netlify bot commented May 16, 2025

Deploy Preview for moadong ready!

Name Link
🔨 Latest commit 44838af
🔍 Latest deploy log https://app.netlify.com/projects/moadong/deploys/683a94742e5624000804bc36
😎 Deploy Preview https://deploy-preview-418--moadong.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 42
Accessibility: 87
Best Practices: 92
SEO: 92
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

@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: 3

🧹 Nitpick comments (10)
frontend/src/mocks/api/index.ts (1)

1-3: 코드가 잘 구성되어 있습니다!

API 핸들러를 중앙에서 관리하는 방식으로 잘 설계되었습니다. 현재는 clubHandlers만 포함하고 있지만, 향후 다른 기능의 핸들러를 추가할 때 확장하기 좋은 구조입니다.

추후 다양한 API 모킹이 추가될 때 아래와 같이 구성하면 좋을 것 같습니다:

import { clubHandlers } from './apply';
import { userHandlers } from './user';
import { notificationHandlers } from './notification';
// 추가 핸들러들...

export const handlers = [
  ...clubHandlers,
  ...userHandlers,
  ...notificationHandlers,
  // 추가 핸들러들...
];
frontend/jest.config.js (1)

4-4: 테스트 환경 설정이 변경되었습니다

기본 jsdom 환경 대신 'jest-fixed-jsdom'을 사용하도록 설정이 변경되었습니다. 이는 MSW를 사용한 API 모킹 테스트에 필요한 변경으로 보입니다.

'jest-fixed-jsdom' 패키지가 어떤 문제를 해결하는지 PR 설명이나 코드 주석에 명시하면 좋을 것 같습니다. 추후 이 설정을 변경하거나 업데이트할 때 참고할 수 있도록 간단한 설명이 있으면 유지보수에 도움이 될 것입니다.

frontend/src/mocks/api/apply.ts (3)

4-8: validateClubId에서 숫자 변환을 두 번 하지 않도록 반환형 개선 제안
parseInt로 변환한 값을 그대로 반환하면 이후 로직에서 다시 파싱할 필요가 없습니다. 숫자 0을 걸러내는 조건까지 포함하여 조금 더 선언적으로 작성해 보면 가독성과 성능이 모두 개선됩니다.

-const validateClubId = (clubId: string | undefined) => {
-  if (!clubId) return false;
-  const numericClubId = parseInt(clubId, 10);
-  return !isNaN(numericClubId) && numericClubId > 0;
-};
+const parseClubId = (raw: string | undefined): number | null => {
+  if (!raw) return null;
+  const id = Number(raw);
+  return Number.isInteger(id) && id > 0 ? id : null;
+};

18-36: clubId 파라미터 재파싱 중복
validateClubId(또는 개선안) 내부에서 이미 숫자로 변환한 값을 받아올 수 있다면 이 구간의 parseInt는 불필요합니다. 하나의 유틸 함수에서 변환과 검증을 모두 담당하도록 통합하면 코드 일관성이 향상됩니다.


38-58: POST 핸들러에서 요청 본문 미검증
실제 제출 기능을 모킹한다고 가정하면, 최소한 JSON 파싱이 가능한지와 필수 답변 필드를 포함하는지 확인하도록 해두면 프론트엔드의 유효성 검사 누락을 빠르게 발견할 수 있습니다.

-async ({ params, request }) => {
+async ({ params, request }) => {
   const clubId = String(params.clubId);

-  if (!validateClubId(clubId)) {
+  if (!validateClubId(clubId)) {
     ...
   }
-  return HttpResponse.json(
+  // 간단한 예: 비어 있는 바디면 422 반환
+  if (!(await request.clone().text())) {
+    return HttpResponse.json(
+      { message: '빈 본문입니다.' },
+      { status: 422 },
+    );
+  }
+
+  return HttpResponse.json(
     ...
   );
 }
frontend/src/mocks/api/clubHandlers.test.ts (3)

49-52: 제목 길이 제한 하드코딩 주의
제목이 20자를 초과하면 바로 실패하도록 되어 있는데, 실제 제품 요구사항이 변경될 경우 테스트가 불필요하게 깨질 수 있습니다. 요구사항을 상수로 분리하거나 mockData에서 직접 검증하도록 수정하는 편이 유지보수에 유리합니다.


55-60: 필수 질문 검증 로직 개선 제안
현재는 items?.length만 확인하지만, 주관식 질문(단답/서술형)의 경우 items는 placeholder일 수 있어 실제 입력 가능 여부를 보장하지 않습니다. 타입별로 다른 검증 규칙을 적용하면 테스트 신뢰도가 높아집니다.


74-77: 테스트 코드에 남아있는 console.log 삭제
디버깅용 console.log는 CI 출력 노이즈를 유발하므로 제거하거나 debug 라이브러리 등으로 대체해 주세요.

-      const data: ApiErrorResponse = await response.json();
-      console.log(data);
+      const data: ApiErrorResponse = await response.json();
frontend/src/mocks/data/mockData.ts (2)

1-8: 문자열 리터럴 유니온 대신 enum 사용 고려
타입 안정성과 자동완성 이점을 위해 QuestionTypeenum으로 선언하면 유지보수가 더 쉽습니다.

-type QuestionType =
-  | 'CHOICE'
-  | 'MULTI_CHOICE'
-  | 'SHORT_TEXT'
-  | 'LONG_TEXT'
-  | 'PHONE_NUMBER'
-  | 'EMAIL'
-  | 'NAME';
+export enum QuestionType {
+  CHOICE = 'CHOICE',
+  MULTI_CHOICE = 'MULTI_CHOICE',
+  SHORT_TEXT = 'SHORT_TEXT',
+  LONG_TEXT = 'LONG_TEXT',
+  PHONE_NUMBER = 'PHONE_NUMBER',
+  EMAIL = 'EMAIL',
+  NAME = 'NAME',
+}

80-93: 목업 데이터에 과도한 길이의 placeholder 문자열
테스트 목적이라도 수백 자의 반복 문자열은 가독성을 떨어뜨립니다. 텍스트 길이만이 중요하다면 Array(20).fill('문장').join('') 처럼 동적으로 생성하거나 줄여서 작성해도 충분합니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ad4cecb and bc0ef77.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • frontend/jest.config.js (1 hunks)
  • frontend/package.json (1 hunks)
  • frontend/public/mockServiceWorker.js (1 hunks)
  • frontend/src/mocks/api/apply.ts (1 hunks)
  • frontend/src/mocks/api/clubHandlers.test.ts (1 hunks)
  • frontend/src/mocks/api/index.ts (1 hunks)
  • frontend/src/mocks/browser.ts (1 hunks)
  • frontend/src/mocks/data/mockData.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
frontend/src/mocks/api/index.ts (1)
frontend/src/mocks/api/apply.ts (1)
  • clubHandlers (10-60)
frontend/src/mocks/browser.ts (1)
frontend/src/mocks/api/index.ts (1)
  • handlers (3-3)
frontend/src/mocks/api/apply.ts (1)
frontend/src/mocks/data/mockData.ts (1)
  • mockData (28-125)
🪛 Biome (1.9.4)
frontend/public/mockServiceWorker.js

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (2)
frontend/package.json (1)

24-31: 새로운 패키지가 추가되었습니다

MSW와 관련 테스트 환경 설정을 위한 패키지가 적절히 추가되었습니다. 다음 사항을 확인해주세요:

  1. Sentry 관련 패키지(@sentry/react, @sentry/webpack-plugin)가 추가되었는데, 현재 리뷰 중인 PR 범위에서 사용되는지 확인이 필요합니다. 에러 모니터링을 위한 것으로 보이지만, 관련 설정 코드가 보이지 않습니다.

  2. jest-fixed-jsdom의 버전이 매우 낮습니다(0.0.9). 실험적인 패키지로 보이는데, 안정성이 검증되었는지 확인해주세요.

MSW 패키지는 적절한 버전으로 추가되어 API 모킹에 잘 활용될 것으로 보입니다.

frontend/public/mockServiceWorker.js (1)

1-308: 라이브러리 자동 생성 파일 – 리뷰 생략
이 파일은 MSW가 자동 생성한 코드이므로 수정하지 않는 것이 권장됩니다.

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

- setupWorker에 전달되는 handlers 배열의 타입을 명시적으로 RequestHandler[]로 지정.
- TypeScript에서 발생한 타입 불일치 오류 해결.
- MSW의 엄격한 타입 검사 규칙에 맞도록 코드 수정.
@seongwon030 seongwon030 added 📬 API 서버 API 통신 작업 ✅ Test test 관련(storybook, jest...) 💻 FE Frontend labels May 16, 2025
- 하드코딩된 API URL을 API_BASE 상수로 대체
- URL 관리 중앙화로 유지보수성 향상
Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
frontend/src/mocks/utils/createApiUrl.ts (1)

1-12: 전반적으로 잘 구현되었습니다!

createApiUrl 함수는 목적이 명확하고 구현이 간단합니다. 다만 몇 가지 개선 사항을 제안합니다:

  1. clubId의 추가적인 엣지 케이스 처리가 필요합니다:

    • 현재는 빈 문자열과 0만 처리하고 있지만, undefined, null, NaN 등의 경우도 고려해야 합니다.
    • 문자열 "0"은 현재 조건에서 캐치되지 않습니다.
  2. 함수에 JSDoc 문서를 추가하면 사용자가 더 쉽게 이해할 수 있습니다.

+/**
+ * 클럽 ID와 액션에 기반하여 API URL을 생성합니다.
+ * @param clubId - 클럽의 고유 식별자
+ * @param action - API 액션 (기본값: 'apply')
+ * @returns 포맷팅된 API URL 문자열
+ */
 export const createApiUrl = (
   clubId: string | number,
   action: string = 'apply',
 ) => {
   // 유효하지 않은 clubId 케이스
-  if (clubId === '' || clubId === 0) {
+  if (!clubId || clubId === '' || clubId === 0 || clubId === '0') {
     return `${API_BASE}/${action}`;
   }
   return `${API_BASE}/${clubId}/${action}`;
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f8a0cf1 and f4f8284.

📒 Files selected for processing (2)
  • frontend/src/mocks/api/clubHandlers.test.ts (1 hunks)
  • frontend/src/mocks/utils/createApiUrl.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/mocks/api/clubHandlers.test.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
frontend/src/mocks/utils/createApiUrl.ts (1)
frontend/src/mocks/constants/api.ts (1)
  • API_BASE (1-1)

Copy link
Contributor

@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: 2

🧹 Nitpick comments (2)
frontend/src/utils/initSDK.ts (2)

18-25: ChannelService 초기화 최적화 필요

현재 구현에서는 환경 변수 유무와 관계없이 항상 loadScript()를 호출합니다. 플러그인 키가 없을 때는 스크립트 로드가 불필요할 수 있으므로, 조건부로 로드하는 것이 좋습니다. 또한 초기화 과정에서의 예외 처리도 추가해주세요.

export function initializeChannelService() {
-  ChannelService.loadScript();
-  if (process.env.CHANNEL_PLUGIN_KEY) {
+  if (process.env.CHANNEL_PLUGIN_KEY && process.env.CHANNEL_PLUGIN_KEY.trim() !== '') {
+    try {
+      ChannelService.loadScript();
       ChannelService.boot({
         pluginKey: process.env.CHANNEL_PLUGIN_KEY,
       });
+    } catch (error) {
+      console.error('ChannelService 초기화 실패:', error);
+    }
   }
}

1-4: 함수 설명 주석 추가 권장

각 SDK 초기화 함수에 대한 설명 주석이 없어 코드의 의도를 파악하기 어렵습니다. 각 함수 위에 JSDoc 스타일 주석을 추가하여 함수의 목적, 사용하는 환경 변수, 그리고 동작 방식에 대한 설명을 추가하는 것이 좋습니다.

import mixpanel from 'mixpanel-browser';
import * as ChannelService from '@channel.io/channel-web-sdk-loader';
import * as Sentry from '@sentry/react';

+/**
+ * Mixpanel 분석 도구를 초기화합니다.
+ * 환경 변수 REACT_APP_MIXPANEL_TOKEN이 필요합니다.
+ * localhost에서는 Mixpanel이 비활성화됩니다.
+ */
export function initializeMixpanel() {
  // ... 기존 코드 ...
}

+/**
+ * Channel.io 고객 메시징 서비스를 초기화합니다.
+ * 환경 변수 CHANNEL_PLUGIN_KEY가 필요합니다.
+ */
export function initializeChannelService() {
  // ... 기존 코드 ...
}

+/**
+ * Sentry 에러 추적 서비스를 초기화합니다.
+ * 환경 변수 SENTRY_DSN이 필요하며, SENTRY_RELEASE도 사용됩니다.
+ * 개인 식별 정보(PII)는 전송되지 않습니다.
+ */
export function initializeSentry() {
  // ... 기존 코드 ...
}

Also applies to: 5-34

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f4f8284 and 96979f4.

📒 Files selected for processing (2)
  • frontend/src/index.tsx (1 hunks)
  • frontend/src/utils/initSDK.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/index.tsx

- 개발 환경에서만 MSW 워커 로드
- 동적 임포트로 초기 로딩 시간 개선
- 불필요한 프로덕션 번들 크기 감소
Copy link
Contributor

@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: 1

🧹 Nitpick comments (2)
frontend/src/mocks/�mswDevSetup.ts (2)

5-5: 타입 단언 방식을 개선하는 것이 좋습니다.

이중 타입 단언(as unknown as RequestHandler[])은 TypeScript의 타입 체크를 우회하는 방법으로, 타입 안전성을 저하시킬 수 있습니다. 타입 안전성을 높이려면 아래 방법 중 하나를 고려하세요.

방법 1: 타입 가드 함수 사용

// API 파일에서 타입 정의 조정
export const handlers: RequestHandler[] = [...];

방법 2: 더 안전한 타입 단언

-export const worker = setupWorker(...(handlers as unknown as RequestHandler[]));
+export const worker = setupWorker(...handlers.map(handler => handler as RequestHandler));

1-5: 파일 목적과 사용 방법에 대한 문서화를 추가하세요.

이 파일은 Mock Service Worker 설정의 중요한 부분이지만, 목적과 사용 방법에 대한 설명이 없습니다. 코드의 가독성과 유지보수성을 위해 파일 상단에 주석을 추가하는 것이 좋습니다.

+/**
+ * MSW(Mock Service Worker) 브라우저 환경 설정 파일
+ * 
+ * 이 파일은 개발 환경에서 API 요청을 가로채고 모의 응답을 반환하는 서비스 워커를 설정합니다.
+ * 애플리케이션 시작 시 이 워커를 초기화하여 API 모킹을 활성화할 수 있습니다.
+ * 
+ * @example
+ * // 개발 환경에서만 MSW 초기화
+ * if (process.env.NODE_ENV === 'development') {
+ *   import('./mocks/mswDevSetup').then(({ worker }) => {
+ *     worker.start();
+ *   });
+ * }
+ */
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e8544f7 and 92faf8a.

📒 Files selected for processing (3)
  • frontend/src/index.tsx (1 hunks)
  • frontend/src/mocks/�mswDevSetup.ts (1 hunks)
  • frontend/src/mocks/api/clubHandlers.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/index.tsx
  • frontend/src/mocks/api/clubHandlers.test.ts

@seongwon030 seongwon030 linked an issue May 17, 2025 that may be closed by this pull request
3 tasks
- 객관식 및 주관식 질문 테스트 추가
- PUT /:clubId/apply 엔드포인트 추가
- 클럽 ID 유효성 검증 로직 구현
- 성공/실패 응답 메시지 정의
- 지원서 수정 성공 케이스 테스트
- 잘못된 클럽 ID로 수정 요청 시 400 에러 테스트
Copy link
Contributor

@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: 7

♻️ Duplicate comments (1)
frontend/src/mocks/api/apply.ts (1)

7-12: 🛠️ Refactor suggestion

에러 메시지 상수화가 필요합니다.

에러 메시지 '유효하지 않은 클럽 ID입니다.'가 코드 내에서 여러 번 반복되고 있습니다. 유지보수성 향상을 위해 이를 상수로 추출하는 것을 권장합니다.

 import { mockData } from '../data/mockData';
 import { API_BASE } from '../constants/clubApi';
 import { validateClubId } from '../utils/validateClubId';
 
+// 상수 정의
+const ERROR_INVALID_CLUB_ID = '유효하지 않은 클럽 ID입니다.';
+
 export const clubHandlers = [
   http.get(`${API_BASE}/apply`, () => {
     return HttpResponse.json(
-      { message: '유효하지 않은 클럽 ID입니다.' },
+      { message: ERROR_INVALID_CLUB_ID },
       { status: 400 },
     );
   }),
🧹 Nitpick comments (3)
frontend/src/mocks/api/apply.ts (1)

14-32: GET 요청 핸들러 구현이 적절합니다.

클럽 ID를 검증하고 적절한 응답을 반환하는 로직이 잘 구현되어 있습니다. 추가로 개선할 점:

  1. 동일한 에러 메시지가 반복되므로 앞서 제안한 상수를 사용하세요.
  2. 응답 형식이 API 명세와 일치하는지 확인하세요.
   http.get(`${API_BASE}/:clubId/apply`, ({ params }) => {
     const clubId = String(params.clubId);
 
     if (!validateClubId(clubId)) {
       return HttpResponse.json(
-        { message: '유효하지 않은 클럽 ID입니다.' },
+        { message: ERROR_INVALID_CLUB_ID },
         { status: 400 },
       );
     }
frontend/src/mocks/api/clubHandlers.test.ts (2)

46-72: 타입 캐스팅 대신 타입 가드 사용을 권장합니다.

현재 여러 곳에서 타입 캐스팅(as)을 사용하고 있습니다. 타입 안전성을 높이기 위해 타입 가드 함수를 사용하는 것이 좋습니다.

+    // 타입 가드 함수 추가
+    function isClubApplyResponse(data: any): data is ClubApplyResponse {
+      return data && typeof data.form_title === 'string' && Array.isArray(data.questions);
+    }

     it('클럽 지원서를 정상적으로 불러온다.', () => {
       expect(response.status).toBe(200);
-      expect((data as ClubApplyResponse).form_title).toBeDefined();
-      expect((data as ClubApplyResponse).questions.length).toBeGreaterThan(0);
+      if (!isClubApplyResponse(data)) {
+        fail('응답이 예상 형식과 일치하지 않습니다');
+      }
+      expect(data.form_title).toBeDefined();
+      expect(data.questions.length).toBeGreaterThan(0);
     });

84-143: POST 테스트 케이스에서 중복 코드 개선이 필요합니다.

여러 POST 테스트 케이스에서 비슷한 검증 로직이 반복되고 있습니다. 테스트 헬퍼 함수나 공통 검증 로직을 추출하여 코드 중복을 줄이는 것이 좋습니다.

+  // 공통 테스트 검증 함수
+  const verifySuccessfulSubmission = async (answers: Record<string | number, string[]>) => {
+    const response = await submitApplication(CLUB_ID, answers);
+    const data: SubmissionResponse = await response.json();
+
+    expect(response.status).toBe(200);
+    expect(data.message).toBe('지원서가 성공적으로 제작되었습니다.');
+    return { response, data };
+  };

   describe('클럽 지원서 POST 테스트', () => {
     it('지원서 제작 성공', async () => {
       const answers = {
         '1': ['답변1', '답변2'],
         '2': ['답변3'],
       };
-
-      const response = await submitApplication(CLUB_ID, answers);
-      const data: SubmissionResponse = await response.json();
-
-      expect(response.status).toBe(200);
-      expect(data.message).toBe('지원서가 성공적으로 제작되었습니다.');
+      await verifySuccessfulSubmission(answers);
     });
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 92faf8a and 7d1b501.

📒 Files selected for processing (2)
  • frontend/src/mocks/api/apply.ts (1 hunks)
  • frontend/src/mocks/api/clubHandlers.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
frontend/src/mocks/api/clubHandlers.test.ts (1)
Learnt from: seongwon030
PR: Moadong/moadong#418
File: frontend/src/mocks/api/clubHandlers.test.ts:0-0
Timestamp: 2025-05-16T06:25:11.156Z
Learning: 이 프로젝트에서는 API URL 생성과 같은 유틸리티 함수는 별도 파일로 분리하여 관리하는 것이 좋습니다. 특히 테스트 파일 내에 정의된 유틸리티 함수는 재사용성과 일관성을 위해 분리가 권장됩니다.
🧬 Code Graph Analysis (1)
frontend/src/mocks/api/apply.ts (3)
frontend/src/mocks/constants/clubApi.ts (1)
  • API_BASE (1-1)
frontend/src/mocks/utils/validateClubId.ts (1)
  • validateClubId (1-4)
frontend/src/mocks/data/mockData.ts (1)
  • mockData (28-125)
🔇 Additional comments (4)
frontend/src/mocks/api/apply.ts (1)

1-5: API 및 유틸리티 임포트 구성이 잘 되었습니다.

필요한 모듈과 유틸리티 함수, 상수들이 명확하게 임포트되어 있어 코드의 가독성과 구조가 좋습니다. validateClubId 유틸리티를 분리하여 재사용한 것이 좋은 패턴입니다.

frontend/src/mocks/api/clubHandlers.test.ts (3)

1-6: 임포트가 명확하게 정의되어 있습니다.

필요한 모듈과 타입 그리고 유틸리티 함수들이 잘 임포트되어 있습니다. MSW와 관련된 설정도 적절히 구성되어 있습니다.


22-26: MSW 서버 설정이 적절합니다.

테스트 환경 설정을 위한 MSW 서버가 잘 구성되어 있으며, Jest의 라이프사이클 훅을 사용하여 테스트 전후 처리가 적절히 구현되어 있습니다.


74-82: 테스트 코드가 잘 구성되어 있습니다.

에러 케이스 테스트가 명확하게 구현되어 있으며, 예상 응답과 상태 코드를 적절히 검증하고 있습니다.

- API 요청 관련 유틸리티 함수들을 별도 파일로 분리
- sendApiRequest, submitApplication, updateApplication 함수를 utils/request.ts로 이동
- 테스트 코드에서 유틸리티 함수 import하여 사용하도록 수정
- DELETE 메서드 지원 추가
Copy link
Contributor

@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: 1

🧹 Nitpick comments (4)
frontend/src/mocks/api/utils/request.ts (4)

3-16: 에러 처리 로직 추가 고려

현재 sendApiRequest 함수는 네트워크 오류나 서버 오류에 대한 명시적인 에러 처리를 포함하지 않습니다. 비록 이것이 목(mock) API용이더라도, 실제 구현과 일관성을 유지하기 위해 기본적인 에러 처리를 추가하는 것이 좋을 수 있습니다.

다음과 같은 에러 처리 로직 추가를 고려해보세요:

export const sendApiRequest = async (
  clubId: string,
  answers: Record<number, string[]>,
  method: 'POST' | 'PUT' | 'DELETE',
) => {
-  const response = await fetch(createApiUrl(clubId), {
-    method,
-    headers: {
-      'Content-Type': 'application/json',
-    },
-    body: JSON.stringify(answers),
-  });
-  return response;
+  try {
+    const response = await fetch(createApiUrl(clubId), {
+      method,
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: JSON.stringify(answers),
+    });
+    return response;
+  } catch (error) {
+    console.error('API 요청 중 오류 발생:', error);
+    throw error;
+  }
};

1-32: JSDoc 문서화 추가 권장

함수의 목적과 사용법을 설명하는 JSDoc 주석이 없습니다. 다른 개발자들이 이 유틸리티 함수들을 이해하고 사용하는 데 도움이 되도록 문서화를 추가하는 것이 좋습니다.

다음과 같은 JSDoc 문서화 추가를 고려해보세요:

import { createApiUrl } from '@/mocks/utils/createApiUrl';

+/**
+ * 클럽 ID와 답변을 사용하여 API 요청을 보내는 함수
+ * @param clubId - 요청을 보낼 클럽 ID
+ * @param answers - 질문 번호/ID를 키로 하고 답변 배열을 값으로 하는 객체
+ * @param method - HTTP 메서드 ('POST', 'PUT', 'DELETE')
+ * @returns fetch API의 응답 객체
+ */
export const sendApiRequest = async (
  clubId: string,
  answers: Record<number, string[]>,
  method: 'POST' | 'PUT' | 'DELETE',
) => {
  // ... 함수 내용 ...
};

+/**
+ * 지원서를 제출하는 함수 (POST 요청)
+ * @param clubId - 지원서를 제출할 클럽 ID
+ * @param answers - 질문 번호/ID를 키로 하고 답변 배열을 값으로 하는 객체
+ * @returns fetch API의 응답 객체
+ */
export const submitApplication = (
  // ... 함수 내용 ...
);

// 나머지 함수들에 대한 JSDoc 추가

8-14: 응답 데이터 처리 로직 고려

현재 sendApiRequest 함수는 원시 응답 객체를 그대로 반환합니다. 사용자가 응답 데이터를 사용하려면 추가적으로 .json()과 같은 메서드를 호출해야 합니다. 일반적인 패턴은 응답 데이터를 자동으로 파싱하여 반환하는 것입니다.

응답 데이터를 자동으로 파싱하는 로직을 추가하는 것을 고려해보세요:

export const sendApiRequest = async (
  clubId: string,
  answers: Record<number, string[]>,
  method: 'POST' | 'PUT' | 'DELETE',
) => {
  const response = await fetch(createApiUrl(clubId), {
    method,
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(answers),
  });
-  return response;
+  if (!response.ok) {
+    throw new Error(`API 요청 실패: ${response.status} ${response.statusText}`);
+  }
+  return response.json();
};

아니면 최소한 응답 상태를 확인하는 로직을 추가하세요.


3-7: HTTP 메서드 타입 확장 고려

현재 sendApiRequest 함수는 'POST', 'PUT', 'DELETE' 메서드만 지원합니다. 나중에 확장성을 고려하여 'GET'과 'PATCH' 같은 다른 HTTP 메서드도 지원하도록 타입을 확장하는 것이 좋을 수 있습니다.

다음과 같이 메서드 타입을 확장하는 것을 고려해보세요:

export const sendApiRequest = async (
  clubId: string,
  answers: Record<number, string[]>,
-  method: 'POST' | 'PUT' | 'DELETE',
+  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
) => {

그리고 GET 메서드일 경우 body를 전송하지 않도록 로직을 추가하세요.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9ca7ed4 and ff9483e.

📒 Files selected for processing (2)
  • frontend/src/mocks/api/clubHandlers.test.ts (1 hunks)
  • frontend/src/mocks/api/utils/request.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/mocks/api/clubHandlers.test.ts
🔇 Additional comments (1)
frontend/src/mocks/api/utils/request.ts (1)

28-31: deleteApplication 함수의 answers 매개변수 필요성 검토

deleteApplication 함수는 삭제 작업을 수행하는데 answers 매개변수가 필요한지 의문입니다. 일반적으로 DELETE 요청은 리소스 식별자(여기서는 clubId)만으로 충분합니다. 만약 특별한 이유가 없다면, 이 매개변수를 제거하는 것이 API 디자인 측면에서 더 일관성 있어 보입니다.

DELETE 요청에 실제로 요청 본문(body)이 필요한지 확인해주세요. 필요하지 않다면 다음과 같이 수정을 고려해보세요:

export const deleteApplication = (
  clubId: string,
-  answers: Record<number | string, string[]>,
) => sendApiRequest(clubId, {}, 'DELETE');

@codecov
Copy link

codecov bot commented May 20, 2025

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

Copy link
Member

@oesnuj oesnuj left a comment

Choose a reason for hiding this comment

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

MSW로 mock API 서버 구성해주신 거 정말 수고 많으셨습니다 👍
실제 API가 아직 없는 상황에서도 빠르게 개발해볼 수 있을 것 같아요!

  • 한 가지 궁금한 점이 있어요
    추후 백엔드 API가 실제로 만들어졌을 때, 관련 테스트를 백엔드에서 받은 실제 API로 검증하는 게 좋을까요?
    아니면 msw로 구성한 mock API를 기반으로 테스트하는 것이 괜찮을까요?

mock 서버가 단순히 더미 데이터를 주는 것 외에도 테스트 용도로 어떻게 사용되는 게 맞는지 궁금해서요!

Copy link
Contributor

@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: 0

♻️ Duplicate comments (2)
frontend/src/mocks/api/apply.ts (2)

35-52: 🛠️ Refactor suggestion

POST 핸들러에 요청 본문 검증이 누락되었습니다

이전 리뷰에서 지적된 요청 본문 검증이 여전히 구현되지 않았습니다. 실제 지원서 제출 시에는 답변 데이터의 유효성을 검증해야 합니다.

-  http.post(`${API_BASE}/:clubId/apply`, ({ params }) => {
+  http.post(`${API_BASE}/:clubId/apply`, async ({ params, request }) => {
     const clubId = String(params.clubId);

     if (!validateClubId(clubId)) {
       return HttpResponse.json(
         { message: ERROR_MESSAGE.INVALID_CLUB_ID },
         { status: 400 },
       );
     }

+    // 요청 본문 검증
+    try {
+      const requestData = await request.json();
+      if (!requestData || typeof requestData !== 'object') {
+        return HttpResponse.json(
+          { message: '올바른 답변 데이터를 제공해주세요.' },
+          { status: 400 },
+        );
+      }
+    } catch (error) {
+      return HttpResponse.json(
+        { message: '잘못된 요청 형식입니다.' },
+        { status: 400 },
+      );
+    }

     return HttpResponse.json(

54-71: 🛠️ Refactor suggestion

PUT 핸들러의 async 사용이 불일치합니다

PUT 핸들러만 async를 사용하고 있지만 실제로는 await를 사용하지 않습니다. POST 핸들러와 일관성을 위해 제거하거나, 요청 본문 검증을 추가하여 await를 실제로 사용하세요.

-  http.put(`${API_BASE}/:clubId/apply`, async ({ params }) => {
+  http.put(`${API_BASE}/:clubId/apply`, async ({ params, request }) => {
     const clubId = String(params.clubId);

     if (!validateClubId(clubId)) {
       return HttpResponse.json(
         { message: ERROR_MESSAGE.INVALID_CLUB_ID },
         { status: 400 },
       );
     }

+    // 요청 본문 검증 (POST와 동일한 로직)
+    try {
+      const requestData = await request.json();
+      if (!requestData || typeof requestData !== 'object') {
+        return HttpResponse.json(
+          { message: '올바른 답변 데이터를 제공해주세요.' },
+          { status: 400 },
+        );
+      }
+    } catch (error) {
+      return HttpResponse.json(
+        { message: '잘못된 요청 형식입니다.' },
+        { status: 400 },
+      );
+    }

     return HttpResponse.json(
🧹 Nitpick comments (5)
frontend/src/mocks/api/applyHandlers.test.ts (3)

35-38: beforeEach에서 중복 호출 최적화 검토

매 테스트마다 동일한 API 호출과 JSON 파싱을 수행하고 있습니다. 응답 데이터가 변경되지 않는다면, 테스트별로 필요한 부분만 호출하는 것이 더 효율적일 수 있습니다.

-    beforeEach(async () => {
-      response = await fetch(createApiUrl(CLUB_ID));
-      data = await response.json();
-    });
+    beforeEach(async () => {
+      response = await fetch(createApiUrl(CLUB_ID));
+      data = await response.json();
+    });

현재 구조도 충분히 괜찮지만, 테스트 성능을 고려한다면 각 테스트에서 필요한 데이터만 가져오는 방식도 고려해볼 수 있습니다.


115-130: 에러 케이스 테스트에서 일관성 확인

POST 에러 테스트에서 submitApplication 함수 대신 직접 fetch를 사용하고 있습니다. 다른 성공 케이스들과 일관성을 위해 submitApplication 함수를 사용하는 것을 고려해보세요.

-    it('잘못된 클럽 ID로 요청 시 400 에러', async () => {
-      const response = await fetch(`${API_BASE}/invalid-id/apply`, {
-        method: 'POST',
-        headers: {
-          'Content-Type': 'application/json',
-        },
-        body: JSON.stringify({
-          '1': ['답변1'],
-          '2': ['답변2'],
-        }),
-      });
+    it('잘못된 클럽 ID로 요청 시 400 에러', async () => {
+      const response = await submitApplication('invalid-id', {
+        '1': ['답변1'],
+        '2': ['답변2'],
+      });

이렇게 하면 유틸리티 함수의 에러 처리도 함께 테스트할 수 있습니다.


147-162: PUT 에러 테스트도 동일한 일관성 이슈가 있습니다

POST 에러 테스트와 마찬가지로 updateApplication 함수를 사용하는 것이 더 일관적입니다.

-    it('잘못된 클럽 ID로 수정 요청 시 400 에러', async () => {
-      const response = await fetch(`${API_BASE}/invalid-id/apply`, {
-        method: 'PUT',
-        headers: {
-          'Content-Type': 'application/json',
-        },
-        body: JSON.stringify({
-          '1': ['수정된 답변1'],
-          '2': ['수정된 답변2'],
-        }),
-      });
+    it('잘못된 클럽 ID로 수정 요청 시 400 에러', async () => {
+      const response = await updateApplication('invalid-id', {
+        '1': ['수정된 답변1'],
+        '2': ['수정된 답변2'],
+      });
frontend/src/mocks/api/apply.ts (2)

8-13: 기본 GET 엔드포인트의 목적이 명확하지 않습니다

/apply 경로로의 GET 요청이 항상 400 에러를 반환하는 이유가 불분명합니다. 이 엔드포인트가 실제로 필요한지, 아니면 문서화나 명확한 에러 메시지가 필요한지 검토해보세요.

실제 API에서 클럽 ID 없이 지원서에 접근하는 것이 잘못된 요청이라면, 더 구체적인 에러 메시지를 고려해볼 수 있습니다:

  http.get(`${API_BASE}/apply`, () => {
    return HttpResponse.json(
-      { message: ERROR_MESSAGE.INVALID_CLUB_ID },
+      { message: '클럽 ID가 필요합니다. /:clubId/apply 형식으로 요청해주세요.' },
      { status: 400 },
    );
  }),
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 9-9: frontend/src/mocks/api/apply.ts#L9
Added line #L9 was not covered by tests


9-9: 테스트 커버리지 누락 해결

정적 분석 도구에서 9번째 라인이 테스트로 커버되지 않는다고 표시됩니다. 이는 기본 GET /apply 엔드포인트에 대한 테스트가 없기 때문입니다.

테스트 파일에 다음 테스트를 추가하는 것을 고려해보세요:

describe('기본 apply 엔드포인트 테스트', () => {
  it('클럽 ID 없이 요청 시 400 에러를 반환한다', async () => {
    const response = await fetch(`${API_BASE}/apply`);
    const data: ApiErrorResponse = await response.json();

    expect(response.status).toBe(400);
    expect(data.message).toBeDefined();
  });
});

테스트 커버리지를 개선하기 위한 추가 테스트 코드를 생성해드릴까요?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 9-9: frontend/src/mocks/api/apply.ts#L9
Added line #L9 was not covered by tests

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 02c4e67 and 44838af.

📒 Files selected for processing (3)
  • frontend/src/mocks/api/apply.ts (1 hunks)
  • frontend/src/mocks/api/applyHandlers.test.ts (1 hunks)
  • frontend/src/mocks/api/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/mocks/api/index.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
frontend/src/mocks/api/applyHandlers.test.ts (6)
frontend/src/mocks/data/mockData.ts (1)
  • Question (14-21)
frontend/src/mocks/api/apply.ts (1)
  • applyHandlers (7-72)
frontend/src/mocks/utils/createApiUrl.ts (1)
  • createApiUrl (4-10)
frontend/src/mocks/constants/clubApi.ts (2)
  • CLUB_ID (3-3)
  • API_BASE (1-1)
frontend/src/mocks/constants/error.ts (1)
  • ERROR_MESSAGE (1-5)
frontend/src/mocks/api/utils/request.ts (2)
  • submitApplication (18-21)
  • updateApplication (23-26)
frontend/src/mocks/api/apply.ts (4)
frontend/src/mocks/constants/clubApi.ts (1)
  • API_BASE (1-1)
frontend/src/mocks/constants/error.ts (1)
  • ERROR_MESSAGE (1-5)
frontend/src/mocks/utils/validateClubId.ts (1)
  • validateClubId (1-4)
frontend/src/mocks/data/mockData.ts (1)
  • mockData (28-125)
🪛 GitHub Check: codecov/patch
frontend/src/mocks/api/apply.ts

[warning] 9-9: frontend/src/mocks/api/apply.ts#L9
Added line #L9 was not covered by tests

🔇 Additional comments (8)
frontend/src/mocks/api/applyHandlers.test.ts (6)

1-7: 임포트 구조가 잘 정리되어 있습니다

필요한 모듈들을 적절히 임포트하고 있으며, MSW 테스트에 필요한 모든 의존성이 포함되어 있습니다.


9-23: 타입 정의가 명확하고 구조적입니다

API 응답에 대한 인터페이스들이 잘 정의되어 있어 타입 안전성을 보장합니다. 특히 ClubApplyResponse, ApiErrorResponse, SubmissionResponse로 명확히 구분한 점이 좋습니다.


24-28: MSW 서버 설정이 적절합니다

테스트 라이프사이클 관리가 올바르게 구현되어 있어 테스트 간 상태 오염을 방지합니다.


52-59: 필수 질문 검증 로직이 견고합니다

옵셔널 체이닝을 사용하여 안전하게 필수 질문의 항목을 검증하고 있습니다. 실제 데이터 구조와 잘 맞는 테스트입니다.


74-84: 다양한 답변 형태에 대한 테스트가 포괄적입니다

문자열과 숫자 키를 모두 포함한 답변 데이터로 테스트하여 실제 사용 시나리오를 잘 반영했습니다.


99-113: 주관식 질문 테스트 데이터가 현실적입니다

다양한 주관식 질문 타입(단답형, 서술형, 이메일, 전화번호, 이름)에 대한 실제적인 답변 예시로 테스트하고 있어 매우 유용합니다.

frontend/src/mocks/api/apply.ts (2)

1-5: 임포트 구조가 체계적으로 개선되었습니다

이전 리뷰에서 지적된 중복 검증 로직과 상수화 이슈가 잘 해결되었습니다. validateClubId 유틸리티와 ERROR_MESSAGE 상수를 적절히 사용하고 있습니다.


15-33: GET 핸들러가 잘 구현되었습니다

클럽 ID 검증과 적절한 응답 구조를 가지고 있습니다. 에러 처리와 성공 응답 모두 일관적입니다.

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

Labels

📬 API 서버 API 통신 작업 💻 FE Frontend ✅ Test test 관련(storybook, jest...)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] FE-107 동아리 지원서 타입 설계 및 Mock API 개발

2 participants

Comments