team logo icon

컴포넌트 분리 기준과 필요성

컴포넌트 분리의 필요성과 그 기준에 대해 응집도와 결합도를 바탕으로 알아보자.

🌐 컴포넌트 분리의 필요성


  • 단일 책임 원칙(SRP) 구현

    : 각 컴포넌트는 하나의 명확한 역할을 수행하여 코드의 이해도와 유지보수성을 향상시킨다.

  • 재사용성 향상

    : 공통 기능을 가진 컴포넌트를 분리하여 여러 페이지에서 재사용 가능하다.

  • 가독성 증대

    : 코드를 작고 독립적인 컴포넌트로 나누어 코드의 가독성과 이해도를 높인다.

  • 테스트 용이성

    : 컴포넌트 단위 테스트를 쉽게 수행하여 코드의 안정성을 높인다.

  • 협업 개선

    : 개발자들이 각 컴포넌트에 집중하여 개발하면서 협업의 효율성을 높인다.


사실 텍스트로만 보면 크게 와닿지 않을 수 있기 때문에 프로젝트에서 컴포넌트에서 공통적으로 쓰이는 부분을 공통 컴포넌트로 제작했던 경험을 가볍게 공유해보고자 한다.


공통 모달 만들기

  • 디자이너 선생님들께 피그마로 전달받은 뷰에서 가져왔다.



모달 본문, 버튼 내용만 다른 모달이 5개의 뷰에서 쓰이고 있는 걸 확인할 수 있다.

이들을 공통 컴포넌트로 빼면 다른 컴포넌트에서 쓸 때 해당 모달 컴포넌트만 불러오면 되기 때문에 훨씬 간편해질 수 있다고 판단했다.


두 가지 모달에서 색이 칠해져 있는 버튼의 내용(예/아니오)이 달랐는데, 나 같은 경우 색이 칠해져있는 버튼의 내용에 초점을 두었고, 색이 칠해져 있는 버튼이 사용자가 누르도록 유도하는 버튼이라고 판단하여 컴포넌트명이 NegativeModal, PositiveModal로 컴포넌트를 나눠 공통 모달을 제작했다.

  • 이 글을 쓰면서 생각해보니 모달 안의 버튼도 공통 컴포넌트로 나눌 수 있을 것 같다는 생각이..

공통 모달의 코드 중 NegativeModal, 즉 아니오를 유도하는 모달 컴포넌트는 아래와 같다.


우선 인자로 어떤 걸 받는지 먼저 확인해보자.

interface ModalContentPropTypes {
  modalContent: string;
  isModalOpen: boolean;
  modalHandler: () => void;
  closeModalHandler: () => void;
}

modalContent: 모달의 본문 내용

isModalOpen : 모달의 현재 상태 (열림 true / 닫힘 false)

modalHandler : '예' 버튼을 눌렀을 때 실행하는 핸들러 함수

closeModalHandler : '아니오' 버튼을 눌렀을 때 모달을 닫는 핸들러 함수

  • 내가 분리했던 모달의 경우 '아니오' 버튼을 눌렀을 때 모두 모달을 닫는 로직이었기 때문에 이렇게 구성하게 되었다.

인터페이스를 활용해서 인자들을 전달받으니 모달마다 로직과 내용이 달라도 재사용 할 수 있는 걸 확인할 수 있다.

// '아니오'를 유도하는 모달
export const NegativeModal = (props: ModalContentPropTypes) => {
  const { modalContent, modalHandler, closeModalHandler, isModalOpen } = props;
  /* 기타 로직들 생략 */

  return (
    <ModalBackgroundWrapper $isModalOpen={isModalOpen}>
      <ModalWrapper ref={modalRef} $isModalOpen={isModalOpen}>
        <ModalContentLayout>{modalContent}</ModalContentLayout>
        <Spacing marginBottom="3.2" />
        <ModalBtnLayout>
          <NegativeButton onClick={modalHandler}>예</NegativeButton>
          <PositiveButton onClick={closeModalHandler}>아니오</PositiveButton>
        </ModalBtnLayout>
      </ModalWrapper>
    </ModalBackgroundWrapper>
  );
};





