Skip to content

Conversation

@Chuseok22
Copy link
Owner

@Chuseok22 Chuseok22 commented Nov 17, 2025

✨ 변경 사항


✅ 테스트


  • 수동 테스트 완료
  • 테스트 코드 완료

Summary by CodeRabbit

릴리스 노트

  • New Features

    • UI 유틸리티 클래스(.main-container, .input-primary) 추가
  • Bug Fixes

    • 서비스워커 오프라인 폴백 및 fetch 흐름 안정화
    • 모달 오버레이 클릭 경계 개선(닫기 일관화)
    • 하단 시트 드래그/닫기 동작·임계값 개선
  • Style

    • 광범위한 JSX/마크업 및 설정 파일 재정렬·주석 정리
  • Refactor

    • 하단 시트 프로퍼티/렌더 구조 조정 및 공급자 값 메모이제이션
    • 쿼리 파라미터 처리 비동기화 및 일부 컴포넌트 공개 인터페이스 정리

@Chuseok22 Chuseok22 self-assigned this Nov 17, 2025
@Chuseok22 Chuseok22 added the refactor 리팩터링 (Refactor) label Nov 17, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 17, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

여러 파일에서 주로 포맷/주석/구성 재정렬이 적용되었고, BottomSheet는 포인터 드래그·ESC 바인딩·공개 prop 변화(isOpen/className 제거 등)를 포함해 리팩토링되었으며 VotePage의 searchParams 처리가 Promise(비동기)로 변경되었습니다.

Changes

코호트 / 파일(s) 변경 요약
ESLint/TS 설정
\.eslintrc.json`, `tsconfig.json``
배열/객체 재포맷팅 및 주석 추가; 동작 불변
GitHub 워크플로우
\.github/workflows/apk-build.yml`, `.github/workflows/chuseok22-issue-helper.yml`, `.github/workflows/sync-issue-labels.yaml``
YAML 공백/인덴테이션 조정 — sync-issue-labels.yaml은 구조적 인덴테이션 변경으로 파싱 영향 가능
퍼블릭 매니페스트/설정
\public/.well-known/assetlinks.json`, `public/browserconfig.xml`, `public/sw.js``
JSON/XML 포맷 재정렬 및 서비스워커의 Promise/오프라인 폴백 체인 정리(동작 유지)
레이아웃·메타데이터
\src/app/layout.tsx``
SITE_URL 상수 추가 및 metadataBase 설정(타이틀/설명 일부 갱신)
VotePage (검색매개변수 비동기화)
\src/app/meeting/[id]/vote/page.tsx``
searchParamsinterface화하고 searchParams: Promise<searchParams>로 변경 → await 후 구조분해; 리다이렉트/렌더링 로직 유지
BottomSheet 리팩토링
\src/components/BottomSheet.tsx`, `src/components/BottomSheetProvider.tsx``
포인터 기반 드래그 도입, ESC 바인딩 변경, className prop 제거, Provider 값 memo화, 높이 초기화/스냅·종료 임계치 로직 추가
Sheet 관련 API 변경 및 사용처 갱신
\src/features/meeting/components/SlotParticipantsSheet.tsx`, `src/features/meeting/components/JoinParticipantSheet.tsx`, `src/features/meeting/components/TimeGridView.tsx``
공개 prop명/타입 변경(예: openisOpen, Props 타입명 변경), BottomSheet 초기 높이 조정 및 호출부 업데이트
컴포넌트·페이지 포맷팅
\src/app/`, `src/components/`, `src/features//*`, `src/lib//`, `src/utils/``
대부분 JSX/TSX/함수 서명 재포맷팅·들여쓰기 정리; 동작 불변(예외는 위 항목들)
스타일 변경
\src/styles/base.css`, `src/styles/components.css``
height: 100% 추가, 폰트 스무딩 위치 조정, .main-container·.input-primary 클래스 추가

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant VotePage
    participant Router
    Note right of VotePage `#DCEFFF`: searchParams가 Promise로 전달됨

    Client->>VotePage: 요청 (searchParams: Promise)
    VotePage->>VotePage: await searchParams
    VotePage->>VotePage: const { participantId, username } = params
    alt participantId 또는 username 누락
        VotePage->>Router: 리다이렉트 처리
    else
        VotePage->>VotePage: 룸 정보 조회 및 렌더링 준비
        VotePage->>Client: TimeGridVote 렌더링
    end
