Conversation
Walkthrough이번 변경 사항은 게시물 목록과 상세 컴포넌트의 데이터 처리 및 UI 렌더링 방식을 수정합니다.
Changes
Sequence Diagram(s)sequenceDiagram
participant 사용자 as 사용자
participant 컴포넌트 as PostList 컴포넌트
participant 훅 as useSearchParams
participant 이미지 as 이미지
사용자->>컴포넌트: URL 접속 (search ?page=<페이지>)
컴포넌트->>훅: 페이지 파라미터 추출 요청
훅-->>컴포넌트: 페이지 번호 반환
컴포넌트->>컴포넌트: useEffect로 게시글 데이터 호출
이미지->>컴포넌트: 이미지 로드 실패 (onError 발생)
컴포넌트->>컴포넌트: handleImageError 호출 (failedImages 업데이트 및 콘솔 로그)
컴포넌트-->>이미지: placeholder 렌더링
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
src/app/(contents)/post/[detailId]/PostDetail.tsx (1)
257-264: 🧹 Nitpick (assertive)접근성 개선 필요
뒤로 가기 버튼에
onClick이벤트만 있고 키보드 이벤트(onKeyUp,onKeyDown또는onKeyPress)가 없습니다. 접근성을 위해 키보드 이벤트도 추가하는 것이 좋습니다.- <div className={styles.backBtn} onClick={() => router.back()}> + <div + className={styles.backBtn} + onClick={() => router.back()} + onKeyDown={(e) => e.key === 'Enter' && router.back()} + tabIndex={0} + role="button" + aria-label="뒤로 가기">
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
src/app/(contents)/post/PostList.tsx(5 hunks)src/app/(contents)/post/[detailId]/PostDetail.tsx(3 hunks)src/styles/pages/postDetail.module.scss(2 hunks)src/styles/pages/postList.module.scss(2 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/app/(contents)/post/PostList.tsx (2)
src/interface/IPost.ts (1) (1)
IPost(1-9)src/interface/IRoot.ts (1) (1)
IPagination(21-33)
🪛 Biome (1.9.4)
src/app/(contents)/post/[detailId]/PostDetail.tsx
[error] 269-270: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
🔇 Additional comments (17)
src/styles/pages/postList.module.scss (3)
26-26: 마진 주석 처리 개선마진을 주석으로 처리한 것은 좋은 접근입니다. 불필요한 상단 여백을 제거하여 컨텐츠가 더 자연스럽게 배치될 수 있습니다.
29-35: 반응형 패딩 추가모바일과 태블릿 화면에서의 패딩 조정이 잘 이루어졌습니다. 각 디바이스 크기에 맞게 적절한 여백을 제공함으로써 사용자 경험이 향상될 것입니다.
62-71: 반응형 높이 및 패딩 조정포스트 리스트 아이템의 높이와 패딩을 반응형으로 조정한 것은 매우 좋은 변경입니다. 작은 화면에서도 콘텐츠가 적절히 표시될 수 있도록 하는 중요한 개선사항입니다.
src/app/(contents)/post/PostList.tsx (5)
8-8: 페이지네이션 방식 개선
usePathname대신useSearchParams를 사용하여 페이지 번호를 추출하는 방식으로 변경한 것은 좋은 접근입니다. 이 방식이 URL 쿼리 파라미터를 사용하는 페이지네이션의 표준적인 처리 방법이며, 더 명확하고 유지보수하기 쉬운 코드가 됩니다.Also applies to: 28-30
33-33: 이미지 로드 실패 상태 관리 추가실패한 이미지를 추적하기 위한 상태를 추가한 것은 사용자 경험을 개선하는 좋은 접근입니다. 이를 통해 로드에 실패한 이미지에 대한 대체 UI를 제공할 수 있게 됩니다.
80-87: 이미지 에러 처리 함수 추가이미지 로딩 실패 시 상태를 업데이트하는 함수를 추가한 것은 좋은 접근입니다. 이를 통해 사용자에게 로드 실패에 대한 적절한 피드백을 제공할 수 있습니다.
92-92: 의존성 배열 수정
useEffect의 의존성 배열을pathname에서page로 변경한 것은 적절합니다. 이제 페이지 번호가 변경될 때만 포스트를 다시 불러오게 되어 불필요한 API 호출을 방지합니다.
120-120: 이미지 로드 실패 시 대체 UI 제공이미지 로드에 실패했을 때 "이미지 없음" 메시지를 표시하는 대체 UI를 구현한 것은 사용자 경험을 크게 향상시키는 좋은 변경입니다. 이미지가 로드되지 않는 상황에서도 사용자에게 적절한 피드백을 제공합니다.
Also applies to: 139-170
src/app/(contents)/post/[detailId]/PostDetail.tsx (3)
238-238: 썸네일 유무에 따른 클래스 조건 추가썸네일 존재 여부에 따라 조건부로 클래스를 적용하는 방식은 매우 유용합니다. 이를 통해 썸네일 유무에 따라 다른 스타일을 적용할 수 있어 UI의 일관성과 가독성이 향상됩니다.
269-271: 긴 제목 텍스트 처리 개선제목 길이에 따라 조건부로 스타일을 적용하는 것은 좋은 접근입니다. 긴 제목의 경우 특별한 스타일을 적용하여 가독성을 높이고 레이아웃이 무너지지 않도록 합니다.
🧰 Tools
🪛 Biome (1.9.4)
[error] 269-270: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
320-320: 스크롤 시 여백 높이 조정스크롤된 상태에서 타이틀을 위한 여백 높이를 70px에서 110px로 증가시킨 것은 좋은 변경입니다. 이는 타이틀이 고정됐을 때 콘텐츠가 타이틀 아래로 가려지지 않도록 하는 중요한 UI 개선입니다.
src/styles/pages/postDetail.module.scss (6)
17-39: 썸네일 유무에 따른 조건부 스타일 추가썸네일 존재 여부에 따라 다른 최소 높이를 설정하는 것은 좋은 접근입니다. 또한 반응형으로 다양한 디바이스 크기에 따라 적절히 조정한 것도 훌륭합니다. 이를 통해 일관된 UI를 유지하면서도 각 상황에 맞는 최적의 레이아웃을 제공할 수 있습니다.
48-58: 타이틀 스크롤 스타일 개선고정 높이 대신 최소/최대 높이를 사용하고, 정렬 방식을 변경한 것은 UI 개선에 효과적입니다. overflow 속성 추가로 콘텐츠가 넘치는 상황도 잘 처리되었습니다. 스크롤 시 타이틀의 가독성과 사용성이 향상될 것입니다.
70-84: 타이틀 래퍼 및 왼쪽 래퍼 스타일 개선타이틀 상단 래퍼의 정렬과 래핑 방식 변경, 그리고 왼쪽 래퍼의 최대 너비를 반응형으로 조정한 것은 다양한 화면 크기에서 타이틀이 적절히 표시되도록 하는 좋은 개선사항입니다.
88-98: 타이틀 텍스트 스타일 개선타이틀 텍스트의 줄바꿈과 오버플로우 처리 방식을 개선한 것은 긴 제목도 가독성 있게 표시하는 데 효과적입니다. 특히 웹킷 기반 브라우저에서의 다중 라인 표시 설정은 매우 유용합니다.
101-115: 버튼 래퍼 스타일 개선버튼 래퍼의 flex 속성과 간격 조정, 모바일에서의 방향 변경 등 반응형 디자인을 고려한 스타일 개선은 다양한 디바이스에서 일관된 사용자 경험을 제공하는 데 도움이 됩니다.
164-173: 제목 텍스트 처리 개선 및 긴 텍스트 클래스 추가타이틀 텍스트의 기본 스타일을 개선하고, 긴 텍스트를 위한 별도의 클래스를 추가한 것은 유연한 UI를 구현하는 좋은 방법입니다. 특히 긴 제목의 경우 말줄임표를 통해 깔끔하게 처리되어 레이아웃이 무너지지 않도록 합니다.
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
src/app/(contents)/post/PostList.tsx(5 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/app/(contents)/post/PostList.tsx (2)
src/interface/IPost.ts (1) (1)
IPost(1-9)src/interface/IRoot.ts (1) (1)
IPagination(21-33)
🔇 Additional comments (1)
src/app/(contents)/post/PostList.tsx (1)
8-8: 라우팅 및 페이지네이션 처리 방식 개선
usePathname대신useSearchParams를 사용하여 페이지 번호를 추출하는 방식으로 변경한 것은 좋은 개선입니다. 이는 쿼리 파라미터가 페이지네이션에 더 적합하며, RESTful URL 구조를 만들어 주기 때문입니다. 또한 useEffect의 의존성을 pathname에서 page로 변경한 것도 일관성 있는 접근법입니다.Also applies to: 28-29, 90-90
|
|
||
| const [postList, setPostList] = useState<IPost[]>([]) | ||
| const [pagination, setPagination] = useState<IPagination<IPost>>({} as IPagination<IPost>) | ||
| const [failedImages, setFailedImages] = useState<Record<string, boolean>>({}) |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
이미지 오류 처리 로직 추가
이미지 로딩 실패 시 처리하는 로직을 추가한 것은 사용자 경험을 개선하는 좋은 변화입니다. 다만, 콘솔 오류 로깅은 프로덕션 환경에서는 더 견고한 에러 처리 메커니즘으로 대체하는 것이 좋습니다.
콘솔 로깅 대신 더 체계적인 에러 추적 방법을 고려해 보세요:
const handleImageError = (postId: number): void => {
setFailedImages((prev) => ({
...prev,
[postId]: true,
}))
- console.error("썸네일 로드 실패:", postId)
+ // 프로덕션 환경에서는 에러 로깅 서비스 사용 고려
+ // 예: errorTrackingService.log(`썸네일 로드 실패: ${postId}`)
}Also applies to: 79-86
| {postList.length > 0 ? ( | ||
| postList.map((post, index) => { | ||
| const diff = dayjs().diff(dayjs(post.createdAt), "hour") | ||
| const imageLoadFailed = failedImages[post.id] |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
이미지 로드 실패 시 대체 UI 표시 개선
이미지 로드 실패 시 대체 UI를 표시하는 것은 좋은 사용자 경험 개선입니다. 하지만 인라인 스타일을 사용하고 있어 코드 유지보수 측면에서 개선의 여지가 있습니다.
인라인 스타일과 하드코딩된 텍스트를 CSS 모듈과 상수로 분리하는 것이 좋습니다:
+// 컴포넌트 상단에 추가
+const NO_IMAGE_TEXT = "이미지 없음"
{!imageLoadFailed ? (
<Image
className={styles.thumbnail}
src={handlePostThumbnail(post.thumbnail)}
alt={"thumbnail"}
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
style={{ objectFit: "cover" }}
loading="eager"
placeholder="blur"
blurDataURL={
darkMode
? "/loading-placeholder-dark.svg"
: "/loading-placeholder.svg"
}
onError={() => handleImageError(post.id)}
/>
) : (
- <div
- style={{
- display: "flex",
- alignItems: "center",
- justifyContent: "center",
- width: "100%",
- height: "100%",
- backgroundColor: darkMode ? "#333" : "#f5f5f5",
- color: darkMode ? "#ccc" : "#666",
- }}
- >
- 이미지 없음
+ <div className={classNames(styles.noImagePlaceholder, darkMode && styles.dark)}>
+ {NO_IMAGE_TEXT}
</div>
)}그리고 CSS 모듈에 다음 스타일을 추가하세요:
.noImagePlaceholder {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: #f5f5f5;
color: #666;
&.dark {
background-color: #333;
color: #ccc;
}
}Also applies to: 137-168
Summary by CodeRabbit
New Features
Style