๐Ÿค– ์ธ๊ณต์ง€๋Šฅ๊ณผ์˜ ํ˜‘์—… ์‹ค์ „ ๊ฐ€์ด๋“œ - devlink-community/gaesubang-app GitHub Wiki

โ„น๏ธ ๊ฐœ์š”


์ด ํ”„๋กœ์ ํŠธ์—์„œ์˜ AU ํ˜‘์—… ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์ฝ”์–ด ๋กœ์ง (๋ฐ์ดํ„ฐ, ์ƒํƒœ, ์œ ์Šค์ผ€์ด์Šค ๋“ฑ)์€ ChatGPT์™€ ํ•จ๊ป˜ ๋น ๋ฅด๊ฒŒ ์„ค๊ณ„ํ•˜๊ณ  ์ž๋™ํ™”
  • ์ธ๊ฐ„ ๊ฐœ๋ฐœ์ž๋“ค์€ ๊ทธ๋งŒํผ UI/UX์— ์ง‘์ค‘
  • ๊ฒฐ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „๋‹ฌ๋˜๋Š” ํ™”๋ฉด์˜ ์™„์„ฑ๋„์— ์‚ฌ๋žŒ์˜ ๋””ํ…Œ์ผ์„ ์Ÿ์•„๋ถ“๋Š” ๊ฒƒ

โœ… ๋ชฉ์ 

์ด ํ”„๋กœ์ ํŠธ์—์„œ ChatGPT๋Š” ๋‹จ์ˆœ ๋ฌธ์„œ ์ž‘์„ฑ ๋ณด์กฐ๊ฐ€ ์•„๋‹Œ

Dart ์ฝ”์–ด ๋กœ์ง์˜ ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„ ํŒŒํŠธ๋„ˆ๋กœ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค.

  • AI๋Š” data/, domain/, usecase/ ๊ณ„์ธต์˜ ์„ค๊ณ„์™€ ๋ฆฌํŒฉํ† ๋ง์„ ์ฃผ๋„
  • ์ธ๊ฐ„ ๊ฐœ๋ฐœ์ž๋Š” UI ์œ„์ ฏ ๊ตฌ์„ฑ, ํ™”๋ฉด ํ๋ฆ„, ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ์ง‘์ค‘
  • .md ๊ฐ€์ด๋“œ๋Š” AI์—๊ฒŒ ํŒ€์˜ ๊ฐœ๋ฐœ ๊ธฐ์ค€์„ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ์ฐธ์กฐ ๋ฌธ์„œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

โœ… ChatGPT ํ”„๋กœ์ ํŠธ ๊ธฐ๋Šฅ์ด๋ž€?

ChatGPT์˜ โ€œํ”„๋กœ์ ํŠธโ€๋Š” ๋‹จ์ˆœ ๋Œ€ํ™” ๊ธฐ๋ก ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋ผ,

AI๊ฐ€ ํ”„๋กœ์ ํŠธ์˜ ๊ฐœ๋ฐœ ๊ตฌ์กฐ, ์—…๋กœ๋“œํ•œ ํŒŒ์ผ, ์ง€์นจ์„ "๊ธฐ์–ต"ํ•˜๊ณ  ์žฅ๊ธฐ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

Flutter ๊ฐœ๋ฐœ์—์„œ ํŠนํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์šฉ๋„๋กœ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค:

  • ํ”„๋กœ์ ํŠธ ์ „์šฉ lib/, core/, docs/ ํŒŒ์ผ ๊ตฌ์กฐ๋ฅผ ๊ทธ๋Œ€๋กœ AI์—๊ฒŒ ์ธ์‹์‹œํ‚ด
  • ๊ฐ ๊ณ„์ธต๋ณ„ ํŒŒ์ผ(์˜ˆ: result.dart, login_use_case.dart)์„ ๋ถ„์„ํ•˜์—ฌ ๊ตฌ์กฐ๋ฅผ ๊ธฐ์–ต
  • ๋ฌธ์„œ ๊ฐ€์ด๋“œ(naming.md, state_guide.md)๋ฅผ ๊ธฐ์ค€์œผ๋กœ AI์—๊ฒŒ ๊ธฐ์ค€ ์ œ์‹œ