다음과 같이 버튼의 경우 내용을 children으로 받아 구성했고, onClick을 통해 props로 받은 핸들러 함수를 넘겨주도록 구성했다.


경험한 바를 기반으로 이런 부분들에서 컴포넌트 분리의 중요성을 느낄 수 있었다.

  • 컴포넌트를 분리한 뒤 컴포넌트가 하나의 역할만 하게 되어 코드의 가독성이 향상되었다 👍

  • 공통 컴포넌트를 분리하면서 재사용성을 높일 수 있었다 👍


그렇다면 컴포넌트의 분리 기준은 어떤 게 있을까?


🌐 컴포넌트 분리 기준


  1. 단일 책임 원칙

    • 각 컴포넌트는 하나의 명확한 역할을 수행해야 한다.

  2. 재사용 가능성

    • 비슷한 기능을 하는 부분은 독립된 컴포넌트로 분리하여 재사용성을 높인다.

  3. 가독성

    • 코드를 작고 독립적인 컴포넌트로 나누어 가독성을 높인다.

  4. 상태와 라이프사이클

    • 컴포넌트가 관리하는 상태와 라이프사이클 메서드를 고려하여 분리한다.

  5. UI 요소

    • 서로 다른 UI 요소는 별도의 컴포넌트로 분리한다.


컴포넌트 분리 기준을 구체화하기 위해 응집도와 결합도라는 개념도 살펴보도록 하자.

응집도와 결합도 ?


응집도 (Cohesion)

💡 모듈에 포함된 내부 요소들이 하나의 책임/목적을 위해 연결되어 있는 연관된 정도

  • 모듈이 하나의 목적을 위해 수행하는 요소들 간의 연관성 척도

  • 모듈 내부의 기능적인 응집 정도

→ 높을 수록 좋음

  • 응집도가 높을수록 필요한 데이터를 한 번에 파악할 수 있기 때문에 코드를 이해하기 쉬워진다.

  • 응집도가 높을 수록 변경 대상과 범위가 명확해지기 때문에 코드를 수정하기 수월해진다.

    • 이에 따라 코드의 테스트를 하기에도 쉬워진다.


결합도 (Coupling)

💡 다른 모듈과의 의존성 정도

  • 모듈이 다른 모듈에 의존하는 정도의 척도

  • 모듈과 모듈 간의 상호 결합 정도

→ 낮을 수록 좋음

  • 결합도가 낮은 상황을 ‘느슨하게 연결되었다’라고 표현하기도 한다.


🧐 결국 응집도가 높고, 결합도가 낮도록 컴포넌트를 구성하는 것이 최적의 분리 방법이라 결론 내릴 수 있는데, 그렇게 구성하기 위해선 어떻게 해야할까?


  1. 인터페이스 기반 프로그래밍 - 결합도 낮추기

    • 인터페이스를 통해 구현된 코드가 변경되더라도 인터페이스를 사용하는 코드에는 영향을 덜 미치게 하여 모듈의 결합도를 낮춘다.

  2. 컴포넌트 단위 테스트에서는 렌더링과 인터렉션만 다루고, 다른 로직들은 훅으로 빼낸다. - 응집도 높이기



참고한 링크들

https://ctrlcccv.github.io/code/2024-03-05-component-split/

https://medium.com/@jang.wangsu/설계-용어-응집도와-결합도-b5e2b7b210ff

https://velog.io/@awesome-hong/%EC%9D%91%EC%A7%91%EB%8F%84%EC%9E%88%EB%8A%94-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%84%A4%EA%B3%84%EB%9E%80

https://curiousjinan.tistory.com/entry/effective-strategies-to-reduce-coupling-in-spring


https://ctrlcccv.github.io/code/2024-03-05-component-split/

https://medium.com/@jang.wangsu/설계-용어-응집도와-결합도-b5e2b7b210ff

최신 아티클
lighthouse에 대해
문성희
|
2024.05.13
lighthouse에 대해
lighthouse에 대해
prettier, eslint, styleLint에 대해
이진
|
2024.05.10
prettier, eslint, styleLint에 대해
4주차 공유과제
Article Thumbnail
박채연
|
2024.05.10
Prettier, ESLint, StyleLint
prettier, eslint, stylelint