PF/Poketmon

[포켓몬 도감 프로젝트] #9: 리스트 정렬 기능 구현

akii 2025. 6. 26. 12:18
반응형

 

📝 [포켓몬 도감 프로젝트] #9: 리스트 정렬 기능 구현

 

 

🎯 목표

📄  페이징 + 검색 + 정렬 기능 구현
✅ 페이징 서버에서 offset, limit 사용
✅ 검색 클라이언트에서 filter(p.name.includes(q))
✅ 정렬 클라이언트에서 sort() 처리

 


 

✅  구현 흐름 순서

  1.  전체 데이터를 먼저 fetchAllPokemon(limit=1302)
  2.  searchParams.get('q'), ('sort'), ('p') 확인
  3.  검색 적용 → sort 적용 → slice(offset, offset + limit) 적용

 

 

🔹 리스트 필터링

https://pokeapi.co/api/v2/pokemon/

위와 같이 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) {
{/* ... */}

 

🎉 결과

이름 오름차순

 

이름 내림차순

 

id 낮은순서

 

id 높은순서

반응형