๐Ÿ› ๏ธ ํ™œ์šฉ์„ ์œ„ํ•œ ๊ธฐ๋ณธ ์„ธํŒ…

1. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

  • ChatGPT ์™ผ์ชฝ ๋ฉ”๋‰ด โ†’ "ํ”„๋กœ์ ํŠธ" โ†’ ์ƒˆ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ
  • ์˜ˆ: SurvivorNet Flutter App

2. ์ดˆ๊ธฐ ์„ธํŒ… ๊ตฌ์„ฑ

ํ•ญ๋ชฉ ์„ค๋ช… ์˜ˆ์‹œ
์ง€์นจ ์„ค์ • ํ”„๋กœ์ ํŠธ์— ์‚ฌ์šฉํ•  ์•„ํ‚คํ…์ฒ˜, ํด๋” ๊ตฌ์กฐ, ๋„ค์ด๋ฐ ๊ทœ์น™ ๋“ฑ โ€œFreezed ๊ธฐ๋ฐ˜ MVI ๊ตฌ์กฐ, ๊ธฐ๋Šฅ ๋‹จ์œ„ ํด๋” ๋ถ„๋ฆฌ, ๋ชจ๋“  Action์€ sealed classโ€
ํŒŒ์ผ ์—…๋กœ๋“œ ํ•ต์‹ฌ .dart ํŒŒ์ผ, .md ๊ฐ€์ด๋“œ ์—…๋กœ๋“œ result.dart, naming_guideline.md ๋“ฑ
๊ธฐ๋ณธ ๊ธฐ๋Šฅ ์˜ˆ์‹œ ๋“ฑ๋ก ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ์„ ๋ฏธ๋ฆฌ ๋“ฑ๋กํ•ด์„œ ๊ธฐ์ค€ ์ œ์‹œ custom_button.dart, login_use_case.dart

๐Ÿ“‚ ์–ด๋–ค ํŒŒ์ผ์„ ๋“ฑ๋กํ•˜๋ฉด ์ข‹์€๊ฐ€?

์œ ํ˜• ์—…๋กœ๋“œ ๋Œ€์ƒ
๊ณตํ†ต ์ฝ”์–ด failure.dart, result.dart, ui_state.dart
๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ custom_button.dart, input_field.dart
์„ค๊ณ„ ๊ฐ€์ด๋“œ ๋ฌธ์„œ naming_guidelines.md, state_structure.md
ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ base_view_model.dart, profile_view_model.dart

๐Ÿง  ํ˜‘์—… ์˜ˆ์‹œ

๐Ÿ“ ํŒŒ์ผ ์—…๋กœ๋“œ ํ›„:

"์ด ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” failure.dart, result.dart, ui_state.dart ๊ธฐ์ค€์„ ๋ณด๊ณ ,
login_use_case.dart๋ฅผ ์„ค๊ณ„ํ•ด์ค˜. API๋Š” ์ด๋ฉ”์ผ/๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธฐ๋ฐ˜์ด์•ผ."

โžก๏ธ ChatGPT๋Š” ํŒŒ์ผ ๋‚ด ๊ธฐ์ค€์„ ์ฝ๊ณ , ๊ทธ์— ๋งž์ถ˜ UseCase ํ…œํ”Œ๋ฆฟ์„ ์ œ์•ˆํ•จ
๐Ÿ“„ ๋ฌธ์„œ ๊ธฐ๋ฐ˜ ์š”์ฒญ:

"์ด ๊ฐ€์ด๋“œ ๋ฌธ์„œ์— ๋”ฐ๋ผ ViewModel์— ํ•„์š”ํ•œ ์ƒํƒœ ํ•„๋“œ ๊ตฌ์„ฑํ•ด์ค˜."
<state_guidelines.md ์ผ๋ถ€ ๋ณต๋ถ™ ๋˜๋Š” ๋“ฑ๋ก>


๐Ÿ“Ž ํŒ: ๋” ๋˜‘๋˜‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฒ•

