본문 바로가기
Darakbang

코드를 컴포넌트화 해서 더 깔끔하고 가독성 좋은 코드로 변경하기

by 민우's 코딩 2024. 4. 22.

 

 

이번 프로젝트에서 내가 가장 고쳐야겠다고 싶었던 것 중에 꽤 높은 비율을 차지했던 사항이였다.

 

말로 장황하게 설명하는 것 보다 코드를 직접 보면서 고쳐나가는게 더 좋다고 보이는 파트이기에

어떤 방식으로 이런 변경을 하는지 살펴 보자!

 

return (
    <>
      <MainNavigation />
      <div className={styles.pageContainer}>
        <section className={styles.flexSection1}></section>
        <section className={styles.flexSection2}>
          <div className={styles.buttonContainer}>
            <Link href="/newpost">
              <button className={styles.button}><MdPostAdd /></button>
            </Link>
          </div>
          <div className={styles.cateSticky}>
            <div className={styles.categoryTitle}>
              <p className={styles.categoryText}>카테고리</p>
            </div>
            <form className={styles.categoryForm}>
              <div className={styles.categoryContainer}>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3001'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>커피 식 음료</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3002'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>영화 관람권</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3003'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>공연 관람권</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3004'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>숙박권</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3005'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>상품권</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3006'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>기타</p>
                </div>
              </div>
            </form>
            <MiniCategoryComponents className={styles.cateminibtn} selectedCategory={selectedCategory} onCategoryChange={handleCategoryChange}/>
          </div>
          <CommuPosts posts={posts} accessToken={accessToken} selectedCategory={selectedCategory} />

          <div className={styles.pagination}>
            {posts && posts.totalPages && currentPage > 1 && (
              <button onClick={goToPreviousPageGroup}><Image src={'/svgs/Polygon2.svg'} alt="" width={26} height={26} className={styles.before} /></button>
            )}
            {posts && posts.totalPages && Array.from({ length: Math.min(PAGE_GROUP_SIZE, posts.totalPages - currentPage + 1) }, (_, index) => (
              <button key={currentPage + index} onClick={() => handlePageChange(currentPage + index)} className={styles.pagebtn}>
                {currentPage + index}
              </button>
            ))}
            {posts && posts.totalPages && currentPage + PAGE_GROUP_SIZE <= posts.totalPages && (
              <button onClick={goToNextPageGroup}><Image src={'/svgs/Polygon3.svg'} alt="" width={26} height={26} /></button>
            )}
          </div>
        </section>
      </div>
    </>
  );

 

이번 프로젝트 중 하나였던 상품을 보여주는 페이지였다.

상품을 가져오는 코드는 잘 분리해서 하나의 컴포넌트로 출력했지만..

 

너무 장황하게 놓여있는 카테고리들과 페이지네이션 코드들이 메인에 바로 나와 있는걸 보면

아직 개발에 익숙치 않은 내가 봐도 어려운데 남이 이 코드를 봤을 때 

정녕 개발자의 코드가 맞을까? 싶을 정도의 혼잡한 코드들이었다.

 

그럼 리팩토링을 시작하게 되었으니

이제 저 코드들을 컴포넌트화 시켜서 가독성을 높히는 작업을 시작해보자!


import styles from './Category.module.css';

export default function CategoryComponents({ handleCategoryChange }) {

    return (
        <>
        <div className={styles.categoryTitle}>
              <p className={styles.categoryText}>카테고리</p>
            </div>
        <form className={styles.categoryForm}>
              <div className={styles.categoryContainer}>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3001'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>커피 식 음료</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3002'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>영화 관람권</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3003'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>공연 관람권</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3004'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>숙박권</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3005'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>상품권</p>
                </div>
                <div className={styles.cateMg}>
                  <input
                    type='checkbox'
                    id='3006'
                    className={styles.Checkboxes}
                    onChange={handleCategoryChange}
                  />
                  <p className={styles.cateTexts}>기타</p>
                </div>
              </div>
            </form>
            </>
    )
}

 

카테고리 코드들을 Category.jsx로 하나의 컴포넌트로 분리시켰다.

props를 통해 기존  handleCategoryChange의 기능을 유지 시켰다. 이런식으로 하나의 컴포넌트로 분리시키면

원래 위에 있던 페이지에 임포트하여 가져와서 출력만 시켜주면 될 것이다. 

 

