Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 62ac063432
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| flexShrink: 0, | ||
| border: '1px dashed #cbd5e1' | ||
| }}> | ||
| 아이디어 사진 |
There was a problem hiding this comment.
현재 코드는 페이지가 데이터 패칭, 로딩/에러 상태, 화면 조립까지 모두 담당하고 있고 목 데이터와 API 책임도 섞여있습니다. 아래 구조로 책임을 나눠서 수정해 주세요.
app/search/page.tsx
└─ IdeaSearchSection
├─ 제목/섹션 UI
└─ SectionErrorBoundary
└─ Suspense fallback={<SectionLoadingSpinner />}
└─ IdeaList (async Server Component)
└─ IdeaItem
권장 파일 구조는 다음과 같습니다.
features/idea-search/
api/get-idea-search-data.ts
components/idea-search-section.tsx
components/idea-list.tsx
components/idea-item.tsx
mocks/idea-search/
dummy-data.ts
types.ts
수정 기준:
page.tsx는IdeaSearchSection조립만 담당해 주세요.- 이 화면은 브라우저 전용 API나 상호작용 상태가 없으므로 Client Component로 만들 필요가 없습니다.
IdeaList를 async Server Component로 만들고 서버에서 데이터를 가져와 주세요. - 섹션에서 React
Suspense와 프로젝트 공용SectionErrorBoundary,SectionLoadingSpinner를 사용해 주세요. 해당 공용 컴포넌트가 포함된 최근 수상작 PR이 main에 반영된 뒤 main을 최신화해서 적용하면 됩니다. - 예상 가능한 빈 결과는
IdeaList에서 직접 표시하고, 예외는 삼키지 말고 섹션 Error Boundary가 처리하게 해 주세요. - 페이지와 컴포넌트의 인라인 스타일은 제거하고 Tailwind CSS를 사용해 주세요.
- 임시 목 데이터와 임시 응답 타입은
mocks/idea-search아래에 두고, API 파일에는 데이터 조회 함수만 남겨 주세요. 실제 API가 붙을 때 타입과 구현을 해당 기능 기준으로 구체화할 예정입니다. - 기존 자동 리뷰가 지적한 것처럼 대표 이미지는
next/image로 실제 렌더링하거나, 아직 사용하지 않을 필드라면 타입과 데이터에서 제거해 주세요. - PR 체크리스트는
[v]가 아니라[x]여야 GitHub task로 인식됩니다.
커밋 메시지도 컨벤션이 지켜지지 않았습니다(검색내용1, 검색내용2). 아래 글을 참고해서 커밋 컨벤션에 맞게 커밋해 주세요.
https://gajicoding.tistory.com/176
이 프로젝트에서는 타입은 영어, 콜론 뒤 제목은 한국어로 작성해 주세요. 예: feat: 아이디어 검색 목록 추가
현재 CI는 통과했지만, 위 구조 수정 후 lint/typecheck/test/build가 다시 모두 통과하는지 확인해 주세요.
| @@ -0,0 +1,44 @@ | |||
| // app/search/page.tsx | |||
| 'use client'; | |||
There was a problem hiding this comment.
이 페이지는 브라우저 API나 사용자 상호작용 상태가 없어서 Client Component일 이유가 없습니다. use client를 제거하고 RSC로 유지해 주세요. page.tsx는 IdeaSearchSection만 조립하고, 섹션 내부에서 Suspense/Error Boundary/List 책임을 구성하는 방식으로 최근 수상작 기능과 맞춰 주세요.
| const [searchData, setSearchData] = useState<SearchData | null>(null); | ||
| const [loading, setLoading] = useState<boolean>(true); | ||
|
|
||
| useEffect(() => { |
There was a problem hiding this comment.
useEffect 데이터 패칭은 첫 HTML 이후 브라우저에서 다시 요청하므로 로딩 플래시가 생기고, 서버 컴포넌트의 장점도 잃습니다. IdeaList를 async Server Component로 만들고 그 안에서 await getIdeaSearchData()를 호출해 주세요. 로딩은 섹션의 <Suspense fallback={<SectionLoadingSpinner />}>가 담당하면 됩니다.
| try { | ||
| const data = await fetchIdeaSearchData(); | ||
| setSearchData(data); | ||
| } catch (error) { |
There was a problem hiding this comment.
여기서 예외를 잡고 console.error만 하면 상위 Error Boundary로 오류가 전달되지 않습니다. 서버 데이터 패칭에서 오류를 삼키지 않고 throw되게 두고, IdeaSearchSection에서 공용 SectionErrorBoundary로 아이디어 검색 결과를 불러오지 못했습니다. 같은 섹션 단위 fallback을 표시해 주세요. 예상 가능한 빈 배열만 리스트 내부에서 별도로 처리하면 됩니다.
| @@ -0,0 +1,55 @@ | |||
| import { SearchData } from '../types/idea'; | |||
|
|
|||
| export const searchMockData: SearchData = { | |||
There was a problem hiding this comment.
목 데이터와 조회 함수를 한 파일에 섞지 말아 주세요. 현재 팀 구조에 맞춰 임시 데이터는 mocks/idea-search/dummy-data.ts, 임시 응답 타입은 mocks/idea-search/types.ts로 옮기고, 기능의 API 파일에는 getIdeaSearchData 조회 함수만 남겨 주세요. 그래야 실제 백엔드 연결 시 호출 구현만 교체할 수 있습니다.
| export default function IdeaItem({ idea }: IdeaItemProps) { | ||
| const isSale = idea.type === '판매'; | ||
|
|
||
| return ( |
There was a problem hiding this comment.
프로젝트에서 Tailwind CSS를 사용하기로 했으므로 인라인 style 객체는 제거해 주세요. 현재처럼 모든 엘리먼트에 스타일 객체가 들어가면 JSX가 정보 구조보다 스타일 코드에 묻히고, 반응형/디자인 토큰/리뷰 일관성도 떨어집니다. 우선 flex, flex-col, gap-*처럼 필요한 최소 Tailwind 클래스만 적용해 주세요.
| summaryText: string; | ||
| ideas: Idea[]; | ||
| } | ||
|
|
There was a problem hiding this comment.
최근 수상작과 같은 책임 구조로 IdeaList가 데이터 조회와 빈 결과 처리, 아이템 매핑을 소유하게 해 주세요. 즉 이 컴포넌트를 async Server Component로 만들고 summaryText/ideas를 페이지에서 받지 말고 내부에서 조회하면 됩니다. 페이지는 목록 데이터 구조를 몰라야 하고, IdeaItem만 단일 항목 렌더링을 담당하는 게 맞습니다.
| id: number; | ||
| image: string; | ||
| projectName: string; | ||
| keywords: string; |
There was a problem hiding this comment.
키워드는 쉼표가 포함된 하나의 문자열보다 readonly string[]로 모델링해 주세요. 그래야 키워드별 배지 렌더링, 필터링, 검색에 문자열 파싱 없이 안전하게 사용할 수 있습니다. 이 타입은 아직 목 응답용이므로 현재 단계에서는 mocks/idea-search/types.ts로 함께 옮겨 주세요.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0c34289e76
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| keywords: ["ai", "해커톤", "해외"], | ||
| description: "해당 프로젝트는 개인별 맞춤 운동이라는 점에서 유사함", | ||
| type: "판매", | ||
| imageUrl: "/images/project-1.png", // 이미지 추가됨 |
There was a problem hiding this comment.
getIdeaSearchData()가 항상 이 mock을 반환하고 IdeaItem이 imageUrl을 next/image의 src로 바로 렌더링하는데, repo-wide rg로 확인해도 /images/project-1.png~3.png는 여기서만 참조되고 public/에는 해당 파일이나 images/ 디렉터리가 없습니다. 따라서 /search의 첫 3개 카드에서는 썸네일 요청이 404가 되어 깨진 이미지가 보이므로, 실제 public 자산을 추가하거나 존재하는 경로/placeholder로 바꿔야 합니다.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9ec8d7c5db
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| projectName: string; | ||
| keywords: readonly string[]; | ||
| description: string; | ||
| type: '판매' | '기부'; |
There was a problem hiding this comment.
docs/product-context.md는 판매·기부·라이선스·공동 개발 등의 거래 및 협업 구조가 아직 확정되지 않았다고 명시하지만, 여기서 type을 '판매' | '기부'로 제한하면 이후 API가 공동 개발이나 라이선스 같은 방식을 제공할 때 모델과 모든 렌더링 분기를 함께 수정해야 합니다. 미확정 정책을 도메인 타입으로 고정하지 말고, 확정된 API 모델이나 확장 가능한 표시 모델로 분리해야 합니다.
AGENTS.md reference: AGENTS.md:L16-L16
Useful? React with 👍 / 👎.
| const isSale = idea.type === '판매'; | ||
|
|
||
| return ( | ||
| <div className="flex items-center justify-between p-5 bg-white border border-slate-200 rounded-xl shadow-sm hover:shadow-md transition-shadow gap-4"> |
There was a problem hiding this comment.
요약
데이터 목록
AI의 검색 결과 요약 문장
아이디어 리스트
아이디어 사진 / 프로젝트 이름/ 겹치는 키워드 / 겹치는 점 서술 텍스트 / 종류(기부인지 판매인지)
아이디어 개별 컴포넌트하나,
아디어리스트 컴포넌트하나
api폴더안에 목업데이터 파일을 만들어서 api에서 목업데이터 호출하는식으로해서 컴포넌트에서 api 호출해서
아이디어 리스트와 데이터 목록들 뿌리기
변경 사항
확인 사항
스크린샷