리액트 아키텍처 패턴 (React Architecture Patterns)

이기훈·2022년 1월 12일
7

Today-I-Learned

목록 보기
9/9

React로 작업을 하다보면 어떤 폴더구조로 작업을 하는게 효율적인지 의문을 가질때가 있다.
hook을 사용하는 사람이 있을것이고 Redux를 사용하는 사람도 있을것이다.
본인이 React를 사용함에 있어 어떤 방식으로 폴더구조를 구성하든지
처음에 폴더구조를 잘 구성해 놓아야 후에 작업 능률 하락 없이 작업 진행이 원할할 것이다.
이 블로그에서는 아키텍처 패턴에 대해서 설명해 놓았지만 본인만의 스타일이 있기 때문에 참고만 하는것이 좋을 것이다.
React Architecture Patterns for Your Projects

React는 프론트엔드 환경에서 주장이 없는(un-opinionated) 프레임워크이다.
React는 어플리케이션을 구성하고 구조하는 방법을 제공하지 않는다.
어플리케이션을 구성하고 구조하는 것은 개발자나 팀이 상호작용하는 방식이다.
잘 짜여진 프로젝트는 개발자들이 자신의 구현에 더 깊이 생각하고 정리하도록 요구한다.
또한 잘 짜여진 프로젝트는 코드베이스를 쉽게 탐색, 수정 및 확장할 수 있다.

조직화된 코드베이스는 팀이 장기적으로 주어진 구조내에서 생산성을 향상시킬수 있다.

디렉토리 구조 탐색

항상 React 어플리케이션의 시작점(Starting point)를 가지는게 좋다.
이 시작점은 assets, components, context, services, hooks, pages, utils 등 다양한 폴더로 구성된다.
이들 폴더 각각은 디렉토리의 목적을 달성하기 위해 다양한 파일이 있다.

create-react-app을 사용하여 React 어플리케이션을 만들었을때 index.js, App.js가 기본적으로 src 폴더 내에 구성된다.
아래는 기본적인 폴더 구성 예이다.

└── /src
    ├── /assets
    ├── /components
    ├── /context
    ├── /hooks
    ├── /pages
    ├── /services
    ├── /utils
    └── App.js
    ├── index.js    
 

여기서 디렉토리 이름을 코드베이스에있는 누구라도 이해할 수 있는 깔끔한 규칙을 따르는게 좋다.
/services 디렉토리는 /api로 대체 될수 있다.

공통 모듈

React의 한가지 이점은 모듈을 어떻게 나누든 상관이 없다.
React 앱에서 페이지를 개발할때는 모듈 형태로 분할 하는것을 고려하는것이 좋다.
이렇게 하면 복잡성을 줄이고 앱 전체에 걸쳐 재사용하거나 공유할 수 있는 구조를 만들 수 있다.

React 앱의 공유 가능한 코드는 자체 도메인으로 구분해야 한다.
공통 모듈은 재사용 가능한 커스텀 component, 커스텀 hook, 비지니스 로직, 상수(Constants) 그리고 유틸리티 함수 등이다.
이러한 재사용가능한 것들은 둘 이상의 페이지, 컴포넌트에서 사용하기 위해 앱 내에서 공유된다.

자체 폴더에 사용자 지정 구성 요소 추가

재사용 가능한 컴포넌트의 예로는 버튼, 입력 필드 및 카드 등이 있다.
이러한 컴포넌트는 /Components의 서브 디렉토리에 구성된다.

└── /src
    ├── /components
    |   ├── /Button
    |   |   ├── Button.js
    |   |   ├── Button.styles.js
    |   |   ├── Button.test.js
    |   |   ├── Button.stories.js
    |   ├──index.js

버튼 컴포넌트의 예로 위와 같이 작성할 수 있다.

그리고 컴포넌트 index.js에는 아래와 같이 작성 가능하다.

// /src/components/index.js
import { Button } from './Button/Button';
import { InputField } from './InputField/InputField';
import { Card } from './Card/Card';

export { Button, Card, InputField };

커스텀 훅 만들기

재사용 가능한 React hook은 재사용 가능한 작업 부분과 같다.
커스텀 훅을 만드는것은 코드 복잡성을 줄이는데 도움이 될 수 있다.

예를 들어 로그인과 가입에 사용하는 비밀번호 가시성을 전환할 수 있는 로직을 만든다면
두개의 페이지에 동일한 로직이 들어가게 된다.
이럴경우 커스텀 훅을 만들어서 사용하는것이 코드 복잡성을 줄일수 있다.

// /src/hooks/useTogglePasswordVisibility/index.js
export const useTogglePasswordVisibility = () => {
  const [passwordVisibility, setPasswordVisibility] = useState(true);
  const [rightIcon, setRightIcon] = useState('eye');
  const handlePasswordVisibility = () => {
    if (rightIcon === 'eye') {
      setRightIcon('eye-off');
      setPasswordVisibility(!passwordVisibility);
    } else if (rightIcon === 'eye-off') {
      setRightIcon('eye');
      setPasswordVisibility(!passwordVisibility);
    }
  };
  return {
    passwordVisibility,
    rightIcon,
    handlePasswordVisibility
  };
};

커스텀 훅은 use를 사용한 네이밍 규칙이 있다.
이 네이밍 규칙은 엄격하지는 않지만 규칙을 따르는 것이 좋다.

└── /src
    ├── /hooks
    |   ├── /useTogglePasswordVisibility
    |   |   ├── index.js
    |   |   ├── useTogglePasswordVisibility.test.js
    |   ├──index.js

절대 경로 사용

jsonconfig.json 파일에 complierOption과 webpack.config.js 를 사용하여

// some file
import { Button } from '../../components';
import { Button } from 'components';
import { Button } from '@components';

../ 를 사용하지 않고 깔끔하게 코드를 작성할 수 있다.

UI와 비지니스 로직 분리

/page 디렉토리는 앱에 대한 UI와 React Component의 구성으로 페이지를 구성할 것이다.
당연히 UI와 로직이 결합 될수 밖에 없지만 이것을 분리한다면 더욱 깔끔한 코드를 작성할 수 있을 것이다.

UI와 로직을 분리하는 방법은 API 요청 하는 등의 커스텀 훅을 제작하는 것이다.

import { useQuery } from 'react-query';
export const moviesApi = {
  nowPlaying: () =>
    fetch(`${BASE_URL}/movie/now_playing?api_key=${API_KEY}&page=1`).then(res =>
      res.json()
    )
};
export const useNowPlayingMovies = () => {
  const { isLoading: nowPlayingLoading, data: nowPlayingData } = useQuery(
    ['movies', 'nowPlaying'],
    moviesApi.nowPlaying
  );
  return {
    nowPlayingLoading,
    nowPlayingData
  };
};

위와 같이 API 호출과 로직을 따로 만들어 페이지나 컴포넌트에서 재사용 하는 것이 좋다.

Utils 디렉토리

Utils 디렉토리는 완전히 선택사항이다.
앱에 일부 글로벌 유틸리티 기능이 있는경우 UI 컴포넌트에서 분리하는것이 좋다.
Utils 디렉토리에는 앱 전체의 상수 등이 포함될 수 있다.

profile
Beyond Code

0개의 댓글