[Flutter] Flutter bloc ํด๋ฆฐ ์•„ํ‚คํ…์ณ (1)

2022. 6. 20. 01:33ใ†Flutter

https://devmuaz.medium.com/flutter-clean-architecture-series-part-1-d2d4c2e75c47

 

Flutter Clean Architecture Seriesโ€Š—โ€ŠPart 1

Sounds awesome? well, wait till we finish the app ๐Ÿ˜Ž!

devmuaz.medium.com

ํ”Œ๋Ÿฌํ„ฐ ํŒจํ„ด์„ ๋„ˆ๋ฌด ๋ฌด์ž‘์œ„๋กœ ํ•˜๊ธฐ๋ณด๋‹ค ์ข‹์€ ๊ตฌ์กฐ๋กœ ์žก๊ณ  ์ฝ”๋”ฉ์„ ํ•˜๋Š”๊ฒŒ ์ข‹์„ ๊ฑฐ ๊ฐ™๋‹ค ์ƒ๊ฐํ•ด์„œ ์ข‹์€ ๊ธ€์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์•„ ๋ฒˆ์—ญํ•˜๋ฉด์„œ ์ •๋ฆฌํ•ด๋ณด๋ ค ํ•ฉ๋‹ˆ๋‹ค.(์˜์–ด ์žผ๋ฏผ์ดใ…œ)

 

 

๊ธฐ๋ณธ์ ์ธ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

counter_app
|-- android // ์ปดํŒŒ์ผ๋œ android์•ฑ
|-- ios // ์ปดํŒŒ์ผ๋œ ios์•ฑ
|-- lib // 99ํผ์˜ ์‹œ๊ฐ„์„ ํ• ์• ํ•˜๋Š” ์žฅ์†Œ
	|-- main.dart // ํ”„๋กœ์ ํŠธ ์ง„์ž…์ . ๋ฐ˜๋“œ์‹œ ์กด์žฌํ•ด์•ผ ํ•˜๋ฉฐ main() ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จํ•ด์•ผํ•จ
|-- test // 50ํผ์˜ ์‹œ๊ฐ„์„ ํ• ์• ํ•ด์•ผ ํ•˜์ง€๋งŒ (^^;;) ๋ณดํ†ต 0.1ํผ์„ผํŠธ์˜ ์‹œ๊ฐ„์„ ์‚ฌ์šฉ
	|-- widget_test.dart 
.gitignore
pubspec.yaml // ๋ชจ๋“  dartํ”„๋กœ์ ํŠธ์— ํ•„์š”ํ•˜๋ฉฐ ์˜์กด์„ฑ๊ณผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ
pubspec.lock // ํŽธ์ง‘ํ•˜๋ฉด ์•ˆ๋˜๋Š” ์ž ๊ธˆ(lock)ํŒŒ์ผ ์ƒ์„ฑ. pubspec.yaml์„ ์—…๋Žƒํ•  ๋•Œ ์ด ์ž ๊ธˆ ํŒŒ์ผ์„ ๊ฐฑ์‹ ํ•˜๋ฉฐ
// ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ํŒจํ‚ค์ง€ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.
README.md

 

 

ํด๋ฆฐ ์•„ํ‚คํ…์ณ๋ฅผ ์žก๊ณ  ๊ฐ€๋ฉด

์žฅ์ 

- ํ…Œ์Šคํ„ฐ๋ธ”ํ•œ ์ฝ”๋“œ ๋ฐ ํ™•์žฅ์„ฑ ์žˆ๋Š” ๊ตฌ์กฐ 

- ์‰ฝ๊ฒŒ ์œ ์ง€ ๋ณด์ˆ˜

- ํ”„๋ ˆ์ž„์›Œํฌ / ํˆด์˜ ๋…๋ฆฝ์„ฑ

- ํฐ ๊ทœ๋ชจ, ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๋“ค์–ด๊ฐ„ ํฐ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉ(๋…๋ฆฝ์ ์ธ ํ˜•ํƒœ๋กœ ๊ตฌ์กฐํ™” ๋˜์–ด ๋ถ„์—…ํ™”์— ์šฉ์ดํ•จ)

- ์ž˜ ๊ตฌ์กฐํ™” ๋จ

 

๋‹จ์ 

- ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ(ํš์ผ์„ฑ)

- ๋ชจ๋“  ํ”„๋กœ์ ํŠธ(ํšŒ์‚ฌ ํ”„๋กœ์ ํŠธ์˜ ๋ฐฉํ–ฅ์„ฑ)์— ์ ํ•ฉํ•˜์ง„ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค (๊ฐ์ž์˜ ์Šคํƒ€์ผ๊ณผ ์š”๊ตฌ์‚ฌํ•ญ์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์œผ๋‹ˆ)

 

