# slices

슬라이스는 Feature-Sliced Design(FSD)의 조직 계층에서 두 번째 수준을 차지한다.\
슬라이스의 주요 목적은 코드의 의미를 기준으로 그룹화하여 제품, 비즈니스 또는 애플리케이션을 보다 명확하게 구성하는 것이다.

슬라이스의 이름은 표준화되어 있지 않으며, 애플리케이션의 비즈니스 도메인에 따라 직접 결정된다. 예를 들어, 사진 갤러리 애플리케이션에서는 `photo`, `create-album`, `gallery-page` 와 같은 슬라이스를 가질 수 있다. 반면 소셜 네트워크에서는 `post`, `add-user-to-friends` , `news-feed` 와 같은 슬라이스가 필요할 수 있다.

관련된 슬라이스는 구조적으로 디렉토리에서 그룹화할 수 있지만, 다른 슬라이스와 동일한 격리 규칙을 적용해야 한다. 즉 그 디렉토리 내에서 코드 공유는 허용되지 않는다.

```bash
📦features
 ┣ 📂post
 ┃ ┣ 📂compose
 ┃ ┣ 📂compose
 ┃ ┣ 📂compose
 ┃ ┣ <> some-shared-code.ts : not allowed
```

Shared와 App 레이어는 슬라이스를 포함하지 않는다. 그 이유는, Shared는 비즈니스 로직을 전혀 포함하지 않아 제품에 대한 의미를 가지지 않기 때문이며, App은 애플리케이션 전체와 관련된 코드만 포함해야 하므로 나눌 필요가 없기 때문이다.

## Public API

슬라이스 (Slice)와 세그먼트 (Segement)의 Public API 규칙은 슬라이스나 세그먼트의 내부 구조가 외부에 드러나지 않도록 하고, 외부 모듈이 오직 Public API 를 통해서만 해당 슬라이스나 세그먼트에 접근하도록 보장하는 규칙이다.

* 모든 슬라이스(그리고 슬라이스가 없는 계층의 세그먼트)는 공개 API정의를 포함해야한다
* 해당 슬라이스/세그먼트 외부의 모듈은 슬라이스/세그먼트의 내부 파일 구조가 아닌, 공개 API만 참조할 수 있다.

### 달성하는 목적

캡슐화 : `Public API` 규칙을 통해 슬라이스의 내부 구현을 외부에 노출 시키지 않음으로써, 내부 구조의 변경이 외부에 영향을 미치지 않게 한다.

모듈 간 결합도 감소 : 슬라이스 간의 의존성을 낮추고, 변경이 발생하더라도 영향 범위를 최소화 할 수 있다.

```bash
└── features/               #
       ├── auth-form /      # Internal structure of the feature
       |     ├── ui/        #|     ├── model/     #|     ├── {...}/     #
       ├── index.ts         # Entrypoint features with its public API
```

```tsx
export { Form as AuthForm } from "./ui";
export * as authFormModel from "./model";
```

## Segements

세그먼트는 조직 계층 구조의 세 번째이자 마지막 레벨이며, 코드를 기술적 성격에 따라 그룹화하는 것이 목적이다.

### 표준화된 세그먼트 이름

* **ui** — UI 컴포넌트, 데이터 포맷팅 함수
* **model** — 비즈니스 로직 및 데이터 저장소, 그리고 이 데이터를 조작하는 함수
* **lib** — 보조 및 인프라 코드
* **api** — 외부 API와의 통신, 백엔드 API 메서드

커스텀 세그먼트도 허용되지만, 신중하게 생성해야 한다. 커스텀 세그먼트가 가장 많이 사용되는 곳은 **App 레이어**와 **Shared 레이어**로, 이곳에서는 슬라이스가 필요하지 않다.

| 레이어          | `ui`                                                  | `model`                                                                                                                          | `lib`                                                                             | `api`                                                     |
| ------------ | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------- |
| **Shared**   | UI 키트                                                 | 보통 사용되지 않음                                                                                                                       | 몇 개의 관련 파일들로 이루어진 유틸리티 모듈. 개별 헬퍼를 사용해야 하는 경우 lodash-es와 같은 유틸리티 라이브러리를 사용하는 것을 고려 | 인증 또는 캐싱과 같은 추가 기능을 갖춘 기본적인 API 클라이언트                     |
| **Entities** | 비즈니스 엔터티의 뼈대로, 인터랙티브 요소를 위한 슬롯 포함                     | 엔터티 인스턴스의 데이터 저장소 및 해당 데이터를 조작하는 함수. 이 세그먼트는 서버 측 데이터를 저장하는 데 가장 적합하다. TanStack Query 또는 다른 암묵적 저장 방법을 사용하는 경우, 이 세그먼트를 생략할 수 있음 | 저장과 관련이 없는 엔터티 인스턴스를 조작하는 함수                                                      | 백엔드와의 쉬운 통신을 위해 Shared에서 API 클라이언트를 사용하는 API 메서드          |
| **Features** | 사용자가 이 기능을 사용할 수 있도록 하는 인터랙티브 요소                      | 필요할 경우, 비즈니스 로직 및 인프라 데이터 저장소(예: 현재 앱 테마). 사용자에게 실제로 가치를 제공하는 코드                                                                 | 모델 세그먼트에서 비즈니스 로직을 간결하게 설명하는 데 도움이 되는 인프라 코드                                      | 백엔드에서 이 기능을 나타내는 API 메서드. Entities의 API 메서드를 구성할 수 있음     |
| **Widgets**  | 엔터티와 기능을 결합하여 독립적인 UI 블록으로 구성. 오류 경계와 로딩 상태도 포함할 수 있음 | 필요할 경우, 인프라 데이터 저장소                                                                                                              | 비즈니스와 관련 없는 인터랙션(예: 제스처) 및 페이지에서 블록이 작동하는 데 필요한 기타 코드                             | 일반적으로 사용되지 않지만, 중첩된 라우팅 컨텍스트에서 데이터 로더를 포함할 수 있음(예: Remix) |
| **Pages**    | 엔터티, 기능, 위젯을 결합하여 완전한 페이지로 구성. 오류 경계와 로딩 상태도 포함할 수 있음 | 보통 사용되지 않음                                                                                                                       | 비즈니스와 관련 없는 인터랙션(예: 제스처) 및 완전한 사용자 경험을 제공하기 위해 페이지에서 필요한 기타 코드                    | SSR 지향 프레임워크의 데이터 로더                                      |
