React Structure 설계

SangHoon·2022년 2월 16일
1

프로젝트를 진행할 때나 과제를 진행할 때마다 프로젝트의 규모가 다른 것도 있지만, 초기설정 설계방식이 달랐다. 당시엔 팀원들이랑 ‘빨리 초기설정을 하고 개발에 들어가자!’라는 마인드로 진행했지만 마음속으론 기획과 구조를 좀 더 체계적으로 계획하고 개발하고 싶은 마음이 있었다. 불충분한 설계로 프로젝트를 진행하였을 때 각자가 맡은 페이지, 컴포넌트의 폴더구조가 달라 다른 팀원이 봤을 때 이해하기 어려웠고 수정해야 할 부분들이 계속해서 생겼다. 그 점을 방지하고자 나만의 리액트 설계구조 가이드를 작성하여 공유해 본다.


⚙️ CRA (create-react-app)

리액트를 접한 지 이제 4개월이 되어간다. 위코드에서도 그렇고 공식문서에서도 처음 리액트를 공부할 때 CRA를 통해 프로젝트를 쉽게 시작할 수 있다고 하여 줄곧 CRA로만 리액트 개발을 해왔다. CRA 개발방식에 대해 첫 의문이 든 계기는 인턴 할 때 리액트 네이티브를 개발하면서였다. 네이티브를 expo로 처음 접했지만 정작 실무에서는 Native-Cli 로 모든 구조를 작성해야 했다. 리액트도 마찬가지로 이젠 webpackbabel을 사용하여 초기 설정과 폴더구조를 직접 설계해야 할 것이다.


📌 관심사의 분리 (Separation of Concerns)

개발하면서 이런 고민을 빈번하게 했을 것이다.

💡 공용 컴포넌트에 다른 조건이 추가되어야 한다면 어떡하지..?
설계할 때 여기까진 생각 못 했는데 이 부분 또 수정 해야 하네..?

기획의 변화, 디자인 변경, 요청 사항 추가 등 적어도 한번은 계획했던 것과 달리 상황에 따라 대응하도록 수정해야 할 필요성이 생길 것이다.

하나의 함수, 변수, 클래스, 컴포넌트에 한 번에 너무 많은 일을 부여하게 되면 혼란에 빠지게 된다. 이러한 문제를 해결하는 방법으로 한 번에 한 가지만 하도록 단위를 나누는 것이다. 단위별로 하나의 관심사만 갖도록 하고 관심사에 대해서만 확실하게 동작하도록 만들어야 한다.

그렇게 되면 문제가 발생했을 때 전체 기능을 파악하기 위해 읽어야 하는 코드의 단위가 줄어들게 되고, 코드에 대한 파악이 빨라지므로 문제를 효과적으로 해결할 수 있게 된다.

이렇게 한 번에 한 가지만 걱정해도 괜찮도록 각각의 관심사에 따라 코드를 분리하는 기법을 관심사의 분리라고 부른다.

관심사의 분리가 적절히 구현된 코드에서는 낮은 결합도(각각의 코드가 서로 얽혀있지 않고 독립적으로 잘 분리되어 있음)과 높은 응집도(유사한 내용끼리 비슷한 위치에 잘 모여 있음)와 같은 특성을 발견할 수 있다.

장점

  • 코드가 더욱 명료해진다. - 자신이 어떤 일을 하고, 어떤 목적을 가지고 설계된 코드인지 보다 잘 드러나게 된다.
  • 코드 재사용성이 올라간다. - 여러 역할이 엉켜있는 코드보다, 역할별로 잘 분리되어 있는 코드를 재사용하기가 쉽다.
  • 유지 보수가 용이하다. - 변경 사항이 생겼을 때 해당 관심사에 연관된 코드만 수정하면 된다.

🗂 디렉터리 구조

PROJECT
├── .vscode/
├── node_modules/
├── package.json
├── package-lock.json
├── .eslintrc
├── .prettierrc
├── .gitignore
├── README.md
│
├── public/                        
│   ├── images/                   // 이미지 파일 폴더
│   └── data/                     // Mock 데이터 폴더
│
└── src/
	├── index.js
	├── utils.js                         // 유틸함수 정의
	├── constants.js                     // 상수데이터 정의
 	├── Router.js                 
    ├── components/                      // 공통 컴포넌트 폴더
    │   └── ComponentName/               // 공통 컴포넌트 별 폴더
    │       ├── ComponentName.jsx
    │       └── ComponentName.style.jsx  // 컴포넌트 style 정의
    │
    ├── pages/                           // 라우트에 의한 분류 페이지 폴더 	
    │   └── PageComponentName/
    │       ├── PageComponentName.jsx
    │       └── PageComponentName.style.jsx	
    │ 
    ├── styles/               	         // styled-component 스타일 폴더
    │   ├── GlobalStyle.jsx
    │   └── theme.js
    │
    ├── redux/                           // redux 폴더
    │   ├── store.js                     // redux store
    │   ├── actions/                     // 액션 정의 폴더
    │   └── reducers/                    // 리듀서 정의 폴더
    │ 
    └── hooks/                           // custom hook 폴더

프로젝트마다 사용하는 기술 스택에 따라 변경될 수 있지만, 현재 기본적으로 styled-components, react-router-dom, redux를 사용하는 기준에서 작성하였다.

나는 디렉터리 구조 설계 시 리액트 공식문서에서 권장하는 구조로 파일의 기능이나 라우트에 의한 분류로 설계하는 것을 지향한다.

  • 컴포넌트의 이름은 PascalCase로 작성하고 그 이외는 camelCase로 작성한다.
  • 공통으로 사용되는 컴포넌트 설계 시 src/components 경로에 Nav, Button 등 폴더로 관리한다. 공통 컴포넌트는 충분한 소통을 통해 필요한 Props를 고려하여 작성한다.
  • pages에서는 라우트에 의한 페이지별 컴포넌트를 작성한다. 각 페이지에서 개별로 필요한 컴포넌트는 각 페이지 폴더 안에 작성한다.
  • styles 폴더는 styled-components의 전역 스타일, reset css, theme을 작성한다.
  • 각 컴포넌트 스타일은 동일 경로에 스타일만 따로 정의하는 파일(ComponentName.style.jsx)을 생성하여 컴포넌트 파일에서 임포트 해서 사용한다. 스타일 파일을 분리함으로써 코드의 가독성이 올라간다.
  • 자주 사용되는 로직이나 상수 데이터의 경우도 따로 constants, util, hooks에 작성하여 임포트하여 작성한다.

💡 마무리

아직 많이 부족한 설계이지만 관심사에 따른 분리, 재사용성, 유지보수, 가독성 등 여러 요인들을 지속적으로 고민하여 같이 개발하는 사람들로 하여금 보일러 플레이트가 될 수 있는 구조를 설계해 보고 싶다.

현재 CRA 설계구조로 개발 중이지만 추가적으로 webpack, babel, TypeScript를 사용한 디렉터리 구조도 설계해 볼 계획이다.

profile
상훈

1개의 댓글

comment-user-thumbnail
2022년 12월 28일

구조 설계로 고민중이였는대 잘보고 갑니다!

답글 달기