Skip to content

[feature] 홍보 상세페이지에 행사 위치 지도를 추가한다#1621

Merged
suhyun113 merged 12 commits into
develop-fefrom
feature/#1620-promotion-detail-map-MOA-922
Jun 2, 2026
Merged

[feature] 홍보 상세페이지에 행사 위치 지도를 추가한다#1621
suhyun113 merged 12 commits into
develop-fefrom
feature/#1620-promotion-detail-map-MOA-922

Conversation

@suhyun113
Copy link
Copy Markdown
Collaborator

@suhyun113 suhyun113 commented Jun 1, 2026

#️⃣연관된 이슈

#1620

📝작업 내용

홍보 상세페이지에 행사 위치 지도를 추가합니다.

주요 변경사항

  • PromotionArticle 타입에 latitude?, longitude? 필드
    추가
  • NaverMap props를 ClubLocation 의존성에서 범용 좌표
    인터페이스({ lat: number; lng: number })로 변경
  • PromotionMapSection 컴포넌트 생성 (데스크탑/모바일 공통)
    • 정적 지도 프리뷰 + location 텍스트 표시
    • 클릭 시 모달 (데스크탑: 일반 모달, 모바일: 풀스크린)
    • 위도/경도 없을 시 미렌더링
  • InteractiveMapView, MapModalbubbleText props 추가
    (동아리방 → 행사 위치)
  • location_icon.svgcurrentColor 방식으로 전환하여 색상
    재사용 가능하게 변경
  • 이미지 갤러리 블러 그라데이션 위치 보정

스크린샷

데스크탑

수정 전 수정 후
before-desktop after-desktop

모바일

수정 전 수정 후
before-mobile after-mobile

지도 모달

데스크탑 모바일
desktop modal

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

  • 지도 모달에서 동아리 로고를 useGetClubDetail로 가져오고
    있는데, 로고 하나를 위해 전체 클럽 상세를 조회하는게 괜찮을까요

🫡 참고사항

  • location_icon.svgcurrentColor로 변경하면서 동아리
    상세페이지의 위치 아이콘도 img → SVG 컴포넌트로
    전환되었습니다
  • 이미지 갤러리 블러 그라데이션이 overflow: hidden 컨테이너
    내에서 bottom: 0이 보이는 영역 하단과 안 맞는 이슈가 있어
    bottom: -20px로 보정했습니다

Summary by CodeRabbit

  • New Features

    • 프로모션 상세에 인터랙티브 지도 섹션이 추가되어 지도 보기 및 모달 열기가 가능합니다
    • 프로모션에 위치 좌표(위도/경도)를 저장할 수 있습니다
  • Improvements

    • 지도 버블(툴팁) 텍스트를 동적으로 설정할 수 있어 표시 문구를 변경할 수 있습니다
    • 위치 아이콘 렌더링이 SVG 컴포넌트로 변경되어 시각 일관성 및 품질이 향상되었습니다
    • 지도 카드 및 관련 레이아웃의 반응형 스타일이 조정되었습니다
  • Chores

    • 클럽 상세 조회 호출에 캐시/활성화 등 옵션 제어가 추가되었습니다

@suhyun113 suhyun113 self-assigned this Jun 1, 2026
@suhyun113 suhyun113 added ✨ Feature 기능 개발 💻 FE Frontend labels Jun 1, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
moadong Ready Ready Preview, Comment Jun 2, 2026 2:16am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b9112a4c-440a-4ae1-b544-231396c6bf10

📥 Commits

Reviewing files that changed from the base of the PR and between 6a4df3d and 6f2c925.

📒 Files selected for processing (2)
  • frontend/src/hooks/Queries/useClub.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/hooks/Queries/useClub.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx

Walkthrough

프로모션 상세에 지도 섹션을 추가하고, 지도 버블 텍스트를 props로 전달 가능하게 확장했으며 SVG 위치 아이콘을 React 컴포넌트로 통일하고 관련 스타일과 타입·훅 시그니처를 조정했습니다.

프로모션 지도 및 아이콘 통합

