ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 20221208 TIL 리팩토링을 조금 더 편하게
    TIL 2022. 12. 8. 23:02

    2주에 걸쳐 과제 구현을 완료했다!

     

    과제를 완료했기 때문에 어제 작업했던 페이지네이션 컴포넌트 리팩토링을 진행하였다.
    이때까지 리팩토링을 할 때 리팩토링을 원래 파일에서 하다보면 혼란스러웠던 경우가 많았다.

    그리고 기존 파일에서 작업할 때 작업을 하는데도 어려움이 느껴졌었기 때문에

    리팩토링을 제대로 하는 경우에 다른 방식으로 접근을 해야겠다는 생각을 했었고,

    예전에 홀맨님께 조언을 구했었다.

    그런데 그동안 리팩토링을 제대로 할 일이 많지 않았기 때문에 그 방식을 한동안 까먹고 있었다.

     

    오늘은 어제 작성한 무지막지한 페이지네이션 컴포넌트 코드를 제대로 리팩토링을 해야됐는데,

    어떻게 하면 조금 편하게 리팩토링을 할 수 있을까 고민하는 중에

    홀맨님이 말씀해주신 방식이 떠올랐다.

    바로 기존 파일을 복사해서 복사한 파일에서 리팩토링을 진행하는 것이었다.

    테스트 코드는 이미 있기 때문에 안심하고 리팩토링을 진행할 수 있었고, 파일을 복사해서 중복되는 로직을 분리했다.

     

    어제 생각해본 대로 결국 페이지네이션 컴포넌트에서 쓰일 값들을 배열로 뽑아내기만 하면

    컴포넌트를 매우 작게 만들 수 있기 때문에 페이지네이션 컴포넌트에서 쓰일 값들(페이지 값들)을 뽑아내는 함수를 만드는 것부터 시작했다.

    두 페이지 사이 값이 2이상 차이나는 경우 ... 으로 표시를 해야했는데, 

    리액트에서 map을 돌리는 경우 고유한 key가 필요하다.

    ...는 최대 두 개가 있을 수 있고, 페이지 값들은 양수이기 때문에 key를 -1과 -2를 주었고,

    여러 번의 리팩토링 끝에 아래와 같이 리팩토링할 수 있었다.

    동기분의 리팩토링 중의 코드를 보고 복잡해보인다는 말을 듣고 rangeOf 메서드를 분리할 수 있었다.

    지금도 깔끔하진 않지만 동기분의 말씀 덕분에 메서드를 하나 더 분리할 수 있어 조금 더 깔끔해진 것 같다.

    const rangeOf = ({ size, start = 0 }) => [...Array(size).keys()].map((i) => i + start);
    
    const pageValues = ({ totalPages, currentPage }) => {
      if (totalPages < 8) {
        return [...rangeOf({ size: totalPages })];
      }
    
      if (currentPage < 5) {
        return [...rangeOf({ size: 5 }),
          { key: -1, value: '...' },
          totalPages - 1];
      }
    
      if (totalPages - currentPage < 4) {
        return [0,
          { key: -1, value: '...' },
          ...rangeOf({ size: 5, start: totalPages - 5 })];
      }
    
      return [0,
        { key: -1, value: '...' },
        ...rangeOf({ size: 3, start: currentPage - 2 }),
        { key: -2, value: '...' },
        totalPages - 1];
    };
    
    export default function Pagination({ url, totalPages, currentPage = 1 }) {
      const navigate = useNavigate();
    
      const handleClickPrevious = () => {
        navigate(`${url}?page=${currentPage - 1}`);
      };
    
      const handleClickNext = () => {
        navigate(`${url}?page=${Number(currentPage) + 1}`);
      };
    
      if (!totalPages) {
        return null;
      }
    
      const pages = pageValues({
        totalPages: Number(totalPages),
        currentPage: Number(currentPage),
      });
    
      return (
        <ul>
          <li>
            <button
              type="button"
              title="previous"
              name="previous"
              disabled={currentPage < 2}
              onClick={handleClickPrevious}
            >
              previous
            </button>
          </li>
          {
            pages
              .map((page) => (
                typeof page === 'number'
                  ? (
                    <li key={page}>
                      <Link
                        to={`${url}?page=${page + 1}`}
                        selected={Number(currentPage) === page + 1}
                      >
                        {page + 1}
    
                      </Link>
                    </li>
                  ) : (
                    <li key={page.key}>
                      <p>
                        {page.value}
                      </p>
                    </li>
                  )
              ))
          }
          <li>
            <button
              type="button"
              title="next"
              name="next"
              disabled={currentPage > totalPages - 1}
              onClick={handleClickNext}
            >
              next
            </button>
          </li>
        </ul>
      );
    }

    항상 복잡해 보이면 분리할 수 있는 메서드가 있는지 꼭 확인하자.

    그리고 이번에 리팩토링할 때 복사를 해서 리팩토링하는 것이 매우 편함을 느꼈다.

    테스트 코드가 있어서 마음놓고 리팩토링을 할 수 있었고, 기존 코드도 이미 있기 때문에 마음을 놓고 리팩토링을 할 수 있었던 것 같다.

    앞으로도 리팩토링할 때 기존 파일을 복사해서 수정해서 테스트가 통과되면

    기존 파일을 리팩토링한 파일로 대체하는 방식으로 작업하면 좋을 것 같다!

    댓글

Designed by Tistory.