์ „๋žต ์„ค๋ช…
๐Ÿ“Œ ์ง€์นจ ์—…๋ฐ์ดํŠธ ์ž์ฃผ ํ•˜๊ธฐ ๊ตฌ์กฐ ๋ณ€๊ฒฝ, ๋„ค์ด๋ฐ ์ปจ๋ฒค์…˜ ๋ฐ”๋€Œ๋ฉด ์ง€์นจ๋„ ์—…๋ฐ์ดํŠธ
๐Ÿ“„ ๋ฌธ์„œ ์šฐ์„  ์ œ๊ณต ๊ธฐ์ค€ .md ๋ฌธ์„œ๋ฅผ ์ฒจ๋ถ€ํ•˜๋ฉด ์ •ํ™•๋„ ์ƒ์Šน
๐Ÿ—‚๏ธ ํŒŒ์ผ๋ช… ๋ช…ํ™•ํžˆ ์–ธ๊ธ‰ โ€œlogin_use_case.dart ๊ธฐ์ค€์œผ๋กœ ๋งŒ๋“ค์–ด์ค˜โ€ ์ฒ˜๋Ÿผ ๋ช…ํ™•ํ•œ ์ง€์‹œ๊ฐ€ ํšจ๊ณผ์ 
๐Ÿงช ๋น„๊ต ์š”์ฒญ ํ™œ์šฉ โ€œA vs B ํŒŒ์ผ ์ค‘ ์–ด๋–ค ๊ตฌ์กฐ๊ฐ€ ์œ ์ง€๋ณด์ˆ˜์— ์œ ๋ฆฌํ•œ๊ฐ€?โ€์™€ ๊ฐ™์€ ๋ถ„์„ ์š”์ฒญ ๊ฐ€๋Šฅ

๐Ÿงฉ ํ˜‘์—… ์—ญํ•  ์š”์•ฝ

์„ค๋ช…
์ธ๊ฐ„ ๊ฐœ๋ฐœ์ž UI ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, AI๊ฐ€ ์ƒ์„ฑํ•œ ๋กœ์ง์˜ ์„ค๊ณ„ ๊ฒ€ํ† , ๋ถ€๋ถ„ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ, ๋„๋ฉ”์ธ ํ๋ฆ„ ์ดํ•ด ๋ฐ ๊ตฌ์กฐ ๊ฐœ์„ ๊นŒ์ง€ ํฌํ•จ
ChatGPT ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง, ์ƒํƒœ ๊ตฌ์กฐ, UseCase/Repository์˜ ์ดˆ์•ˆ ์„ค๊ณ„ ๋ฐ ์ž๋™ํ™” ์ƒ์„ฑ ์ง€์›
๊ฐœ๋ฐœ ๊ฐ€์ด๋“œ ๋ฌธ์„œ ํŒ€์˜ ์„ค๊ณ„ ๊ธฐ์ค€์„ ๋ช…ํ™•ํžˆ ์ „๋‹ฌํ•˜๋Š” ์ฐธ์กฐ์šฉ ๋ฌธ์„œ
ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ ๊ตฌ์กฐ์™€ ์„ค๊ณ„ ํ๋ฆ„์˜ ์ž๋™ ์ƒ์„ฑ ๊ธฐ์ค€ (AI ์ƒ์„ฑ ๊ฒฐ๊ณผ ํ’ˆ์งˆ ํ–ฅ์ƒ์— ๊ธฐ์—ฌ)

๐Ÿง  ๋ณด์™„ ์„ค๋ช… ๋ฌธ๊ตฌ

โš ๏ธ ์ฃผ์˜: AI๋Š” ๋กœ์ง ์ž๋™ํ™”์˜ ๋ณด์กฐ์ž์ด๋ฉฐ, ์ตœ์ข… ์ฑ…์ž„์€ ์ธ๊ฐ„ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒ์„ฑ๋œ ์ฝ”๋“œ์˜ ์˜๋„ ํŒŒ์•…, ์„ค๊ณ„ ๊ฒ€์ฆ, ๋ถ€๋ถ„ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ, ๋„๋ฉ”์ธ ์—ฐ๊ฒฐ์„ฑ์€ ๋ฐ˜๋“œ์‹œ ์‚ฌ๋žŒ์ด ์ง์ ‘ ๊ฒ€ํ† ํ•˜๊ณ  ๋ณด์™„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํŠนํžˆ ์ƒํƒœ ๋ถ„๋ฆฌ, ์œ ์Šค์ผ€์ด์Šค ํ๋ฆ„, ViewModel ๋‚ด ์—ญํ•  ๊ตฌ๋ถ„์€ ํŒ€์˜ ๊ธฐ์ค€์— ๋”ฐ๋ผ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ฐœ์„ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ’ฌ ChatGPT์— ์š”์ฒญํ•  ๋•Œ ํšจ๊ณผ์ ์ธ ํ”„๋กฌํ”„ํŠธ ๊ฐ€์ด๋“œ

