-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 리뷰 작성 레이아웃 #132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 리뷰 작성 레이아웃 #132
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the ✨ Finishing touches🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Summary of ChangesHello @oaoong, 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! 이 Pull Request는 리뷰 작성 기능을 전면적으로 개편하여 사용자 경험을 개선하고 코드 구조를 효율화했습니다. 기존의 복잡한 리뷰 타입 선택 방식을 단순화하고, 각 리뷰 종류에 맞는 다단계 폼을 도입하여 사용자가 보다 체계적으로 리뷰를 작성할 수 있도록 했습니다. 또한, 동적으로 질문-답변을 추가할 수 있는 컴포넌트를 개발하고, 폼의 공통 요소들을 재사용 가능한 컴포넌트로 분리하여 개발 효율성을 높였습니다. Highlights
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
이번 PR은 리뷰 작성 플로우를 대대적으로 리팩터링하여 사용자 경험과 코드 구조를 크게 개선했습니다. 기존의 normal/premium 타입 구분을 제거하고, paper/interview/activity 종류에 따라 단계별 폼을 도입한 점이 인상적입니다. 특히 DynamicQASection과 같은 재사용 가능한 컴포넌트를 만들어 코드 중복을 줄이고 유지보수성을 높인 점이 돋보입니다.
전반적으로 훌륭한 리팩터링이지만, 몇 가지 개선점을 제안합니다. react-hook-form의 내부 속성을 사용하는 부분은 안정성을 위해 수정이 필요하며, API 요청 데이터 구조와 대규모 데이터 처리 방식에 대해서도 장기적인 관점에서의 개선을 제안했습니다. 또한, 코드 가독성을 위한 작은 제안도 포함되어 있습니다. 자세한 내용은 각 파일의 리뷰 코멘트를 참고해주세요.
| </div> | ||
|
|
||
| {fields.map((field, index) => { | ||
| const questionValue = control._formValues[name]?.[index]?.question || '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
react-hook-form의 비공식적인 내부 속성인 control._formValues에 직접 접근하고 있습니다. 이 속성은 라이브러리 업데이트 시 예고 없이 변경되거나 제거될 수 있어, 애플리케이션의 안정성을 심각하게 해칠 수 있는 위험한 방법입니다.
대신 공식적으로 지원하는 useWatch 훅을 사용하여 필드 값을 안전하게 구독하는 것을 강력히 권장합니다. 이렇게 하면 컴포넌트가 필요한 값의 변경에만 반응하도록 최적화할 수도 있습니다.
수정 제안:
컴포넌트 상단에서 useWatch를 사용하여 전체 배열을 구독하고, map 함수 내에서 해당 값을 사용하도록 리팩터링해야 합니다.
// DynamicQASection 컴포넌트 내부
import { useWatch } from 'react-hook-form';
// ...
const qaItems = useWatch({ control, name });
// ...
{fields.map((field, index) => {
const questionValue = qaItems?.[index]?.question || '';
const answerValue = qaItems?.[index]?.answer || '';
// ...
})}| data.qaItems.forEach((qa, index) => { | ||
| questions.push({ | ||
| questionId: 100 + index, // 동적 QA용 ID | ||
| questionType: QuestionType.Subjective, | ||
| value: `Q: ${qa.question}\nA: ${qa.answer}`, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
동적으로 추가된 Q&A 항목을 API로 전송할 때, questionId를 100 + index로 임의 생성하고 질문과 답변을 하나의 문자열로 조합하고 있습니다. 이 방식은 다음과 같은 잠재적 문제를 가집니다:
- 취약성: 백엔드에서
questionId100번 이상을 동적 Q&A로 처리한다는 암묵적인 약속에 의존하므로, 변경에 취약합니다. - 확장성: 질문과 답변 외에 다른 메타데이터(예: 질문 타입)를 추가하기 어렵습니다.
- 데이터 무결성: 문자열 파싱 오류가 발생할 수 있습니다.
백엔드와 협의하여 Q&A 데이터를 구조화된 객체 배열(예: { question: string, answer: string }[]) 형태로 보내는 것을 고려해보시는 것이 장기적으로 더 안정적이고 확장성 있는 설계가 될 것입니다. 만약 현재 백엔드 구조상 변경이 어렵다면, 해당 로직에 대한 상세한 주석을 추가하여 다른 개발자들이 컨텍스트를 쉽게 파악할 수 있도록 하는 것이 좋습니다.
| // <DropdownMenu> | ||
| // <DropdownMenuTrigger asChild> | ||
| // <Button size="small" variant="solid" className="typo-button"> | ||
| // 후기 작성 | ||
| // </Button> | ||
| // </DropdownMenuTrigger> | ||
| // <DropdownMenuContent className="w-40 mt-4 mr-10"> | ||
| // <DropdownMenuItem className="typo-body-3-3-r text-grey-color-5"> | ||
| // <Link href={AppPath.reviewNew('paper')} className="w-full px-4 py-2"> | ||
| // 서류 후기 | ||
| // </Link> | ||
| // </DropdownMenuItem> | ||
| // <DropdownMenuItem className="typo-body-3-3-r text-grey-color-5"> | ||
| // <Link | ||
| // href={AppPath.reviewNew('interview')} | ||
| // className="w-full px-4 py-2" | ||
| // > | ||
| // 인터뷰/면접 후기 | ||
| // </Link> | ||
| // </DropdownMenuItem> | ||
| // <DropdownMenuItem className="typo-body-3-3-r text-grey-color-5"> | ||
| // <Link | ||
| // href={AppPath.reviewNew('activity')} | ||
| // className="w-full px-4 py-2" | ||
| // > | ||
| // 활동 후기 | ||
| // </Link> | ||
| // </DropdownMenuItem> | ||
| // </DropdownMenuContent> | ||
| // </DropdownMenu> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| jobId: data.jobId, | ||
| questions, | ||
| rate: data.rate, | ||
| resultType: ResultType.Pass, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| control, | ||
| selectedClubId, | ||
| }: ReviewFormHeaderProps<T>) { | ||
| const { data: clubsData } = useClubsList({ size: 100 }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
동아리 선택을 위해 useClubsList({ size: 100 })를 사용하여 최대 100개의 동아리 목록을 한 번에 가져오고 있습니다. 현재는 문제가 되지 않을 수 있지만, 동아리 수가 크게 증가할 경우 초기 로딩 성능에 영향을 줄 수 있고 사용자 경험을 저해할 수 있습니다.
향후 확장성을 고려하여 다음과 같은 개선 방안을 제안합니다:
- 무한 스크롤(Infinite Scroll): 드롭다운 메뉴를 스크롤할 때 추가 데이터를 동적으로 불러옵니다.
- Debounced 검색: 사용자가 입력할 때마다 검색 API를 호출하여 관련 동아리 목록만 보여줍니다.
shadcn/ui의 Combobox 컴포넌트가 이러한 기능을 구현하는 데 좋은 참고 자료가 될 수 있습니다.
* Feat/#99 (#107) * feat: 검색 부분 미비한 로직 추가 * fix: 이미지 수정 * Feat/#79 (#96) * fix: 히어로 이미지 수정 * feat: 프리미엄 후기 구현 * feat: 세부페이지 구현 * fix: 에러해결 --------- Co-authored-by: yura <[email protected]> * feat: 좋아요 API 명세 추가 --------- Co-authored-by: oaoong <[email protected]> Co-authored-by: yura <[email protected]> * style: 디자인토큰, 타이포그래피 수정 (#112) * style: 디자인토큰, 타이포그래피 수정 * fix: onsuccess 콜백에 mutaiton 인자 추가 --------- Co-authored-by: yura <[email protected]> * fix : 디자인 토큰, 타이포그래피 수정 (#113) * style: 디자인토큰, 타이포그래피 수정 * fix: onsuccess 콜백에 mutaiton 인자 추가 * fix: mutation파일에 onmutationresult 추가 --------- Co-authored-by: yura <[email protected]> * style: 배경 기본 색상 변경 * fix: tab filter 마감순 추가 (#129) Co-authored-by: yura <[email protected]> * fix: 탐색하기 레이아웃 수정 (#131) * style: 탐색하기 사이드바, 히어로 이미지 수정 * style: 탐색하기 레이아웃 수정 --------- Co-authored-by: yura <[email protected]> * feat: 리뷰 작성 레이아웃 (#132) * feat: 리뷰 작성 연결 페이지 재정의 * feat: 리뷰 UI 개발사항 반영 * fix: formatting * feat: QnA 컴포넌트 추가 * feat: 모바일카드 컴포넌트 구현 (#135) * refactor: card 컴포넌트 수정 * feat: 북마크 추가 * refactor: card 컴포넌트 수정 * feat: 모바일 카드 구현 * feat: 탐색하기 리팩토링 (#137) * feat: drawer 구현 * feat: 탐색 반응형 구현 * build: next 버전 패치 * build: lock파일 삭제 및 재설치 --------- Co-authored-by: oaoong <[email protected]> Co-authored-by: yura <[email protected]>
* Feat/#99 (#107) * feat: 검색 부분 미비한 로직 추가 * fix: 이미지 수정 * Feat/#79 (#96) * fix: 히어로 이미지 수정 * feat: 프리미엄 후기 구현 * feat: 세부페이지 구현 * fix: 에러해결 --------- Co-authored-by: yura <[email protected]> * feat: 좋아요 API 명세 추가 --------- Co-authored-by: oaoong <[email protected]> Co-authored-by: yura <[email protected]> * style: 디자인토큰, 타이포그래피 수정 (#112) * style: 디자인토큰, 타이포그래피 수정 * fix: onsuccess 콜백에 mutaiton 인자 추가 --------- Co-authored-by: yura <[email protected]> * fix : 디자인 토큰, 타이포그래피 수정 (#113) * style: 디자인토큰, 타이포그래피 수정 * fix: onsuccess 콜백에 mutaiton 인자 추가 * fix: mutation파일에 onmutationresult 추가 --------- Co-authored-by: yura <[email protected]> * style: 배경 기본 색상 변경 * fix: tab filter 마감순 추가 (#129) Co-authored-by: yura <[email protected]> * fix: 탐색하기 레이아웃 수정 (#131) * style: 탐색하기 사이드바, 히어로 이미지 수정 * style: 탐색하기 레이아웃 수정 --------- Co-authored-by: yura <[email protected]> * feat: 리뷰 작성 레이아웃 (#132) * feat: 리뷰 작성 연결 페이지 재정의 * feat: 리뷰 UI 개발사항 반영 * fix: formatting * feat: QnA 컴포넌트 추가 * feat: 모바일카드 컴포넌트 구현 (#135) * refactor: card 컴포넌트 수정 * feat: 북마크 추가 * refactor: card 컴포넌트 수정 * feat: 모바일 카드 구현 * feat: 탐색하기 리팩토링 (#137) * feat: drawer 구현 * feat: 탐색 반응형 구현 * build: next 버전 패치 (#139) * build: next 버전 업데이트 (#143) * build: 빌드수정 --------- Co-authored-by: oaoong <[email protected]> Co-authored-by: yura <[email protected]>
🔗 관련 이슈
Closes #119
✨ 변경사항
🎯 리뷰 포인트
📝 추가 정보