파일 구조가 뭐길래

Yi Kanghoon·2023년 2월 5일
1

개요

SCG에서 진행하는 졸업논문 시스템 리뉴얼 중에 프론트엔드 파일 구조를 정립하는데 여러 레퍼런스와 의견이 충돌. barrel export를 적용하는 방향으로 논의가 진행됨

기존에는?

Ourlim 프로젝트의 경우 모든 컴포넌트 파일(tsx)은 폴더 내부에 존재하고, 동일 폴더에 스타일링 관련 파일이 존재하는 아래의 파일 구조를 따르고 있었음

components
├── common
│   └── comp1
│   	├── index.tsx
│   	└── styles.tsx
│   └── comp2
│   	├── index.tsx
│   	└──  styles.tsx
└── pages
    └── about
    	└── styles.tsx
    		├── index.tsx
    		└── styles.tsx

문제점

깔끔해보이지만 생각보다 큰 불편함이 있었다. (사실 난 해당 프로젝트에서 백엔드였지만 당연하다는 생각으로 공감할 수 있었다.)
경로
경로가 나오긴 하지만 파일명이 전부 index.tsx라서.... 탭을 전환할때 매우 불편하다.

졸논 리뉴얼에서는?

mantine을 적용하면서 위와 같은 파일 구조를 폐기하기는 했다. 그럼에도 createStyles를 활용하다 보니 스타일링 파일의 분리가 필요했고, 공통 컴포넌트를 구성하는 전용(?)컴포넌트의 위치도 정해야 했다. 그것을 정하고 시작하지 않았던 결과....
공통 컴포넌트 작업을 한 3명의 파일 구조가 모두 달랐다(!)

의논 시작

처음 참고한 사례는 mantine의 파일 구조였다.

components/
ㄴ Card/
    ㄴ index.ts             // export 모아둔 곳
    ㄴ Card.tsx             // 카드 메인 컴포넌트
    ㄴ Card.styles.ts       // 카드 스타일
    ㄴ ...

와 같은 구조였는데, 상주 이전까지 나의 경우는 index.ts에서 모든 export를 모아두는 barrel export이외에 다른 방식들은 따르고 있었다.
문제가 되는 부분은 해당 컴포넌트를 구성하는 컴포넌트이고, 해당 컴포넌트에서만 사용되는(단지 코드의 반복을 줄이기 위한) 컴포넌트의 위치였다.
또한 여러 종류의 컴포넌트가 존재할때, 같은 계층의 컴포넌트를 사용하는 컴포넌트의 경우.... 등 많은 것들도 논의가 필요했다.

index.ts의 위치?

일단 index.ts의 경우 외부에서 사용되는 컴포넌트와 같은 경로에만, 즉 각각의 컴포넌트 경로의 최상단에만 넣기로 했다.

Comp1
├── index.ts
├── Comp1.tsx
├── Comp1.styles.ts
└── Comp11
	├── Comp11.tsx           //이건 comp1에서만 사용되는 컴포넌트!
	└── Comp11.styles.ts

일단 무언가 깔끔해졌다. 물론 이견은 있었다. 이렇게 구성하면
import Comp1 from ~~/comp1/comp1.tsx와 같이 같은 이름이 경로에서 반복된다는 것이었는데, 어차피 실사용처에서는 index.ts에서 barrel export한 것을 사용하기에 import {Comp1} from ~~/comp1/index.ts로 사용하게 되니 상관없다는 의견 하에 위의 파일 구조를 따르기로 했다.

컴포넌트의 종류에 따른 index.ts

현재 컨벤션에서는 공통컴포넌트, 섹션컴포넌트, 페이지별 컴포넌트가 있는데, 각각의 바로 하위 디렉토리를 컴포넌트 디렉토리로 보고 그 디렉토리당 하나의 index.ts를 갖도록 했다. 그러니까...

