-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/#62 이벤트 정보 조회 api 응답 분기처리 #63
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
Conversation
개요이벤트 데이터를 공개 및 비공개 정보로 분리하고, 해당하는 쿼리, 스키마, 서비스 함수를 업데이트했습니다. 또한 여러 컴포넌트에서 Next.js 링크 프리페칭을 비활성화하고, 캠퍼스 선택기 로직을 간소화했습니다. 변경사항
예상 코드 리뷰 난이도🎯 3 (중간) | ⏱️ ~20-25분 특히 주의가 필요한 부분:
관련 가능성 있는 PR
제안 라벨
시
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
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.
Actionable comments posted: 2
♻️ Duplicate comments (3)
apps/admin/src/app/_components/RequestListItem/RequestListItem.tsx (1)
18-18: prefetch 비활성화 관련PlaceListItem.tsx에서 언급한 것과 동일한 우려사항입니다. 여러 컴포넌트에서 일괄적으로 prefetch를 비활성화하는 것보다 근본 원인(캠퍼스 선택 관련 캐시 이슈)을 해결하는 것이 더 나은 접근일 수 있습니다.
apps/web/app/requests/_components/PlaceListItem/PlaceListItem.tsx (1)
23-23: prefetch 비활성화 관련동일한 prefetch 비활성화 패턴입니다. 앞서 언급한 검증이 필요합니다.
apps/web/app/_components/Categories/CategoryItem.tsx (1)
11-11: prefetch 비활성화 관련동일한 prefetch 비활성화 패턴입니다.
🧹 Nitpick comments (2)
apps/web/app/_mocks/handlers/eventHandlers.ts (1)
7-9: 주석 처리된 코드를 제거하는 것을 권장합니다.주석 처리된 핸들러 코드는 버전 관리 시스템(Git)에 이미 기록되어 있으므로, 필요시 언제든지 복원할 수 있습니다. 코드베이스를 깔끔하게 유지하기 위해 주석 처리된 코드를 완전히 제거하는 것을 권장합니다.
다음 diff를 적용하여 주석 처리된 코드를 제거하세요:
export const EventHandlers = [ - // http.get(addBaseUrl(API_PATH.EVENT.INFO), () => { - // return HttpResponse.json(event) - // }), http.post(addBaseUrl(API_PATH.EVENT.PARTICIPATIONS), () => {apps/web/app/_apis/queries/event.ts (1)
16-25: 사용 가이드라인 추가를 권장합니다.쿼리 옵션이 올바르게 구성되어 있지만, 개발자들이 언제
publicInfo()를 사용하고 언제privateInfo()를 사용해야 하는지에 대한 가이드가 없습니다.JSDoc 주석을 추가하여 사용 시나리오를 명확히 하는 것을 고려해주세요.
다음과 같이 JSDoc 주석을 추가할 수 있습니다:
export const useEventQueries = { + /** + * 비인증 사용자를 위한 공개 이벤트 정보 조회 + * 상품/경품 정보만 포함 + */ publicInfo: () => queryOptions({ queryKey: EventQueryKeys.publicInfo(), queryFn: getPublicEventInfo, }), + /** + * 인증된 사용자를 위한 전체 이벤트 정보 조회 + * 상품/경품 정보 + 사용자의 티켓 수, 참여 정보 등 포함 + */ privateInfo: () => queryOptions({ queryKey: EventQueryKeys.privateInfo(), queryFn: getPrivateEventInfo, }),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
apps/admin/src/app/_components/RequestListItem/RequestListItem.tsx(1 hunks)apps/web/app/_apis/queries/event.ts(1 hunks)apps/web/app/_apis/schemas/event.ts(2 hunks)apps/web/app/_apis/services/event.ts(1 hunks)apps/web/app/_components/CampusSelector/CampusSelector.tsx(3 hunks)apps/web/app/_components/Categories/CategoryItem.tsx(1 hunks)apps/web/app/_components/PlaceListItem/PlaceListItem.tsx(1 hunks)apps/web/app/_mocks/handlers/eventHandlers.ts(1 hunks)apps/web/app/events/lucky-draw/_components/Pages/Participation/Participation.tsx(1 hunks)apps/web/app/events/lucky-draw/page.tsx(1 hunks)apps/web/app/places/new/_components/Step/EventWelcome/EventWelcome.tsx(1 hunks)apps/web/app/requests/_components/PlaceListItem/PlaceListItem.tsx(1 hunks)apps/web/next.config.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
apps/admin/src/app/_components/RequestListItem/RequestListItem.tsx (1)
apps/web/app/_components/BottomNavigation/TabItem.tsx (1)
TabItemProps(20-43)
apps/web/app/requests/_components/PlaceListItem/PlaceListItem.tsx (3)
packages/ui/src/components/Layout/JustifyAround/JustifyAround.tsx (1)
restProps(4-20)apps/web/app/_components/BottomNavigation/TabItem.tsx (1)
TabItemProps(20-43)apps/web/app/_components/BottomNavigation/BottomNavigation.tsx (1)
JustifyBetween(13-32)
apps/web/app/_components/PlaceListItem/PlaceListItem.tsx (2)
apps/web/app/map/_components/PreviewPlace/PreviewPlace.tsx (1)
place(11-60)apps/web/app/_components/RankingPlaceList/RankingPlaceList.tsx (2)
Props(13-28)place(18-24)
apps/web/app/_components/CampusSelector/CampusSelector.tsx (1)
apps/web/app/_constants/campus.ts (1)
CAMPUS_LIST(21-21)
apps/web/app/_apis/schemas/event.ts (1)
apps/web/app/events/lucky-draw/_components/Pages/Participation/ParticipationPrize.tsx (1)
Props(14-37)
apps/web/app/events/lucky-draw/_components/Pages/Participation/Participation.tsx (1)
apps/web/app/_apis/queries/event.ts (1)
useEventQueries(15-31)
apps/web/app/events/lucky-draw/page.tsx (1)
apps/web/app/_apis/queries/event.ts (1)
useEventQueries(15-31)
apps/web/app/places/new/_components/Step/EventWelcome/EventWelcome.tsx (1)
apps/web/app/_apis/queries/event.ts (1)
useEventQueries(15-31)
apps/web/app/_apis/queries/event.ts (1)
apps/web/app/_apis/services/event.ts (2)
getPublicEventInfo(12-16)getPrivateEventInfo(18-22)
apps/web/app/_apis/services/event.ts (1)
apps/web/app/_apis/schemas/event.ts (4)
PublicEvent(30-30)PublicEventSchema(3-8)PrivateEvent(31-31)PrivateEventSchema(10-21)
🔇 Additional comments (10)
apps/web/app/_components/CampusSelector/CampusSelector.tsx (2)
20-25: 캠퍼스 변경 핸들러 구현이 올바릅니다.Selection에서 첫 번째 키를 추출하고 타입 가드로 검증한 후 상태를 업데이트하는 로직이 정확합니다.
disallowEmptySelection이 설정되어 있어Array.from(keys)[0]이 안전하게 작동합니다.배포 환경에서 캠퍼스 선택 시 UI가 제대로 업데이트되는지 확인해주세요. 이전에 발생했던 문제가 해결되었는지 검증이 필요합니다.
56-59: 타입 가드 구현이 올바릅니다.
CAMPUS_LIST.includes()를 사용한 검증 로직이 정확합니다.readonly string[]로의 타입 캐스팅은 TypeScript의 타입 추론 제한으로 인해 필요한 부분입니다.apps/web/app/events/lucky-draw/_components/Pages/Participation/Participation.tsx (1)
15-15: privateInfo 사용 및 데이터 구조 일치 확인
privateInfo()사용이 적절하며, 구조 분해된 모든 필드가PrivateEventSchema에 정의되어 있습니다.apps/web/app/places/new/_components/Step/EventWelcome/EventWelcome.tsx (1)
16-16: publicInfo 사용이 적절합니다이벤트 환영 화면은 비인증 사용자도 볼 수 있어야 하므로
publicInfo()사용이 올바릅니다. 상품 정보(prize)만 사용하고 있어PublicEventSchema와 완벽하게 일치합니다.공개/비공개 데이터 분리 원칙이 잘 지켜진 좋은 예시입니다.
apps/web/app/events/lucky-draw/page.tsx (1)
18-18: 비인증 사용자 접근 시 에러 처리 확인 필요합니다현재 코드 구조상 다음과 같은 문제가 있습니다:
HydrationBoundaryPage의prefetch단계에서 에러 처리 로직이 없음axiosInstance에 401 인터셉터 등 인증 에러 처리가 구현되어 있지 않음- Route 레벨의 인증 미들웨어나 보호 메커니즘이 없음
- 비인증 사용자가 페이지에 접근하면
getPrivateEventInfo()요청이 401로 실패할 가능성 높음페이지가 제대로 보호되고 있는지, 그리고 인증되지 않은 사용자가 접근했을 때 로그인 페이지로 리다이렉션되는지 수동으로 검증해주세요.
apps/web/app/_components/PlaceListItem/PlaceListItem.tsx (1)
30-30: 캠퍼스별 쿼리 키 구조 검증 필요검증 결과, 리뷰의 우려사항이 타당합니다. 현재 상황:
- PlaceQueryKeys: ✓ 올바르게
byRanking(sort, campus)와byCategory(id, campus)에 campus 포함- CategoryQueryKeys: ✗ campus 미포함 (list(), items(categoryId)만 있음)
- RequestQueryKeys: ✗ campus 미포함 (list(), detail()만 있음)
- Campus 변경 시: Zustand 상태만 업데이트되고 쿼리 무효화 로직 없음
- next.config.ts: staleTimes 미설정
prefetch={false}만으로는 근본 원인을 해결하지 못합니다. 다음을 확인하세요:
카테고리와 요청 데이터가 캠퍼스별로 달라지는가?
- 그렇다면: CategoryQueryKeys와RequestQueryKeys에 campus 파라미터 추가 필수
- 아니라면: prefetch 비활성화 이유를 다시 검토 필요
권장 해결책 (우선순위순):
- apps/web/app/_apis/queries/category.ts와 request.ts의 쿼리 키에 campus 추가 (필요시)
- 또는 CampusSelector에서
setCampus()호출 시 관련 쿼리 무효화 로직 추가- 또는 next.config.ts에서
staleTimes설정으로 라우터 캐시 제어apps/web/app/_apis/schemas/event.ts (1)
3-31: 단일 엔드포인트/events사용으로 인한 아키텍처 재검토 필요검증 결과, 두 함수 모두 **동일한 엔드포인트(
/events)**를 호출합니다:
getPublicEventInfo:API_PATH.EVENT.INFO(=/events)getPrivateEventInfo:API_PATH.EVENT.INFO(=/events)원래 리뷰에서 "두 API 엔드포인트가 서로 다른지" 확인을 요청하셨으나, 실제로는 같은 엔드포인트를 공유합니다. 인증은 쿠키 기반(
withCredentials: true)으로 처리되며, 요청 헤더 분기가 아닙니다.이 구조에서는 백엔드에서 인증 상태에 따라 다른 데이터를 반환해야 하고, 클라이언트는 Zod 스키마로만 유효성을 검증합니다. 클라이언트 스키마 검증은 보안 강제를 제공하지 않으므로 백엔드의 접근 제어 구현이 필수입니다.
검증 필요 사항:
- 백엔드
/events엔드포인트에서 인증 여부에 따른 데이터 반환 로직 확인- 인증되지 않은 요청에 대한 401/403 응답 처리 확인
- 에러 응답 처리 구현 확인 (현재 서비스 레이어에서 보이지 않음)
apps/web/app/_apis/queries/event.ts (2)
2-6: LGTM!Import 문이 올바르게 업데이트되어 새로운
getPublicEventInfo와getPrivateEventInfo함수를 사용합니다.
10-11: LGTM!쿼리 키가
'public'과'private'접미사를 사용하여 명확하게 구분되어 있으며, TanStack Query의 계층적 키 구조를 올바르게 따릅니다.apps/web/app/_apis/services/event.ts (1)
12-22: 백엔드가 인증 상태별로 올바른 데이터 구조를 반환하는지 확인 필요동일한
/events엔드포인트에PublicEventSchema와PrivateEventSchema를 적용하고 있습니다.withCredentials: true설정으로 쿠키가 자동 전송되므로, 백엔드가 인증 여부에 따라 정확히 다른 데이터를 반환해야 합니다:
- 인증됨 →
eventId,totalWinnersCount,participantsCount등 모든 필드 포함- 미인증 →
prize필드만 포함스키마 검증 실패 시 명확한 오류 메시지가 필요하며, MSW 핸들러(현재 주석 처리됨)를 구현하여 이 동작을 테스트하시기 바랍니다.
| @@ -1,12 +1,12 @@ | |||
| import { http, HttpResponse } from 'msw' | |||
| import { event, eventResult } from '../data/event' | |||
| import { eventResult } from '../data/event' | |||
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.
🧩 Analysis chain
새로운 public/private 엔드포인트에 대한 mock 핸들러 추가를 고려하세요.
event import를 제거한 것은 주석 처리된 핸들러와 일관성이 있습니다. 그러나 PR 목표에 따르면 이벤트 정보 API가 public/private 버전으로 분리되고 있습니다. 개발 및 테스트 환경에서 새로운 엔드포인트들이 제대로 작동하도록 하려면, API_PATH.EVENT.PUBLIC_INFO와 API_PATH.EVENT.PRIVATE_INFO(또는 유사한 경로)에 대한 mock 핸들러를 추가해야 할 수 있습니다.
다음 스크립트를 실행하여 새로운 public/private 엔드포인트가 정의되어 있는지 확인하세요:
🏁 Script executed:
#!/bin/bash
# Description: Check for new public/private event info API paths and their usage
# Search for new API path definitions
rg -n "EVENT\.(PUBLIC_INFO|PRIVATE_INFO)" --type=ts
# Search for services using these new endpoints
rg -n "(getPublicEventInfo|getPrivateEventInfo)" --type=ts -A 3Length of output: 1516
Wait, I need to actually check the repository. Let me correct that:
Let me also search for where eventResult mock data is defined:
🏁 Script executed:
#!/bin/bash
# Description: View the full eventHandlers.ts file to see current state
cat apps/web/app/_mocks/handlers/eventHandlers.tsLength of output: 527
🏁 Script executed:
#!/bin/bash
# Description: View the full eventHandlers.ts file to see current state and check for mock handlers
cat apps/web/app/_mocks/handlers/eventHandlers.tsLength of output: 527
🏁 Script executed:
#!/bin/bash
# Description: Find mock data files
fd -t f "event" apps/web/app/_mocks/data/ --type fLength of output: 33
---
🏁 Script executed:
```shell
#!/bin/bash
# Description: View mock data file to see available mock structures
cat apps/web/app/_mocks/data/event.ts
Length of output: 703
API_PATH.EVENT.INFO 핸들러 복구 필요
event import 제거와 핸들러 주석 처리가 불일치합니다. 주석 처리된 핸들러(라인 7-9)의 event 변수가 정의되지 않습니다. 새 서비스 함수들(getPublicEventInfo, getPrivateEventInfo)은 동일한 API_PATH.EVENT.INFO 엔드포인트를 호출하므로, 이 핸들러가 복구되어야 mock 환경에서 작동합니다.
필요한 조치:
- 핸들러 주석 제거 후
eventimport 복구 (라인 2에 추가) - 또는 의도적으로 이 엔드포인트를 mock하지 않으려면, 주석을 완전히 제거하고 주석 처리된 코드를 정리
현재 상태에서는 주석 처리된 라인이 남아 있어 혼동의 여지가 있습니다.
🤖 Prompt for AI Agents
In apps/web/app/_mocks/handlers/eventHandlers.ts around line 2, the file removed
the `event` import but left the API_PATH.EVENT.INFO handler commented out (lines
~7-9) causing an undefined `event` reference and inconsistent mock behavior;
restore the `event` import at line 2 and uncomment the API_PATH.EVENT.INFO
handler so it uses the new service functions
(getPublicEventInfo/getPrivateEventInfo) against the same endpoint, or if you
intend to not mock this endpoint remove the commented handler entirely to avoid
confusion — do one or the other and keep the file consistent.
| { | ||
| protocol: 'https', | ||
| hostname: 'example.com', | ||
| pathname: '/**', | ||
| }, |
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.
🧩 Analysis chain
프로덕션 환경에서 작동하지 않을 가능성이 높은 도메인입니다.
example.com은 RFC 2606에서 정의한 문서화 및 예제용 예약 도메인입니다. 실제 상품 이미지가 이 도메인에서 호스팅되지 않으므로, 프로덕션 환경에서 이미지 로딩이 실패할 것입니다.
실제 이미지가 호스팅되는 도메인(예: CDN, 클라우드 스토리지)으로 교체해야 합니다.
다음 스크립트를 실행하여 코드베이스에서 example.com이 다른 곳에서도 사용되는지 확인하세요:
🏁 Script executed:
#!/bin/bash
# Description: example.com 도메인 사용처 확인
# example.com 참조 검색
rg -n "example\.com" --type ts --type tsx -C 3Length of output: 27
🏁 Script executed:
#!/bin/bash
# Description: example.com 도메인 사용처 확인 (수정된 버전)
# 전체 저장소에서 example.com 검색 (파일 타입 제한 없이)
rg -n "example\.com" -C 3Length of output: 306
🏁 Script executed:
#!/bin/bash
# Description: next.config.ts 파일 전체 내용 확인
# next.config.ts 파일 확인
cat apps/web/next.config.tsLength of output: 785
🏁 Script executed:
#!/bin/bash
# Description: remotePatterns 섹션 주변 코드 확인
# remotePatterns 관련 코드 검색
rg -n "remotePatterns" apps/web/next.config.ts -A 20 -B 5Length of output: 589
example.com은 실제 프로덕션 도메인이 아니며 교체가 필요합니다.
코드베이스 전체 검색 결과, example.com은 apps/web/next.config.ts 줄 35에서만 나타납니다. 다른 설정된 도메인들(pstatic.net, daumcdn.net, blog.kakaocdn.net)은 실제 한국 CDN 제공자들인 반면, example.com은 RFC 2606에서 정의한 예제용 예약 도메인으로 프로덕션 환경에서 작동하지 않습니다.
실제 상품 이미지가 호스팅되는 CDN 또는 클라우드 스토리지 도메인으로 교체하세요.
🤖 Prompt for AI Agents
In apps/web/next.config.ts around lines 33 to 37, the remotePatterns entry uses
the placeholder domain "example.com" which is not a real production CDN; replace
it with your actual CDN or cloud storage hostname (e.g., mycdn.example.net) or
reference an environment variable so the real domain can be injected
per-deployment (e.g., process.env.ASSET_HOST) and keep the protocol/ path
pattern intact (protocol: 'https', hostname: <real-host-or-env>, pathname:
'/**'); ensure the chosen hostname is added consistently to any other
image/asset configuration and deploy-time envs/secrets so production can resolve
assets.
#️⃣연관된 이슈
📝작업 내용
서버에서 인증 안 된 사용자와 인증된 사용자에 따른 이벤트 정보 조회 api 응답 분기처리
getPublicEventInfo,getPrivateEventInfo으로 따로 함수를 분리=> 상태 업데이트 방식 변경
스크린샷 (선택)
💬리뷰 요구사항(선택)
Summary by CodeRabbit
릴리스 노트
성능 개선
새로운 기능
개선사항