Layer / File(s) Summary
지도 버블 텍스트 설정 가능화
frontend/src/components/map/InteractiveMapView/InteractiveMapView.tsx, frontend/src/components/map/MapModal/MapModal.tsx, frontend/src/components/map/NaverMap/NaverMap.tsx
InteractiveMapViewPropsMapModalPropsbubbleText?: string을 추가하고 useNaverMap 호출 시 전달하도록 변경. NaverMap의 location 타입을 { lat: number; lng: number }로 단순화.
위치 아이콘 SVG에서 React 컴포넌트로 마이그레이션
frontend/src/components/map/MapClubInfoCard/*, frontend/src/pages/ClubDetailPage/*, frontend/src/pages/ClubDetailPage/components/ClubProfileCard/*
SVG를 ?react로 임포트해 <LocationIcon />로 렌더링하도록 변경하고, 관련 스타일에서 img 셀렉터를 svg로 전환해 크기/여백/색상을 조정. ClubDetailPage의 MapCardbutton으로 변경.
PromotionMapSection 컴포넌트 및 타입 확장
frontend/src/types/promotion.ts, frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/*, frontend/src/pages/PromotionPage/PromotionDetailPage.tsx
PromotionArticle에 선택적 latitude/longitude 추가. PromotionMapSection을 구현해 좌표 존재 시 NaverMap을 렌더링하고 모달로 클럽 로고를 전달하며, 모달 열림 상태에 따라 useGetClubDetail를 조건 실행.
프로모션 페이지 레이아웃 및 스타일 조정
frontend/src/pages/PromotionPage/components/detail/*, frontend/src/pages/PromotionPage/components/list/*
CTA 패딩/마진, 이미지 갤러리 그라데이션 오프셋, 반응형 조건, 정보 섹션 패딩, CardMeta 아이콘 색상 등 스타일 값을 조정.
useGetClubDetail 훅 시그니처 확장
frontend/src/hooks/Queries/useClub.ts
useGetClubDetail(clubParam, options?) 시그니처로 확장하여 enabled, staleTime, gcTime을 외부에서 제어 가능하도록 변경.

Sequence Diagram (PromotionMapSection 흐름):

sequenceDiagram
  participant PromotionDetailPage
  participant PromotionMapSection
  participant NaverMap
  participant useGetClubDetail
  participant MapModal

  PromotionDetailPage->>PromotionMapSection: article (latitude/longitude, location)
  PromotionMapSection->>NaverMap: render({ lat, lng })
  PromotionMapSection->>useGetClubDetail: fetch(clubId) [enabled when modal open]
  useGetClubDetail-->>PromotionMapSection: clubDetail.logo
  PromotionMapSection->>MapModal: openModal(clubLogo, location)
  MapModal->>NaverMap: showInteractiveMap(bubbleText)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • Moadong/moadong#1260: useGetClubDetail 관련 시그니처·동작 변경과 연관됩니다.
  • Moadong/moadong#1402: InteractiveMapView/MapModal의 bubbleText 전달 경로와 코드 레벨로 연관됩니다.
  • Moadong/moadong#1483: PromotionArticle의 latitude/longitude 필드 추가 및 데이터 연계 관련 변경과 직접 연관됩니다.

Suggested reviewers

  • oesnuj
  • seongwon030
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 주요 변경 사항을 명확하게 설명하고 있습니다. 홍보 상세페이지에 행사 위치 지도 추가라는 핵심 기능 변경을 직관적으로 전달합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#1620-promotion-detail-map-MOA-922

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a map section (PromotionMapSection) to the promotion detail page to display event locations, makes the map bubble text customizable, and refactors the location icon into a React component across multiple files for better styling flexibility. Feedback on these changes suggests optimizing the useGetClubDetail query in the new map section by using the enabled option so that the API call is only triggered when the map modal is actually open, preventing unnecessary network requests.

Comment on lines +15 to +16
const [isMapModalOpen, setIsMapModalOpen] = useState(false);
const { data: clubDetail } = useGetClubDetail(`@${article.clubName}`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

PR 본문에서 언급해주신 것처럼, 동아리 로고 하나를 가져오기 위해 페이지가 로드될 때마다 항상 전체 동아리 상세 정보를 조회하는 것은 비효율적일 수 있습니다. 특히 위도/경도 정보가 없어 지도가 렌더링되지 않는 상황(return null)에서도 불필요하게 API 요청이 발생하게 됩니다.\n\n이를 개선하기 위해 useGetClubDetail 훅에 enabled 옵션을 추가(또는 이미 지원하는 경우 활용)하여, 모달이 실제로 열렸을 때만(isMapModalOpen) 데이터를 조회하도록 제한하는 것을 추천합니다. 이렇게 하면 불필요한 초기 API 호출을 방지하고 성능을 개선할 수 있습니다.

  const [isMapModalOpen, setIsMapModalOpen] = useState(false);
  const { data: clubDetail } = useGetClubDetail(`@${article.clubName}`, {
    enabled: isMapModalOpen,
  });

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

백엔드에 필드를 늘리도록 요청하는것도 고민했는데, 좋은 것 같습니다! 수정했습니다. 0ea2663

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

✅ UI 변경사항 없음

구분 링크
📖 Storybook https://67904e61c16daa99a63b44a7-kpsdcwfedd.chromatic.com/

전체 57개 스토리 · 22개 컴포넌트

Copy link
Copy Markdown
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 (3)
frontend/src/pages/PromotionPage/components/detail/PromotionClubCTA/PromotionClubCTA.styles.ts (1)

10-10: ⚡ Quick win

패딩 단축 표기 사용을 권장합니다.

padding: 24px 20px 24px 20px는 상하 값이 동일하므로 padding: 24px 20px로 단축할 수 있습니다.

♻️ 제안하는 수정
-    padding: 24px 20px 24px 20px;
+    padding: 24px 20px;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/pages/PromotionPage/components/detail/PromotionClubCTA/PromotionClubCTA.styles.ts`
at line 10, The padding declaration in PromotionClubCTA.styles.ts uses a
redundant four-value form; update the padding on the PromotionClubCTA style rule
from "24px 20px 24px 20px" to the shortened equivalent "24px 20px" so top/bottom
and left/right are preserved but the rule is simplified.
frontend/src/pages/PromotionPage/components/detail/PromotionInfoSection/PromotionInfoSection.styles.ts (1)

9-9: ⚡ Quick win

패딩 단축 표기 사용을 권장합니다.

padding: 24px 20px 0px 20px는 좌우 값이 동일하므로 padding: 24px 20px 0px로 단축할 수 있습니다.

♻️ 제안하는 수정
-    padding: 24px 20px 0px 20px;
+    padding: 24px 20px 0px;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/pages/PromotionPage/components/detail/PromotionInfoSection/PromotionInfoSection.styles.ts`
at line 9, In PromotionInfoSection.styles.ts update the padding declaration:
replace the four-value form that repeats left/right with the three-value
shorthand (top, horizontal, bottom) so the rule becomes equivalent but more
concise; locate the padding line inside the PromotionInfoSection styles and
apply the shorthand.
frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx (1)

16-16: ⚡ Quick win

모달 오픈 시점에 맞춰 클럽 상세 조회를 지연해 주세요.

현재 Line 16에서 상세 조회가 항상 실행되어, 모달을 열지 않아도 로고 조회 비용이 발생합니다. isMapModalOpen(또는 좌표 존재 + 오픈 상태) 기준으로 쿼리를 조건부 실행하는 쪽이 더 안전합니다.

제안 diff
-  const { data: clubDetail } = useGetClubDetail(`@${article.clubName}`);
+  const { data: clubDetail } = useGetClubDetail(`@${article.clubName}`, {
+    enabled: isMapModalOpen,
+  });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx`
at line 16, The club detail query is always fired because useGetClubDetail is
called unconditionally; update the call to only run when the map modal is open
(or when coordinates exist + modal open). Modify the useGetClubDetail invocation
(the call that currently uses `@${article.clubName}` and returns `clubDetail`)
to be conditional—either pass a null/empty key when `isMapModalOpen` (and
optionally `article.lat`/`article.lng`) is false, or use the hook's options
(e.g., an enabled flag) so the query only executes when `isMapModalOpen` is true
and the article.clubName is present.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx`:
- Around line 1-54: Prettier reported formatting mismatches in
PromotionMapSection.tsx; run Prettier --write on this file (or your project) and
reformat the code around the PromotionMapSection component (including imports,
the location object, JSX return block, and MapModal props) so it matches the
repo's Prettier settings, then stage and commit the formatted file; ensure no
semantic changes to functions/components (PromotionMapSection, NaverMap,
MapModal) while applying only whitespace/format fixes.
- Around line 33-35: The clickable map wrapper Styled.MapCard currently opens
the modal via onClick only, blocking keyboard users; update the component so it
is keyboard-accessible by either replacing Styled.MapCard with a semantic
<button> or adding accessibility attributes and handlers: give Styled.MapCard
role="button", tabIndex={0}, aria-haspopup="dialog" (or aria-label if needed),
and implement an onKeyDown handler that listens for Enter and Space and calls
setIsMapModalOpen(true) (same action as the onClick that opens NaverMap modal);
ensure focus styles remain visible and that NaverMap remains a child of the
interactive element.

In `@frontend/src/pages/PromotionPage/PromotionDetailPage.tsx`:
- Line 12: Change the relative import for PromotionMapSection to use the project
path alias: replace the current
"./components/detail/PromotionMapSection/PromotionMapSection" import in
PromotionDetailPage.tsx with the alias-based path starting with "`@/`": import
PromotionMapSection from
'`@/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection`';
ensure you update only the import statement referencing the PromotionMapSection
symbol so it resolves via the configured src/* alias.

---

Nitpick comments:
In
`@frontend/src/pages/PromotionPage/components/detail/PromotionClubCTA/PromotionClubCTA.styles.ts`:
- Line 10: The padding declaration in PromotionClubCTA.styles.ts uses a
redundant four-value form; update the padding on the PromotionClubCTA style rule
from "24px 20px 24px 20px" to the shortened equivalent "24px 20px" so top/bottom
and left/right are preserved but the rule is simplified.

In
`@frontend/src/pages/PromotionPage/components/detail/PromotionInfoSection/PromotionInfoSection.styles.ts`:
- Line 9: In PromotionInfoSection.styles.ts update the padding declaration:
replace the four-value form that repeats left/right with the three-value
shorthand (top, horizontal, bottom) so the rule becomes equivalent but more
concise; locate the padding line inside the PromotionInfoSection styles and
apply the shorthand.

In
`@frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx`:
- Line 16: The club detail query is always fired because useGetClubDetail is
called unconditionally; update the call to only run when the map modal is open
(or when coordinates exist + modal open). Modify the useGetClubDetail invocation
(the call that currently uses `@${article.clubName}` and returns `clubDetail`)
to be conditional—either pass a null/empty key when `isMapModalOpen` (and
optionally `article.lat`/`article.lng`) is false, or use the hook's options
(e.g., an enabled flag) so the query only executes when `isMapModalOpen` is true
and the article.clubName is present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ba51bbbe-26c9-4904-8780-e79cd7f833a8

📥 Commits

Reviewing files that changed from the base of the PR and between b7439f5 and ea954e2.

⛔ Files ignored due to path filters (1)
  • frontend/src/assets/images/icons/location_icon.svg is excluded by !**/*.svg
