-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 리뷰 홈 레이아웃 추가 #146
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: 리뷰 홈 레이아웃 추가 #146
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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)
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 |
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! 이 PR은 사용자가 후기를 탐색하고 필터링할 수 있는 포괄적인 인터페이스를 제공하는 새로운 '후기 탐색' 페이지를 도입합니다. 기존의 임시 페이지를 대체하며, 다양한 필터링 및 정렬 옵션을 지원하고 데스크톱과 모바일 기기 모두에 적합하도록 반응형으로 설계되었습니다. 동시에, 후기 생성에 사용되는 기본 API 요청 구조가 업데이트된 백엔드 사양에 맞춰 리팩토링되어 데이터 일관성을 보장하고 새로운 검색 기능을 가능하게 합니다. 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은 리뷰 홈 레이아웃을 추가하고 관련 API 연동을 구현한 것으로 보입니다. 새로운 Explore 컴포넌트가 추가되었고, 리뷰 작성 로직도 새로운 API 명세에 맞게 수정되었습니다. 전반적으로 기능 구현이 잘 이루어졌지만, 몇 가지 개선점을 제안합니다. 필터링 로직의 잠재적인 버그, 컴포넌트의 key prop 사용, 타입 정의의 일관성 및 정확성, 그리고 사용자 경험(UX) 개선에 관한 피드백을 포함했습니다. 자세한 내용은 각 파일의 주석을 확인해주세요.
| const mappedResult = | ||
| resultArray.length === 0 || resultArray.includes('all') | ||
| ? undefined | ||
| : resultArray[0] |
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.
MultiDropDown 컴포넌트는 여러 값을 선택할 수 있도록 구현되어 있고, handleResultChange 함수에서도 여러 값을 콤마로 연결하여 result 상태를 업데이트합니다. 하지만 mappedResult에서는 resultArray[0]으로 첫 번째 값만 사용하고 있어, 사용자가 여러 필터를 선택하더라도 첫 번째 선택만 적용됩니다. 이는 사용자의 의도와 다르게 동작할 수 있는 버그입니다.
API가 여러 result 값을 지원하지 않는다면, MultiDropDown 대신 단일 선택이 가능한 드롭다운 컴포넌트를 사용하는 것을 고려해보세요. 만약 여러 값을 콤마로 구분하여 지원한다면, mappedResult 로직을 resultArray.join(',')과 같이 수정해야 합니다.
| className={`grid ${isDesktop ? 'grid-cols-3 gap-6' : 'grid-cols-1 gap-4'}`} | ||
| > | ||
| {bestReviewsData.content.map((review) => ( | ||
| <BestReviewCard key={review.title} review={review} /> |
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.
map 함수 내에서 key prop으로 review.title을 사용하고 있습니다. 제목은 고유하지 않을 수 있으므로, 중복될 경우 React의 리스트 렌더링 시 예기치 않은 동작이나 성능 저하가 발생할 수 있습니다. review 객체에 고유 ID인 reviewId가 있으므로 이를 key로 사용하는 것이 가장 좋습니다. reviewId가 없는 경우를 대비한 fallback 처리도 함께 추가하는 것을 권장합니다.
| <BestReviewCard key={review.title} review={review} /> | |
| <BestReviewCard key={review.reviewId ?? `${review.clubName}-${review.title}`} review={review} /> |
| <div className="flex flex-col gap-4"> | ||
| {reviewsData.content.map((review) => ( | ||
| <ReviewListItem | ||
| key={`${review.title}-${review.clubName}`} |
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.
map 함수 내에서 key prop으로 review.title과 review.clubName의 조합을 사용하고 있습니다. 이는 단순히 title만 사용하는 것보다 낫지만, 여전히 고유성을 100% 보장하지는 않습니다. review 객체에 고유 ID인 reviewId가 있으므로 key={review.reviewId}와 같이 사용하는 것이 가장 안정적입니다. reviewId가 없는 경우를 대비한 fallback을 함께 사용하는 것이 좋습니다.
| key={`${review.title}-${review.clubName}`} | |
| key={review.reviewId ?? `${review.title}-${review.clubName}`} |
| export default function Page() { | ||
| return <ConstructionPage /> | ||
| return ( | ||
| <Suspense fallback={null}> |
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.
| review: { | ||
| reviewId?: number | ||
| clubName: string | ||
| jobName: string | ||
| title: string | ||
| answerSummaries: { answerSummary: string }[] | ||
| rate: number | ||
| likeCount: number | ||
| commentCount: number | ||
| } |
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.
BestReviewCard 컴포넌트의 review prop 타입을 인라인으로 정의하고 있습니다. 이 타입은 features/review/types.ts에 정의된 ReviewSearchItem 타입과 거의 동일합니다. 코드 중복을 줄이고 타입 일관성을 유지하기 위해 ReviewSearchItem 타입을 직접 import하여 사용하는 것을 권장합니다.
import { type ReviewSearchItem } from '@/features/review/types'
function BestReviewCard({ review }: { review: ReviewSearchItem }) {
// ...
}또한, 현재 answerSummaries의 인라인 타입이 API 응답 타입(ReviewAnswerSummary[])과 일치하지 않습니다. questionTitleSummary 필드가 누락되어 있어 타입 안정성이 떨어집니다.
| review: { | ||
| reviewId?: number | ||
| clubName: string | ||
| jobName: string | ||
| generation: number | ||
| title: string | ||
| answerSummaries: { answerSummary: string }[] | ||
| rate: number | ||
| likeCount: number | ||
| commentCount: number | ||
| category?: string | ||
| } |
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.
ReviewListItem 컴포넌트의 review prop 타입을 인라인으로 정의하고 있습니다. 이 타입은 features/review/types.ts에 정의된 ReviewSearchItem 타입과 거의 동일합니다. 코드 중복을 줄이고 타입 일관성을 유지하기 위해 ReviewSearchItem 타입을 직접 import하여 사용하는 것을 권장합니다.
import { type ReviewSearchItem } from '@/features/review/types'
function ReviewListItem({ review }: { review: ReviewSearchItem }) {
// ...
}또한, 현재 answerSummaries의 인라인 타입이 API 응답 타입(ReviewAnswerSummary[])과 일치하지 않습니다. questionTitleSummary 필드가 누락되어 있어 타입 안정성이 떨어집니다.
| export interface ReviewAnswerRequest { | ||
| /** | ||
| * 노출 순서 | ||
| */ | ||
| sequence: number | ||
| /** | ||
| * 질문 ID | ||
| */ | ||
| question_id: number | ||
| /** | ||
| * 질문 타입 | ||
| */ | ||
| question_type: QuestionType | ||
| /** | ||
| * 답변 값 (객관식 또는 주관식) | ||
| */ | ||
| value: ReviewAnswerValue | ||
| } |
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.
ReviewAnswerRequest 인터페이스의 속성명으로 question_id, question_type과 같이 snake_case가 사용되었습니다. 프로젝트의 다른 타입 정의(예: BasicReviewCreateRequest의 clubId, jobId)에서는 camelCase를 사용하고 있으므로, 코드 스타일의 일관성을 위해 camelCase(questionId, questionType)로 통일하는 것을 고려해보세요. 만약 백엔드 API가 snake_case를 요구한다면, API 요청을 보내기 직전에 camelCase를 snake_case로 변환하는 어댑터나 함수를 사용하는 것이 프론트엔드 코드베이스의 일관성을 유지하는 데 도움이 됩니다.
🔗 관련 이슈
#119
✨ 변경사항
🎯 리뷰 포인트
📝 추가 정보