최우진 sprint5#76
Hidden character warning
Conversation
| --- | ||
|
|
||
| 본 프로젝트는 [코드잇](https://www.codeit.kr)의 소유이며, 교육 목적으로만 사용됩니다. © 2025 Codeit. All rights reserved. | ||
| dddd |
There was a problem hiding this comment.
불필요한 텍스트가 있습니다.
파일 마지막에 dddd라는 텍스트가 있습니다. 제거해주세요.
| <Routes> | ||
| <Route path="/products" element={<ProductListPage />} /> | ||
| <Route path="/" element={<MainHome />} /> | ||
| </Routes> |
There was a problem hiding this comment.
URL path 요구사항 미준수
요구사항에 따르면 중고마켓 페이지의 URL path는 /items이어야 합니다.
// 현재
<Route path="/products" element={<ProductListPage />} />
// 수정 필요
<Route path="/items" element={<ProductListPage />} />| </p> | ||
| </div> | ||
| </div> | ||
| <img className={styles.img} src="./src/assets/Img_home_02.svg" /> |
There was a problem hiding this comment.
target="_blank" 보안 취약점
target="_blank"를 사용할 때 rel="noopener noreferrer" 속성이 누락되면 Tabnabbing 공격에 취약해질 수 있습니다.
// 수정 전
<a href="https://www.facebook.com/..." target="_blank">
// 수정 후
<a href="https://www.facebook.com/..." target="_blank" rel="noopener noreferrer">참고:
Footer.jsx에서는ExternalLink컴포넌트를 통해 올바르게 처리하고 있습니다. 해당 컴포넌트를 재사용하면 좋겠습니다.
|
|
||
| export default function MainHome() { | ||
| return ( | ||
| <> |
There was a problem hiding this comment.
Header/Footer 컴포넌트 재사용
이미 Header.jsx와 Footer.jsx 컴포넌트가 존재합니다. 직접 마크업을 작성하는 대신 해당 컴포넌트를 재사용하면 일관성과 유지보수성이 향상됩니다.
import Header from '../../components/header/Header';
import Footer from '../../components/footer/Footer';
export default function MainHome() {
return (
<>
<Header />
<main>{/* ... */}</main>
<Footer />
</>
);
}| @@ -0,0 +1,76 @@ | |||
| import likeIcon from '@/assets/ic_heart.svg'; | |||
| import { useEffect, useState } from 'react'; | |||
There was a problem hiding this comment.
import 경로 일관성
alias(@/)와 상대 경로(../../../../)가 혼용되어 있습니다. 일관성 있게 한 가지 방식을 사용하는 것이 좋습니다.
// 현재
import likeIcon from '@/assets/ic_heart.svg';
import { priceFormat } from '../../../../utils/format';
// 권장 (alias 통일)
import likeIcon from '@/assets/ic_heart.svg';
import { priceFormat } from '@/utils/format';| setOrderBy(orderBy); | ||
| setIsOpen(false); | ||
| }; | ||
| const handleIsOpen = () => { |
There was a problem hiding this comment.
로딩 상태 관리 누락
setLoading(true)가 호출되지 않아 로딩 상태가 표시되지 않습니다. BestProductList.jsx에서는 올바르게 구현되어 있으니 참고해주세요.
const getProducts = async () => {
try {
setLoading(true); // 추가 필요
setError(null); // 에러 상태 초기화도 필요
// ... fetch 로직
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};|
|
||
| useEffect(() => { | ||
| const timer = setTimeout(() => { | ||
| setDebouncedKeyword(keyword); |
There was a problem hiding this comment.
빈 img 태그
src와 alt 속성이 없는 빈 <img /> 태그가 있습니다. 검색 아이콘으로 사용하려면 적절한 속성을 추가해주세요.
import searchIcon from '@/assets/ic_search.svg';
<img src={searchIcon} alt="검색" />| const [isOpen, setIsOpen] = useState(false); | ||
| const [orderBy, setOrderBy] = useState('recent'); | ||
| const [keyword, setKeyword] = useState(''); | ||
| const [currentPage, setCurrentPage] = useState(1); |
There was a problem hiding this comment.
검색 시 페이지 초기화 누락
검색어가 변경되면 페이지를 1로 초기화해야 합니다. 그렇지 않으면 검색 결과가 적을 때 빈 페이지가 표시될 수 있습니다.
useEffect(() => {
setCurrentPage(1); // 검색어 변경 시 페이지 초기화
}, [debouncedKeyword]);| <> | ||
| <header> | ||
| <nav className={styles.nav}> | ||
| <div className={styles.logoGroup}> |
There was a problem hiding this comment.
불필요한 Fragment
최상위 요소가 <header> 하나이므로 Fragment(<>...</>)가 불필요합니다.
export default function Header() {
return (
<header>
{/* ... */}
</header>
);
}|
|
||
| export default function Footer() { | ||
| return ( | ||
| <> |
There was a problem hiding this comment.
불필요한 Fragment
다른 파일과 마찬가지로 최상위 요소가 <footer> 하나이므로 Fragment(<>...</>)가 불필요합니다.
export default function Footer() {
return (
<footer className={styles.footer}>
{/* ... */}
</footer>
);
}
No description provided.