📒 Files selected for processing (17)
  • frontend/src/components/map/InteractiveMapView/InteractiveMapView.tsx
  • frontend/src/components/map/MapClubInfoCard/MapClubInfoCard.styles.ts
  • frontend/src/components/map/MapClubInfoCard/MapClubInfoCard.tsx
  • frontend/src/components/map/MapModal/MapModal.tsx
  • frontend/src/components/map/NaverMap/NaverMap.tsx
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx
  • frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.styles.ts
  • frontend/src/pages/ClubDetailPage/components/ClubProfileCard/ClubProfileCard.tsx
  • frontend/src/pages/PromotionPage/PromotionDetailPage.tsx
  • frontend/src/pages/PromotionPage/components/detail/PromotionClubCTA/PromotionClubCTA.styles.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionImageGallery/PromotionImageGallery.styles.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionInfoSection/PromotionInfoSection.styles.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.styles.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx
  • frontend/src/pages/PromotionPage/components/list/PromotionCard/CardMeta/CardMeta.styles.ts
  • frontend/src/types/promotion.ts

import PromotionDetailTopBar from './components/detail/PromotionDetailTopBar/PromotionDetailTopBar';
import PromotionImageGallery from './components/detail/PromotionImageGallery/PromotionImageGallery';
import PromotionInfoSection from './components/detail/PromotionInfoSection/PromotionInfoSection';
import PromotionMapSection from './components/detail/PromotionMapSection/PromotionMapSection';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

