Skip to content

Commit 37401c5

Browse files
Gaic4o김
andauthored
docs: add slice-groups documentation (#906)
* docs(en): add slice-groups documentation * docs(ko): add slice-groups documentation * docs: apply review feedback on slice-groups documentation * docs: add slice-group-not-a-slice light/dark SVG * docs: apply review feedback on slice-groups documentation --------- Co-authored-by: 김 <minsu@gim-ui-Macmini.local>
1 parent feaa167 commit 37401c5

6 files changed

Lines changed: 426 additions & 2 deletions

File tree

src/content/docs/docs/reference/public-api.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Public API
33
sidebar:
4-
order: 3
4+
order: 4
55
---
66

77
import { FileTree, Aside } from '@astrojs/starlight/components';
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
title: Slice groups
3+
sidebar:
4+
order: 3
5+
---
6+
7+
import { FileTree } from '@astrojs/starlight/components';
8+
9+
import StaticImage from '../../../../shared/ui/static-image/StaticImage.astro';
10+
11+
A slice group places related slices close together within the same layer, making the structure easier to navigate.
12+
13+
It is not a required part of FSD. You can introduce slice groups selectively when the number of slices grows large enough that a flat structure becomes hard to browse.
14+
15+
## Overview
16+
17+
It is a structure for making code easier to read and navigate, and does not affect dependency rules between slices.
18+
19+
A slice group is not a slice. It does not have its own segments like `model`, `ui`, or `api`, nor does it have a public API such as `index.ts`. Shared code used across multiple slices should not be placed in a slice group either.
20+
21+
<StaticImage path={['/img/slice-group-not-a-slice-light.svg', '/img/slice-group-not-a-slice-dark.svg']} alt="A slice group does not have segments or a public API" />
22+
23+
Each slice remains independent even when it belongs to a slice group. The isolation and dependency rules between slices do not change.
24+
25+
## Why it is needed
26+
27+
As the number of slices grows, a flat structure can make it hard to locate related code. When slices that share the same context are scattered across a layer, you end up scanning the entire layer multiple times.
28+
29+
A slice group addresses this by bringing related slices closer together, making the structure easier to navigate.
30+
31+
## When to consider introducing one
32+
33+
Consider introducing a slice group when there is a grouping criterion that feels obvious at a glance, and splitting the structure actually makes it easier to read.
34+
35+
- Several slices sharing the same business context are scattered across a layer.
36+
- The slice names clearly suggest they belong to the same topic.
37+
- The number of slices in a layer has grown to the point where it is hard to take in at a glance.
38+
39+
Conversely, it may not be needed yet in the following cases.
40+
41+
- Names alone are enough for quick navigation.
42+
- There is no natural grouping criterion.
43+
- Too few slices would end up in the group.
44+
45+
## How to apply it
46+
47+
### entities
48+
49+
You can group slices that are close from a domain model perspective.
50+
51+
For example, suppose the `entities` layer has accumulated many payment-related slices.
52+
53+
**Without a group:**
54+
55+
<FileTree>
56+
- entities/
57+
- invoice/
58+
- model/
59+
- ui/
60+
- receipt/
61+
- model/
62+
- ui/
63+
- transaction/
64+
- model/
65+
- ui/
66+
- user/
67+
- model/
68+
- ui/
69+
- product/
70+
- model/
71+
- ui/
72+
- ...
73+
</FileTree>
74+
75+
To find the payment-related slices (`invoice`, `receipt`, `transaction`), you would need to scan the entire layer and pick them out one by one.
76+
77+
**With a group:**
78+
79+
<FileTree>
80+
- entities/
81+
- payment/
82+
- invoice/
83+
- model/
84+
- ui/
85+
- receipt/
86+
- model/
87+
- ui/
88+
- transaction/
89+
- model/
90+
- ui/
91+
- user/
92+
- model/
93+
- ui/
94+
- product/
95+
- model/
96+
- ui/
97+
- ...
98+
</FileTree>
99+
100+
Now every payment-related slice can be found directly under `payment/`.
101+
102+
Not every slice needs to belong to a group. A slice like `user/`, whose meaning is clear on its own, can remain ungrouped.
103+
104+
### pages
105+
106+
You can group related pages in the pages layer in a similar way. This is one possible example and does not represent the default structure for the pages layer.
107+
108+
<FileTree>
109+
- pages/
110+
- order/
111+
- create/
112+
- ui/
113+
- detail/
114+
- ui/
115+
- list/
116+
- ui/
117+
- customer/
118+
- detail/
119+
- ui/
120+
- list/
121+
- ui/
122+
- settings/
123+
- ui/
124+
- ...
125+
</FileTree>
126+
127+
This structure helps when there are multiple pages on the same topic, such as list, detail, create, and edit.
128+
129+
### Can they be used in features as well?
130+
131+
Yes, slice groups can be applied to the features layer as well. However, a feature often spans multiple entities rather than being tied to a single domain. This makes it harder to find a natural grouping criterion compared to entities.
132+
133+
If you create a group like `features/cart/` without a clear criterion, use cases like `add-to-cart` and `remove-from-cart` will end up there, but cart-related DTOs and mappers may start accumulating as well. At that point the group folder stops serving as a navigational structure and begins acting as a home for the entire cart domain, weakening the principle that features should be split by use case.
134+
135+
To introduce a slice group in features, first check whether there are enough slices to warrant a group. If there are only two or three, a flat structure is likely sufficient. You should also check whether the group contains only feature slices, or whether code that belongs in entities has crept in as well.
136+
137+
## References
138+
139+
- [Russian Telegram FSD community — Discussion on structural grouping, slice groups, and layer extension](https://t.me/c/1216849846/1/2785)
140+
- [Russian Telegram FSD community — Nested vs. flat structure, forms and boundaries of slice groups](https://t.me/c/1216849846/1/5051)
141+
- [Russian Telegram FSD community — Why there are fewer grouping examples in features, and whether slice groups work in features](https://t.me/c/1216849846/1/80620)
142+
- [KakaoPay — A case of applying slice grouping in the pages layer](https://tech.kakaopay.com/post/fsd/#2-slice-grouping-%ED%97%88%EC%9A%A9-%EB%B0%8F-pages-%EB%A0%88%EC%9D%B4%EC%96%B4-%EA%B5%AC%EC%84%B1)

src/content/docs/kr/docs/reference/public-api.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Public API
33
sidebar:
4-
order: 3
4+
order: 4
55
---
66

77
import { FileTree, Aside } from '@astrojs/starlight/components';
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
---
2+
title: Slice groups
3+
sidebar:
4+
order: 3
5+
---
6+
7+
import { FileTree } from '@astrojs/starlight/components';
8+
9+
import StaticImage from '../../../../../shared/ui/static-image/StaticImage.astro';
10+
11+
Slice group은 같은 layer 안에서 관련된 slice를 가까이 배치해, 구조를 더 쉽게 탐색할 수 있게 하는 방식입니다.
12+
13+
Slice group은 FSD에서 반드시 적용해야 하는 구조는 아닙니다.
14+
slice 수가 많아져 flat한 구조만으로 탐색하기 어려울 때 선택적으로 도입할 수 있습니다.
15+
## 개요
16+
17+
코드를 읽고 탐색하기 쉽게 만들기 위한 구조이며, slice 간 의존성 규칙에는 영향을 주지 않습니다.
18+
19+
Slice group은 slice가 아닙니다.
20+
따라서 `model`, `ui`, `api` 같은 segment나 `index.ts` 같은 public API를 갖지 않습니다.
21+
여러 slice가 함께 쓰는 공용 코드도 slice group에 포함하지 않습니다.
22+
23+
<StaticImage path={['/img/slice-group-not-a-slice-light.svg', '/img/slice-group-not-a-slice-dark.svg']} alt="Slice group은 segment나 public API를 갖지 않는다" />
24+
25+
같은 slice group에 속하더라도 각 slice는 독립적으로 유지됩니다.
26+
slice 사이의 격리와 의존성 규칙도 달라지지 않습니다.
27+
28+
## 왜 필요한가
29+
30+
slice가 많아지면 flat한 구조만으로는 관련 코드를 찾기 어려워질 수 있습니다.
31+
특히 같은 맥락의 slice가 여러 곳에 흩어져 있으면 layer 전체를 여러 번 훑게 됩니다.
32+
33+
slice group은 이런 상황에서 관련된 slice를 가까이 모아 구조를 더 쉽게 탐색할 수 있게 합니다.
34+
35+
## 언제 도입을 고려하는가
36+
37+
한눈에 같은 묶음으로 보이는 기준이 있고, 실제로 구조를 나누는 편이 더 읽기 쉬울 때 도입을 고려합니다.
38+
판단 기준은 다음과 같습니다.
39+
40+
- 같은 비즈니스 맥락의 slice가 layer 안에 여러 개 흩어져 있다.
41+
- slice 이름만 봐도 같은 주제로 묶이는 게 자연스럽게 보인다.
42+
- layer 안의 slice 수가 많아져 스크롤 없이 전체를 파악하기 어렵다.
43+
44+
반대로 다음과 같은 경우에는 아직 필요하지 않을 수 있습니다.
45+
46+
- 이름만으로도 충분히 빠르게 탐색된다.
47+
- 그룹 기준이 자연스럽지 않다.
48+
- 그룹 안에 들어갈 slice가 너무 적다.
49+
50+
## 어떻게 적용하는가
51+
52+
### entities
53+
54+
도메인 모델 관점에서 가까운 slice를 묶을 수 있습니다.
55+
56+
예를 들어 `entities` layer에 결제와 관련된 slice가 많아졌다고 가정해 보겠습니다.
57+
58+
**group 없이 두면:**
59+
60+
<FileTree>
61+
- entities/
62+
- invoice/
63+
- model/
64+
- ui/
65+
- receipt/
66+
- model/
67+
- ui/
68+
- transaction/
69+
- model/
70+
- ui/
71+
- user/
72+
- model/
73+
- ui/
74+
- product/
75+
- model/
76+
- ui/
77+
- ...
78+
</FileTree>
79+
80+
결제 관련 slice(`invoice`, `receipt`, `transaction`)를 찾으려면 layer 전체를 보면서 관련 항목을 골라내야 합니다.
81+
82+
**group으로 묶으면:**
83+
84+
<FileTree>
85+
- entities/
86+
- payment/
87+
- invoice/
88+
- model/
89+
- ui/
90+
- receipt/
91+
- model/
92+
- ui/
93+
- transaction/
94+
- model/
95+
- ui/
96+
- user/
97+
- model/
98+
- ui/
99+
- product/
100+
- model/
101+
- ui/
102+
- ...
103+
</FileTree>
104+
105+
이제 결제와 관련된 slice는 `payment/` 아래에서 바로 확인할 수 있습니다.
106+
107+
모든 slice를 그룹에 넣을 필요는 없습니다.
108+
`user/`처럼 그 자체로 의미가 분명한 slice는 그룹 없이 그대로 둘 수 있습니다.
109+
110+
### pages
111+
112+
pages layer에서도 비슷한 방식으로 관련 page를 묶을 수 있습니다.
113+
이는 가능한 예시 중 하나이며, pages layer의 기본 구조를 뜻하지는 않습니다.
114+
115+
<FileTree>
116+
- pages/
117+
- order/
118+
- create/
119+
- ui/
120+
- detail/
121+
- ui/
122+
- list/
123+
- ui/
124+
- customer/
125+
- detail/
126+
- ui/
127+
- list/
128+
- ui/
129+
- settings/
130+
- ui/
131+
- ...
132+
</FileTree>
133+
134+
이 구조는 목록, 상세, 생성, 수정처럼 같은 주제의 page가 여러 개 있을 때 도움이 됩니다.
135+
136+
### features에서도 사용할 수 있나요?
137+
138+
features layer에도 slice group을 적용할 수 있습니다.
139+
다만 feature는 하나의 도메인에만 묶이지 않고 여러 entity에 걸치는 경우가 많습니다. 그래서 entities에 비해 자연스러운 그룹핑 기준을 잡기 어렵습니다.
140+
141+
기준이 명확하지 않은 상태에서 `features/cart/` 같은 그룹을 만들면, `add-to-cart`, `remove-from-cart` 같은 use case뿐 아니라 cart와 관련된 DTO, mapper까지 그 아래에 모이기 시작할 수 있습니다. 그러면 group 폴더가 탐색 구조가 아니라 cart 도메인 전체를 담는 폴더처럼 쓰이게 되고, feature가 use case 단위로 나뉘어야 한다는 원칙이 약해집니다.
142+
143+
features에서 slice group을 도입하려면, 먼저 그룹에 들어갈 slice가 충분히 많은지 확인합니다. slice가 두세 개뿐이라면 그룹 없이도 탐색에 문제가 없을 가능성이 높습니다. 그리고 그룹 안에 feature slice만 남아 있는지, entities에 속해야 할 코드가 함께 놓이고 있지는 않은지를 살펴봐야 합니다.
144+
145+
## 참고 자료
146+
147+
- [러시아 텔레그램 FSD 커뮤니티 - 구조적 그룹핑, slice group, 계층 확장에 대한 논의](https://t.me/c/1216849846/1/2785)
148+
- [러시아 텔레그램 FSD 커뮤니티 - 중첩 구조와 flat 구조, slice group의 형태와 허용 범위](https://t.me/c/1216849846/1/5051)
149+
- [러시아 텔레그램 FSD 커뮤니티 - 왜 features에서는 그룹핑 예시가 적은가, features에서도 slice group이 가능한가](https://t.me/c/1216849846/1/80620)
150+
- [카카오페이 - pages layer에서 slice grouping을 적용한 사례](https://tech.kakaopay.com/post/fsd/#2-slice-grouping-%ED%97%88%EC%9A%A9-%EB%B0%8F-pages-%EB%A0%88%EC%9D%B4%EC%96%B4-%EA%B5%AC%EC%84%B1)
Lines changed: 66 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)