본문 바로가기

Etc

FSD 폴더 구조란?

728x90

1. FSD(Folder-by-Feature Structure)

기능별로 프로젝트를 나누어 관리하는 구조를 말한다.

각 기능이 독립된 모듈로 관리되도록 구성되며 UI, 데이터 모델, API 호출, 상태관리를 독립적으로 구현할 수 있다.

 

FSD 폴더 구조를 사용하면, 각각의 기능이 독립적으로 동작할 수 있어 유지보수와 확장이 쉬워진다.

주로 대규모 프로젝트에서 사용된다.

 

2. FSD 폴더 구조 

 

FSD의 폴더 구조는 Layers > Slices > Segments로 구성되어 있다.

1) Layer

역할에 따라 나뉜 폴더 그룹을 의미한다.

총 7가지 레이어가 존재한다.

 

- App 레이어

전역 설정과 초기화 설정을 관리하는 최상위 레이어이다.

상태 관리 설정, 라우팅 설정, 스토어 초기화, 다국어 설정, 글로벌 설정 등이 포함된다.

 

ex) store.ts, router.ts, App.tsx

 

 

- Processes 레이어

비즈니스 프로세르 레이어를 말한다.

사용자 인증, 결제 프로세스, 회원가입 단계별 진행 등에 사용한다.

 

현재는 depercated되어 사용하지 않는다. 

 

 

- Pages 레이어

페이지 컴포넌트를 관리하는 레이어를 말한다.

사용자에게 제공되는 주요 화면을 담당하며, features, entities, widgets에서 제공하는 모듈을 조합해 화면을 구성한다.

 

홈페이지, 상품목록 페이지, 마이페이지 등 페이지 단위라고 생각하면 된다.

 

ex) 

pages/
|-- Home/
|   |-- index.tsx       // 홈 페이지 컴포넌트
|   |-- model/          // 홈 페이지 상태 및 로직
|-- Profile/
|   |-- index.tsx       // 프로필 페이지 컴포넌트
|   |-- model/          // 프로필 페이지 상태 및 로직

 

 

- Widgets 레이어 

여러 곳에서 재사용 가능한 UI 컴포넌트를 모아둔 레이어를 말한다.

버튼, 입력 폼, 모달과 같은 공통 UI 요소들이 여기에 포함된다.

 

ex) Button.tsx, Modal.tsx

 

 

- Features 레이어

특정 기능을 담당하는 모듈을 모아둔 레이어를 말한다.

좋아요 버튼, 상품 정렬 기능 등 독립적인 기능 별로 폴더가 구성된다.

 

 

- Entities 레이어

주요 데이터 모델과 관련된 상태 관리 및 로직을 포함하는 레이어를 말한다.

데이터를 집중적으로 관리한다.

 

사용자 모델, 주문 모델 등이 포함된다.

 

ex) User.tsx

 

 

- Shared 레이어

여러 곳에서 재사용 할 수 있는 공통 컴포넌트와 유틸리티, 설정 파일 등을 관리하는 레이어이다.

유틸리티 함수, 전역 설정 파일, 타입 정의 등이 포함되며 재사용 가능하다. 

 

 

 

2) Slices

하나의 엔티티나 기능을 여러 작은 부분으로 나누어 독립성을 부여하는 레이어의 하위 디렉터리이다.

슬라이스 내부에서 비즈니스와 연관된 로직을 작성할 수 있으며, app과 shared에서는 사용하지 않는다.

entities/
|-- User/         //user slice
|-- sesstion/     //sesstion slice

 

 

 

3) Segment

slice보다 작은 단위로, 특정 기능의 세부적인 기능을 구분하여 다룬다.

각 슬라이스는 세그먼트로 구성된다.

- ui 세그먼트

비즈니스 로직을 포함하지 않는 재사용 가능한 UI 컴포넌트를 말한다.

props를 통해 데이터와 이벤트 핸들러를 받는다.

// ui/ProductCard.tsx
const ProductCard = ({ product }) => {
  return (
    <div>
      <h3>{product.name}</h3>
      <PriceDisplay price={product.price} />
      <AddToCartButton productId={product.id} />
    </div>
  );
};

 

 

 

 - model 세그먼트

상태관리와 비즈니스 로직을 포함하는 세그먼트이다.

주로 상태관리 라이브러리를 사용해 해당 슬라이스의 상태를 정의하고, 이 상태를 업데이트하거나 조회하는 로직을 구현한다.

 

상태 정의 및 초기화, 데이터 처리와 상태 변경 로직, 액션 및 리듀서 등이 해당 세그먼트에 포함된다.

// model/types.ts
interface Product {
  id: string;
  name: string;
  price: number;
}

// model/store.ts
const addProduct => (product: Product) {
  return [...products, product]
}

const getProduct => (id: string) {
  return products.find(p => p.id === id);
}

const validateProductData = (product: Product): boolean => {
  return product.name.length > 0 && product.price > 0;
};

 

 

- api 세그먼트

서버와의 데이터 통신을 담당하는 부분을 말한다.

데이터 요청, api 엔드포인트, 데이터 변환, 에러처리 등이 포함된다.

// api/productApi.ts
export const productApi = {
  fetchProducts: async () => {
    const response = await axios.get('/api/products');
    return response.data;
  },

  createProduct: async (product: Product) => {
    const response = await axios.post('/api/products', product);
    return response.data;
  }
};

 

 

- lib 세그먼트

유틸리티 함수들의 모음으로, 순수 함수들로 구성된다.

유틸리티 함수, 슬라이스에 특화된 라이브러리 설정, 비즈니스 로직 보조 함수 등이 포함 된다.

// lib/helpers.ts
export const formatPrice = (price: number): string => {
  return new Intl.NumberFormat('ko-KR', {
    style: 'currency',
    currency: 'KRW'
  }).format(price);
};

 

 

- config 세그먼트

설정 파일이나 구성 옵션을 관리하는 세그먼트이다.

환경변수, 상수 설정, 기본 구성 설정 등이 포함된다.  

// config/constants.ts
export const PRODUCT_CONFIG = {
  MAX_NAME_LENGTH: 100,
  MIN_PRICE: 100,
  DEFAULT_CURRENCY: 'KRW',
  IMAGE_SIZES: {
    THUMBNAIL: { width: 200, height: 200 },
    FULL: { width: 800, height: 600 }
  }
};

 

 

 

728x90