새로 추가한 import는 @/* 경로 별칭으로 통일해 주세요.

상대 경로 대신 별칭을 쓰면 리팩터링/이동 시 안정성이 좋아집니다.

제안 diff
-import PromotionMapSection from './components/detail/PromotionMapSection/PromotionMapSection';
+import PromotionMapSection from '`@/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection`';

As per coding guidelines, Use path alias @/* mapped to src/* for imports.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import PromotionMapSection from './components/detail/PromotionMapSection/PromotionMapSection';
import PromotionMapSection from '`@/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection`';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/PromotionPage/PromotionDetailPage.tsx` at line 12, Change
the relative import for PromotionMapSection to use the project path alias:
replace the current
"./components/detail/PromotionMapSection/PromotionMapSection" import in
PromotionDetailPage.tsx with the alias-based path starting with "`@/`": import
PromotionMapSection from
'`@/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection`';
ensure you update only the import statement referencing the PromotionMapSection
symbol so it resolves via the configured src/* alias.

Copy link
Copy Markdown
Member

@seongwon030 seongwon030 left a comment

Choose a reason for hiding this comment

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

api는 호출 횟수가 중요하지, api에 있는 모든 필드를 무조건 사용하지 않아도 됩니다!
clubDetail 을 가져올 때 레이턴시가 길어질만한 요소가 있는지, 얼마나 걸리는지 한 번 측정해보면 좋을 것 같습니다.
로고는 잘 바뀌지 않으니 응답을 긴 시간 캐싱하면 큰 문제는 없어보이긴 하네요.

그리고 api 호출 횟수가 중요한 이유는 한 번 고민해보셨으면 좋겠네요

@suhyun113
Copy link
Copy Markdown
Collaborator Author

api는 호출 횟수가 중요하지, api에 있는 모든 필드를 무조건 사용하지 않아도 됩니다! clubDetail 을 가져올 때 레이턴시가 길어질만한 요소가 있는지, 얼마나 걸리는지 한 번 측정해보면 좋을 것 같습니다. 로고는 잘 바뀌지 않으니 응답을 긴 시간 캐싱하면 큰 문제는 없어보이긴 하네요.

그리고 api 호출 횟수가 중요한 이유는 한 번 고민해보셨으면 좋겠네요

답변 감사합니다 api에 있는 모든 필드를 사용하지 않아도 되는건 알고있었지만, 하나의 필드 사용을 위해 api를 호출하는건 비효율적인가라는 고민이 있었습니다. 필드를 하나만 쓰더라도 api 호출 자체가 한 번이면 비효율은 아니라는거군요. 이해했습니다!

API 호출 횟수가 중요한 이유는 역시 서버 입장에서 요청마다 비용이 발생하기 때문이 아닐까요. 동시 사용자가 많아지면 그 비용이 배로 늘어나기 때문이라고 생각합니다.

모달을 열지 않았을때 API를 호출하는 것을 방지하는 것으로 이 문제를 조금 완화할 수 있다고 생각했는데, API 호출 횟수를 고려했을때 모달을 다시 열 때 또 API를 호출하는 것을 방지하는 것이 효과적이겠네요

@suhyun113 suhyun113 closed this Jun 1, 2026
로고만 사용하므로 긴 staleTime 적용, 기존 호출부는 1분 유지
@suhyun113
Copy link
Copy Markdown
Collaborator Author

React Query의 기본 gcTime이 있어서 모달을 닫았다 5분 안에 열면 캐시된 데이터를 쓰네요. 로고는 거의 안 바뀌니까 말해주신 것처럼 staleTime을 길게 잡으면 될 것 같습니다. api 문서 참고하여 거의 변하지 않는 정적 데이터이니 1시간으로 수정했습니다. 6a4df3d

@suhyun113 suhyun113 reopened this Jun 1, 2026
Copy link
Copy Markdown
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 (1)
frontend/src/hooks/Queries/useClub.ts (1)

37-38: ⚡ Quick win

enabled 조건 순서를 같은 파일의 다른 훅과 일관되게 맞추는 것을 고려하세요.

Line 58의 useGetClubCalendarEvents(options?.enabled ?? true) && !!clubParam 순서를 사용하지만, 여기서는 !!clubParam && (options?.enabled ?? true) 순서를 사용합니다. 논리적으로는 동일하지만 같은 파일 내에서 패턴을 일관되게 유지하면 가독성이 향상됩니다.

참고: !!clubParam을 먼저 체크하는 현재 방식이 미세하게 더 효율적이므로, 오히려 Line 58을 이 패턴으로 통일하는 것도 방법입니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/hooks/Queries/useClub.ts` around lines 37 - 38, The enabled
condition ordering is inconsistent across hooks in this file: change the enabled
expression in useClub (currently "!!clubParam && (options?.enabled ?? true)") to
match the other hook pattern "(options?.enabled ?? true) && !!clubParam" (or
vice versa—pick the pattern you want to standardize on), so update the enabled
boolean in useClub.ts (the query options where staleTime and enabled are set) to
use the same operand order as useGetClubCalendarEvents to keep the file
consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts`:
- Around line 59-61: MapCard (the styled.button defined in
ClubDetailPage.styles.ts) lacks a visible keyboard focus state; add a
:focus-visible (and :focus fallback) rule to the MapCard styled component to
provide a clear visual indicator (e.g., outline or box-shadow with accessible
contrast) when focused via keyboard, ensuring you do not alter existing
padding/font and that the focus style is applied consistently for keyboard
navigation.

---

Nitpick comments:
In `@frontend/src/hooks/Queries/useClub.ts`:
- Around line 37-38: The enabled condition ordering is inconsistent across hooks
in this file: change the enabled expression in useClub (currently "!!clubParam
&& (options?.enabled ?? true)") to match the other hook pattern
"(options?.enabled ?? true) && !!clubParam" (or vice versa—pick the pattern you
want to standardize on), so update the enabled boolean in useClub.ts (the query
options where staleTime and enabled are set) to use the same operand order as
useGetClubCalendarEvents to keep the file consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ee8bbf84-1663-4ea8-81f3-8d9b8f31d378

📥 Commits

Reviewing files that changed from the base of the PR and between ea954e2 and 6a4df3d.

📒 Files selected for processing (4)
  • frontend/src/hooks/Queries/useClub.ts
  • frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.styles.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.styles.ts
  • frontend/src/pages/PromotionPage/components/detail/PromotionMapSection/PromotionMapSection.tsx

Comment on lines +59 to +61
export const MapCard = styled.button`
padding: 0;
font: inherit;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if global focus styles exist

# Search for global focus styles in theme or global styles
rg -n --type ts --type tsx -C 2 'focus-visible|:focus(?!-)' -g 'frontend/src/styles/**/*' -g 'frontend/src/**/global*'

