Skip to content

[Feature/#97] 모임방 조회 관련 api 연동#131

Merged
holdn2 merged 9 commits into
mainfrom
feature/#97/room-query-api-integration
Jul 15, 2026
Merged

[Feature/#97] 모임방 조회 관련 api 연동#131
holdn2 merged 9 commits into
mainfrom
feature/#97/room-query-api-integration

Conversation

@holdn2

@holdn2 holdn2 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

📌 Related Issues

📄 Tasks

모임방 조회 API 구성

  • 모임방 검색 API 연동
  • 홈 모집 중인 모임방 조회 API 연동
  • 나의 모임방 목록 조회 API 연동
  • 홈 참여 중인 모임방 조회 API 연동
  • 조회 조건별 Query Key와 API 요청/응답 타입 정의
  • 커서 기반 useInfiniteQuery 페이지네이션 적용

모임방 검색 화면

  • 키워드, 카테고리, 정렬 및 모집 완료 여부를 검색 조건에 반영
  • 검색 결과 무한 스크롤 적용
  • 초기 로딩, 다음 페이지 로딩 및 빈 결과 상태 처리
  • 검색 완료 후 최근 검색어 쿼리 갱신
  • 기존 더미 데이터 및 화면 내부 타입 제거

홈 모집 중인 모임방 캐러셀

  • 마감 임박, 인기, 최근 생성된 모임방 데이터를 API와 연동
  • 카테고리 변경에 따른 데이터 재조회
  • 로딩, 오류 및 빈 데이터 상태 처리
  • 화면 너비에 따른 리스트/그리드 레이아웃 대응
  • 모임방 카드 선택 시 참여 화면으로 이동

나의 모임방 목록

  • 참여 중·모집 중·진행 중·만료된 모임방 필터 연동
  • 모임방 목록 무한 스크롤 적용
  • Pull-to-refresh 및 다음 페이지 로딩 처리
  • 초기 로딩, 오류 및 빈 목록 상태 처리
  • 모임방 상태에 따라 참여 화면 또는 상세 화면으로 이동

홈 참여 중인 모임방 캐러셀

  • 참여 중인 모임방 조회 API 연동
  • 초기 로딩, 오류, 빈 데이터 및 단일 카드 상태 처리
  • 캐러셀 순환 동작 유지
  • 마지막 카드까지 2장이 남았을 때 다음 페이지를 미리 조회하도록 적용

기타

  • 공용 MyGroupCard를 API 응답 타입에 맞게 변경
  • 모임방 API 타입과 화면 타입 통합
  • 사용하지 않는 더미 상수 및 타입 파일 제거
  • 모집 중인 모임방 관련 네이밍 정리

TODO

  • 모임방 command 관련 api 연동 후 다른 조회 api 연동
  • 홈 참여 중인 내 모임방 조회 api 는 여러 모임방 참여 이후 테스트 필요

Summary by CodeRabbit

  • 새로운 기능
    • 내 모임/만료된 모임을 실제 데이터로 조회하고, 무한 스크롤 페이지네이션을 지원합니다.
    • 목록 새로고침 및 하단 로딩 표시를 제공합니다.
    • 모집 중인 모임을 카테고리별로 조회합니다.
  • 개선 사항
    • 검색 및 모임 카테고리 처리 기준을 API 응답 기준으로 정리했습니다.
    • 데이터 없음/로딩 실패 시 상태별 안내 문구와 오류 코드를 표시합니다.

@holdn2 holdn2 self-assigned this Jul 15, 2026
@holdn2 holdn2 added the feature Add new features label Jul 15, 2026
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: accacdb1-a1fe-401f-8c59-8f9f5a2e1319

📥 Commits

Reviewing files that changed from the base of the PR and between d4f776b and eacb760.

📒 Files selected for processing (1)
  • screens/my-group-list/my-group-list-screen.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • screens/my-group-list/my-group-list-screen.tsx

📝 Walkthrough

Walkthrough

모임방 조회 엔드포인트와 타입, 쿼리 훅을 추가했습니다. 내 모임방과 만료 모임방 목록은 API 기반 페이지네이션·새로고침·로딩·오류 상태를 사용합니다. 홈 캐러셀은 참여 중인 방과 모집 중인 방 데이터를 서버에서 조회하며, 검색 화면의 카테고리와 방 타입도 API 타입으로 통합했습니다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Poem

더미 방은 살며시 떠나고
커서가 다음 페이지를 열었네
캐러셀은 빙글, 목록은 척척
오류도 상태로 인사하니
모임방 데이터, 이제 API와 함께 춤춘다 ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 모임방 조회 API 연동이라는 핵심 변경을 간결하게 잘 요약합니다.
Description check ✅ Passed 필수 Related Issues와 Tasks는 채워졌고, 템플릿의 비핵심 섹션만 일부 비어 있습니다.
Linked Issues check ✅ Passed 요구된 내 모임방/참여중인 방/모집중 검색/홈 모집·참여중 조회가 모두 API와 화면에 반영되었습니다.
Out of Scope Changes check ✅ Passed 목표와 무관한 변경은 두드러지지 않고, 대부분 조회 API 연동과 타입 정리에 수렴합니다.
✨ 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/#97/room-query-api-integration

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
screens/group/components/my-group-carousel/index.tsx (1)

74-76: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

[P3] 무한 스크롤과 순환(Loop) 캐러셀 옵션 충돌 방지 ⚠️

react-native-reanimated-carousel에서 loop가 활성화되어 있으면 무한 스크롤(onSnapToItem 기반 데이터 페칭)과 충돌할 여지가 있습니다.
사용자가 첫 번째 아이템에서 역방향으로 스와이프해 마지막 아이템으로 넘어갈 경우, 의도치 않게 다음 페이지(fetchNextPage)가 조기 호출되거나 새 데이터 추가 시 인덱스가 꼬이면서 UI 글리치가 발생할 수 있습니다.
데이터를 동적으로 계속 추가해야 하는 뷰라면 loop={false}로 설정하는 것이 UX와 안정성 측면에서 훨씬 튼튼할 것 같습니다! 캐러셀과 API를 멋지게 연결해주신 점 최고입니다. 🚀

🛠️ 루프 비활성화 제안
      ) : (
        <Carousel
-         loop
+         loop={false}
          width={screenWidth}
          height={175}
🤖 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 `@screens/group/components/my-group-carousel/index.tsx` around lines 74 - 76,
Update the Carousel configuration in the group carousel component to disable
looping by setting its loop option to false. Preserve the existing
onSnapToItem-based pagination and dynamic data-loading behavior.
🧹 Nitpick comments (14)
screens/group/components/my-group-carousel/index.tsx (2)

41-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

[P5] 상수 분리를 통한 클린 코드 작성 🧹

무한 스크롤(미리 불러오기) 로직을 onSnapToItem에 깔끔하게 연동해주셨네요! 👍
다만 DEFAULT_PRELOAD_THRESHOLD와 같은 상수는 스와이프할 때마다 함수 내에서 재선언할 필요가 없으므로 컴포넌트 외부로 분리하는 것을 추천합니다. 가독성도 챙기고 사소한 메모리 재할당도 방지할 수 있습니다.

✨ 제안하는 리팩터링 코드
+ const DEFAULT_PRELOAD_THRESHOLD = 2;
+ 
  export default function MyGroupCarousel() {
// ...
  const handleSnapToItem = (index: number) => {
-   const DEFAULT_PRELOAD_THRESHOLD = 2;
    const shouldLoadNextCarouselPage =
      homeMyRoomData.length - 1 - index <= DEFAULT_PRELOAD_THRESHOLD;
    if (shouldLoadNextCarouselPage) handleLoadMore();
  };
🤖 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 `@screens/group/components/my-group-carousel/index.tsx` around lines 41 - 47,
Move the DEFAULT_PRELOAD_THRESHOLD constant out of handleSnapToItem and define
it at module scope, then keep handleSnapToItem using that shared constant for
the preload calculation.

19-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

[P4] 단위 테스트 작성을 통한 TODO 해결 제안 🧪

TODO 주석을 꼼꼼하게 남겨주신 점 훌륭합니다! 잊지 않고 잘 기록해주셔서 든든하네요.
이후 다수의 모임방 데이터가 주어졌을 때 캐러셀 컴포넌트가 올바르게 렌더링되고 제스처(onSnapToItem)가 의도대로 동작하는지 확인하기 위해, React Native Testing Library를 활용한 단위 테스트 추가를 제안합니다. 자동화된 테스트가 있다면 추후 리팩터링 시에도 든든한 방어막이 되어줄 거예요!

원하신다면 테스트 코드 초안을 작성해 드리거나 이슈를 생성해 드릴까요?

🤖 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 `@screens/group/components/my-group-carousel/index.tsx` at line 19, Replace the
TODO near the group carousel component with unit tests using React Native
Testing Library that cover rendering multiple group-room items and verify the
carousel’s onSnapToItem gesture behavior. Remove the TODO once these cases are
automated, reusing the component’s existing test patterns and interaction APIs.
screens/group/components/my-group-carousel/my-group-carousel-empty.tsx (1)

26-34: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

[P3] 에러 발생 시 재시도(Retry) UX 추가 제안 🔄

에러 상태와 정상 상태를 명확하게 분기 처리하신 설계가 돋보입니다! 🎉
다만 현재는 데이터를 불러오지 못했을 때 사용자에게 안내 문구만 보여주고 있습니다. 네트워크 오류 등 일시적인 문제일 수 있으므로, 사용자가 다시 API를 호출할 수 있는 '새로고침' 또는 '다시 시도' 액션(예: 버튼)을 추가하는 것을 추천합니다. 부모 컴포넌트에서 onRetry={refetch} 형태의 prop을 넘겨받도록 확장하면 예외 상황에서도 끊김 없는 사용자 경험을 제공할 수 있을 거예요!

🤖 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 `@screens/group/components/my-group-carousel/my-group-carousel-empty.tsx`
around lines 26 - 34, Extend the error branch in my-group-carousel-empty to
provide a retry action alongside the failure message. Add an onRetry callback
prop to the component, pass the query refetch function from the parent, and
invoke it from a clearly labeled retry button while preserving the existing
errorCode display.
screens/group/components/recruiting-group-carousel/recruiting-group-carousel-item.tsx (2)

101-101: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

[P4] 에러 코드 노출 시 빈 괄호 방지 디테일 ✨

에러 객체가 없지만 !roomList 조건에 의해 에러 분기를 타게 될 경우, homeRecruitingRoomError?.codeundefined로 평가되어 화면에 데이터를 불러오지 못했어요 ()처럼 괄호 안이 비어있게 노출될 수 있습니다.

조건부 렌더링을 활용해 에러 코드가 있을 때만 괄호를 표시하면 더 완성도 높은 UX를 제공할 수 있습니다.

💡 제안하는 코드
-            데이터를 불러오지 못했어요 ({homeRecruitingRoomError?.code})
+            데이터를 불러오지 못했어요{homeRecruitingRoomError?.code ? ` (${homeRecruitingRoomError.code})` : ""}
🤖 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
`@screens/group/components/recruiting-group-carousel/recruiting-group-carousel-item.tsx`
at line 101, Update the error message rendering in the recruiting group carousel
item so the parentheses and homeRecruitingRoomError?.code appear only when an
error code exists; otherwise render only “데이터를 불러오지 못했어요” while preserving the
existing !roomList error branch.

83-139: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

[P3] 상태별 UI 단위 테스트(Unit Test) 작성 제안 🛠️

캐러셀이 서버 데이터를 바라보게 되면서 로딩, 에러, 빈 상태, 정상 목록 등 여러 가지 UI 상태를 가지게 되었습니다. 현재 렌더링 로직이 매우 깔끔하게 잘 분기되어 있습니다! 👍

경로 지침에 따라 테스트 및 확장성을 고려하여, 추후 이 컴포넌트의 리팩터링이나 기능 추가 시 상태별 렌더링이 깨지지 않도록 아래 케이스들에 대한 컴포넌트 단위 테스트(Unit Test) 추가를 권장합니다.

  • isPending일 때 ActivityIndicator 정상 노출 여부
  • isError일 때 에러 문구 렌더링 여부
  • roomList.length === 0일 때 빈 화면 노출 여부
  • roomList에 데이터가 있을 때 RecruitingGroupCard 정상 렌더링 여부
🤖 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
`@screens/group/components/recruiting-group-carousel/recruiting-group-carousel-item.tsx`
around lines 83 - 139, 모임방 목록 상태별 렌더링을 검증하는 컴포넌트 단위 테스트를 추가하세요.
renderRoomListContent를 사용하는 RecruitingGroupCarousel에서 로딩 시 ActivityIndicator, 오류
시 에러 문구, 빈 목록 시 빈 상태 문구, 데이터 존재 시 각 RecruitingGroupCard 렌더링을 확인하고, 각 테스트에서 해당
상태를 명확히 설정하세요.

Source: Path instructions

screens/search-group/components/search-group-result/index.tsx (1)

62-84: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

[P2] 불필요한 최근 검색어 캐시 무효화 방지 (성능 최적화) 🚀

현재 useEffect 로직에 따르면 무한 스크롤로 다음 페이지를 불러올 때(fetchNextPage 호출)도 isFetchingSearchRoom 상태가 갱신되어, 매 스크롤마다 의존성 배열에 의해 이펙트가 실행되고 최근 검색어 목록(RECENT_SEARCH_QUERY_KEY.LIST)을 불필요하게 무효화(invalidate)하는 사이드 이펙트가 발생합니다.

불필요한 API 재호출을 방지하기 위해 useRef를 사용하여 이전에 무효화 처리한 검색어인지 추적하고, 순수하게 새로운 검색이 완료되었을 때만 무효화를 수행하도록 개선하는 것을 제안합니다. (렌더링을 유발하지 않도록 useState 대신 useRef를 사용하는 것이 좋습니다.)

💡 캐시 무효화 최적화 예시
+  const lastInvalidatedKeyword = useRef("");
+
   useEffect(() => {
     const normalizedSearchText = searchText.trim();
 
     if (
       !hasSearched ||
       normalizedSearchText === "" ||
       isPendingSearchRoom ||
       isFetchingSearchRoom
     ) {
       return;
     }
 
-    queryClient.invalidateQueries({
-      queryKey: RECENT_SEARCH_QUERY_KEY.LIST("ROOM"),
-      refetchType: "all",
-    });
+    // 이미 무효화 처리한 검색어라면 재호출하지 않음
+    if (lastInvalidatedKeyword.current !== normalizedSearchText) {
+      queryClient.invalidateQueries({
+        queryKey: RECENT_SEARCH_QUERY_KEY.LIST("ROOM"),
+        refetchType: "all",
+      });
+      lastInvalidatedKeyword.current = normalizedSearchText;
+    }
   }, [
     hasSearched,
     isFetchingSearchRoom,
     isPendingSearchRoom,
     queryClient,
     searchText,
   ]);
🤖 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 `@screens/search-group/components/search-group-result/index.tsx` around lines
62 - 84, Update the useEffect invalidation flow to track the last invalidated
search text with useRef, so RECENT_SEARCH_QUERY_KEY.LIST("ROOM") is invalidated
only once when a genuinely new search completes, not during fetchNextPage-driven
isFetchingSearchRoom changes. Keep the existing guards for hasSearched, trimmed
empty text, and pending/fetching states, and update the ref only after
invalidation.

Source: Path instructions

src/apis/room/room.types.ts (1)

29-36: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

[P3] 카테고리 타입 중복 선언 개선 제안 (DRY 원칙) 🧹

현재 SearchRoomCategoryRoomCategory 간에 카테고리 문자열이 일부 중복 선언되어 있습니다. 추후 새로운 카테고리가 추가될 때 누락을 방지하고 유지보수성을 높이기 위해 유니온(Union) 타입을 활용해 합치는 것을 제안합니다.

💡 제안하는 타입 선언
-export type SearchRoomCategory =
-  | "전체"
-  | "문학"
-  | "과학·IT"
-  | "사회과학"
-  | "인문학"
-  | "예술";
+export type SearchRoomCategory = "전체" | RoomCategory;

이렇게 작성하면 코드가 더 간결해지고 타입 간의 관계가 명확해집니다!

🤖 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 `@src/apis/room/room.types.ts` around lines 29 - 36, Update the
SearchRoomCategory type to reuse the existing RoomCategory union and add only
the unique "전체" value, removing duplicated category string literals while
preserving the current supported values.

Source: Path instructions

src/apis/room/room.api.ts (2)

21-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

P3 · 함수명 오타 정리하면 미래의 나(그리고 동료)에게 박수 받을 겁니다 👏

getHomeRecuitingRoomApi에서 "Recruiting"의 r이 하나 빠졌어요(Recuiting). 같은 도메인의 타입(GetHomeRecruitingRoomRequest/Response)과 훅(useGetHomeRecruitingRoomListQuery)은 정확히 철자가 맞아서, 이 함수만 눈에 띄게 됩니다. 이미 room.queries.ts(101번째 줄)와 room/index.ts(재-export)에도 같은 이름이 그대로 퍼져있으니, 지금 고치는 게 나중에 3곳을 리팩터링하는 것보다 훨씬 쌉니다.

✏️ 제안 diff
-export const getHomeRecuitingRoomApi = async ({
+export const getHomeRecruitingRoomApi = async ({
   category,
 }: GetHomeRecruitingRoomRequest) => {

(room.queries.ts, room/index.ts의 참조도 함께 이름 변경 필요)

🤖 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 `@src/apis/room/room.api.ts` around lines 21 - 32, Rename
getHomeRecuitingRoomApi to getHomeRecruitingRoomApi and update all references
and re-exports in room.queries.ts and room/index.ts to use the corrected
spelling.

34-57: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

P4 · cursor 분기 로직, 단위 테스트로 보험 들어두시죠 📋

getMyRoomListApi(cursor 유무에 따라 {type} vs {type, cursor})와 getHomeMyRoomApi(cursor 없으면 params: undefined)는 분기가 미묘해서 리팩터링 중 실수하기 쉬운 지점입니다. apiClient.get을 모킹해 각 함수가 cursor null/undefined/값 있음 케이스별로 올바른 params를 전달하는지 확인하는 단위 테스트를 추천합니다.

As per path instructions, "미작성한 테스트 코드 케이스가 있다면, 어떤 테스트가 필요한지 제안해주세요."

🤖 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 `@src/apis/room/room.api.ts` around lines 34 - 57, 커서 분기 동작을 검증하는 단위 테스트를
추가하세요. getMyRoomListApi는 cursor가 null 또는 undefined일 때 {type}, 값이 있을 때 {type,
cursor}를 apiClient.get에 전달하는지 확인하고, getHomeMyRoomApi는 cursor가 null 또는 undefined일
때 params: undefined, 값이 있을 때 {cursor}를 전달하는지 검증하세요.

Source: Path instructions

screens/my-group-list/my-group-list-screen.tsx (2)

18-18: 📐 Maintainability & Code Quality | 🔵 Trivial

P4 · TODO 주석, 그냥 두면 언젠가 화석이 됩니다 🦴

"참여중인 내모임방 조회 api 까지는 가능할듯?" TODO가 남아있어요. 이 PR에서 참여중인 방 캐러셀(useGetHomeMyRoomQuery)까지 이미 연동하신 것 같은데, 이 화면에서도 처리 가능한 상태라면 TODO를 정리하거나 별도 이슈로 옮기는 게 좋겠습니다. 제가 이슈 생성이나 정리 작업 도와드릴까요?

🤖 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 `@screens/my-group-list/my-group-list-screen.tsx` at line 18, Remove the
obsolete TODO comment near the my-group list screen, since the
participating-room carousel is already integrated through useGetHomeMyRoomQuery;
leave the existing screen implementation unchanged.

96-135: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

P3 · expired-group-list-screen.tsx와 같은 뼈대, 리팩터 후보로 등록해둘게요 🧩

FlatList의 footer 스피너, onEndReached, refreshControl 배선이 expired-group-list-screen.tsx와 동일한 패턴입니다. 자세한 통합 제안은 아래 consolidated 코멘트에 정리했습니다.

🤖 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 `@screens/my-group-list/my-group-list-screen.tsx` around lines 96 - 135,
MyGroupListScreen의 FlatList footer spinner, onEndReached, onEndReachedThreshold,
refreshControl 구성이 expired-group-list-screen.tsx와 중복됩니다. 두 화면의 공통 FlatList 설정과
로딩·새로고침 배선을 공유 컴포넌트 또는 공통 설정으로 추출하는 리팩터링 후보로 등록하고, 각 화면 고유의 데이터와 렌더링 설정은 유지하세요.
src/apis/room/room.queries.ts (2)

64-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

P3 · getNextPageParam 삼형제, 한 지붕 아래 살게 해주세요 🏠

lastPage.isLast ? undefined : lastPage.nextCursor || undefined 로직이 useSearchRoomQuery, useGetMyRoomListQuery, useGetHomeMyRoomQuery 세 곳에 동일하게 복붙되어 있습니다. 커서 정책이 바뀌면 세 곳을 다 고쳐야 하니, 공용 헬퍼로 뽑아두면 유지보수성이 확 올라갑니다.

♻️ 제안 diff
 type RoomCursor = string | null;
+
+const getNextRoomCursor = (lastPage: {
+  isLast: boolean;
+  nextCursor?: string | null;
+}) => (lastPage.isLast ? undefined : lastPage.nextCursor || undefined);

이후 각 훅에서 getNextPageParam: getNextRoomCursor로 교체하시면 됩니다.

Also applies to: 133-134, 171-172

🤖 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 `@src/apis/room/room.queries.ts` around lines 64 - 65, Extract the duplicated
pagination logic from useSearchRoomQuery, useGetMyRoomListQuery, and
useGetHomeMyRoomQuery into a shared getNextRoomCursor helper, then reference
that helper via getNextPageParam in all three hooks while preserving the
existing isLast and nextCursor behavior.

99-186: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

P3 · TErrorApiError로 맞추는 편이 더 정확합니다 apiClient가 실패 응답을 ApiError로 던지므로, ApiErrorResponse는 실제 런타임 타입과 어긋납니다. code/message 사용은 유지되니 타입만 정리하면 됩니다.

🤖 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 `@src/apis/room/room.queries.ts` around lines 99 - 186, Update the query error
generic in the affected hooks, including useGetMyRoomListQuery and
useGetHomeMyRoomQuery, from ApiErrorResponse to ApiError so it matches the error
type thrown by apiClient. Preserve the existing code and message usage while
changing only the error type annotation.
screens/expired-group-list/expired-group-list-screen.tsx (1)

91-135: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

P3 · my-group-list-screen.tsx와 판박이인 로딩/빈/footer/refresh 로직, 한 번만 부탁드립니다 🧩

여기 FlatList 구성(로딩 스피너, footer 인디케이터, refreshControl, onEndReached)이 my-group-list-screen.tsx와 거의 1:1로 겹칩니다. 공용 훅(예: useRoomListPagination)이나 공용 리스트 래퍼 컴포넌트로 뽑아두면 두 화면이 따로 갈라져서 버그가 벌어질 위험을 줄일 수 있어요. 자세한 내용은 아래 통합 코멘트에서 함께 정리했습니다.

🤖 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 `@screens/expired-group-list/expired-group-list-screen.tsx` around lines 91 -
135, Extract the duplicated FlatList loading, empty-state, footer,
refreshControl, and onEndReached behavior from the expired-group screen and
my-group-list-screen into a shared hook such as useRoomListPagination or a
shared list wrapper. Update both screens to consume the shared implementation
while preserving their existing data, card rendering, styles, and pagination
behavior.
🤖 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 `@screens/my-group-list/my-group-list-screen.tsx`:
- Around line 20-58: Keep MyGroupTopFilter rendered while MyGroupListScreen
transitions between room types instead of returning a full loading view from
isPendingMyRoomList. Configure useGetMyRoomListQuery with TanStack Query v5’s
placeholderData: keepPreviousData behavior, and restrict the loading spinner to
the list area while preserving the existing filter and previous list content.

---

Outside diff comments:
In `@screens/group/components/my-group-carousel/index.tsx`:
- Around line 74-76: Update the Carousel configuration in the group carousel
component to disable looping by setting its loop option to false. Preserve the
existing onSnapToItem-based pagination and dynamic data-loading behavior.

---

Nitpick comments:
In `@screens/expired-group-list/expired-group-list-screen.tsx`:
- Around line 91-135: Extract the duplicated FlatList loading, empty-state,
footer, refreshControl, and onEndReached behavior from the expired-group screen
and my-group-list-screen into a shared hook such as useRoomListPagination or a
shared list wrapper. Update both screens to consume the shared implementation
while preserving their existing data, card rendering, styles, and pagination
behavior.

In `@screens/group/components/my-group-carousel/index.tsx`:
- Around line 41-47: Move the DEFAULT_PRELOAD_THRESHOLD constant out of
handleSnapToItem and define it at module scope, then keep handleSnapToItem using
that shared constant for the preload calculation.
- Line 19: Replace the TODO near the group carousel component with unit tests
using React Native Testing Library that cover rendering multiple group-room
items and verify the carousel’s onSnapToItem gesture behavior. Remove the TODO
once these cases are automated, reusing the component’s existing test patterns
and interaction APIs.

In `@screens/group/components/my-group-carousel/my-group-carousel-empty.tsx`:
- Around line 26-34: Extend the error branch in my-group-carousel-empty to
provide a retry action alongside the failure message. Add an onRetry callback
prop to the component, pass the query refetch function from the parent, and
invoke it from a clearly labeled retry button while preserving the existing
errorCode display.

In
`@screens/group/components/recruiting-group-carousel/recruiting-group-carousel-item.tsx`:
- Line 101: Update the error message rendering in the recruiting group carousel
item so the parentheses and homeRecruitingRoomError?.code appear only when an
error code exists; otherwise render only “데이터를 불러오지 못했어요” while preserving the
existing !roomList error branch.
- Around line 83-139: 모임방 목록 상태별 렌더링을 검증하는 컴포넌트 단위 테스트를 추가하세요.
renderRoomListContent를 사용하는 RecruitingGroupCarousel에서 로딩 시 ActivityIndicator, 오류
시 에러 문구, 빈 목록 시 빈 상태 문구, 데이터 존재 시 각 RecruitingGroupCard 렌더링을 확인하고, 각 테스트에서 해당
상태를 명확히 설정하세요.

In `@screens/my-group-list/my-group-list-screen.tsx`:
- Line 18: Remove the obsolete TODO comment near the my-group list screen, since
the participating-room carousel is already integrated through
useGetHomeMyRoomQuery; leave the existing screen implementation unchanged.
- Around line 96-135: MyGroupListScreen의 FlatList footer spinner, onEndReached,
onEndReachedThreshold, refreshControl 구성이 expired-group-list-screen.tsx와 중복됩니다.
두 화면의 공통 FlatList 설정과 로딩·새로고침 배선을 공유 컴포넌트 또는 공통 설정으로 추출하는 리팩터링 후보로 등록하고, 각 화면
고유의 데이터와 렌더링 설정은 유지하세요.

In `@screens/search-group/components/search-group-result/index.tsx`:
- Around line 62-84: Update the useEffect invalidation flow to track the last
invalidated search text with useRef, so RECENT_SEARCH_QUERY_KEY.LIST("ROOM") is
invalidated only once when a genuinely new search completes, not during
fetchNextPage-driven isFetchingSearchRoom changes. Keep the existing guards for
hasSearched, trimmed empty text, and pending/fetching states, and update the ref
only after invalidation.

In `@src/apis/room/room.api.ts`:
- Around line 21-32: Rename getHomeRecuitingRoomApi to getHomeRecruitingRoomApi
and update all references and re-exports in room.queries.ts and room/index.ts to
use the corrected spelling.
- Around line 34-57: 커서 분기 동작을 검증하는 단위 테스트를 추가하세요. getMyRoomListApi는 cursor가
null 또는 undefined일 때 {type}, 값이 있을 때 {type, cursor}를 apiClient.get에 전달하는지 확인하고,
getHomeMyRoomApi는 cursor가 null 또는 undefined일 때 params: undefined, 값이 있을 때
{cursor}를 전달하는지 검증하세요.

In `@src/apis/room/room.queries.ts`:
- Around line 64-65: Extract the duplicated pagination logic from
useSearchRoomQuery, useGetMyRoomListQuery, and useGetHomeMyRoomQuery into a
shared getNextRoomCursor helper, then reference that helper via getNextPageParam
in all three hooks while preserving the existing isLast and nextCursor behavior.
- Around line 99-186: Update the query error generic in the affected hooks,
including useGetMyRoomListQuery and useGetHomeMyRoomQuery, from ApiErrorResponse
to ApiError so it matches the error type thrown by apiClient. Preserve the
existing code and message usage while changing only the error type annotation.

In `@src/apis/room/room.types.ts`:
- Around line 29-36: Update the SearchRoomCategory type to reuse the existing
RoomCategory union and add only the unique "전체" value, removing duplicated
category string literals while preserving the current supported values.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 41804fc8-e834-4125-99c9-8f417172eeb1

📥 Commits

Reviewing files that changed from the base of the PR and between 33500a4 and d4f776b.

📒 Files selected for processing (24)
  • screens/expired-group-list/constants/index.ts
  • screens/expired-group-list/expired-group-list-screen.tsx
  • screens/group/components/my-group-carousel/index.tsx
  • screens/group/components/my-group-carousel/my-group-carousel-empty.tsx
  • screens/group/components/recruiting-group-carousel/recruiting-group-card.tsx
  • screens/group/components/recruiting-group-carousel/recruiting-group-carousel-header.tsx
  • screens/group/components/recruiting-group-carousel/recruiting-group-carousel-item.tsx
  • screens/my-group-list/components/my-group-top-filter/index.tsx
  • screens/my-group-list/constants/index.ts
  • screens/my-group-list/my-group-list-screen.tsx
  • screens/search-group/components/search-group-result/index.tsx
  • screens/search-group/components/searched-group-item/index.tsx
  • screens/search-group/constants/index.ts
  • screens/search-group/search-group-screen.tsx
  • screens/search-group/types/index.ts
  • src/apis/endpoint.ts
  • src/apis/room/index.ts
  • src/apis/room/room.api.ts
  • src/apis/room/room.queries.ts
  • src/apis/room/room.query-key.ts
  • src/apis/room/room.types.ts
  • src/shared/ui/index.ts
  • src/shared/ui/my-group-card/index.tsx
  • src/stores/search-group/index.ts
💤 Files with no reviewable changes (3)
  • screens/expired-group-list/constants/index.ts
  • screens/my-group-list/constants/index.ts
  • screens/search-group/types/index.ts

Comment thread screens/my-group-list/my-group-list-screen.tsx Outdated
@holdn2
holdn2 merged commit a346fc8 into main Jul 15, 2026
1 check passed
@holdn2
holdn2 deleted the feature/#97/room-query-api-integration branch July 15, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Add new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 모임방 조회 관련 api

1 participant