React.js 지식 - React.js에서 컴포넌트를 분리하는 것.

이유승·2023년 11월 2일
1

React.js 지식

목록 보기
4/8

React.js에서 컴포넌트를 분리하는 것은 애플리케이션의 확장성, 유지보수성, 그리고 개발의 효율성을 향상시키는 핵심적인 방법 중 하나이다. 개발자가 애플리케이션의 다양한 부분을 더 작고 관리 가능한 단위로 나눌 수 있게 하며, 팀 작업에서도 협업을 용이하게 하는 장점이 존재한다.

그런데 컴포넌트를 무조건 분리하기만 한다고 좋은 것이 아니다. 필요 이상으로 분리된 컴포넌트는 코드의 복잡성을 증대시키고 프로그램의 성능에도 악영향을 줄 수 있기 때문이다.



1. 컴포넌트 분리의 장점.

재사용성, 유지보수성, 가독성, 테스트 용이성

재사용성

export function Button({ onClick, label }) {
  return <button onClick={onClick}>{label}</button>;
}

동일한 구조의 버튼이 프로젝트 여러 곳에서 사용된다면 모든 컴포넌트에서 버튼 코드를 따로 작성하는 것 보다는 Button 컴포넌트를 따로 만들어두고 재사용하는 것이 편하다. 위 예시는 버튼 클릭시 실행될 onClick 함수와 버튼의 이름을 인자로 받아 사용하기 때문에 재사용이 가능해진다.

유지보수성

export function UserProfile({ user }) {
  return (
    <div>
      <Avatar src={user.avatarUrl} />
      <h1>{user.name}</h1>
    </div>
  );
}

이 가상의 UserProfile 컴포넌트는 상위 컴포넌트로부터 user 데이터를 받는다. Avatar 컴포넌트는 user 데이터의 아바타 이미지 url을 받아 이미지를 출력하는 역할을, 그 아래에서는 유저의 이름을 출력하고 있다.

만약 기능을 구현하면서 프로필 쪽의 무언가를 변경해야할 일이 생긴다면 UserProfile 컴포넌트를 바로 찾아서 바로바로 수정이 가능하다. 컴포넌트가 분리되어있지 않고 가령 User 컴포넌트에 모든 코드와 기능들이 밀집해 있다면 User 컴포넌트에 들어가서 프로필 부분을 찾는 것부터 시작해야한다. 코드와 기능의 복잡성이 늘어나면 늘어날 수록 필요한 파트를 찾는 시간과 노력이 커진다.

가독성

export function Layout({ header, content, footer }) {
  return (
    <div>
      <Header/>
      <Content/>
      <Footer/>
    </div>
  );
}

이 가상의 레이아웃 컴포넌트는 어떤 프로젝트에서 페이지의 구성 요소들을 배치하는 역할을 수행한다. 페이지 최상단부터 헤더, 컨텐츠 내용, 푸터 영역을 갖도록 위치를 지정해준다.

컴포넌트를 분리하게 되면 한 페이지에 어떤 요소들이 어떻게 배치될 것인가의 '레이아웃' 문제를 위 예시처럼 간단하게 처리할 수 있다. 하나의 페이지 혹은 컴포넌트에서 하나의 문제만을 다룰 수 있어 코드를 관리하기가 한결 편안해진다.

테스트 용이성

// tests/Button.test.js
it('calls onClick when clicked', () => {
  const onClick = jest.fn();
  const { getByText } = render(<Button onClick={onClick} label="Click me" />);
  fireEvent.click(getByText('Click me'));
  expect(onClick).toHaveBeenCalled();
});

소프트웨어 테스트의 Unit Test를 실행한다고 생각해보자, 컴포넌트가 적절하게 분리되어 있다면 테스트를 실행하는 것도 아주 간편하다. 그렇지 않고 페이지 하나에 여러 기능과 UI들이 섞여있다면 Unit Test를 실시하기 이전에 각 요소들을 Unit 단위로 나누는 것부터 시작해야한다.



2. 컴포넌트 분리의 단점.

코드의 복잡성 증가, 성능 저하, 상태 관리의 어려움 증가

코드의 복잡성 증가

컴포넌트를 분리하기 전에는 한 페이지에서 모든 요소들을 한번에 관찰하고 제어, 수정할 수 있었지만 컴포넌트가 나누어지게 되면 우선 전체 구조가 어떻게 되는지 파악해야하고 다수의 코드를 수정해야할 때 나누어진 컴포넌트를 일일이 들어가서 확인해봐야 한다.

성능 저하

분리된 컴포넌트는 필연적으로 다른 컴포넌트와 부모-자식 관계를 갖게 된다. React.js에서는 부모 컴포넌트가 업데이트되면 리렌더링이 발생하고, 뒤이어 자식 컴포넌트에도 리렌더링이 발생하게 된다. 이렇게 되면 개발자가 의도하지 않은 연쇄 리렌더링으로 인해 기능의 이상이나 성능상의 문제가 발생할 수 있다.

  • 반대로 자식 컴포넌트에서 리렌더링이 발생할 때에는, 아래와 같은 특정 조건에서만 부모 컴포넌트의 리렌더링이 발생한다.
    -> 부모 컴포넌트가 Context Provider일 때. 자식 컴포넌트에서 Context의 값을 업데이트하면 해당 Context를 사용하는 모든 컴포넌트들이 리렌더링 된다.
    -> setState나 상태 업데이트 함수 등을 이용하여 자식 컴포넌트가 부모 컴포넌트로부터 받은 상태를 변경하는 함수를 호출할 때.
    -> 자식 컴포넌트가 부모 컴포넌트로부터 받은 콜백 함수를 실행시키고, 그 콜백 함수가 부모 컴포넌트의 상태를 변경할 때.
    -> forceUpdate() 함수를 사용하여 상태나 props의 변경 없이도 강제로 리렌더링을 발생시킬 때.

상태 관리의 어려움 증가

같은 데이터를 여러 컴포넌트에서 동시에 사용하는 상황이 발생하게 되면, 상태 관리의 구조가 복잡해질 수밖에 없다. 이는 곧 Context API나 Redux같은 상태 관리 라이브러리의 사용을 유도하게 된다.



3. 컴포넌트 분리의 주의점.

적절한 크기 유지, 컴포넌트 사이의 의존성 주의하기

적절한 크기 유지

컴포넌트 분리의 대원칙, 하나의 컴포넌트는 하나의 기능한 수행하도록 하라.

컴포넌트 사이의 의존성 주의하기

분리된 컴포넌트가 서로 의존성을 갖게되면 컴포넌트를 분리한 의미가 없어진다. 하나의 컴포넌트가 변화할 때 다른 컴포넌트가 영향을 받아서는 안된다.

profile
프론트엔드 개발자를 준비하고 있습니다.

0개의 댓글