return (
    <>
      <MainNavigation />
      <div className={styles.pageContainer}>
        <section className={styles.flexSection1}></section>
        <section className={styles.flexSection2}>
          <div className={styles.buttonContainer}>
            <Link href="/newpost">
              <button className={styles.button}><MdPostAdd /></button>
            </Link>
          </div>
          <div className={styles.cateSticky}>
            <CategoryComponents handleCategoryChange={handleCategoryChange} />
            <MiniCategoryComponents className={styles.cateminibtn} selectedCategory={selectedCategory} onCategoryChange={handleCategoryChange}/>
          </div>
          <CommuPosts posts={posts} accessToken={accessToken} selectedCategory={selectedCategory} />

          <div className={styles.pagination}>
            {posts && posts.totalPages && currentPage > 1 && (
              <button onClick={goToPreviousPageGroup}><Image src={'/svgs/Polygon2.svg'} alt="" width={26} height={26} className={styles.before} /></button>
            )}
            {posts && posts.totalPages && Array.from({ length: Math.min(PAGE_GROUP_SIZE, posts.totalPages - currentPage + 1) }, (_, index) => (
              <button key={currentPage + index} onClick={() => handlePageChange(currentPage + index)} className={styles.pagebtn}>
                {currentPage + index}
              </button>
            ))}
            {posts && posts.totalPages && currentPage + PAGE_GROUP_SIZE <= posts.totalPages && (
              <button onClick={goToNextPageGroup}><Image src={'/svgs/Polygon3.svg'} alt="" width={26} height={26} /></button>
            )}
          </div>
        </section>
      </div>
    </>
  );

 

맨 처음 장황했던 코드들이 하나의 컴포넌트를 임포트 해온 것 만으로 정말 간결한 코드로 변경되었다.

 

자 이제 그럼 밑에 페이지네이션 코드들도 분리 시켜보는 작업을 시작하자..

 


import Image from 'next/image';
import styles from "./Paginations.module.css";

export default function Pagination({ currentPage, posts, PAGE_GROUP_SIZE, handlePageChange, goToPreviousPageGroup, goToNextPageGroup }) {
  return (
    <div className={styles.pagination}>
      {posts && posts.totalPages && currentPage > 1 && (
        <button onClick={goToPreviousPageGroup}>
          <Image src={'/svgs/Polygon2.svg'} alt="" width={26} height={26} className={styles.before} />
        </button>
      )}
      {posts && posts.totalPages && Array.from({ length: Math.min(PAGE_GROUP_SIZE, posts.totalPages - currentPage + 1) }, (_, index) => (
        <button key={currentPage + index} onClick={() => handlePageChange(currentPage + index)} className={styles.pagebtn}>
          {currentPage + index}
        </button>
      ))}
      {posts && posts.totalPages && currentPage + PAGE_GROUP_SIZE <= posts.totalPages && (
        <button onClick={goToNextPageGroup}>
          <Image src={'/svgs/Polygon3.svg'} alt="" width={26} height={26} />
        </button>
      )}
    </div>
  );
}

 

원래 있던 코드들을 그대로 가져와 컴포넌트로 만들고 Props들을 전달만 한다면..

return (
    <>
      <MainNavigation />
      <div className={styles.pageContainer}>
        <section className={styles.flexSection1}></section>
        <section className={styles.flexSection2}>
          <div className={styles.buttonContainer}>
            <Link href="/newpost">
              <button className={styles.button}><MdPostAdd /></button>
            </Link>
          </div>
          <div className={styles.cateSticky}>
            <CategoryComponents handleCategoryChange={handleCategoryChange} />
            <MiniCategoryComponents className={styles.cateminibtn} selectedCategory={selectedCategory} onCategoryChange={handleCategoryChange}/>
          </div>
          <CommuPosts posts={posts} accessToken={accessToken} selectedCategory={selectedCategory} />

          <Pagination
            currentPage={currentPage}
            posts={posts}
            PAGE_GROUP_SIZE={PAGE_GROUP_SIZE}
            handlePageChange={handlePageChange}
            goToPreviousPageGroup={goToPreviousPageGroup}
            goToNextPageGroup={goToNextPageGroup}
          />
        </section>
      </div>
    </>
  );

정말 간단한 코드들로 변경된걸 볼 수 있다.

 

 

자 그럼 이렇게 컴포넌트들로 분리 한다면 장점이 있지 않겠는가?

 

1. 가독성

가독성 부분은 위에서 직접 확인한 것 처럼 코드 자체를 볼 때 이해하기 쉬워진다.

2. 모듈화하여 컴포넌트의 재 사용성

이렇게 코드를 작은 단위로 분리하여 관리한다면 코드를 재사용하기 쉬워질 것이다.

3. 유지보수

컴포넌트가 하나씩 독립적으로 작동하기 때문에 코드의 수정 및 유지보수가 매우 쉬워질 것이다.

4. 불 필요한 렌더링을 줄여 성능을 향상 시킨다.

컴포넌트가 필요한 경우에만 렌더링 될 것이기에 성능 자체가 당연히 향상 될 것이다.

 

 

 

오늘은 코드를 컴포넌트화 하여 분리 시키는 작업 및 장점에 대해서 알아보았다.

리팩토링하면서 오늘 소개한 부분만 분리 시키는 것이 아닌 

필요하다고 판단 되는 부분들을 전부 컴포넌트화 하여 분리 시킬 예정이다.