폴더 구조 고민할 시간에 코딩 한 줄 더하자 (FSD)
폴더 구조란??
개발자가 눈으로 볼 수 있는 소프트웨어의 아키텍처가 아닐까?
폴더 구조는 다양하게 사용되고 있고 쉽게 찾아볼 수 있다.
NEXT.js
- 넥스트만의 컨벤션이 있음(앱 디렉토리나 정해진 폴더,파일 이름들)
- 이외에도 여러 컨벤션이 있음
Nest.js
- 컨트롤러, 모듈, 서비스 등 파일의 역할이 분명하고 컨벤션이 있어서 통일성있게 구분할 수 있음
- 모듈식 아키텍처
사용해봤던 예시
아토믹 디자인
- Atom
- atom은 더 이상 분해할 수 없는 기본 컴포넌트(input, button)
- Molecule
- 여러 개의 atom을 결합한 고유의 컴포넌트 (input과 버튼으로 이루어진 검색 창?)
- Organism
- 좀 더 복잡하고 서비스에서 표현될 수 있는 명확한 영역과 특정 컨텍스트를 가집니다.(상단 네비게이션 바 -> header), 재사용성은 상대적으로 위에 두개보다 낮아짐
- Template
- 템플릿은 page를 만들 수 있도록 여러 개의 organism, molecule로 구성할 수 있습니다. 아래 이미지와 같이 실제 컴포넌트를 레이아웃에 배치하고 구조를 잡는 와이어 프레임입니다. 즉, 실제 콘텐츠가 없는 page 수준의 스켈 레톤이라고 정의할 수 있습니다.
- Page
- page는 유저가 볼 수 있는 실제 콘텐츠를 담고 있습니다. template의 인스턴스라고 할 수 있습니다. 예를 들어 장바구니 페이지에 유저가 담은 상품이 없거나 10개를 담는 다양한 template의 인스턴스를 볼 수 있습니다.
내 프로젝트
- 아토믹 디자인도 알려진 대로 잘 적용하고 나누면 될 거 같지만 기준 자체는 주관적일 수 있다.
pages와 components
추가로 horizontal, vertical 폴더 구조도 있음
설계에는 정답이 없다. 폴더구조에도 정답은 없다.
프로젝트 성격에 맞는 적절한 폴더구조를 고민하고 적용하면 된다. 아주 작은 규모의 프로젝트라면 pages와 component 구조로만 나누는게 제일 효율적일 수 있다. 아니면 고민할 시간에 코딩한 줄 치는게 더 이득일 수도 그러나 고민은 필요하다. 중요하다.
고민은 미리하자.
고민하지 않았더니 생기는 일들
처음 만들때는 메인페이지가 블로그 게시글들을 리스트 형태로 보여주는 페이지였다. 그래서 컴포넌트는 sidebar, header, postfeed로 구분하고 그냥 거기서 재사용되는거 잘 나누고 전역적으로 재사용되는 컴포넌트들은 shared로 따로 만들어서 관리하면 되겠다생각했음
문제들
- 아무래도 랜딩 페이지가 필요할거 같다.
- 생각해보니 글쓰기,글 수정 페이지도 필요하다.
- 유저 관리 페이지도 있어야 함
- 로그인, 회원가입도 있어야 함
여러 시나리오가 생기는데 구분하는 기준이 없었음.
- 라우터가 몇개 없지만 write, edit 으로 나누어지고 수정, 글쓰기는 동일한 ui일텐데 어디에 위치시킬건지 정해져있지 않음
- 갑자기 이상한 landing 폴더 만들더니 거기서 쓰는 컴포넌트 다 때려넣었음.
- editor도 만들더니 일단 모르겠다. 하고 그냥 정리를 포기하기 시작했음.
- 이대로는 안되겠다 싶어서 어떻게 정리를 해야되나 생각을 해보았습니다.
그대로 냅뒀으면
- 계속 추가될때마다 이름부터 시작해서 어디에 둬야할지 계속 고민을 하게된다.
- 기준이 없으니 행동이 매번 달라진다.
- 찾기가 점점 어려워지고 일관성, 통일성이 없어진다.
- 예측이 불가능한 프로젝트가 된다.
FSD (Feature-Sliced Design)
어떻게 폴더를 나누는게 좋을까 고민하면서 검색해보다가 걸렸다.
아토믹 디자인
- 오히려 이것저것 나누다보니까 더 헷갈리고 찾기가 어려웠던거 같다.
pages, component
- 다양한 시나리오에 대응하기에는 구분하는 기준이 부실하다.
FSD
공식문서 내용
우선 폴더구조는 정답이 없다. 나에게 맞는지가 중요하다
- 이 방법은 프런트엔드 프로젝트에만 적용됩니다. 백엔드 아키텍처를 찾고 있다면 Clean Architecture를 고려해보세요 .
- 이 방법은 사용자 지향 애플리케이션에만 적용되며 라이브러리나 UI 키트에는 적용되지 않습니다. UI 키트의 아키텍처를 찾고 있다면 Material UI 에서 영감을 얻으세요.
- 단일 페이지의 매우 간단한 앱에는 FSD의 이점이 필요하지 않으며 오버헤드가 발생할 수 있습니다. 그러나 FSD는 좋은 사고 방식을 장려하므로 원하는 경우 가장 작은 프로젝트에 자유롭게 사용해 보세요.
- Google Cloud 관리 대시보드 크기의 대규모 앱에는 커스텀 아키텍처가 필요합니다. 그건 그렇고, 여전히 FSD를 기반으로 할 수 있습니다.
레이어
레이어는 최상위 디렉토리이자 애플리케이션 분해의 첫 번째 단계입니다. 레이어의 수는 최대 7개로 제한되어 있으며, 일부는 선택 사항이지만 표준화되어 있습니다. 현재 다음과 같이 레이어가 구분되어 있습니다.
app
- 애플리케이션 로직이 초기화되는 곳입니다. 프로바이더, 라우터, 전역 스타일, 전역 타입 선언 등이 여기에서 정의됩니다. 애플리케이션의 진입점 역할을 합니다.
processes
- 이 레이어는 여러 단계로 이루어진 등록과 같이 여러 페이지에 걸쳐 있는 프로세스를 처리합니다. 이 레이어는 더 이상 사용되지 않는 것으로 간주되지만 여전히 가끔씩 마주할 수 있습니다. 선택적 레이어입니다.
pages
- 이 레이어에는 애플리케이션의 페이지가 포함됩니다.
widgets
- 페이지에 사용되는 독립적인 UI 컴포넌트입니다.
features
- 이 레이어는 비즈니스 가치를 전달하는 사용자 시나리오와 기능을 다룹니다. 예를 들어 좋아요, 리뷰 작성, 제품 평가 등이 있습니다. 선택적 레이어입니다.
entities
- 이 레이어는 비즈니스 엔티티를 나타냅니다. 이러한 엔티티에는 사용자, 리뷰, 댓글 등이 포함될 수 있습니다. 선택적 레이어입니다.
shared
- 이 레이어에는 특정 비즈니스 로직에 종속되지 않은 재사용 가능한 컴포넌트와 유틸리티가 포함되어 있습니다. 여기에는 UI 키트, axios 설정, 애플리케이션 설정, 비즈니스 로직에 묶이지 않은 헬퍼 등이 포함됩니다.
note !! In most cases, it is recommended to place api and config only in the shared layer, unless your API client is also your storage (GraphQL, TanStack Query, etc.)
슬라이스
-
각 레이어에는 애플리케이션 분해의 두 번째 수준인 슬라이스라는 하위 디렉토리가 있습니다. 슬라이스에서 연결은 추상적인 것이 아니라 특정 비즈니스 엔티티에 대한 것입니다. 슬라이스의 주요 목표는 코드를 값별로 그룹화하는 것입니다.
-
슬라이스 이름은 프로젝트의 비즈니스 영역에 따라 직접 결정되므로 표준화되어 있지 않습니다. 예를 들어 사진 갤러리에는 사진, 앨범, 갤러리와 같은 섹션이 있을 수 있습니다. 소셜 네트워크에는 게시물, 사용자, 뉴스피드와 같은 슬라이스가 필요할 수 있습니다.
-
밀접하게 관련된 조각들은 구조적으로 디렉토리 내에 그룹지을 수 있지만 다른 슬라이스와 동일한 격리 규칙을 준수해야 하며, 이 디렉토리에 있는 코드는 직접적으로 공유되지 않아야 합니다.
세그먼트
각 슬라이스는 세그먼트로 구성됩니다. 세그먼트는 목적에 따라 슬라이스 내의 코드를 나누는 데 도움이 됩니다. 팀의 합의에 따라 세그먼트의 구성과 이름이 변경될 수 있습니다. 일반적으로 사용되는 세그먼트들은 다음과 같습니다.
api
- 필요한 서버 요청.
UI
- 슬라이스의 UI 컴포넌트.
model
- 비즈니스 로직, 즉 상태와의 상호 작용. actions 및 selectors가 이에 해당
lib
- 슬라이스 내에서 사용되는 보조 기능.
config
- 슬라이스에 필요한 구성값이지만 구성 세그먼트는 거의 필요하지 않음.
consts
- 필요한 상수.
example
소셜 네트워크 애플리케이션을 생각해 봅시다.
- app/라우팅, 저장 및 전역 스타일 설정이 포함되어 있습니다.
- pages/앱의 각 페이지에 대한 경로 구성 요소가 포함되어 있으며 대부분 구성 요소이며 논리는 거의 없습니다. 해당 애플리케이션 내에서 뉴스피드의 엽서를 고려해 보겠습니다.
- widgets/백엔드의 관련 호출에 연결된 콘텐츠 및 대화형 버튼과 함께 "조립된" 엽서가 포함되어 있습니다.
- features/카드의 상호 작용(예: 버튼)과 이러한 상호 작용을 처리하는 논리가 포함되어 있습니다.
- entities/콘텐츠 슬롯과 대화형 요소가 있는 카드 껍질이 포함되어 있습니다. 게시물 작성자를 나타내는 타일도 여기에 있지만 다른 조각에 있습니다.
결론
폴더 구조에 정답은 없다.
폴더 구조 고민할 시간에 코딩 한 줄 더하자.
하지만 우리가 개발을 더 생산적으로 하고 비즈니스 로직을 작성하기 위해서는 미리 고민하고 미리 약속된 폴더 구조를 정의해서 적용해야 생산성을 높일 수 있다.
어제 지하철을 타고 집에 오는데 유튜브에서 구독하고 있던 개발자가 유튜브 라이브를 하길래 무슨 이야기하나 들어가봤습니다. 근데 fsd 이야기를 하길래 신기해서 봤더니 주니어보다 시니어가 돈을 더 많이 받는 이유는 생산성이 높기 때문. 그 사람이 생산성이 높은 이유는 이미 많은 경험을 통해서 고민을 다 해봤고 주니어보다 고민을 적게하기 때문이다. 고민을 적게하고 바로바로 적용하니까 주니어보다 개발 속도가 빠른거다. 이런 폴더 구조도 이미 다 고민을 해봤기 때문에 폴더구조를 어떻게 짤지 고민하지 않는다. 주니어에서 더 올라갈려면 이런 고민들을 미리 해야 하고 돈을 더 많이 받을 수 있다.
개발자가 눈으로 볼 수 있는 소프트웨어의 아키텍처
- 폴더 구조는 소프트웨어의 트리 구조랑 닮았다.
- FSD, 아토믹 디자인과 같이 컨벤션이 있는 폴더 구조는 소프트웨어를 예측 가능하게 하고 우리가 흔히 잘 알고 있는 관심사를 분리한다던지 의존성을 낮추고, 디자인 패턴(hoc, ui와 로직의 분리) 등 이런 것에 영향을 주고 자연스럽게 유도한다고 느꼈다.
- 코드의 품질을 보장할 수는 없겠지만 최소한으로 보장은 할 수 있지않을까 생각했다.