Repository: Moadong/moadong

Length of output: 308


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect MapCard styles around the reported lines
FILE="frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts"
if [ -f "$FILE" ]; then
  echo "== $FILE (lines 40-120) =="
  nl -ba "$FILE" | sed -n '40,120p'
else
  echo "File not found: $FILE" >&2
fi

# 2) Search for global focus styles (use --pcre2 to support look-arounds)
echo
echo "== Search: global focus indicators =="
rg -n --pcre2 \
  '(:focus-visible\b|:focus(-visible)?\b)' \
  -S -g 'frontend/src/styles/**/*' -g 'frontend/src/**/global*' -g 'frontend/src/**/*.{css,scss,ts,tsx}' \
  frontend/src >/tmp/focus_hits.txt || true

head -n 200 /tmp/focus_hits.txt || true

echo
echo "== Search: focus-ring utilities / outline in styles =="
rg -n \
  '(focus-ring|ring-|outline:|box-shadow:.*(focus|ring))' \
  -S -g 'frontend/src/styles/**/*' -g 'frontend/src/**/*.{css,scss,ts,tsx}' \
  frontend/src >/tmp/outline_hits.txt || true

head -n 200 /tmp/outline_hits.txt || true

Repository: Moadong/moadong

Length of output: 200


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts"
if [ -f "$FILE" ]; then
  echo "== $FILE (around MapCard) =="
  # show around lines 50-110 even if line counts differ slightly
  cat -n "$FILE" | sed -n '45,110p'