AI์™€ ํ˜‘์—…ํ•  ๋•Œ ํ•ต์‹ฌ์€ โ€œ๋ฌด์—‡์„ ์–ด๋–ป๊ฒŒ ์š”์ฒญํ•˜๋А๋ƒโ€ ์ž…๋‹ˆ๋‹ค.

๊ธฐ์ค€ ๋ฌธ์„œ๋‚˜ ํ…œํ”Œ๋ฆฟ์ด ์ž˜ ๊ฐ–์ถฐ์ ธ ์žˆ์–ด๋„, ์š”์ฒญ ๋ฐฉ์‹์ด ๋ชจํ˜ธํ•˜๋ฉด ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

์ด ์„น์…˜์€ ์šฐ๋ฆฌ ํŒ€์˜ ์•„ํ‚คํ…์ฒ˜์™€ ๊ฐœ๋ฐœ ๊ตฌ์กฐ์— ๋งž์ถฐ,

์‹ค์ œ๋กœ ํšจ๊ณผ์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•œ ์š”์ฒญ ์˜ˆ์‹œ ํ…œํ”Œ๋ฆฟ์„ ์ •๋ฆฌํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.


โœ… ๊ธฐ๋ณธ ViewModel ์ƒ์„ฑ ์š”์ฒญ

์ด ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” base_view_model.dart์™€ ui_state.dart ๊ธฐ์ค€์œผ๋กœ,
saved_recipes_view_model.dart ์ƒ์„ฑํ•ด์ค˜.
์ƒํƒœ๋Š” UiState<List<Recipe>> ํ•˜๋‚˜๋งŒ ์‚ฌ์šฉํ•˜๊ณ , ๋ถ๋งˆํฌ ์ถ”๊ฐ€/์‚ญ์ œ ๊ธฐ๋Šฅ๋„ ํฌํ•จ์‹œ์ผœ. 


โœ… ๊ตฌ์กฐ ๋น„๊ต / ๋ฆฌํŒฉํ† ๋ง ์š”์ฒญ

์ด์ „ ๋ฒ„์ „์˜ profile_state.dart์™€ ๋‚ด๊ฐ€ ์ˆ˜์ •ํ•œ ๋ฒ„์ „ ๋น„๊ตํ•ด์„œ
์ƒํƒœ ํ•„๋“œ ์„ค๊ณ„๊ฐ€ ์–ด๋–ค ์ ์—์„œ ๊ฐœ์„ ๋๋Š”์ง€ ์„ค๋ช…ํ•ด์ค˜.
ํ•„์š” ์—†๋Š” ์ค‘๋ณต์ด๋‚˜ ๋ถˆํ•„์š”ํ•œ ์ƒํƒœ๊ฐ€ ์žˆ์œผ๋ฉด ํ•จ๊ป˜ ์ง€์ ํ•ด์ค˜.


โœ… ์ƒํƒœ ์„ค๊ณ„ ๊ณ ๋ฏผ ์š”์ฒญ

๊ธ€์“ฐ๊ธฐ ํ™”๋ฉด์—์„œ ๋‹ค์Œ ์ƒํƒœ๊ฐ€ ํ•„์š”ํ•ด:
- ์ œ๋ชฉ ์ž…๋ ฅ
- ๋ณธ๋ฌธ ์ž…๋ ฅ
- ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๋ฆฌ์ŠคํŠธ
- ์ž„์‹œ์ €์žฅ ์—ฌ๋ถ€

์ด ์ƒํƒœ๋“ค์„ ๊ตฌ์กฐํ™”ํ•ด์„œ freezed ๊ธฐ๋ฐ˜ ProfilePostState๋กœ ์„ค๊ณ„ํ•ด์ค˜.
ํ•„์š”ํ•˜๋ฉด ๊ฐ’ ๊ฐ์ฒด(ValueObject)๋„ ์ œ์•ˆํ•ด์ค˜.