ํ”„๋กœ์ ํŠธ

news ์•ฑ ( REST API)์„ ๋ฐ์ดํ„ฐ ์š”์ฒญํ•ด์„œ ๊ฐ€์ ธ์˜ค๊ณ  ๋””๋ฐ”์ด์Šค์—์„œ ๋กœ์ปฌ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹œํ•˜๋Š” ๋‰ด์Šค์•ฑ์„ ๋งŒ๋“ฆ.

์ด ์•ฑ์—์„œ ์‚ฌ์šฉํ•  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ํด๋” ๊ตฌ์กฐ , ํ”„๋กœ์ ํŠธ ์„ค์ • ๋ฐ ์ฃผ์š” ์•„ํ‚คํ…์ฒ˜ ์†Œ๊ฐœ

 

๊ธฐ๋Šฅ

- ๋ฐ์ผ๋ฆฌ ๋‰ด์Šค List ๊ฐ€์ ธ์˜ค๊ธฐ

- ์ƒ์„ธ ๊ธฐ์‚ฌ ๋ณด๊ธฐ 

- ๊ด€์‹ฌ ๊ธฐ์‚ฌ save 

 

 

์‚ฌ์šฉํ•  ํŒจํ‚ค์ง€(๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)

- retrofit

Dio(https://pub.dev/packages/dio) ๋ฅผ http ํด๋ผ์ด์–ธํŠธ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์†Œ์Šค์ฝ”๋“œ ์ƒ์„ฑ ํŒจํ‚ค์ง€๋กœ REST APIs ๋ฉ”์†Œ๋“œ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์ƒ์„ฑํ•˜๋„๋ก ์ถ”์ƒํ™” ๋˜์–ด์žˆ๋‹ค! (์•ˆ๋“œ๋กœ์ด๋“œ Retrofit์—์„œ ์˜๊ฐ•์„ ๋ฐ›์Œ)

- floor 

  Sqlite๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ์ปฌ๋กœ ์ €์žฅํ•˜๋Š” typesafeํ•˜๊ณ  reactiveํ•œ ๊ฒฝ๋Ÿ‰ ์†Œ์Šค ์ฝ”๋“œ ์ƒ์„ฑ๊ธฐ ํŒจํ‚ค์ง€. (์•ˆ๋“œ๋กœ์ด๋“œ Room์—์„œ ์˜๊ฐ ๋ฐ›์Œ)

 

- flutter_bloc

์ƒํƒœ ๊ด€๋ฆฌ ํŒจํ‚ค์ง€ (react์˜ ๋ฆฌ๋•์Šค ๊ฐ™์€) Provider๊ฐ™์ด ์ „์—ญ์ ์œผ๋กœ ์ ‘๊ทผํ•ด์•ผํ•  ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌ

 

- equtable

dart๊ฐ์ฒด๋ฅผ ๋™๋“ฑํ•˜๊ฒŒ ๋น„๊ตํ•˜๋Š” ํ”Œ๋Ÿฌํ„ฐ ํŒจํ‚ค์ง€?

 

- get_it

์„œ๋น„์Šค ๋กœ์ผ€์ดํ„ฐ. DI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ (์•ˆ๋“œ๋กœ์ด๋“œ Dagger๋ผ๋Š” DI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์˜๊ฐ) ์ข…์†์„ฑ์„ ์ˆ˜๋™์œผ๋กœ ์ฃผ์ž…. ์ฆ‰, ์ข…์†์„ฑ ์ฃผ์ž…๊ธฐ..

 

- flutter_hooks

react hooks์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ƒํƒœ์˜ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๋ฉฐ ์ƒํƒœ ๋ณ€๊ฒฝ

 

- lint

dart์˜ ์Šคํƒ€์ผ ์ง€์นจ์— ๋”ฐ๋ผ ๊น”๋”ํ•œ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋Š”๋ฐ ๋„์›€์„ ์ฃผ๋Š” ํŒจํ‚ค์ง€

 

- ionicons

์˜ˆ์œ ์•„์ด์ฝ˜ ์„ธํŠธ

 

 

REST API

https://newsapi.org/docs/get-started์˜ ๋‰ด์Šค API๋ฅผ ์‚ฌ์šฉํ•ด json์œผ๋กœ ๊ฒ€์ƒ‰. ๋กœ๊ทธ์ธํ•ด์„œ APIํ‚ค ์–ป์–ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

 

๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ

lib/src ๋ฐ‘์œผ๋กœ



 

DI (Dependency Injection)  ํ•˜๋Š” ๋ฒ•
src๋‚ด์˜ injector.dartํŒŒ์ผ์€ get_it ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•ด DI (์ข…์†์„ฑ ์ฃผ์ž…)์„ ํ•˜๋Š” ์—ญํ• ์„ ํ•จ

 

์•„ํ‚คํ…์ณ ์„ค๋ช…

 

* config 

์•ฑ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. (ํ…Œ๋งˆ , ๊ฒฝ๋กœ ๋“ฑ๋“ฑ)

 

* core

์•ฑ ์ „์—ญ์œผ๋กœ ํ•„์š”ํ•œ ํ•ต์‹ฌ ํ•™๋ชฉ์ด ํฌํ•จ๋˜์–ด ์žˆ์Œ. ๊ธฐ๋Šฅ์— ํ•„์š”ํ•œ ์ž‘์—…/ ์•ก์…˜ ๊ฐ™์€ ๊ฒƒ์„ core์— ๊ตฌํ˜„

resources , utilities ๋“ฑ๊ณผ ๊ฐ™์€ ํด๋”๋“ค๋„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 


data ๊ณ„์ธต 


๋งจ ์•„๋ž˜ ๋ ˆ์ด์–ด์ธ Data๊ณ„์ธต์€ REST API, GraphQL ๊ฐ™์€ httpํ†ต์‹ ์œผ๋กœ ๋ฐ›์€ data , sqlite๊ฐ™์€ local DB์˜ raw data๋ฅผ <br>
  ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ. ๊ทธ ๋‹ค์Œ raw data(Json, Xml ..๋“ฑ)์„ ๋งคํ•‘ํ•˜๊ฑฐ๋‚˜ ์ง๋ ฌํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ Model(dart๊ฐ์ฒด)๋กœ ๋ณ€ํ™˜ํ•ด ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค. 
  
data๊ณ„์ธต์˜ models์€ Domain๊ณ„์ธต์˜ entities์™€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. 
์ด๋Ÿฐ ๊ณ„์ธต์œผ๋กœ ๋‚˜๋ˆ„๋Š” ์ด์œ ๋Š” raw data ์ง๋ ฌํ™”๋ฅผ  Json์—์„œ xml๋กœ ๋ณ€๊ฒฌํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์ด๋Ÿฐ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๋‚ด๋ถ€ entity (domain๊ณ„์ธต์˜ entity)์—
์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ.
Data๊ณ„์ธต์˜ Model์€ Domain๊ณ„์ธต์˜ entities์—์„œ property(์†์„ฑ)๋“ค์„ ํ™•์žฅํ•˜๊ณ  Model์ด entities์—์„œ ๋ชจ๋“  ์†์„ฑ์„ ํ™•์žฅํ•˜๋ฏ€๋กœ 
ํ•ญ์ƒ Domain๊ณ„์ธต์— ์ข…์†๋จ.

domain๊ณ„์ธต์—์„œ ์ธํ„ฐํŽ˜์ด์Šค(์ถ”์ƒํ™”๋œ ํด๋ž˜์Šค)๋ฅผ ์ •์˜.
data๊ณ„์ธต์—์„œ repository๋ฅผ ํฌํ•จํ•˜๋Š” domain๊ณ„์ธต์˜ ์ถ”์ƒํ™” ํด๋ž˜์Šค์˜ ์‹ค์ œ ๊ตฌํ˜„.
domain๊ณ„์ธต๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜์ง€ ์•Š๊ณ  ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•ด ์—ฌ๋Ÿฌ ๊ตฌํ˜„์„ ๋ณ€๊ฒฝ, ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด์„œ ์˜์กด์„ฑ์„ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

presentation๊ณ„์ธต

์ด ๊ณ„์ธต์€ 2๊ฐ€์ง€ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค. Bloc(ViewModel ํฌํ•จ)๊ณผ UI (widgets, state, animation..)

 * Bloc
 Bloc์—์„œ๋Š” ์™ธ๋ถ€(remote๋˜๋Š” local)๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”๋กœ ํ•˜๋Š” ๋ชจ๋“  ์ƒํ˜ธ์ž‘์šฉ์„ ์ด bloc์ด ์ฒ˜๋ฆฌํ•จ (redux๊ฐ™์€..)
   bloc์˜ ํŒจํ„ด์€ ๋‹จ์ผ ํด๋ž˜์Šค๋ฅผ ๊ฐ–๋Š” ๋Œ€์‹  ์ด๋Ÿฌํ•œ ์ƒํ˜ธ ์ž‘์šฉ์„ Event๋กœ ๋ถ„๋ฆฌํ•˜๊ณ  event๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  state์˜ ๊ฒฐ๊ณผ๋ฅผ UI๋กœ ๋ฆฌํ„ด
   UI์ชฝ์—์„  state์˜ ์ƒํƒœ๋ฅผ (stream of states) ๋ฐ›์•„ actionํ•˜๊ณ  ์œ„์ ฏ์„ ๋นŒ๋“œํ•ด์„œ ์—…๋ฐ์ดํŠธ
   
bloc์„ ์จ์„œ event, state, bloc์œผ๋กœ  role์„ ๋‚˜๋ˆ„๊ณ  ๋” ํด๋ฆฐํ•œ ์ฝ”๋“œ ๋ฒ ์ด์Šค๋ฅผ ๊ฐ€์ ธ๊ฐ.
presentation๊ณ„์ธต๋„ domain๊ณ„์ธต์— ์˜์กด - bloc์ด ์ฃผ์ž…(injected)๋œ domain์ข…์†์„ฑ(ex. usecase)๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ž‘์—… ์ฒ˜๋ฆฌํ•ด์„œ.


domain ๊ณ„์ธต 

- domain๊ณ„์ธต์€ ๋‚ด์˜ entities๋งŒ ํฌํ•จํ•˜๊ณ , ์šฐ๋ฆฌ domain์˜ entities๊ฐ€ domain ๊ณ„์ธต ์™ธ๋ถ€์—์„œ ๋ฐœ์ƒํ•  ๋ณ€๊ฒฝ ์‚ฌํ•ญ๊ณผ
์™„์ „ํžˆ ๋…๋ฆฝ์ ์ž„.
  
- persentation ๊ณ„์ธต๊ณผ data๊ณ„์ธต๋ชจ๋‘ domain๊ณ„์ธต์— ์˜์กดํ•จ. (ํ•„์ˆ˜์ ์ธ ์˜์กด์„ฑ)
- data๊ณ„์ธต์˜ domain๊ณ„์ธต์—์„œ ์ž‘์„ฑ๋œ ๊ณ„์•ฝ(์ถ”์ƒํด๋ž˜์Šค)๋ฅผ ์‹ค์ œ ๊ตฌํ˜„ / presentation๊ณ„์ธต์€ ์ฃผ์ž…๋œ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ๋•Œ ์ด๋Ÿฐ ๊ณ„์•ฝ๋“ค์„ ์‚ฌ์šฉ.

- presentation๊ณ„์ธต์€ model์ด ์•„๋‹Œ entity๋กœ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์–ด ๊ฐ ๊ณ„์ธต์„ ๋…๋ฆฝ์ ์œผ๋กœ ๋ถ„๋ฆฌํ•ด์•ผํ•จ.
- ๋Œ€ํ˜• ํ”„๋กœ์ ํŠธ๋Š” ๊ฐ ๊ณ„์ธต์— ๋งคํ•‘ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ ๊ณ„์ธต๋ณ„๋กœ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ณ  ์„œ๋กœ ์ข…์†๋˜์ง€ ์•Š๋„๋ก ํ•˜๋Š”๊ฒŒ ์ข‹์Œ (ํ•ด๋‹น ํ”„๋กœ์ ํŠธ๋Š” ์ž‘์•„์„œ ๊ทธ๋ ‡๊ฒŒ๊นŒ์ง€์€ ์•ˆํ•จ!)

usecase
usecase๋Š” ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋ƒ๋ฉด repository์— ์˜์กดํ•˜๋Š” ๊ฐœ๋ณ„ ํด๋ž˜์Šค๋กœ, ํ•˜๋‚˜์˜ ์ •ํ™•ํ•œ ์ž‘์—…(๊ธฐ์‚ฌ ๊ฐ€์ ธ์˜ค๊ธฐ, data ๊ฒŒ์‹œ, ๋กœ๊ทธ์ธ ๋“ฑ)๋งŒ์„ ์ˆ˜ํ–‰.
  usecase์— ์ฃผ์ž…๋œ ์—ฌ๋Ÿฌ repository๋ฅผ ์ทจํ•  ์ˆ˜ ์žˆ๊ณ  bloc(viewmodel)์€ ๊ทธ๊ฒƒ์— ์ฃผ์ž…๋œ ์—ฌ๋Ÿฌ usecase๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.