else
  echo "File not found: $FILE" >&2
fi

echo
echo "== Search: :focus-visible / :focus in global styles =="
# Search common focus selectors in styles & global-like files
rg -n -S \
  '(:focus-visible\b|:focus\b)' \
  -g 'frontend/src/styles/**/*' \
  -g 'frontend/src/**/global*' \
  -g 'frontend/src/**/*.{css,scss,ts,tsx}' \
  frontend/src >/tmp/focus_selector_hits.txt || true

head -n 200 /tmp/focus_selector_hits.txt || true

echo
echo "== Search: focus-ring / outline / box-shadow in global-ish styles =="
rg -n -S \
  '(focus-ring|ring-|outline:|outline-offset|box-shadow:.*(focus|ring))' \
  -g 'frontend/src/styles/**/*' \
  -g 'frontend/src/**/*.{css,scss}' \
  -g 'frontend/src/**/global*' \
  frontend/src >/tmp/outline_hits.txt || true

head -n 200 /tmp/outline_hits.txt || true

Repository: Moadong/moadong

Length of output: 3230


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts"
echo "== $FILE (head/imports) =="
# show first 120 lines (should be safe)
cat -n "$FILE" | sed -n '1,120p'

echo
echo "== Search within file for colors.primary usage =="
rg -n 'colors\.primary' "$FILE" || true

