ํด๋ ๊ตฌ์กฐ - Feature-first vs Layer-first
์ง๊ธ๊น์ง ์์ ๋ ํ์ผ ํ๋ ๊ฐ์ ๋ค ๋ค์ด๊ฐ๋ค. ํ์ง๋ง ์ฑ์ ํ๋ฉด๊ณผ ๊ธฐ๋ฅ์ด ๋์ด๋๋ฉด lib ํด๋๊ฐ ์ ์ ์ด์ง๋ฌ์์ง๋ค. ๊ฐ์ฅ ๋จผ์ ๋ ์ค๋ฅด๋ ์ ๋ฆฌ๋ฒ์ ์ข
๋ฅ๋ณ๋ก ํด๋๋ฅผ ๋๋๋ ๊ฒ์ด๋ค. ๋ชจ๋ธ์ ๋ชจ๋ธ๋ผ๋ฆฌ, ํ๋ฉด์ ํ๋ฉด๋ผ๋ฆฌ, ์๋น์ค๋ ์๋น์ค๋ผ๋ฆฌ ๋ชจ์๋ค.
lib/
models/
user.dart
todo.dart
views/
user_list_page.dart
user_detail_page.dart
todo_page.dart
services/
user_service.dart
todo_service.dart
providers/
user_provider.dart
todo_provider.dart
main.dart์ฒ์์ ๊น๋ํด ๋ณด์ธ๋ค. ๊ทธ๋ฐ๋ฐ "์ฌ์ฉ์ ์์ธ ํ๋ฉด์ ์ด๋ฉ์ผ์ ์ถ๊ฐํ๋ผ"๋ ์์ ์ ํด๋ณด์. ๊ณ ์ณ์ผ ํ ํ์ผ์ ์ด๋ ๋ค.
models/user.dart: ํ๋ ์ถ๊ฐservices/user_service.dart: ์๋ต ํ์ฑ ์์ providers/user_provider.dart: ์ํ ์์ views/user_detail_page.dart: ํ๋ฉด ์์
๋ค ๊ฐ์ ํด๋๋ฅผ ์ค๊ฐ๋ฉฐ ํ์ผ์ ์ด์ด์ผ ํ๋ค. ๊ธฐ๋ฅ์ด ์ด ๊ฐ๋ก ๋๋ฉด views ํด๋์ ํ๋ฉด์ด ์๋ฅธ ๊ฐ ์์ฌ์, ์ด ํ๋ฉด์ด ์ด๋ ๊ธฐ๋ฅ์ ๊ฒ์ธ์ง๋ ํ์ผ ์ด๋ฆ์ผ๋ก๋ง ์ง์ํด์ผ ํ๋ค. ๋ฐ๋๋ก "ํ ์ผ ๊ธฐ๋ฅ์ ํต์งธ๋ก ์ง์ฐ์"๊ณ ํ๋ฉด ๋ค ํด๋์ ํฉ์ด์ง ํ์ผ์ ์ผ์ผ์ด ๊ณจ๋ผ๋ด์ผ ํ๋ค.
์์ธ: ๊ฐ์ด ๋ฐ๋๋ ํ์ผ์ด ๋ฉ๋ฆฌ ๋จ์ด์ ธ ์๋ค
ํด๋๋ฅผ ๋๋๋ ๊ธฐ์ค์ด "์ข ๋ฅ"(๋ชจ๋ธ, ํ๋ฉด, ์๋น์ค)์๋ค. ๊ทธ๋ฐ๋ฐ ์ฝ๋๋ฅผ ๊ณ ์น ๋๋ ๋ณดํต ํ ๊ธฐ๋ฅ์ ์ํ ํ์ผ๋ค์ด ๊ฐ์ด ๋ฐ๋๋ค. ๊ฐ์ ์ด์ ๋ก ๋ฐ๋๋ ํ์ผ์ ๊ฐ๊น์ด ๋ชจ์๋ฌ์ผ ํ๋ค. ์ด๊ฒ ํด๋ ๊ตฌ์กฐ๋ฅผ ๊ณ ๋ฅด๋ ๊ฐ์ฅ ํฐ ๊ธฐ์ค์ด๋ค.
๋ ๊ฐ์ง ๋ฐฉ์
- Layer-first(๊ณ์ธต ์ฐ์ ): ์์ ๊ตฌ์กฐ์ฒ๋ผ ์ข
๋ฅ(๊ณ์ธต)๋ก ๋จผ์ ๋๋๋ค.
models/,views/,services/์๋์ ๋ชจ๋ ๊ธฐ๋ฅ์ ํ์ผ์ด ์์ฌ ๋ค์ด๊ฐ๋ค - Feature-first(๊ธฐ๋ฅ ์ฐ์ ): ๊ธฐ๋ฅ์ผ๋ก ๋จผ์ ๋๋๊ณ , ๊ทธ ๊ธฐ๋ฅ ์์์ ์ข ๋ฅ๋ฅผ ๋๋๋ค
๊ฐ์ ์ฑ์ Feature-first๋ก ๋ฐ๊พธ๋ฉด ์ด๋ ๋ค.
lib/
main.dart
core/ # ์ฌ๋ฌ ๊ธฐ๋ฅ์ด ๊ฐ์ด ์ฐ๋ ๊ฒ
network/
dio_client.dart
router/
app_router.dart
theme/
app_theme.dart
features/
user/
data/
user_api_service.dart
user_repository.dart
model/
user.dart
ui/
user_list_page.dart
user_detail_page.dart
user_view_model.dart
todo/
data/
todo_repository.dart
model/
todo.dart
ui/
todo_page.dart
todo_view_model.dart์ด์ "์ฌ์ฉ์ ์์ธ์ ์ด๋ฉ์ผ ์ถ๊ฐ"๋ features/user/ ์์์ ๋๋๋ค. "ํ ์ผ ๊ธฐ๋ฅ ์ญ์ "๋ features/todo/ ํด๋ ํ๋๋ฅผ ์ง์ฐ๋ฉด ๋๋ค. ์ ๊ธฐ๋ฅ์ ๋ง๋ค ๋๋ features/ ์๋์ ํด๋๋ฅผ ํ๋ ๋ ๋ง๋ค๊ณ ๊ฐ์ ๋ชจ์์ผ๋ก ์ฑ์ฐ๋ฉด ๋๋ค.
import๋ package ๊ฒฝ๋ก๋ก ์ด๋ค
ํด๋๊ฐ ๊น์ด์ง๋ฉด ์๋ ๊ฒฝ๋ก๊ฐ ์ง์ ๋ถํด์ง๋ค.
import '../../../core/network/dio_client.dart'; // ๋ช ๋จ๊ณ ์์ธ์ง ์ธ์ด์ผ ํจDart๋ lib ์์ ํ์ผ์๋ ํจํค์ง ๊ฒฝ๋ก๋ฅผ ์ฐ๋ ๊ฑธ ๊ถํ๋ค. ์ฑ ์ด๋ฆ์ด my_app์ด๋ผ๋ฉด ์ด๋ ๊ฒ ์ด๋ค.
import 'package:my_app/core/network/dio_client.dart';ํ์ผ์ ๋ค๋ฅธ ํด๋๋ก ์ฎ๊ฒจ๋ import ์ค์ ๊ทธ๋๋ก ์ฝํ๋ค.
๊ท์น ์ธ ๊ฐ์ง
Feature-first๋ ํด๋๋ง ๋๋๋ค๊ณ ๋๋์ง ์๊ณ , ์ง์ผ์ผ ํ ๊ท์น์ด ์๋ค.
- ์์กด์ ํ ๋ฐฉํฅ์ผ๋ก๋ง ํ๋ฅธ๋ค:
features/*๋core/๋ฅผ ๊ฐ์ ธ๋ค ์ธ ์ ์์ง๋ง,core/๊ฐfeatures/*๋ฅผ ๊ฐ์ ธ๋ค ์ฐ๋ฉด ์ ๋๋ค.core๊ฐuser๊ธฐ๋ฅ์ ์๊ฒ ๋๋ฉดuser๋ฅผ ๊ณ ์น ๋core๋ ๊ฐ์ด ๊นจ์ง๋ค - ๊ธฐ๋ฅ๋ผ๋ฆฌ๋ ๋ด๋ถ ํ์ผ์ ์ง์ ๊ฑด๋๋ฆฌ์ง ์๋๋ค:
todo๊ธฐ๋ฅ์ดuser๊ธฐ๋ฅ์user_view_model.dart๋ฅผ importํ๊ธฐ ์์ํ๋ฉด ๋ ํด๋๊ฐ ํ ๋ฉ์ด๋ฆฌ๊ฐ ๋์ด Feature-first์ ์๋ฏธ๊ฐ ์ฌ๋ผ์ง๋ค. ๊ผญ ํ์ํ๋ฉดmodel/์ฒ๋ผ ๊ณต์ ํด๋ ๋๋ ๋ถ๋ถ๋ง ์ฐ๋ค shared,commonํด๋๋ฅผ ์กฐ์ฌํ๋ค: "์ด๋ ๋์ง ๋ชจ๋ฅด๊ฒ ๋ ํ์ผ"์ ๊ฑฐ๊ธฐ ๋์ง๋ค ๋ณด๋ฉด ์ฐ๋ ๊ธฐํต์ด ๋๋ค. ์ ๋ง ๋ ์ด์์ ๊ธฐ๋ฅ์ด ์ฐ๊ณ ์์ ๋๋งcore๋ก ์ฌ๋ฆฐ๋ค
๊ทธ๋ผ ๋ ์ค ๋ญ ์จ์ผ ํ๋
- ์์ ์ฑ, ํ๋ฉด ์๋ ๊ฐ, ํผ์ ๊ฐ๋ฐ: Layer-first๋ก ์ถฉ๋ถํ๋ค. ํด๋๊ฐ ๋จ์ํด์ ์ฒ์ ๋ง๋ค๊ธฐ ์ฝ๋ค
- ๊ธฐ๋ฅ์ด ๋์ด๋๊ณ ํ๋ฉด์ด ์ด ๊ฐ๋ฅผ ๋์ด๊ฐ๊ฑฐ๋ ์ฌ๋ฌ ์ฌ๋์ด ๊ฐ์ด ์์ : Feature-first๊ฐ ๋ซ๋ค. ํ ์ฌ๋์ด ํ ๊ธฐ๋ฅ ํด๋๋ง ๋งก์ผ๋ฉด ์ถฉ๋๋ ์ค์ด๋ ๋ค
์ฒ์๋ถํฐ Feature-first๋ก ์์ํ๋ ๊ฒ๋ ๋์์ง ์๋ค. ๊ธฐ๋ฅ์ด ํ๋๋ฟ์ด์ด๋ features/home/ ํ๋๋ง ๋ง๋ค์ด ๋๋ฉด, ๋์ค์ ๊ธฐ๋ฅ์ด ๋์ด๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์์์ ์ผ์ด ์๋ค.
๋ ๋ฐฉ์์ ์๋ ๊ฒฝ์ฐ๋ ๋ง๋ค
Flutter ๊ณต์ ์ฑ ์ํคํ
์ฒ ๊ฐ์ด๋๋ ์ฑ์ UI ๊ณ์ธต๊ณผ ๋ฐ์ดํฐ ๊ณ์ธต์ผ๋ก ๋๋๋ผ๊ณ ๊ถํ๋ค. UI ์์๋ ํ๋ฉด(View)๊ณผ ViewModel์ด ์๊ณ , ๋ฐ์ดํฐ ์ชฝ์๋ Repository์ Service๊ฐ ์๋ค. ์ด ๊ณ์ธต ๊ฐ๋
์ ๊ธฐ๋ฅ ํด๋ ์์ ๋ฃ์ ๊ฒ์ด ์์ features/user/{data,model,ui}์ด๋ค. "๊ธฐ๋ฅ์ผ๋ก ๋จผ์ ๋๋๊ณ , ๊ทธ ์์์ ๊ณ์ธต์ผ๋ก ๋๋๋ค"๊ฐ ํ์ค์์ ๊ฐ์ฅ ํํ ์ ์ถฉ์์ด๋ค. ์ด ๊ณ์ธต์ด ๊ฐ๊ฐ ๋ฌด์จ ์ผ์ ํ๋์ง๋ ๋ค์ ๊ธ์์ ๋ค๋ฃฌ๋ค.
Android, iOS์ ๋น๊ตํ๋ฉด
- ์ข
๋ฅ๋ณ๋ก ๋ชจ์ผ๊ธฐ: Flutter Layer-first / Android
package-by-layer(ui,dataํจํค์ง) / iOS์Models,Views๊ทธ๋ฃน - ๊ธฐ๋ฅ๋ณ๋ก ๋ชจ์ผ๊ธฐ: Flutter Feature-first / Android
package-by-feature์ ๊ธฐ๋ฅ๋ณ ๋ชจ๋ / iOS ๊ธฐ๋ฅ๋ณ ๊ทธ๋ฃน์ด๋ Swift Package - ์์กด ๋ฐฉํฅ ๊ฐ์ : Flutter๋ ๊ท์น์ผ๋ก ์งํด / Android๋ Gradle ๋ชจ๋๋ก ๊ฐ์ ํ ์ ์์ / iOS๋ ๋ชจ๋ ๋ถ๋ฆฌ๋ก ๊ฐ์ ํ ์ ์์
์๋๋ก์ด๋์์๋ ui, data๋ก ๋จผ์ ๋๋์ง ๊ธฐ๋ฅ๋ณ๋ก ๋๋์ง๋ ๊ฐ์ ๊ณ ๋ฏผ์ด๋ค. ๋ค๋ง Gradle ๋ชจ๋์ "์ด ๋ชจ๋์ ์ ๋ชจ๋์ ๋ชป ์ด๋ค"๋ฅผ ๋น๋๊ฐ ๋ง์์ฃผ๋๋ฐ, Flutter์ ํด๋๋ ๊ท์น์ ๊ฐ๋ฐ์๊ฐ ์ค์ค๋ก ์ง์ผ์ผ ํ๋ค๋ ์ ์ด ๋ค๋ฅด๋ค. ์ฑ์ด ์ ๋ง ์ปค์ง๋ฉด ๊ธฐ๋ฅ์ ๋ณ๋ ํจํค์ง๋ก ๋๋๊ธฐ๋ ํ๋ค.
์ ๋ฆฌ
- ์ข ๋ฅ๋ณ(Layer-first)๋ก๋ง ํด๋๋ฅผ ๋๋๋ฉด ๊ธฐ๋ฅ ํ๋๋ฅผ ๊ณ ์น ๋ ์ฌ๋ฌ ํด๋๋ฅผ ์ค๊ฐ๊ณ , ๊ธฐ๋ฅ์ ์ง์ฐ๊ธฐ๋ ์ด๋ ต๋ค
- ๊ฐ์ ์ด์ ๋ก ๋ฐ๋๋ ํ์ผ์ ๊ฐ๊น์ด ๋ชจ์ผ๋ ๊ฒ ํด๋ ๊ตฌ์กฐ์ ๊ธฐ์ค์ด๊ณ , ๊ทธ๋์
features/๊ธฐ๋ฅ์ด๋ฆ/์๋์ ๋ฐ์ดํฐ, ๋ชจ๋ธ, UI๋ฅผ ๋ชจ์ผ๋ Feature-first๋ฅผ ๋ง์ด ์ด๋ค - ์ฌ๋ฌ ๊ธฐ๋ฅ์ด ๊ฐ์ด ์ฐ๋ ๊ฑด
core/์ ๋๊ณ , ์์กด์features๊ฐcore๋ฅผ ๊ฐ๋ฆฌํค๋ ํ ๋ฐฉํฅ์ผ๋ก๋ง ํ๋ฅด๊ฒ ํ๋ค - ๊ธฐ๋ฅ๋ผ๋ฆฌ ์๋ก์ ๋ด๋ถ ํ์ผ์ importํ์ง ์๊ณ ,
shared,common์ ์ฐ๋ ๊ธฐํต์ผ๋ก ๋ง๋ค์ง ์๋๋ค lib์์ ํ์ผ์package:์ฑ์ด๋ฆ/...๊ฒฝ๋ก๋ก importํ๋ค- ์์ ์ฑ์ Layer-first๋ก ์ถฉ๋ถํ๊ณ , ํ๋ฉด๊ณผ ์ฌ๋์ด ๋๋ฉด Feature-first๋ก ๊ฐ๋ฉฐ, ๊ธฐ๋ฅ ์์์ UI/๋ฐ์ดํฐ ๊ณ์ธต์ ๋๋๋ ์ ์ถฉ์์ด ๊ฐ์ฅ ํํ๋ค
๋ค์ ๊ธ์์๋ ์ด ํด๋ ์์ data์ ui๊ฐ ๊ฐ๊ฐ ๋ฌด์จ ์ญํ ์ธ์ง, Repository ํจํด๊ณผ MVVM์ ๋ค๋ค๋ณด๊ฒ ๋ค.