components
├── common
│   ├── Comp1
│   │	├── index.ts
│   │	├── Comp1.tsx
│	│	└── Comp1.styles.ts
│   └── Comp2
│       ├── index.ts
│       ├── Comp2.tsx
│		└── Comp2.styles.ts
├── pages
	├── section
    │	├── Section1
    │   │	├── index.ts
    │   │	├── Section1.tsx
	│	│	└── Section1.styles.ts
    │   └── Section2
    │   	├── index.ts
    │   	├── Section2.tsx
	│		└── Section2.styles.ts
	└── 페이지명
    	├── Comp3
    	│	├── index.ts
    	│	├── Comp3.tsx
		│	└── Comp3.styles.ts
       	└── Comp4
       		├── index.ts
       		├── Comp4.tsx
			└── Comp4.styles.ts

이렇게 하기로 했다...(트리 그리기 힘드네)

여러 종류의 컴포넌트를 export 한다면?

Row,ActionRow,FavoriteRow와 같이 여러 종류의 컴포넌트를 export할 때는 어떻게 해야할지도 정해야 했는데, 이는 생각보다 빨리 아래와 같이 확정됐다. 스타일링 파일을 어떻게 작성할지만 고려하였고, 오히려 아랫단에서 이야기할 다음 문제로 의논이 길어졌다.

```bash
comp1s                      //여러가지니까 복수형으로!
├── index.ts
├── Comp1A.tsx
├── Comp1B.tsx
├── Comp1C.tsx
├── Comp1s.styles.ts       //스타일링 파일은 각 디렉토리당 최대 하나로 정했다고 생각하자
└── Comp11
	├── Comp11.tsx
	└── Comp11.styles.ts

위와 같이 모든 종류의 컴포넌트의 스타일링 파일을 하나의 파일로 묶되, 파일 내부에서

export const useComp1AStyle = createStyles();
export const useComp1BStyle = createStyles();
export const useComp1CStyle = createStyles();

와 같이 작성하는 것으로 결정했다.

같은 계층의 컴포넌트를 사용하는 컴포넌트가 있다면?

Row,ActionRow,FavoriteRow가 이런 상황이었다. 뒤의 두가지 컴포넌트는 앞의 Row컴포넌트를 사용하는 상황이었다. 사실 그냥 해도 상관은 없지만 외부에서 사용하는 컴포넌트 위치(컴포넌트별 디렉토리 최상단)에 있는 녀석을 내부에서도 사용한다는 것이 좀 찜찜했던 것인데, 결론적으로는 이렇게 하기로 했다. 최상단의 컴포넌트 자체로는 내부에서 사용하지 않기로. 무슨 뜻인지는 트리를 보면서 다시 설명해보자.

rows
├── index.ts
├── BasicRow.tsx
├── ActionRow.tsx
├── FavoriteRow.tsx
├── rows.styles.ts
└── Row
	├── Row.tsx
	└── Row.styles.ts

위와 같이 구성하는 것이다. 기존의 Row는 내부 컴포넌트로 만들고, return(<Row>{children}</Row>);와 같이 단순히 Row를 리턴하는 새로운 파일을 BasicRow로 작성하여 내부 컴포넌트와 외부 컴포넌트의 경계를 확실히 했다.

보류해둔 것들

컴포넌트 폴더들이 위치한 디렉토리(~~/common/, ~~/pages/페이지명/, ~~/pages/sections/)에 index.ts를 추가한다면

import {comp1} from ~~/common/comp1/index.ts
import {comp2} from ~~/common/comp2/index.ts
import {comp3} from ~~/common/comp3/index.ts
import {comp4} from ~~/pages/about/comp4/index.ts
import {comp5} from ~~/pages/about/comp5/index.ts

과 같이 반복되는 import 구문을

import {comp1, comp2, comp3} from ~~/common/index.ts
import {comp4, comp5} from ~~/pages/about/index.ts

로 줄일 수도 있을거 같았는데, 일단은 보류하고 이후에 리팩토링때 다시 검토하는 것으로 했다.

효과는?

사실 아직 모른다
이제 본격적으로 컴포넌트 작성을 시작했고, 당연히 유지보수는 당장 할 일도 없기에 효과는 어떨지 잘 모르겠다. 하지만 대략 1시간 이상을 컨벤션 결정에 쏟은 만큼 개발과정과 유지보수 과정에서, 특히 개발 참여진 말고 28,29,... 기 부원들이 유지보수 할 때 마치 라이브러리를 사용하는 듯한 개발 경험을 줄 수 있으면 좋겠다.

profile
Full 'Snack' Developer

0개의 댓글