Loading
sequenceDiagram
    participant User
    participant BottomSheet
    participant PointerEvents
    Note right of BottomSheet `#FFF1D6`: 초기화: 높이 재계산, 드래그 리셋

    User->>BottomSheet: isOpen=true (시트 열기)
    BottomSheet->>BottomSheet: calculateHeight, set heightPct
    User->>PointerEvents: pointerdown on handle
    PointerEvents->>BottomSheet: pointermove => 높이 업데이트
    alt 최종 높이 < closeThreshold (예: 12vh)
        PointerEvents->>BottomSheet: close() 호출
    else 높이 < initialHeightPct
        PointerEvents->>BottomSheet: snap to initialHeightPct
    end
    PointerEvents->>BottomSheet: pointerup/cancel => 이벤트 정리
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 분

  • 주의 검토 항목:
    • src/components/BottomSheet.tsx: 포인터 이벤트 등록/해제, 스냅·닫기 임계치, 접근성(ARIA/키보드) 보장, className 제거 영향
    • src/app/meeting/[id]/vote/page.tsx: searchParams가 Promise인 경로의 타입/예외 처리 및 서버/클라이언트 환경 영향
    • .github/workflows/sync-issue-labels.yaml: 들여쓰기 변경으로 워크플로우 필터 동작 여부 확인
    • 전역: openisOpen prop rename에 따른 호출부 누락 여부 확인

Possibly related PRs

Poem

🐰 들여쓰기 굴에서 토끼가 말하네
줄 바꿈을 가지런히, 주석도 놓고
시트는 부드럽게 당기고 ESC로 닫히네
검색은 잠시 기다려서 꺼내오고
당근 한 조각으로 축하해요, 깔끔한 코드! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 변경사항의 주요 내용과 일치합니다. 바텀시트 개선이라는 핵심 목적이 명확하게 표현되어 있습니다.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d913f25 and f89b68c.

📒 Files selected for processing (1)
  • src/features/meeting/components/SlotParticipantsSheet.tsx (2 hunks)

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

@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 (5)
public/sw.js (1)

80-108: 오프라인 폴백 로직 개선, 단 미세한 개선 여지 있음

오프라인 폴백을 외부 catch로 이동한 것은 좋은 개선입니다. 전체 흐름(캐시 조회 + 네트워크 요청)을 커버하게 되었습니다.

다만, 106번 라인의 caches.match('/')가 실패하면 undefined를 반환할 수 있습니다. 더 견고한 폴백을 위해 다음과 같이 개선할 수 있습니다:

     .catch(() => {
       // 오프라인 시 기본 페이지 반환
       if (event.request.destination === 'document') {
-        return caches.match('/');
+        return caches.match('/').then(response => {
+          return response || new Response(
+            '<!DOCTYPE html><html><body><h1>오프라인</h1><p>네트워크 연결을 확인해주세요.</p></body></html>',
+            { headers: { 'Content-Type': 'text/html' } }
+          );
+        });
       }
     })
src/app/meeting/[id]/vote/page.tsx (1)

12-25: Next.js 15 비동기 파라미터 마이그레이션 완료

Next.js 15에서 searchParams가 비동기로 변경된 것에 맞춰 올바르게 구현되었습니다. Promise로 타입을 변경하고 await로 값을 추출하는 패턴이 정확합니다.

다만, TypeScript 컨벤션에 따라 인터페이스명을 PascalCase로 변경하는 것을 권장합니다:

-interface searchParams {
+interface SearchParams {
   participantId?: string;
   username?: string;
 }

 export default async function VotePage({
   params,
   searchParams,
 }: {
   params: Promise<{ id: string }>;
-  searchParams: Promise<searchParams>;
+  searchParams: Promise<SearchParams>;
 }): Promise<JSX.Element> {
src/features/meeting/components/JoinParticipantForm.tsx (1)

13-19: 인터페이스 이름을 더 명확하게 변경하는 것을 권장합니다.

인터페이스 이름을 JoinParticipantFormProps에서 props로 변경했는데, props는 너무 일반적이며 TypeScript 컨벤션(PascalCase)을 따르지 않습니다. 가독성과 유지보수성을 위해 원래 이름을 유지하거나 JoinParticipantFormProps로 되돌리는 것을 권장합니다.

-interface props {
+interface JoinParticipantFormProps {
   roomId: string;
 }
 
 export default function JoinParticipantForm({
   roomId,
-}: props): JSX.Element {
+}: JoinParticipantFormProps): JSX.Element {
src/features/meeting/components/SlotParticipantsSheet.tsx (2)

4-4: React import가 필요한지 확인하세요.

React를 import했지만 코드에서 React.ReactNode나 다른 React 네임스페이스 멤버를 직접 사용하지 않습니다. JSXuseMemo만 사용되므로 React import는 불필요할 수 있습니다.

-import React, { JSX, useMemo } from "react";
+import { JSX, useMemo } from "react";

10-24: 인터페이스 이름을 더 명확하게 변경하는 것을 권장합니다.

인터페이스 이름을 props로 변경했는데, 이는 TypeScript 컨벤션(PascalCase)을 따르지 않으며 너무 일반적입니다. SlotParticipantsSheetProps 같은 명확한 이름을 사용하는 것이 좋습니다.

-interface props {
+interface SlotParticipantsSheetProps {
   isOpen: boolean;
   onClose: () => void;
   roomInfo: RoomInfoResponse;
   date: string | null;
   timeSlot: string | null;
 }
 
 export default function SlotParticipantsSheet({
   isOpen,
   onClose,
   roomInfo,
   date,
   timeSlot,
-}: props): JSX.Element | null {
+}: SlotParticipantsSheetProps): JSX.Element | null {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aadc3cc and d04f223.

⛔ Files ignored due to path filters (5)
  • public/file.svg is excluded by !**/*.svg
  • public/globe.svg is excluded by !**/*.svg
  • public/next.svg is excluded by !**/*.svg
  • public/vercel.svg is excluded by !**/*.svg
  • public/window.svg is excluded by !**/*.svg
📒 Files selected for processing (40)
  • .eslintrc.json (1 hunks)
  • .github/workflows/apk-build.yml (2 hunks)
  • .github/workflows/chuseok22-issue-helper.yml (1 hunks)
  • .github/workflows/sync-issue-labels.yaml (1 hunks)
  • public/.well-known/assetlinks.json (1 hunks)
  • public/browserconfig.xml (1 hunks)
  • public/sw.js (4 hunks)
  • src/app/create-meeting/page.tsx (1 hunks)
  • src/app/error.tsx (1 hunks)
  • src/app/join-meeting/page.tsx (1 hunks)
  • src/app/layout.tsx (1 hunks)
  • src/app/meeting/[id]/page.tsx (1 hunks)
  • src/app/meeting/[id]/vote/page.tsx (2 hunks)
  • src/app/page.tsx (1 hunks)
  • src/app/privacy/page.tsx (1 hunks)
  • src/components/BodySection.tsx (1 hunks)
  • src/components/BottomSheet.tsx (3 hunks)
  • src/components/BottomSheetProvider.tsx (2 hunks)
  • src/components/Header.tsx (1 hunks)
  • src/features/create-meeting/components/Calendar.tsx (2 hunks)
  • src/features/create-meeting/hooks/useCalendar.ts (1 hunks)
  • src/features/home/components/ActionCard.tsx (1 hunks)
  • src/features/home/components/HelpButton.tsx (1 hunks)
  • src/features/home/components/HelpModal.tsx (1 hunks)
  • src/features/join-meeting/components/JoinCodeForm.tsx (1 hunks)
  • src/features/meeting/components/CopyButton.tsx (1 hunks)
  • src/features/meeting/components/JoinParticipantForm.tsx (2 hunks)
  • src/features/meeting/components/JoinParticipantSheet.tsx (2 hunks)
  • src/features/meeting/components/SlotParticipantsSheet.tsx (2 hunks)
  • src/features/meeting/components/TimeGridView.tsx (1 hunks)
  • src/features/meeting/components/slotParticipantsSheetHelper.ts (2 hunks)
  • src/features/meeting/components/timeGridHelper.ts (1 hunks)
  • src/lib/api/apiClient.ts (1 hunks)
  • src/lib/api/apiServer.ts (1 hunks)
  • src/lib/bff/proxy.ts (2 hunks)
  • src/lib/errors/customError.ts (1 hunks)
  • src/styles/base.css (1 hunks)
  • src/styles/components.css (2 hunks)
  • src/utils/dateUtils.ts (1 hunks)
  • tsconfig.json (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (14)
src/features/home/components/HelpButton.tsx (1)
src/features/home/components/HelpModal.tsx (1)
  • HelpModal (11-129)
src/features/create-meeting/hooks/useCalendar.ts (1)
src/utils/dateUtils.ts (1)
  • isSameDate (2-6)
src/lib/bff/proxy.ts (1)
src/lib/bff/proxyTypes.ts (1)
  • ProxyConfig (9-18)
src/features/meeting/components/timeGridHelper.ts (1)
src/features/meeting/components/TimeGridVote.tsx (1)
  • SelectedMap (12-12)
src/app/create-meeting/page.tsx (3)
src/components/Header.tsx (1)
  • Header (11-41)
src/components/BodySection.tsx (1)
  • BodySection (3-13)
src/features/create-meeting/components/Calendar.tsx (1)
  • Calendar (13-113)
src/app/meeting/[id]/vote/page.tsx (4)
src/components/Header.tsx (1)
  • Header (11-41)
src/components/BodySection.tsx (1)
  • BodySection (3-13)
src/features/meeting/components/CopyButton.tsx (1)
  • CopyButton (15-56)
src/features/meeting/components/TimeGridVote.tsx (1)
  • TimeGridVote (24-463)
src/features/meeting/components/slotParticipantsSheetHelper.ts (1)
src/features/meeting/types/apiTypes.ts (2)
  • RoomInfoResponse (17-25)
  • DateAvailabilityResponse (12-15)
src/features/meeting/components/SlotParticipantsSheet.tsx (2)
src/features/meeting/types/apiTypes.ts (1)
  • RoomInfoResponse (17-25)
src/components/BottomSheet.tsx (1)
  • BottomSheet (15-183)
src/app/join-meeting/page.tsx (3)
src/components/Header.tsx (1)
  • Header (11-41)
src/components/BodySection.tsx (1)
  • BodySection (3-13)
src/features/join-meeting/components/JoinCodeForm.tsx (1)
  • JoinCodeForm (10-72)
src/components/BottomSheet.tsx (1)
src/components/bottomSheetHelper.ts (1)
  • calculateHeight (1-3)
src/features/meeting/components/JoinParticipantSheet.tsx (2)
src/components/BottomSheet.tsx (1)
  • BottomSheet (15-183)
src/features/meeting/components/JoinParticipantForm.tsx (1)
  • JoinParticipantForm (17-143)
src/app/meeting/[id]/page.tsx (9)
src/components/Header.tsx (1)
  • Header (11-41)
src/components/BottomSheetProvider.tsx (1)
  • BottomSheetProvider (17-40)
src/components/BodySection.tsx (1)
  • BodySection (3-13)
src/features/meeting/components/CopyButton.tsx (1)
  • CopyButton (15-56)
src/lib/types.ts (1)
  • ORIGIN_URL (12-12)
src/utils/dateUtils.ts (2)
  • formatDateForDetailDisplay (45-53)
  • toLocalDate (29-32)
src/types/timeSlot.ts (1)
  • TIME_SLOT_MAP (1-34)
src/features/meeting/components/JoinParticipantSheet.tsx (1)
  • JoinParticipantSheet (12-55)
src/features/meeting/components/TimeGridView.tsx (1)
  • TimeGridView (20-101)
src/app/page.tsx (2)
src/features/home/components/ActionCard.tsx (1)
  • ActionCard (15-49)
src/features/home/components/HelpButton.tsx (1)
  • HelpButton (7-44)
src/features/meeting/components/TimeGridView.tsx (1)
src/features/meeting/components/SlotParticipantsSheet.tsx (1)
  • SlotParticipantsSheet (18-130)
🔇 Additional comments (54)
src/lib/api/apiClient.ts (1)

6-9: 요청 메서드 서명 서식 변경 — 승인됨

매개변수 목록의 들여쓰기만 조정되었으며, 동작이나 타입에 변화는 없습니다. 순수 포맷팅 개선입니다.

src/lib/api/apiServer.ts (1)

16-19: 요청 메서드 서명 서식 변경 — 승인됨

매개변수 목록의 들여쓰기만 조정되었으며, 동작이나 타입에 변화는 없습니다. apiClient.ts와 일관된 서식으로 통일되었습니다.

public/.well-known/assetlinks.json (1)

3-5: JSON 형식 정리 - 기능상 변화 없음.

relation 배열의 형식만 변경되었으며, 의미있는 콘텐츠는 동일합니다. Google Digital Asset Links 사양상 유효한 변경입니다.

public/browserconfig.xml (1)

5-5: XML 요소 순서 정리 - 기능상 변화 없음.

Microsoft 공식 문서의 browserconfig.xml 예제들에서도 TileColor와 로고 요소들의 순서가 유연하게 나타나 이러한 요소 재배치는 기능에 영향을 주지 않습니다.

Also applies to: 8-8

src/utils/dateUtils.ts (1)

3-5: 포맷팅 변경만 반영됨.

isSameDate 함수의 반환문 들여쓰기가 개선되었습니다. 기능상 변화는 없습니다.

src/features/create-meeting/hooks/useCalendar.ts (2)

25-26: 포맷팅 개선: findIndex 콜백 들여쓰기.

들여쓰기만 정렬되었으며, 기능상 변화는 없습니다.


1-59: PR 제목과 변경 내용 불일치 확인.

PR 제목은 "페이지 내부 바텀시트 개선"이지만, 실제 변경사항은 dateUtils.tsuseCalendar.ts의 순수 포맷팅(들여쓰기)입니다. 바텀시트 구현 자체에 대한 변경이 보이지 않습니다. PR 설명에서 변경 사항을 명확히 기술해주기 바랍니다.

또한 PR 체크리스트에서 "Manual testing completed"와 "Test code completed"가 모두 미완료 상태입니다. 병합 전에 이를 완료해주시기 바랍니다.

src/lib/bff/proxy.ts (3)

13-15: 매개변수 재정렬 형식 변경은 적절합니다.

함수 시그니처의 매개변수들이 일관된 들여쓰기로 재포맷팅되었으며, 의미론적 변화는 없습니다. 코드 스타일 통일 관점에서 긍정적입니다.


107-113: 에러 응답 객체 재포맷팅은 가독성을 개선합니다.

500 에러 응답의 객체 리터럴이 다중 라인으로 재포맷팅되어 더 명확합니다. 응답 내용 및 상태코드는 동일하게 유지되어 의미론적 변화가 없습니다.


1-116: PR 범위와 파일 내용 간 스코프 불일치 확인

PR 제목은 "바텀시트 개선"을 언급하지만, 이 파일(proxy.ts)은 BFF 프록시 유틸리티입니다. 현재 변경사항들은 순수 포맷팅 조정(들여쓰기, 줄바꿈)만 포함하며, 바텀시트 또는 UI 컴포넌트와 직접적인 관련이 없습니다.

AI 요약에 따르면 이러한 포맷팅 변경들은 "프로젝트 전역에 걸친 광범위한 포맷팅 조정" 일부인 것으로 보입니다. 코드 정확성에 영향을 주지는 않으나, PR 설명을 확인하여 의도적인 범위 확대인지 확인하시기 바랍니다.

PR 설명에서 구체적인 변경사항 설명이 누락되어 있습니다. 이 파일이 포함된 의도와 모든 변경사항을 정리한 명확한 설명을 추가해 주시기 바랍니다.

public/sw.js (5)

1-155: PR 제목과 실제 변경 내용 간 불일치

PR 제목은 "페이지 내부 바텀시트 개선"이지만, 실제 변경사항은 서비스 워커 파일의 Promise 체인 구조 개선입니다. PR 설명에서 실제 변경 내용에 대한 구체적인 설명을 추가해주세요.


16-47: 코드 가독성 개선

Promise 체인의 들여쓰기가 일관되게 개선되어 코드 가독성이 향상되었습니다.


54-56: 명시적 반환문 추가

GET 요청이 아닌 경우 명시적으로 return하여 제어 흐름이 더 명확해졌습니다.


61-73: LGTM!

API 요청 실패 시 적절한 503 응답을 반환하는 로직이 유지되고 있습니다.


114-116: 방어적 코딩 개선

이벤트 데이터가 없을 때 조기 반환하여 불필요한 처리를 방지합니다.

src/features/meeting/components/timeGridHelper.ts (1)

30-36: 포매팅 변경 확인 완료

함수 파라미터의 들여쓰기만 변경되었으며, 로직과 시그니처는 동일합니다.

src/components/BodySection.tsx (1)

9-11: 포매팅 변경 확인 완료

JSX 들여쓰기만 조정되었으며, 렌더링 결과는 동일합니다.

src/lib/errors/customError.ts (1)

8-12: 포매팅 변경 확인 완료

생성자 파라미터의 들여쓰기만 변경되었으며, 동작은 동일합니다.

src/app/create-meeting/page.tsx (1)

54-105: 포매팅 변경 및 CSS 유틸리티 클래스 적용 확인

JSX 구조가 재정렬되었으며, 새로 추가된 CSS 유틸리티 클래스(main-container, input-primary)가 적절히 사용되었습니다. 컴포넌트 로직은 변경되지 않았습니다.

.github/workflows/sync-issue-labels.yaml (1)

13-14: YAML 들여쓰기 확인 완료

tags-ignore 하위 리스트 항목의 들여쓰기가 올바르게 적용되었습니다.

.github/workflows/chuseok22-issue-helper.yml (1)

5-5: 포매팅 변경 확인 완료

배열 내부 공백이 추가되었으나 동작에는 영향이 없습니다.

src/app/error.tsx (1)

10-19: 포매팅 변경 확인 완료

에러 페이지 JSX의 들여쓰기만 조정되었으며, 렌더링 결과와 이벤트 핸들러는 동일합니다.

src/styles/components.css (3)

10-12: 새로운 input 스타일 클래스 추가 확인

재사용 가능한 input 스타일 클래스가 추가되었습니다. 프로젝트 전반에서 일관된 input 스타일링을 위해 좋은 개선입니다.


21-23: 포매팅 변경 확인 완료

스크롤바 숨김 스타일의 들여쓰기가 조정되었으며, 동작은 동일합니다.


6-8: 유틸리티 클래스 추가 확인됨 - 추가 적용 제안

.main-container 클래스가 src/styles/components.css에 올바르게 정의되어 있고, 현재 세 개의 주요 페이지(join-meeting, meeting/[id], create-meeting)에 적절하게 적용되어 있습니다.

검색 결과 src/app/page.tsx 라인 25의 className="flex flex-col w-full gap-8 px-4 lg:px-8"은 유사한 패턴을 보이므로, 요구사항에 맞는 경우 main-container 적용을 고려할 수 있습니다. 단, src/components/BodySection.tsxsrc/app/error.tsx 같은 다른 컴포넌트들은 서로 다른 패딩(px-6, p-4) 또는 추가 스타일(배경색, 높이 제약)을 가지고 있어 현재 상태 유지가 적절합니다.

src/features/create-meeting/components/Calendar.tsx (1)

1-113: LGTM! 일관된 코드 포맷팅 개선

Calendar 컴포넌트의 JSX 구조를 일관되게 재정렬한 변경사항입니다. 모든 기능과 로직은 그대로 유지되고 있습니다.

src/styles/base.css (1)

3-5: LGTM! 브라우저 호환성 개선

height: 100%;를 fallback으로 추가하여 dvh 단위를 지원하지 않는 브라우저에서도 정상적으로 동작하도록 개선되었습니다.

tsconfig.json (1)

1-40: LGTM! 가독성 개선

TypeScript 설정의 가독성을 위한 포맷팅 변경입니다. 설정 내용은 동일하게 유지됩니다.

.github/workflows/apk-build.yml (1)

5-5: LGTM! YAML 포맷 정규화

워크플로우 동작에는 영향 없는 포맷팅 변경입니다.

src/app/privacy/page.tsx (1)

1-169: LGTM! 일관된 JSX 포맷팅

개인정보 처리방침 페이지의 JSX 구조를 일관되게 재정렬한 변경사항입니다. 모든 콘텐츠와 기능은 동일하게 유지됩니다.

.eslintrc.json (1)

1-54: LGTM! 가독성 및 문서화 개선

ESLint 설정에 한국어 주석을 추가하고 포맷을 개선했습니다. 실제 린팅 규칙은 변경되지 않았습니다.

src/features/home/components/ActionCard.tsx (1)

26-47: LGTM! 레이아웃 구조 개선

ActionCard의 레이아웃이 재구성되었습니다. 아이콘과 텍스트를 별도 컬럼으로 분리하고 버튼을 하단으로 이동하여 시각적 계층이 개선되었습니다. 모든 props와 기능은 동일하게 유지됩니다.

src/app/meeting/[id]/vote/page.tsx (1)

34-72: LGTM! 일관된 JSX 포맷팅

투표 페이지의 JSX 구조를 일관되게 재정렬한 변경사항입니다. 모든 기능과 로직은 동일하게 유지됩니다.

src/features/join-meeting/components/JoinCodeForm.tsx (1)

38-70: 포매팅 개선으로 보임 - 함수 로직은 변경 없음

폼 구조의 들여쓰기와 줄 바꿈만 조정되었으며, JSX 계층 구조, 이벤트 핸들러, 상태 관리는 모두 동일합니다.

src/features/meeting/components/CopyButton.tsx (1)

41-53: 포매팅 정리만 이루어짐

버튼 JSX의 들여쓰기만 조정되었으며, 클래스명, 이벤트 핸들러, 렌더링 로직은 변경되지 않았습니다.

src/app/layout.tsx (1)

71-79: 레이아웃 들여쓰기 정리만 해당

body 및 div 래퍼 요소의 들여쓰기만 조정되었으며, 클래스명과 계층 구조는 유지됩니다.

src/features/meeting/components/slotParticipantsSheetHelper.ts (1)

7-20: 함수 매개변수 들여쓰기 정리

함수 매개변수 목록의 들여쓰기만 조정되었으며, 함수 서명과 로직은 변경되지 않았습니다.

src/components/Header.tsx (1)

25-39: 헤더 JSX 들여쓰기 정리

헤더 요소의 들여쓰기와 줄 바꿈만 조정되었으며, 접근성 속성, 이벤트 핸들러, 렌더링 로직은 유지됩니다.

src/app/join-meeting/page.tsx (1)

7-18: 페이지 레이아웃 들여쓰기 정리

JoinMeetingPage의 JSX 구조 들여쓰기만 조정되었으며, 컴포넌트 사용과 프로퍼티는 변경되지 않았습니다.

src/features/home/components/HelpButton.tsx (1)

24-42: 헬프 버튼 JSX 들여쓰기 정리

버튼과 모달 요소의 들여쓰기만 조정되었으며, 상태 관리, 이벤트 핸들러, 접근성 속성은 유지됩니다.

src/app/meeting/[id]/page.tsx (1)

28-101: 주요 변경사항: 레이아웃 구조화 및 비동기 params 처리

다음 사항을 확인해주세요:

  1. Next.js 15 비동기 params 처리 (라인 16-21): params: Promise<{ id: string }>로 선언하고 await params로 처리하는 것은 Next.js 15의 올바른 패턴입니다.

  2. TimeGridView와 SlotParticipantsSheet 통합: 제공된 relevant_code_snippets에서 TimeGridView는 SlotParticipantsSheet에 isOpen 프로퍼티를 전달합니다 (라인 96). 이것이 SlotParticipantsSheet의 프로퍼티 이름과 일치하는지 확인이 필요합니다.

  3. BottomSheetProvider 위치 (라인 30): main 요소를 감싸도록 올바르게 위치했습니다.

다음을 확인해주세요:

  • SlotParticipantsSheet 컴포넌트가 isOpen 프로퍼티를 받도록 업데이트되었는지 확인
  • TimeGridView에서 SlotParticipantsSheet로 전달되는 모든 프로퍼티가 정의된 인터페이스와 일치하는지 확인
src/components/BottomSheetProvider.tsx (1)

32-36: 컨텍스트 값 메모이제이션 적용이 적절합니다.

useMemo를 사용하여 컨텍스트 값을 메모이제이션함으로써 activeId가 변경될 때만 새 객체가 생성되도록 최적화했습니다. 이는 하위 컴포넌트의 불필요한 리렌더링을 방지합니다.

src/app/page.tsx (1)

8-52: 레이아웃 구조 개선이 적절합니다.

페이지 레이아웃을 정리하고 HelpButton을 우하단 고정 위치로 배치한 것은 사용자 경험 측면에서 적절한 개선입니다.

src/features/meeting/components/JoinParticipantSheet.tsx (2)

34-41: 모달 오버레이 패턴 적용이 적절합니다.

참여 시트에 모달 오버레이를 추가하여 사용자가 폼 작성에 집중할 수 있도록 개선했습니다. backdrop-blur와 어두운 배경이 적절히 적용되었습니다.


46-47: 바텀시트 높이 증가를 확인하세요.

initialHeightPct를 50에서 60으로, maxHeightPct를 70에서 80으로 증가시켰습니다. 폼 콘텐츠가 더 넓은 화면에서도 잘 표시되는지 다양한 기기에서 테스트하여 확인하시기 바랍니다.

src/features/meeting/components/TimeGridView.tsx (1)

89-98: Props 이름 변경이 일관성을 개선합니다.

SlotParticipantsSheet의 prop 이름을 open에서 isOpen으로 변경하여 BottomSheet 컴포넌트의 API와 일관성을 유지했습니다.

src/features/home/components/HelpModal.tsx (1)

22-35: 모달 클릭 처리 개선이 적절합니다.

외부 컨테이너에 onClick={onClose}를 배치하고 내부 콘텐츠에서 이벤트 전파를 중단하는 패턴은 모달 UX의 표준 구현입니다. 반응형 사이징 추가도 모바일 경험을 개선합니다.

src/features/meeting/components/SlotParticipantsSheet.tsx (1)

57-57: 초기 높이 증가를 확인하세요.

initialHeightPct를 25에서 40으로 증가시켰습니다. 이는 사용자 경험을 개선할 수 있지만, 작은 화면에서 콘텐츠가 과도하게 화면을 차지하지 않는지 테스트하여 확인하시기 바랍니다.

src/components/BottomSheet.tsx (6)

35-41: 높이 초기화 로직이 적절합니다.

isOpen이 변경될 때마다 높이를 초기값으로 리셋하는 것은 이전 상태가 다음 열림에 영향을 주지 않도록 하는 좋은 패턴입니다.


43-55: ESC 키 핸들링 개선이 적절합니다.

Effect를 사용하여 ESC 키 리스너를 관리하는 것은 깔끔한 분리를 제공하며, isOpen이 false일 때 리스너를 추가하지 않아 성능도 개선됩니다.


66-73: 전역 포인터 이벤트 처리가 우수합니다.

드래그 중 포인터가 핸들 영역을 벗어나도 계속 추적할 수 있도록 전역 리스너를 사용한 것은 모바일 환경에서 드래그 UX를 크게 개선합니다. preventDefault()로 스크롤 충돌도 방지했습니다.


86-95: 드래그 종료 임계값 로직을 검증하세요.

12vh 미만에서 닫고, initialHeightPct 미만에서 초기 높이로 스냅하는 로직이 구현되었습니다. 다양한 기기와 콘텐츠 높이에서 이 임계값들이 적절하게 동작하는지 테스트하여 확인하시기 바랍니다.


135-181: 바텀시트 렌더링 구조 개선이 우수합니다.

새로운 렌더링 구조는 다음과 같은 개선사항을 제공합니다:

  • 외부 컨테이너의 pointer-events-none과 내부 시트의 pointer-events-auto로 적절한 이벤트 처리
  • 분리된 드래그 핸들 영역으로 명확한 상호작용 영역 제공
  • overflow-y-autooverscroll-y-contain으로 스크롤 동작 개선
  • transform-gpu로 애니메이션 성능 최적화

7-21: Props 인터페이스 단순화가 적절하고 안전합니다.

className prop 제거가 검증되었습니다. 기존 코드에서 BottomSheet에 className prop을 전달하는 사용처가 없으므로, 이 리팩토링은 컴포넌트 API를 단순화하고 책임을 명확히 하는 좋은 변경입니다:

  • src/features/meeting/components/JoinParticipantSheet.tsx (43-50): className 없음
  • src/features/meeting/components/SlotParticipantsSheet.tsx (54-58): className 없음

모든 호출이 isOpen, onClose, initialHeightPct, maxHeightPct 프로퍼티만 사용하므로 변경사항은 안전합니다.

Copy link

@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

♻️ Duplicate comments (1)
src/components/BottomSheet.tsx (1)

138-140: aria-modal 속성을 동적으로 제어할 수 있도록 수정하세요.

aria-modal="true"로 하드코딩되어 있지만, 이전 리뷰에서 지적된 대로 오버레이가 있는 경우(JoinParticipantSheet)와 없는 경우(SlotParticipantsSheet)를 구분해야 합니다. 오버레이 없이 백그라운드와 상호작용이 가능한 경우 aria-modal="false"가 의미적으로 올바릅니다.

이전 리뷰의 제안대로 ariaModal prop을 추가하세요:

 interface Props {
   isOpen: boolean;
   onClose: () => void;
   initialHeightPct?: number;
   maxHeightPct?: number;
+  ariaModal?: boolean;
   children: React.ReactNode;
 }

 export default function BottomSheet({
   isOpen,
   onClose,
   initialHeightPct = 25,
   maxHeightPct = 70,
+  ariaModal = false,
   children
 }: Props): JSX.Element | null {
   // ...
   
   <div
     ref={sheetRef}
     role="dialog"
-    aria-modal="true"
+    aria-modal={String(ariaModal)}
     aria-label="바텀시트"

그런 다음 JoinParticipantSheet에서 ariaModal={true}를 전달하세요.

🧹 Nitpick comments (2)
src/features/meeting/components/SlotParticipantsSheet.tsx (1)

10-16: 인터페이스 이름을 PascalCase로 변경하세요.

TypeScript 명명 규칙에 따라 인터페이스 이름은 대문자로 시작해야 합니다.

다음 diff를 적용하세요:

-interface props {
+interface Props {
   isOpen: boolean;
   onClose: () => void;
   roomInfo: RoomInfoResponse;
   date: string | null;
   timeSlot: string | null;
 }

그리고 함수 시그니처도 업데이트하세요:

 export default function SlotParticipantsSheet({
   isOpen,
   onClose,
   roomInfo,
   date,
   timeSlot,
-}: props): JSX.Element | null {
+}: Props): JSX.Element | null {
src/components/BottomSheet.tsx (1)

7-13: 인터페이스 이름을 PascalCase로 변경하세요.

TypeScript 명명 규칙에 따라 인터페이스 이름은 대문자로 시작해야 합니다.

다음 diff를 적용하세요:

-interface props {
+interface Props {
   isOpen: boolean;
   onClose: () => void;
   initialHeightPct?: number;
   maxHeightPct?: number;
   children: React.ReactNode;
 }

그리고 함수 시그니처도 업데이트하세요:

 export default function BottomSheet({
   isOpen,
   onClose,
   initialHeightPct = 25,
   maxHeightPct = 70,
   children
-}: props): JSX.Element | null {
+}: Props): JSX.Element | null {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d04f223 and c5740de.

📒 Files selected for processing (2)
  • src/components/BottomSheet.tsx (3 hunks)
  • src/features/meeting/components/SlotParticipantsSheet.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/features/meeting/components/SlotParticipantsSheet.tsx (2)
src/features/meeting/types/apiTypes.ts (1)
  • RoomInfoResponse (17-25)
src/components/BottomSheet.tsx (1)
  • BottomSheet (15-183)
src/components/BottomSheet.tsx (1)
src/components/bottomSheetHelper.ts (1)
  • calculateHeight (1-3)
🔇 Additional comments (3)
src/features/meeting/components/SlotParticipantsSheet.tsx (1)

54-59: 변경 사항이 적절합니다.

isOpen prop으로의 이름 변경과 initialHeightPct를 40으로 증가시킨 것은 일관성과 사용자 경험을 개선합니다.

src/components/BottomSheet.tsx (2)

35-41: 시트가 열릴 때 높이를 초기화하는 로직이 잘 구현되었습니다.

isOpentrue가 될 때 높이와 드래그 상태를 초기화하는 것은 사용자 경험을 개선합니다.


43-55: ESC 키 처리 개선이 적절합니다.

isOpentrue일 때만 ESC 리스너를 등록하도록 변경한 것은 불필요한 이벤트 처리를 방지하고 메모리 효율성을 개선합니다.

Copy link

@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)
src/app/layout.tsx (1)

32-33: 환경 변수 사용을 고려해보세요.

프로덕션 URL을 하드코딩하는 대신 환경 변수를 사용하는 것이 좋습니다. 이렇게 하면 개발/스테이징/프로덕션 환경에서 유연하게 대응할 수 있습니다.

다음과 같이 수정할 수 있습니다:

-const SITE_URL = "https://meet.chuseok22.com"
+const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || "https://meet.chuseok22.com"

그리고 .env.local 파일에 다음을 추가하세요:

NEXT_PUBLIC_SITE_URL=http://localhost:3000
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5740de and d913f25.

📒 Files selected for processing (1)
  • src/app/layout.tsx (2 hunks)
🔇 Additional comments (1)
src/app/layout.tsx (1)

35-38: LGTM!

metadataBase 설정과 메타데이터 업데이트가 올바르게 적용되었습니다. 이중 언어 설명은 SEO와 국제 사용자 지원에 도움이 됩니다.

@Chuseok22 Chuseok22 merged commit ec5cb34 into main Nov 17, 2025
1 of 2 checks passed
@Chuseok22 Chuseok22 linked an issue Nov 17, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor 리팩터링 (Refactor)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🚀 [기능개선][바텀시트] 페이지 내부 바텀시트 개선

2 participants