[REACT] 어디까지 컴포넌트를 분리해야하는가? (1)

요즘 이래저래 개발을 진행하면서 로직을 작성하고있는데, 문득 그런 생각이 들었습니다.

 

지금까지는 단순히 '재사용을 할 것 같다', '나눠야 할 것 같다' 와 같은 구체화 되지는 않은 기준에 따라 로직을 작성했는데

확실한 기준을 잡고 컴포넌트를 분리해야 하지 않을까? 라는 생각이 말이죠

 

또, 컴포넌트 분리도 분리고 로직의 디자인패턴 또한 그렇습니다. 워낙 이전까지는 Redux 라이브러리를 사용했기때문에 전체적인 구조를 Page - Container - Component의 구성으로 로직을 작성했는데 이번 프로젝트부터는 recoil을 사용하면서 이러한 고민이 더 깊어진 것 같습니다.

 

Redux를 사용해보신 분들이라면 알겠지만, Redux에서는 Redux 와 연결된 (Store와 연결된) Container를 만들어 주고, 그 내부에 Component를 불러와서 렌더링시키는데, 이 때 Component에는 단순 렌더링 로직만 담는것을 권장했었습니다

 

근데 Recoil로 들어오니까 Atom과 Selector라는 개념이 등장하면서, 기존에 사용하던방식으로 설계를 하다보면 이곳저곳 어긋나는 모습을 보여줬었습니다. 이거 고민하다보니까 어떤식으로 계층을 만들어야할지 고민도 많이 했구요

 

아무튼 글이 좀 샜는데, 하여간 이번에 가장 고민 많이했던건 컴포넌트의 분리를 어디까지 해야하는가? 입니다.

저는 일반적으로 어떠한 컴포넌트가 재사용을 위해, 혹은 유지보수의 간편함을 위해 파일을 좀 다양하게 나누는 편 입니다.

 

 

해당 페이지를 만드는데만 해도 약 6개를 나눠놓았네요. 한 페이지에 너무 많은 컴포넌트를 나눠놓은게 아닌가? 라는 생각이 들긴합니다.

한 페이지를 구성하는데 너무 많은 컴포넌트를 나눠놓은게 아닌가 하며 고민하던 도중 컴포넌트 분리에 대해 정리해놓은 양질의 글이 있었습니다.

 

 

프론트엔드 아키텍처: 컴포넌트를 분리하는 기준과 방법

컴포넌트를 언제 분리해야 하고 어떻게 분리해야 하는지 살펴봅니다.

medium.com

( 생각해보기에 매우 좋은 글이라고 생각해서 한 번 읽어보시는 걸 추천드립니다. )

 

해당 글을 요약해보자면, 컴포넌트 분리에는 다음과 같은 기준이 필요하다고 합니다.

 

재사용 가능한 컴포넌트

재사용이 가능하다는 것은 일반적인 컴포넌트를 의미한다.

우리는 일반적으로 컴포넌트를 재사용한다고 했을 때, '속성이 보편적'인지 고민합니다. 즉, '다른 컴포넌트가 가져가서 사용할 수 있을만큼 보편적인가' 라는 것을 고려하고 있다고 말할 수 있습니다.

 

HTML 요소 측면에서의 재사용성을 고려하기.

우리가 만들어내는 컴포넌트는 결국 HTML을 포함하고 있습니다. 따라서 컴포넌트를 분리할 때 HTML 요소 측면에서 고려해야할 것을 놓치지 않는것이 중요합니다. 요소의 구조를 잡을 때는 BEM의 개념을 사용하는것이 컴포넌트를 분리할 때 기준으로서 도움이 된다고 합니다.

BEM에 대해서는 하단을 참조하시면 더 많은 내용을 얻으실 수 있습니다.

 

[CSS 방법론] BEM 방식

오늘은 CSS 방법론을 다뤄보겠습니다 ;-) 말이 거창하긴 한데 쉽게 풀어쓰면 'CSS 클래스네임을 어떻게 지으면 좋을지' 고민해보는 거죠. 방법론에는 여러 가지가 있는데, 최근 BEM을 실무에 도입하

nykim.work

쉽게 말해보자면 'css 클래스네임을 어떻게 지으면 좋을지' 에 대한 한가지 방법이라고 할 수 있겠습니다.

BEM을 고려하여 컴포넌트를 분리하다 보면 결론적으로는 HTML 요소들이 주변 문맥에 크게 의존적이지 않을수록 좋다고 할 수 있겠습니다. 재사용성이 늘어나기 때문이죠

 

중복을 고려한 재사용성

우리가 컴포넌트의 재사용성에 대해 말할 땐 보통 중복을 떠올리고, 두 곳 이상에서 사용된 중복된 무언가를 추출하는 과정을 거칩니다. (재사용을 위해서) 하지만 서로 다른부분이 조금 존재한다면 조건문을 사용하게되는데 이런 경우에는 간단한 컴포넌트라면 큰 문제가 되지 않을수도있지만 실제 사례에서는 점점 거대해질겁니다

 

글에서는 이러한 현상을 약한 결합에서 강한 결합으로 바뀌어간다고 설명하고있습니다. 강한 결합이 될수록 변경이 어려워진다는 것이죠

또한, 많은 컴포넌트가 하나의 컴포넌트를 사용할수록 해당 컴포넌트에 의존하는 다른 컴포넌트에서 문제가 일어날 가능성 또한 높아집니다

 

추출한 컴포넌트 내부에 사용하는 방법에 따라 조건문이 추가된다는 건, 사용하는 컴포넌트들이 서로 다른 수정의 이유를 갖는것이기에 중복 제거와 재사용의 대상이 아니라고 할 수 있습니다. 물론, 조건문이 없는 컴포넌트는 만들기에는 너무나 어렵겠지만, 적어도 조건문을 추가할 때 컴포넌트의 관계에 어떤 영향을 주는지 아는것이 중요합니다.

 

또, 앞서 말한 의존성 문제의 연장선상에서 한 컴포넌트에 의존하는 대상이 많아지면 상위 컴포넌트들은 변경의 이유가 너무 많아질 수 있습니다.

따라서 이러한 문제를 해결하기 위해서는 재사용하려는 컴포넌트에는 정말 공통적인 것들만 남겨두고, 고유한 것들은 속성으로 전달하는 방법이 있겠습니다.

 

function Page1() {
  return (
    <ul>
      <li>
        <Card
          summary={<p>요약...</p>}
        />
      </li>
    </ul>
  );
}

function Page2() {
  return (
    <ul>
      <li>
        <Card ... />
      </li>
    </ul>
  );
}

function Card(props) {
  return (
    <section>
      <h3>...</h3>
      <p>가격...</p>
      {props.summary}
    </section>
  );
}

이러한 방법은 props drilling 피하거나 컴포넌트의 제어를 역전하는 등 좋은점을 더 많이 갖고있다고 하니 속성으로 컴포넌트를 전달하는 방법을 꼭 숙지해야해야겠습니다. 해당 방법은 공식문서에서도 소개중이라고 하네요.

 

Passing Props to a Component – React

The library for web and native user interfaces

react.dev

 

또, 해당 링크를 참조하여 보시면 더 자세한 이유또한 확인 가능합니다.

 

React component as prop: the right way™️

Exploring how to pass React components as props, why we would want to do it, and what is the best pattern for the job

www.developerway.com

 


 

내용이 많기때문에 나머지 내용은 추후 정리 예정입니다.