PF/Poketmon
[포켓몬 도감 프로젝트] #9: 리스트 정렬 기능 구현
akii
2025. 6. 26. 12:18
반응형
📝 [포켓몬 도감 프로젝트] #9: 리스트 정렬 기능 구현
🎯 목표
📄 페이징 + 검색 + 정렬 기능 구현
✅ 페이징 | 서버에서 offset, limit 사용 |
✅ 검색 | 클라이언트에서 filter(p.name.includes(q)) |
✅ 정렬 | 클라이언트에서 sort() 처리 |
✅ 구현 흐름 순서
- 전체 데이터를 먼저 fetchAllPokemon(limit=1302)
- searchParams.get('q'), ('sort'), ('p') 확인
- 검색 적용 → sort 적용 → slice(offset, offset + limit) 적용
🔹 리스트 필터링
위와 같이 Pokemon api 가 전체 데이터를 서버가 한 번에 주지 않고, 페이징 처리되어 있기 때문에 검색/정렬 기능을 구현하기에 어려움이 있어 리스트 전체를 한번에 받아오기로 했다.
const res = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=1302`);
👉 limit=1302로 리스트 전체를 수동으로 받아오게 해주었다.
const filtered = data
.filter((p: any) =>
p.name.toLowerCase().includes(search.toLowerCase()),
)
.map((p: any) => ({
name: p.name,
id: Number(p.url.split("/")[6]),
}));
👉 id 기준의 오름차순, 내림차순 정렬 기능구현을 위해 데이터의 url 에서 id만 추출해 다시 배열을 만들어 주었다.
const offset = (curPage - 1) * ITEMS_PER_PAGE;
const paginated = sorted.slice(offset, offset + ITEMS_PER_PAGE);
👉 필터링된 리스트를 다시 일정갯수로만 잘라서 페이지네이션을 구현하였다.
📄 정렬 로직
const sorted = filtered.sort((a: any, b: any) =>
sort === "asc"
? a.name.localeCompare(b.name)
: sort === "desc"
? b.name.localeCompare(a.name)
: sort === "id-desc"
? b.id - a.id
: a.id - b.id,
);
정렬 기준
- "asc" : 이름 A → Z
- "desc" : 이름 Z → A
- "id-desc" : 숫자 큰 순 (ID 높은 순)
- "id-asc" : 숫자 작은 순 (ID 낮은 순)
localeCompare : 브라우저의 로케일에 따라 작동하는 문자열 비교 함수, 1, -1, 0 만 리턴
👉 pokemon 이름에 특수문자가 들어가는 경우도 있어서 정확한 비교를 위해 localCompare 함수를 사용하였다.
📌 전체 코드
// app/page.tsx
{/* ... */}
try {
const data = type
? await fetchPokemonByType(type)
: await fetchAllPokemon();
const filtered = data
.filter((p: any) =>
p.name.toLowerCase().includes(search.toLowerCase()),
)
.map((p: any) => ({
name: p.name,
id: Number(p.url.split("/")[6]),
}));
const sorted = filtered.sort((a: any, b: any) =>
sort === "asc"
? a.name.localeCompare(b.name)
: sort === "desc"
? b.name.localeCompare(a.name)
: sort === "id-desc"
? b.id - a.id
: a.id - b.id,
);
const offset = (curPage - 1) * ITEMS_PER_PAGE;
const paginated = sorted.slice(offset, offset + ITEMS_PER_PAGE);
setTotalItems(filtered.length);
setPokemonList(paginated);
} catch (err) {
{/* ... */}
🎉 결과
반응형