Home 2주차 - 나는 리액트를 어떻게 설계할 것인가?
Post
Cancel

2주차 - 나는 리액트를 어떻게 설계할 것인가?

😎나만의 리액트 설계 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
├── index.tsx
├── App.tsx
├── components
│   ├── atomic  //가장 작은 단위 ex) 버튼, text, 수평선...
         └── Button
             ├── index.tsx          //컴포넌트 함수
             ├── styled.(ts | css)  //스타일
             └── types.ts           //타입스크립트 적용 시 props에 대한 정의필요하므로 타입선언
│   ├── molecules //2개 이상의 atomic ex) 인풋+버튼 => 입력창
│   ├── organisms // atomic과 molecules가 합쳐진 곳 중복되지 않음
│   ├── templates // 하위 항목의 컴포넌트들을 배치하고 설계한 구조
│   └── pages  // templates 하나만 받아와 로직을 작동
├── store  //전역상태 관리
├── hooks  //커스텀 Hook 폴더
├── styles //기본 스타일 전역 선언 및 theme사용
├── routes // 리액트 라우터 함수 
├── constants // 상수
├── apis //API모음 
└── utils //재사용 함수모음, reducer 포함  

설계를 고민하는 이유

프로젝트를 시작하기 전 항상 디렉터리 구조에 대해 많은 고민을 한다. 디렉터리를 고민하는 것은 프로젝트를 어떻게 설계할 것이냐 라고 생각한다. 왜냐하면 구현해야 하는 작업을 순서대로 하게 된다면 작은 단위에서 큰 단위로 만들게 되기 때문에 디렉터리 구조가 프로젝트 작업프로세스에 영향을 미친다고 생각한다. 컴포넌트를 폴더에 컴포넌트 함수파일과 스타일파일을 따로 분리할지, import export 방식은 어떻게 할지를 생각한다. 이 고민을 하는 이유가 뭘까 곰곰이 생각해보니 얼마나 효율적인 개발방법 모색이다.

컴포넌트 vs 비컴포넌트

나는 리액트 개발 시 로직과 컴포넌트를 분리하려고 최대한 노력한다. 이 방법의 장점은 로직이 한눈에 보여진다는 점이 있고 단점은 컴포넌트 구현 시 많은 props들이 생겨날 수 있다는 점이다.

위의 디렉터리 구조는 많은 고민을 하고 지금까지 해왔던 프로젝트에서 가장 괜찮다고 생각한 부분과 atomic design을 합성해 설계한 구조이다. 구조는 컴포넌트 모음과 비 컴포넌트 모음으로 분리되어있다. 이렇게 한 이유는 컴포넌트에는 컴포넌트만 들어가게 해야 로직의흐름을 이해하기 편하다고 생각한다. 그러면 무조건 분리되어 있냐는 아니다. pages에서 데이터를 불러와 props로 내려주거나, 전역상태에서 컴포넌트에 넣어주면 되기 때문에 이는 프로젝트 특성상 조금은 달라질 수 있다.

규칙

컴포넌트 선언

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//index.(jsx | ts)
// 1. import 라이브러리, 연관된 것, 멀리있는것부터 순서대로

// 2. 컴포넌트 정의 (함수선언식으로 정의)

// 3. propType TS 쓸 때는 types.ts로 선언

// 4. 간단한 상수 설정(컴포넌트 함수 외부)

// 5. 해당 컴포넌트에서만 사용할 함수

//styled.(js | ts)
//export const 컴포넌트 명
//export const 컴포넌트 명
//export const 컴포넌트 명
//index에서 불러올 때는 import * as S from "./styled"
// 사용시 <S.컴포넌트 />

//types.ts 
// Props정의

store

  • 전역 상태를 정할 때는 propDrilling을 피하기 위해 확인 후 사용한다.
  • propDrilling을 해결하기 위해 합성 컴포넌트를 사용할 수 있지만 결합도를 따져 전역상태를 사용할지 정한다.

hooks

  • 컴포넌트에서 hook을 따로 정의한다.
  • 공통된 로직이 있는 경우 커스텀 훅으로 만든다.

constants

  • 2번이상 공통되는 매직스트링, 매직넘버를 피하기 위해 관련이름명.(js|ts)로 한다.

apis

  • 백엔드와 통신을 유의하여 파라미터로 url주소나 토큰을 받는 request라는 재사용 함수를 선언한다.
  • 이후 관련페이지이름.(js|ts)로 짓고 해당 url, options를 받는 함수들을 request에서 불러와 조합하여 사용한다.

utils

  • 최대한 재사용가능한 순수 함수들을 모아 놓는다.

방향성을 가지자

리액트에서는 구조를 따로 정의하지 않았기 때문에 설계는 다양하다고 생각한다. 또한 나도 작은 프로젝트는 많이 해봤지만 상대적으로 규모가 큰 프로젝트 경험은 많지 않기에 내가 설계한 구조를 절대적 맹신은 하지는 않는다.

다만 새롭게 시작 또는 팀에 합류해서 프로젝트 시작 시 어느정도 가이드 라인이 있으면 내가 정한 설계에서 변화에 대처하는 기준선이 될 것이라 생각한다.

-- Missing configuration options! --