echo
echo "== Search within file for focus styles =="
rg -n 'focus-visible|&:\s*focus\b|:focus\b' "$FILE" || true

Repository: Moadong/moadong

Length of output: 3080


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the colors theme file referenced in MapCard styles
ls -la frontend/src/styles/theme/colors.* 2>/dev/null || true

# Search for primary token usage/definition
rg -n 'primary' frontend/src/styles/theme/colors* frontend/src/styles/theme -S || true

# Print the colors export file header/body near where primary is defined (if found)
for f in $(fd -e ts -e tsx -a "colors" frontend/src/styles/theme 2>/dev/null || true); do
  echo "== $f (top 200 lines) =="
  head -n 200 "$f"
  echo
done

Repository: Moadong/moadong

Length of output: 1820


MapCard에 키보드 포커스(:focus-visible) 스타일이 누락되었습니다.
frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.tsMapCardstyled.button으로 바뀌었지만 :focus-visible(또는 :focus)이 없어 키보드 네비게이션 시 포커스가 시각적으로 확인되지 않습니다.

♿ 포커스 상태 추가 제안
 export const MapCard = styled.button`
   padding: 0;
   font: inherit;
   width: 100%;
   height: 189px;
 
   border-radius: 20px;
   border: 1px solid ${colors.gray[400]};
   overflow: hidden;
   cursor: pointer;
 
   background-color: `#f2f2f2`;
