refactor: 모임 생성 폼 리팩토링 (PR 리뷰 대응)#49
Conversation
Summary of ChangesHello @youngminss, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 모임 생성 폼의 리팩토링을 통해 코드의 유지보수성과 견고성을 향상시키는 데 중점을 둡니다. 폼 제출 로직을 중앙화하고, Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
전반적으로 모임 생성 폼의 로직을 개선하는 좋은 리팩토링입니다. 특히 API 호출 로직을 페이지 최상단으로 옮기고, 각 스텝 컴포넌트의 책임을 명확히 분리한 점이 인상적입니다. react-hook-form의 useController를 도입하여 상태 관리를 개선하려는 시도도 좋습니다. 다만, 몇몇 컴포넌트에서 useController가 중복으로 사용되어 잠재적인 문제를 일으킬 수 있는 부분이 발견되었습니다. 각 스텝의 Footer 컴포넌트에서 useController 대신 useWatch를 사용하도록 수정하는 것을 제안합니다. 자세한 내용은 각 파일에 남긴 리뷰 코멘트를 참고해주세요.
| name: "scheduledDate", | ||
| rules: scheduledDateRules, | ||
| }); | ||
|
|
||
| const { field: timeSlotField } = useController({ | ||
| control, | ||
| name: "timeSlot", | ||
| rules: timeSlotRules, | ||
| }); | ||
|
|
||
| const isValid = | ||
| !isNil(scheduledDateField.value) && | ||
| isValidDateFormat(scheduledDateField.value) && | ||
| !isNil(timeSlotField.value); | ||
|
|
||
| return ( |
There was a problem hiding this comment.
useController는 동일한 필드에 대해 여러 번 호출하면 안 됩니다. 현재 DateStepContent와 DateStepFooter에서 scheduledDate와 timeSlot 필드에 대해 각각 useController를 사용하고 있어, react-hook-form의 예기치 않은 동작을 유발할 수 있습니다. Footer에서는 useController 대신 useWatch를 사용하여 필드 값을 구독하고 유효성을 검사하는 것이 올바른 방법입니다. useWatch를 사용하려면 react-hook-form에서 import해야 합니다.
const [scheduledDate, timeSlot] = useWatch({
control,
name: ["scheduledDate", "timeSlot"],
});
const isValid =
!isNil(scheduledDate) &&
isValidDateFormat(scheduledDate) &&
!isNil(timeSlot);
| const { field } = useController({ | ||
| control, | ||
| name: "peopleCount", | ||
| rules, | ||
| }); | ||
|
|
||
| const isValid = !isNil(field.value); |
There was a problem hiding this comment.
useController는 동일한 필드에 대해 여러 번 호출하면 안 됩니다. 현재 PeopleStepContent와 PeopleStepFooter에서 peopleCount 필드에 대해 각각 useController를 사용하고 있어, react-hook-form의 예기치 않은 동작을 유발할 수 있습니다. Footer에서는 useController 대신 useWatch를 사용하여 필드 값을 구독하고 유효성을 검사하는 것이 올바른 방법입니다. useWatch를 사용하려면 react-hook-form에서 import해야 합니다.
| const { field } = useController({ | |
| control, | |
| name: "peopleCount", | |
| rules, | |
| }); | |
| const isValid = !isNil(field.value); | |
| const peopleCount = useWatch({ | |
| control, | |
| name: "peopleCount", | |
| }); | |
| const isValid = !isNil(peopleCount); |
There was a problem hiding this comment.
@RookieAND 흠 이 친구 의견은 우리가 생각하는거랑 반대로 이야기하네 흥미롭네
| const { control } = useFormContext<CreateMeetingForm>(); | ||
|
|
||
| const handleComplete = () => { | ||
| const formData = getValues(); | ||
| const { field } = useController({ | ||
| control, | ||
| name: "region", | ||
| rules, | ||
| }); |
There was a problem hiding this comment.
useController는 동일한 필드에 대해 여러 번 호출하면 안 됩니다. 현재 RegionStepContent와 RegionStepFooter에서 region 필드에 대해 각각 useController를 사용하고 있어, react-hook-form의 예기치 않은 동작을 유발할 수 있습니다. Footer에서는 useController 대신 useWatch를 사용하여 필드 값을 구독하고 유효성을 검사하는 것이 올바른 방법입니다. useWatch를 사용하려면 react-hook-form에서 import해야 합니다.
| const { control } = useFormContext<CreateMeetingForm>(); | |
| const handleComplete = () => { | |
| const formData = getValues(); | |
| const { field } = useController({ | |
| control, | |
| name: "region", | |
| rules, | |
| }); | |
| const region = useWatch({ | |
| control, | |
| name: "region", | |
| }); | |
| const isValid = !isNil(region); |
694e4cb to
ee3cde5
Compare
- mutationOptions 함수 사용하여 queryOptions/mutationOptions 파일 분리 - Step 컴포넌트에 useController 적용하여 setValue + useWatch 제거 - 커스텀 validation 훅 제거하고 field.value로 직접 유효성 검사 - form submit을 page.tsx로 위임하여 react-hook-form에 제출 액션 위임 - Chip 컴포넌트에 type="button" 기본값 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
776b6d1 to
27eee87
Compare
* feat: DotsLoader 컴포넌트 추가 3개의 점이 순차적으로 bouncing되는 로딩 UI 컴포넌트 구현 - size variant 지원 (small, medium) - bg-current로 부모 텍스트 색상 상속 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: Button 컴포넌트 높이 고정 (h-14) 로딩 상태에서 버튼 크기가 변하지 않도록 높이 고정 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: RegionStep 로딩 UI를 DotsLoader로 변경 Spinner 대신 DotsLoader 사용으로 버튼 배경색과의 대비 개선 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: 모임 생성 폼 리팩토링 (PR 리뷰 대응) (#49) * refactor: 모임 생성 폼 리팩토링 (PR 리뷰 대응) - mutationOptions 함수 사용하여 queryOptions/mutationOptions 파일 분리 - Step 컴포넌트에 useController 적용하여 setValue + useWatch 제거 - 커스텀 validation 훅 제거하고 field.value로 직접 유효성 검사 - form submit을 page.tsx로 위임하여 react-hook-form에 제출 액션 위임 - Chip 컴포넌트에 type="button" 기본값 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: 코드 포맷팅 * fix: queryOptions 모듈 분기 처리 과정에서 capacity 가 누락되었던 이슈 수정 --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: RookieAND <gwangin1999@naver.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: RookieAND <gwangin1999@naver.com>
* feat: DotsLoader 컴포넌트 추가 3개의 점이 순차적으로 bouncing되는 로딩 UI 컴포넌트 구현 - size variant 지원 (small, medium) - bg-current로 부모 텍스트 색상 상속 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: Button 컴포넌트 높이 고정 (h-14) 로딩 상태에서 버튼 크기가 변하지 않도록 높이 고정 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: RegionStep 로딩 UI를 DotsLoader로 변경 Spinner 대신 DotsLoader 사용으로 버튼 배경색과의 대비 개선 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: 모임 생성 폼 리팩토링 (PR 리뷰 대응) (#49) * refactor: 모임 생성 폼 리팩토링 (PR 리뷰 대응) - mutationOptions 함수 사용하여 queryOptions/mutationOptions 파일 분리 - Step 컴포넌트에 useController 적용하여 setValue + useWatch 제거 - 커스텀 validation 훅 제거하고 field.value로 직접 유효성 검사 - form submit을 page.tsx로 위임하여 react-hook-form에 제출 액션 위임 - Chip 컴포넌트에 type="button" 기본값 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore: 코드 포맷팅 * fix: queryOptions 모듈 분기 처리 과정에서 capacity 가 누락되었던 이슈 수정 --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: RookieAND <gwangin1999@naver.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: RookieAND <gwangin1999@naver.com>
## 1.0.0-beta.1 (2026-02-16) ### Features * [#70](#70) ([#72](#72)) ([b676e0e](b676e0e)) * [QA] 모임 생성 완료, 결과페이지 페이지 UI 개선 ([#66](#66)) ([f10225d](f10225d)) * [QA] 서비스 전체 배경색 및 Layout Root 그림자 효과 적용 ([#59](#59)) ([384b56f](384b56f)) * api client 모듈 생성 ([#37](#37)) ([a37b0a9](a37b0a9)), closes [#38](#38) [#39](#39) [#40](#40) [#41](#41) * Button 컴포넌트 추가 ([#11](#11)) ([83b7607](83b7607)) * Chip Component 추가 ([#9](#9)) ([e9d8b8f](e9d8b8f)) * Color theme 초기화 ([#2](#2)) ([97f1dcc](97f1dcc)) * DotsLoader 컴포넌트 추가 ([#48](#48)) ([cfe4582](cfe4582)), closes [#49](#49) * GA4 이벤트 트래킹 통합 ([#70](#70)) ([0c1b9fa](0c1b9fa)) * GTM(Google Tag Manager) 통합을 위한 Analytics 컴포넌트 추가 ([#57](#57)) ([87a6ded](87a6ded)) * IconBase 컴포넌트 및 아이콘 컴포넌트들 구축 ([#13](#13)) ([8557b75](8557b75)), closes [#FFCD00](https://github.com/Nexters/yogieat/issues/FFCD00) [#FFAD00](https://github.com/Nexters/yogieat/issues/FFAD00) [#15](#15) [#ff5a3c](https://github.com/Nexters/yogieat/issues/ff5a3c) * InputField 컴포넌트 추가 ([#16](#16)) ([99b8aa2](99b8aa2)) * Landing / Opinion Form 페이지 분리 ([#61](#61)) ([0f11e71](0f11e71)) * Layout 컴포넌트 추가 ([#10](#10)) ([9efce6f](9efce6f)) * Semantic Color Token 추가 ([#19](#19)) ([fcaedaf](fcaedaf)) * Spacing utility 클래스 초기화 ([#8](#8)) ([2e38d7a](2e38d7a)) * Tag 컴포넌트 추가 ([#20](#20)) ([f69dd05](f69dd05)) * Toast 컴포넌트 추가 ([#21](#21)) ([76e84b0](76e84b0)) * 모임 생성 퍼널 Step 1 (인원 선택) 구현 ([#23](#23)) ([7fc01a1](7fc01a1)), closes [#24](#24) [#1f2933](https://github.com/Nexters/yogieat/issues/1f2933) [#ff5a3c](https://github.com/Nexters/yogieat/issues/ff5a3c) [#25](#25) [#26](#26) [#27](#27) [#28](#28) [#29](#29) [#30](#30) [#31](#31) [#32](#32) [#34](#34) * 프로젝트 기초 세팅 진행 ([aa0ec20](aa0ec20)) * 프로젝트 폴더 구조 반영 ([e54962d](e54962d)) ### Bug Fixes * 1순위를 1개라도 선택했다면 바로 CTA 가 활성화 되도록 수정 ([#60](#60)) ([e5758b4](e5758b4)) * 1차 MVP 배포 이전 최종 QA 항목 반영 ([#58](#58)) ([6574231](6574231)) * Button/Chip type 속성 추가 및 의견 수렴 UX 개선 ([#50](#50)) ([7e86e4a](7e86e4a)), closes [#51](#51) [#52](#52) [#53](#53) [#54](#54) [#55](#55) [#56](#56) * cat 에서 echo 로 env.production 파일을 생성하도록 수정 ([f15307d](f15307d)) * CI/CD health check 타이밍 개선 및 수동 배포 기능 추가 ([54fd2b8](54fd2b8)) * Docker build-args로 환경 변수 전달 방식 변경 ([#77](#77)) ([e5fa0b9](e5fa0b9)) * Docker 이미지 강제 pull 및 컨테이너 재생성 ([#79](#79)) ([c253ec1](c253ec1)) * Health check 전략 개선 및 curl 기반으로 변경 ([765d3da](765d3da)) * nginx http2 deprecated 경고 해결 ([2fd9c75](2fd9c75)) * PendingView 내에서 ShareButton 을 렌더링 하지 않도록 수정 ([7bc3e12](7bc3e12)) * 결과 페이지 맛집 이미지 기본 placeholder, 공유하기 toast 미노출 ([#68](#68)) ([3c80844](3c80844)) * 동시 배포 방지를 위한 concurrency 설정 추가 ([e9bfd52](e9bfd52)) * 모임 생성 퍼널 필드 상태 초기화 버그 수정 ([#64](#64)) ([3934066](3934066)), closes [#65](#65) * 모임 생성 폼 필드명 변경 (meetingDate → scheduledDate, location → region) ([#35](#35)) ([e90beed](e90beed)) * 배포 워크플로우에 GA4 환경 변수 추가 ([#73](#73)) ([835ae1f](835ae1f)) * 의견 수렴 페이지 내 UI 수정 및 인터렉션 개선 ([#36](#36)) ([a74f7da](a74f7da)) * 의견 수합 Form Capacity 폴링 제거 및 ErrorCode 타입 시스템 추가 ([#67](#67)) ([d55dba1](d55dba1)) * 인원 수 선택 Grid 및 의견 수렴 QA 수정 사항 반영 ([f01626e](f01626e)) * 테스트 용으로 추가했던 페이지 제거 및 icons 폴더 추가 ([4116025](4116025)) ### Code Refactoring * Button 컴포넌트 스펙을 Figma 명세에 맞춰 수정 ([#14](#14)) ([2e27f17](2e27f17)) ### Build System * Docker 빌드 시 NEXT_PUBLIC 환경변수 주입 프로세스 추가 ([#47](#47)) ([88ba163](88ba163)) ### Documentation * 프로젝트 개발 가이드 문서 추가 ([#84](#84)) ([4313145](4313145))
## 1.0.0 (2026-02-16) ### Features * [#70](#70) ([#72](#72)) ([b676e0e](b676e0e)) * [QA] 모임 생성 완료, 결과페이지 페이지 UI 개선 ([#66](#66)) ([f10225d](f10225d)) * [QA] 서비스 전체 배경색 및 Layout Root 그림자 효과 적용 ([#59](#59)) ([384b56f](384b56f)) * analytics 개선 및 네이버 서치 어드바이저 등록 ([#88](#88)) ([4372aa5](4372aa5)) * api client 모듈 생성 ([#37](#37)) ([a37b0a9](a37b0a9)), closes [#38](#38) [#39](#39) [#40](#40) [#41](#41) * Button 컴포넌트 추가 ([#11](#11)) ([83b7607](83b7607)) * Chip Component 추가 ([#9](#9)) ([e9d8b8f](e9d8b8f)) * Color theme 초기화 ([#2](#2)) ([97f1dcc](97f1dcc)) * DotsLoader 컴포넌트 추가 ([#48](#48)) ([cfe4582](cfe4582)), closes [#49](#49) * GA4 이벤트 트래킹 통합 ([#70](#70)) ([0c1b9fa](0c1b9fa)) * GTM(Google Tag Manager) 통합을 위한 Analytics 컴포넌트 추가 ([#57](#57)) ([87a6ded](87a6ded)) * IconBase 컴포넌트 및 아이콘 컴포넌트들 구축 ([#13](#13)) ([8557b75](8557b75)), closes [#FFCD00](https://github.com/Nexters/yogieat/issues/FFCD00) [#FFAD00](https://github.com/Nexters/yogieat/issues/FFAD00) [#15](#15) [#ff5a3c](https://github.com/Nexters/yogieat/issues/ff5a3c) * InputField 컴포넌트 추가 ([#16](#16)) ([99b8aa2](99b8aa2)) * Landing / Opinion Form 페이지 분리 ([#61](#61)) ([0f11e71](0f11e71)) * Layout 컴포넌트 추가 ([#10](#10)) ([9efce6f](9efce6f)) * Semantic Color Token 추가 ([#19](#19)) ([fcaedaf](fcaedaf)) * Spacing utility 클래스 초기화 ([#8](#8)) ([2e38d7a](2e38d7a)) * Tag 컴포넌트 추가 ([#20](#20)) ([f69dd05](f69dd05)) * Toast 컴포넌트 추가 ([#21](#21)) ([76e84b0](76e84b0)) * 모임 생성 완료 페이지 UI 리뉴얼 ([#89](#89)) ([17a3fc1](17a3fc1)) * 모임 생성 퍼널 Step 1 (인원 선택) 구현 ([#23](#23)) ([7fc01a1](7fc01a1)), closes [#24](#24) [#1f2933](https://github.com/Nexters/yogieat/issues/1f2933) [#ff5a3c](https://github.com/Nexters/yogieat/issues/ff5a3c) [#25](#25) [#26](#26) [#27](#27) [#28](#28) [#29](#29) [#30](#30) [#31](#31) [#32](#32) [#34](#34) * 프로젝트 기초 세팅 진행 ([aa0ec20](aa0ec20)) * 프로젝트 폴더 구조 반영 ([e54962d](e54962d)) ### Bug Fixes * 1순위를 1개라도 선택했다면 바로 CTA 가 활성화 되도록 수정 ([#60](#60)) ([e5758b4](e5758b4)) * 1차 MVP 배포 이전 최종 QA 항목 반영 ([#58](#58)) ([6574231](6574231)) * Button/Chip type 속성 추가 및 의견 수렴 UX 개선 ([#50](#50)) ([7e86e4a](7e86e4a)), closes [#51](#51) [#52](#52) [#53](#53) [#54](#54) [#55](#55) [#56](#56) * cat 에서 echo 로 env.production 파일을 생성하도록 수정 ([f15307d](f15307d)) * CI/CD health check 타이밍 개선 및 수동 배포 기능 추가 ([54fd2b8](54fd2b8)) * Docker build-args로 환경 변수 전달 방식 변경 ([#77](#77)) ([e5fa0b9](e5fa0b9)) * Docker 이미지 강제 pull 및 컨테이너 재생성 ([#79](#79)) ([c253ec1](c253ec1)) * Health check 전략 개선 및 curl 기반으로 변경 ([765d3da](765d3da)) * nginx http2 deprecated 경고 해결 ([2fd9c75](2fd9c75)) * PendingView 내에서 ShareButton 을 렌더링 하지 않도록 수정 ([7bc3e12](7bc3e12)) * 결과 페이지 맛집 이미지 기본 placeholder, 공유하기 toast 미노출 ([#68](#68)) ([3c80844](3c80844)) * 동시 배포 방지를 위한 concurrency 설정 추가 ([e9bfd52](e9bfd52)) * 모임 생성 퍼널 필드 상태 초기화 버그 수정 ([#64](#64)) ([3934066](3934066)), closes [#65](#65) * 모임 생성 폼 필드명 변경 (meetingDate → scheduledDate, location → region) ([#35](#35)) ([e90beed](e90beed)) * 배포 워크플로우에 GA4 환경 변수 추가 ([#73](#73)) ([835ae1f](835ae1f)) * 의견 수렴 페이지 내 UI 수정 및 인터렉션 개선 ([#36](#36)) ([a74f7da](a74f7da)) * 의견 수합 Form Capacity 폴링 제거 및 ErrorCode 타입 시스템 추가 ([#67](#67)) ([d55dba1](d55dba1)) * 인원 수 선택 Grid 및 의견 수렴 QA 수정 사항 반영 ([f01626e](f01626e)) * 테스트 용으로 추가했던 페이지 제거 및 icons 폴더 추가 ([4116025](4116025)) ### Code Refactoring * Button 컴포넌트 스펙을 Figma 명세에 맞춰 수정 ([#14](#14)) ([2e27f17](2e27f17)) ### Build System * Docker 빌드 시 NEXT_PUBLIC 환경변수 주입 프로세스 추가 ([#47](#47)) ([88ba163](88ba163)) ### Documentation * 프로젝트 개발 가이드 문서 추가 ([#84](#84)) ([4313145](4313145))
🎯 PR 제목
refactor: 모임 생성 폼 리팩토링 (PR 리뷰 대응)
📑 작업 상세 내역
PR #38, #42에서 @RookieAND 가 남긴 리뷰 코멘트 반영
PR #38 반영 내용
page.tsx에<form onSubmit={handleSubmit(onSubmit)}>추가, API 호출 로직을 page 레벨로 이동useController활용setValue+useWatch조합을useController로 변경usePeopleStepValidation,useDateStepValidation,useRegionStepValidation제거하고field.value로 직접 유효성 검사PR #42 반영 내용
mutationOptions함수 사용mutationOptions()함수로 mutation option 생성queryOptions.ts,mutationOptions.ts로 분리반영하지 않은 코멘트
PR #38 -
CreateMeetingForm필드 required 변경각 Step에서 toggle 기능(선택 해제)이 있어 폼 작성 중 값이
undefined가 될 수 있으므로 optional 유지onChange(isSelected ? undefined : count)onChange(slot === value ? undefined : slot)onChange(region === value ? undefined : region)추가 수정사항
Chip컴포넌트에type="button"기본값 추가 (form 내에서 의도치 않은 submit 방지)🙏 리뷰 요청 사항
📃 참고 자료
🖼️ 작업 결과물
테스트 완료 항목