โœ… UseCase ์„ค๊ณ„ ์š”์ฒญ

login_use_case.dart ํŒŒ์ผ ๊ธฐ์ค€์œผ๋กœ,
fetch_saved_recipes_use_case.dart ์„ค๊ณ„ํ•ด์ค˜.
๊ฒฐ๊ณผ๋Š” UiState๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , Repository๋Š” ์ด๋ฏธ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด.


โœ… ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์š”์ฒญ

onTapFollow(int userId) ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•˜๋Š” follow_view_model.dart๊ฐ€ ์žˆ์–ด.
mock_follow_repository.dart๋„ ์—…๋กœ๋“œํ•ด๋†จ๊ณ ,
๋‹จ์ˆœ toggle ๊ตฌ์กฐ์•ผ. ์ƒํƒœ๊ฐ€ Success/Favorite โ†’ UnFavorite๋กœ ๋ฐ”๋€Œ๋Š” ํ๋ฆ„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด์ค˜.


โœ… ๋””์ž์ธ ๊ธฐ์ค€ ๋ฐ˜์˜ ์œ„์ ฏ ์š”์ฒญ

์ด ๋ฒ„ํŠผ์€ custom_button.dart ํ…œํ”Œ๋ฆฟ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ค˜.
- ๋†’์ด๋Š” ๊ณ ์ •๊ฐ’ 48
- ์•„์ด์ฝ˜ ์œ ๋ฌด, isLoading, isDisabled ์†์„ฑ ํฌํ•จ
- ํญ์€ ๋ถ€๋ชจ ์œ„์ ฏ์˜ maxWidth ๊ธฐ์ค€์œผ๋กœ responsiveํ•˜๊ฒŒ

์™ธ๋ถ€ ์Šคํƒ€์ผ(AppTextStyles, ColorStyle ๋“ฑ)๊นŒ์ง€ ํฌํ•จํ•ด์„œ ์„ค๊ณ„ํ•ด์ค˜.


๐Ÿ“Œ ํ”„๋กฌํ”„ํŠธ ์ž‘์„ฑ ์‹œ ์ฃผ์˜์‚ฌํ•ญ

  • ๊ธฐ์ค€ ํŒŒ์ผ๋ช…์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์ œ์‹œํ•  ๊ฒƒ

    (์˜ˆ: "login_use_case.dart ๊ธฐ์ค€", "profile_state.dart ์ฐธ๊ณ ")

  • ์š”๊ตฌ ํ•ญ๋ชฉ์„ ๋ช…์‹œ์ ์œผ๋กœ ๋‚˜์—ดํ•  ๊ฒƒ

    (์˜ˆ: โ€œ์„ธ ๊ฐ€์ง€ ์ƒํƒœ๋งŒ ํฌํ•จํ•ด์ฃผ์„ธ์š”โ€, โ€œ๋ถˆํ•„์š”ํ•œ ์ƒํƒœ๋Š” ์ง€์ ํ•ด์ฃผ์„ธ์š”โ€)

  • ๋ฌธ์„œ/ํŒŒ์ผ ๊ธฐ๋ฐ˜ ์š”์ฒญ ์‹œ .md ๋˜๋Š” .dart ์ผ๋ถ€๋ฅผ ๋ถ™์—ฌ์„œ ์ œ์‹œ

    (AI๊ฐ€ ๊ตฌ์กฐ๋ฅผ ๊ธฐ์–ตํ•˜๊ณ  ๊ธฐ์ค€์— ๋”ฐ๋ผ ์‘๋‹ต ๊ฐ€๋Šฅ)


์ด ์„น์…˜์€ ํ–ฅํ›„ ์‹ค์ œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์ถ•์ ๋˜๋ฉด ๋” ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณด์™„๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒ€์›์ด ์ง์ ‘ ์‹คํ—˜ํ•œ ์œ ํšจํ•œ ์š”์ฒญ ํ…œํ”Œ๋ฆฟ์€ ์ž์œ ๋กญ๊ฒŒ ๊ณต์œ ํ•˜๊ณ  ๋ฐ˜์˜ํ•ด์ฃผ์„ธ์š”.


โš ๏ธ **GitHub.com Fallback** โš ๏ธ