+
+  &:focus-visible {
+    outline: 2px solid ${colors.primary[500]};
+    outline-offset: 2px;
+  }
 
   * {
     cursor: pointer !important;
   }
 `;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const MapCard = styled.button`
padding: 0;
font: inherit;
export const MapCard = styled.button`
padding: 0;
font: inherit;
width: 100%;
height: 189px;
border-radius: 20px;
border: 1px solid ${colors.gray[400]};
overflow: hidden;
cursor: pointer;
background-color: `#f2f2f2`;
&:focus-visible {
outline: 2px solid ${colors.primary[500]};
outline-offset: 2px;
}
* {
cursor: pointer !important;
}
`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/ClubDetailPage/ClubDetailPage.styles.ts` around lines 59 -
61, MapCard (the styled.button defined in ClubDetailPage.styles.ts) lacks a
visible keyboard focus state; add a :focus-visible (and :focus fallback) rule to
the MapCard styled component to provide a clear visual indicator (e.g., outline
or box-shadow with accessible contrast) when focused via keyboard, ensuring you
do not alter existing padding/font and that the focus style is applied
consistently for keyboard navigation.

@seongwon030
Copy link
Copy Markdown
Member

React Query의 기본 gcTime이 있어서 모달을 닫았다 5분 안에 열면 캐시된 데이터를 쓰네요. 로고는 거의 안 바뀌니까 말해주신 것처럼 staleTime을 길게 잡으면 될 것 같습니다. api 문서 참고하여 거의 변하지 않는 정적 데이터이니 1시간으로 수정했습니다. 6a4df3d

모달을 닫았다 5분 안에 열면 캐시된 데이터를 쓰는 것은 staleTime으로 인한 것 아닌가요?

gcTime은 해당 쿼리를 구독 중인 옵저버가 없어진 순간부터 타이머가 돈다고 하네요!
그리고 보통 staleTime <= gcTime 으로 설정한다고 합니다. 이건 데이터가 아직 fresh한데도 gcTime이 다 되어서
불필요한 네트워크 요청이 늘어날 수 있다는 점에서 이해할 수 있을 것 같아요.

그렇다면 gcTime 도 1시간정도로 설정하면 어떨까요?

모달 닫힘 시 옵저버가 사라져 gcTime 타이머가 시작되므로,
기본 gcTime(5분)이 staleTime(1시간)보다 먼저 만료되어 캐시가 삭제되는 문제 방지
@suhyun113
Copy link
Copy Markdown
Collaborator Author

React Query의 기본 gcTime이 있어서 모달을 닫았다 5분 안에 열면 캐시된 데이터를 쓰네요. 로고는 거의 안 바뀌니까 말해주신 것처럼 staleTime을 길게 잡으면 될 것 같습니다. api 문서 참고하여 거의 변하지 않는 정적 데이터이니 1시간으로 수정했습니다. 6a4df3d

모달을 닫았다 5분 안에 열면 캐시된 데이터를 쓰는 것은 staleTime으로 인한 것 아닌가요?

gcTime은 해당 쿼리를 구독 중인 옵저버가 없어진 순간부터 타이머가 돈다고 하네요! 그리고 보통 staleTime <= gcTime 으로 설정한다고 합니다. 이건 데이터가 아직 fresh한데도 gcTime이 다 되어서 불필요한 네트워크 요청이 늘어날 수 있다는 점에서 이해할 수 있을 것 같아요.

그렇다면 gcTime 도 1시간정도로 설정하면 어떨까요?

staleTime을 1시간으로 늘려도 모달을 닫으면 옵저버가 사라져 gcTime이 시작되는데 여전히 5분이기 때문에 캐시가 삭제되어 의미가 없겠네요. gcTime도 1시간으로 늘리겠습니다! 6f2c925

@suhyun113 suhyun113 merged commit 059e772 into develop-fe Jun 2, 2026
7 checks passed
@suhyun113 suhyun113 deleted the feature/#1620-promotion-detail-map-MOA-922 branch June 2, 2026 02:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend ✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants