FrontEnd Develop/Project : Team Nova MJ Search

MJS _ 명대방송국 연계

Frisbeen 2025. 8. 8. 15:28

 

1. 페이지네이션 설계안

 

요구사항

 

  1. 한 페이지에 9개의 데이터를 보여준다.
  2. 페이지 하단에 점(dot) 형태의 페이지네이션 UI를 표시한다.
  3. 한 번에 최대 5개의 점만 표시한다.
  4. 다음/이전 버튼으로 페이지를 이동하면 점이 슬라이드처럼 움직인다.
  5. 점을 클릭하면 해당 페이지로 이동한다.

 


2. 기본 프로토타입 구현

 

초기 구현은 단순하게 현재 페이지 기준으로 start/end 계산 후 점 배열을 만들고,

이전/다음 버튼, 점 클릭 시 onChange()로 페이지 변경 요청을 하는 구조였습니다.

 

type Props = {
  currentPage: number;
  totalPages: number;
  onChange: (page: number) => void;
  window?: number; // 보이는 점 개수
};

export default function Pagination({ currentPage, totalPages, onChange, window = 5 }: Props) {
  if (totalPages <= 1) return null;

  const half = Math.floor(window / 2);
  let start = Math.max(0, currentPage - half);
  let end = Math.min(totalPages - 1, start + window - 1);
  start = Math.max(0, Math.min(start, end - window + 1));

  const pages = [];
  for (let p = start; p <= end; p++) pages.push(p);

  return (
    <div>
      <button onClick={() => onChange(currentPage - 1)}>이전</button>
      {pages.map((p) => (
        <button key={p} onClick={() => onChange(p)} />
      ))}
      <button onClick={() => onChange(currentPage + 1)}>다음</button>
    </div>
  );
}

 

3. 발생한 문제

 

증상

 

  • 다음 버튼 클릭 시 점이 이동하지 않음
  • 점 클릭 시 UI가 갱신되지 않음
  • 간혹 버튼 클릭 시 페이지가 리프레시되는 현상 발생

 

원인 분석

 

  1. 상태(state) 갱신 누락 : 클릭 이벤트가 발생해도 currentPage가 변경되지 않았습니다.부모 컴포넌트에서 onChangesetCurrentPage와 연결하지 않아 클릭 이벤트가 발생해도 currentPage가 변경되지 않았습니다.
  2. 버튼 기본 동작 문제 : <form> 안에 페이지네이션이 있을 경우, 기본 <button>type"submit"이라 클릭 시 페이지가 새로고침됐습니다.
  3. 창(window) 슬라이드 로직 미비4 → 5로 넘어갈 때 점의 시작 위치가 갱신되지 않아 점이 고정되어 보였습니다.

 


 

4. 버그 수정 KEY.

(1) 부모와 상태 연결

<Pagination
  currentPage={currentPage}
  totalPages={totalPages}
  onChange={(p) => setCurrentPage(p)} // 필수
/>

 

(2) 슬라이드 방식 start/end 계산

window 단위 블록으로 페이지를 계산하여,

5개의 점만 유지하면서 블록 단위로 슬라이드되도록 수정했습니다.

const windowIndex = Math.floor(currentPage / window);
const start = windowIndex * window;
const end = Math.min(start + window - 1, totalPages - 1);

 

 

5. 최종 구현 코드

export default function Pagination({ currentPage, totalPages, onChange, window = 5 }: Props) {
  if (totalPages <= 1) return null;

  const windowIndex = Math.floor(currentPage / window);
  const start = windowIndex * window;
  const end = Math.min(start + window - 1, totalPages - 1);

  const pages: number[] = [];
  for (let p = start; p <= end; p++) pages.push(p);

  const go = (p: number) => {
    if (p < 0 || p > totalPages - 1 || p === currentPage) return;
    onChange(p);
  };

  return (
    <div className="w-full flex items-center justify-center gap-4 py-6">
      <button type="button" onClick={() => go(currentPage - 1)} disabled={currentPage === 0}>
        ‹ 이전
      </button>
      <div className="flex items-center gap-3">
        {pages.map((p) => (
          <button
            type="button"
            key={p}
            onClick={() => go(p)}
            className={p === currentPage ? 'bg-blue-10' : 'bg-grey-10'}
          />
        ))}
      </div>
      <button
        type="button"
        onClick={() => go(currentPage + 1)}
        disabled={currentPage >= totalPages - 1}
      >
        다음 ›
      </button>
    </div>
  );
}