Maui: MVU๋Š” ๋‹น์‹ ์ด ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

์— ๋งŒ๋“  2020๋…„ 05์›” 27์ผ  ยท  50์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: dotnet/maui

์š”์ „์— ๊ณต์‹ ๋ฐœํ‘œ๋ฅผ ์ฝ์—ˆ์„ ๋•Œ MVU๋กœ ํ‘œ์‹œ๋œ ๋‚ด์šฉ์— ๋†€๋ž์Šต๋‹ˆ๋‹ค.

readonly State<int> count = 0;

[Body]
View body() => new StackLayout
{
    new Label("Welcome to .NET MAUI!"),
    new Button(
        () => $"You clicked {count} times.",
        () => count.Value ++)
    )
};

๋‚ด๊ฐ€ ์•„๋Š” ํ•œ ์ด๊ฒƒ์€ MVU๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค . ๋‚˜๋Š” ์ด๋ฏธ ์—ฌ๊ธฐ ์— ์™œ ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ƒ๊ฐ ์„ ์ ์—ˆ์Šต๋‹ˆ๋‹ค .

๋‚ด๊ฐ€ ์•Œ๊ธฐ๋กœ๋Š” Xamarin.Forms ์œ„์— MVU๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๋‚˜์ค‘์— Fabulous ๊ฐ€ ๋œ ๊ฒƒ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ 2018๋…„ ๋ช‡ ๋‹ฌ์„ ๋ณด๋‚ธ Don Syme ๋Š” ์ข€ ๋” ์™ธ๊ต์  ์ด์ง€๋งŒ ๊ฒฐ๋ก ์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ, ๋‚ด ์š”์ ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

  • C#์ด๋“  F#์ด๋“  ์ƒ๊ด€์—†์ด ์‹ค์ œ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์„ ๊ตฌํ˜„ํ–ˆ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค. Fabulous ๋’ค์— ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋‹ค๊ฐ€๊ฐ€๋Š” ๊ฒƒ์ด ์—ฌ๊ธฐ์—์„œ ์‹œ์ž‘๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๊ฒƒ์— ๊ด€์‹ฌ์ด ์—†์ง€๋งŒ ํ˜„์žฌ Comet ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๋ช…ํ™•ํ•œ ๋น„์ „์ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น "์•ฑ ๋ชจ๋ธ"์— ๋” ์ ์ ˆํ•œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค. ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐœ๋ช…ํ•˜์‹ญ์‹œ์˜ค. ์ด๋ฆ„์„ MSMVU๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ฌด์—‡์ด๋“ . ๊ทธ๋Ÿฌ๋‚˜ ์˜ค๋ Œ์ง€๋ฅผ ์œ„ํ•ด ์‚ฌ๊ณผ๋ฅผ ํŒ”์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๊ฑด๋ฐฐ!

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์—ฌ๊ธฐ์—์„œ ์–ธ๊ธ‰๋˜์—ˆ์œผ๋ฏ€๋กœ ๋ช‡ ๊ฐ€์ง€๋งŒ ๋ง์”€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

  • MAUI๋Š” ํ›Œ๋ฅญํ•˜๊ณ  ์•„ํ‚คํ…์ฒ˜๋กœ์„œ์˜ MVU์— ๋Œ€ํ•ด ๋ฐฐ์šฐ๋Š” ๊ฒƒ์€ ์‚ฌ๋žŒ๋“ค์ด MAUI๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

  • ๋‹จ์–ด์— ์–ฝ๋งค์ด๊ธฐ ์‰ฝ๊ณ , ์ด ๋‹จ๊ณ„์—์„œ ์šฐ๋ฆฌ ๋ชจ๋‘ ์ˆจ์„ ์‰ฌ๊ณ  ๊ฑฑ์ •ํ•˜์ง€ ์•Š์œผ๋ ค๊ณ  ๋…ธ๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ๋˜๋Š” ๋‹จ์–ด๋ฅผ ์กฐ์ •ํ•  ์‹œ๊ฐ„์ด ์ถฉ๋ถ„ํ•˜๊ณ  ์ •ํ™•ํ•œ ์šฉ์–ด์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „๋‹ฌ๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋“ค์—ˆ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ Elm์€ "MVU"์˜ ๊พธ๋ฐˆ์ด ์—†๊ณ  ํ•œ์ •๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ด ๋ช…์‹œ์  ๋ฉ”์‹œ์ง€, ๋ช…์‹œ์  ์—…๋ฐ์ดํŠธ, ๊ธฐ๋Šฅ์  ๋ชจ๋ธ, ๊ธฐ๋Šฅ์  ๋ทฐ ์žฌ๊ณ„์‚ฐ ๋ฐ ์ฐจ๋“ฑ ์—…๋ฐ์ดํŠธ๋ฅผ ์˜๋ฏธํ•œ๋‹ค๋Š” ๊ฒƒ์„ ํ™•๋ฆฝํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ MVU ์—๋Š” ๋งŽ์€

  • ๋‚˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ด ๋ถ„์•ผ์— ๋Œ€ํ•ด ๋งค์šฐ ๊ฐ•ํ•œ ์‹ ๋…๊ณผ ์˜๊ฒฌ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๊ณ  ๋งค์šฐ ๊ฐœ์ธ์ ์œผ๋กœ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์–ด๋–ค ๊ฒƒ์ธ์ง€ ์•Œ๊ณ  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ๋””์ž์ธ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ณต๊ฐ„์˜ ๋ชจ๋“  ์ง€์ ์—๋Š” ์žฅ๋‹จ์ ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ์ตœ๊ณ ์˜ ๊ธฐ์ˆ ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋ชจ๋“  ์‚ฌ๋žŒ์ด ํ•จ๊ป˜ ์‹œ๋„ํ•˜๊ณ , ์‚ฌ์šฉํ•˜๊ณ , ๋ฐฐ์šฐ๊ณ , ๊ณต์œ ํ•˜๊ณ , ํ˜‘๋ ฅํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  50 ๋Œ“๊ธ€

@aspnetde ์—๊ฒŒ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์•ž์œผ๋กœ 18๊ฐœ์›” ์ •๋„ ๋™์•ˆ ์ด ์•„์ด๋””์–ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์ž‘์—…์—

.NET MAUI ๊ฐ€ ์•„์ง ์‹ค์ œ๋กœ ๋นŒ๋“œ ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— .NET MAUI๊ฐ€ MVU์ธ์ง€ ์•„๋‹Œ์ง€ ๋งํ•˜๊ธฐ์—๋Š” ๋„ˆ๋ฌด ์ด๋ฅด๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. :)

์˜ˆ, ํ”„๋กœํ† ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋„ค, Comet ์‹คํ—˜์—์„œ ์˜๊ฐ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜ˆ, ์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ๊นŒ์ง€ ์šฐ๋ฆฌ๊ฐ€ ๋ณด์—ฌ์ค€ ๊ฒƒ์ด MVU์— ๋Œ€ํ•œ ๋ชจ๋“  ์‚ฌ๋žŒ์˜ ์ •์˜์™€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์šฐ๋ ค๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ํฌ๋ง์€ ์šฐ๋ฆฌ๊ฐ€ ํ˜‘๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค! ์šฐ๋ฆฌ๊ฐ€ ์ตœ์ข…์ ์œผ๋กœ ๋””์ž์ธํ•˜๊ณ  ๋ฐฐ์†กํ•˜๋Š” ๊ฒƒ์ด ๋‹ค๋ฅธ ๋ผ๋ฒจ์„ ๋ฐ›์„ ์ž๊ฒฉ์ด ์žˆ๋‹ค๋ฉด, ๋‚˜๋Š” ๊ทธ๊ฒƒ์— ํ•˜๋‚˜๋ฅผ ๋ถ€์—ฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

.NET MAUI์—์„œ C# MVU๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด๊ฒŒ ๋ ๊นŒ์š”?

ํ•„์š”ํ•˜๋‹ค๋ฉด ์–ด๋–ค ์ƒˆ๋กœ์šด ์–ธ์–ด ๊ธฐ๋Šฅ์ด ํ•„์š”ํ• ๊นŒ์š”?

Fabulous ๋ฐ/๋˜๋Š” C#๊ณผ F# ๊ฐ„์— ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉ๋˜๋Š” ํŒจํ„ด์€ ๋ฌด์—‡์ด๋ฉฐ ๋ฌด์—‡์ด ๋‹ฌ๋ผ์•ผ ํ•ฉ๋‹ˆ๊นŒ? ํ†ตํ•ฉ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

.NET MAUI์—์„œ C# MVU๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด๊ฒŒ ๋ ๊นŒ์š”?

C# MVC ๋˜๋Š” C# MVVM์ด๋ผ๋Š” ๋ง์„ ๋“ค์–ด๋ณธ ์ ์ด ์žˆ์Šต๋‹ˆ๊นŒ? _Model-View-Update_ aka _The Elm Architecture_๋Š” ์–ธ์–ด ์ข…์† ๊ตฌํ˜„์ด ์•„๋‹ˆ๋ผ ์ž˜ ์ •์˜๋œ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

ํ•„์š”ํ•˜๋‹ค๋ฉด ์–ด๋–ค ์ƒˆ๋กœ์šด ์–ธ์–ด ๊ธฐ๋Šฅ์ด ํ•„์š”ํ• ๊นŒ์š”?

  • ๊ณต์šฉ์ฒด ์œ ํ˜•์€ ๋ฉ”์‹œ์ง€ ์ •์˜๋ฅผ ํฌ๊ฒŒ ๋‹จ์ˆœํ™”ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜์ง€๋งŒ ์ธํ„ฐํŽ˜์ด์Šค/์ถ”์ƒ ํด๋ž˜์Šค ๋ฐ ๋ฉ”์‹œ์ง€๋‹น ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ž‘์„ฑํ•˜๋ ค๋ฉด ์ข€ ๋” ๋งŽ์€ ์ƒ์šฉ๊ตฌ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํŒจํ„ด ์ผ์น˜๊ฐ€ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์‹œ์ง€์˜ ํ˜•ํƒœ๊ฐ€ ๋‹จ์ˆœํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— C# ์Šค์œ„์น˜ ํ‘œํ˜„์‹์˜ ํ˜„์žฌ ์ƒํƒœ๋Š” ์ด๋ฏธ ์ถฉ๋ถ„ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
  • ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ถˆ๋ณ€์„ฑ์ด๋ฉฐ ๊ตฌ์กฐ์  ๋™๋“ฑ์„ฑ ๋น„๊ต๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. C# 9(์ผ๋ช… ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค)์˜ ๋ ˆ์ฝ”๋“œ์— ๋Œ€ํ•œ ํ˜„์žฌ ์ œ์•ˆ์„ ๊ธฐ์–ตํ•˜๋Š” ํ•œ, ๊ทธ๊ฒƒ๋“ค์€ ์ •ํ™•ํžˆ ๊ทธ๊ฒƒ์„ ์ œ๊ณตํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ C# 9๋Š” ์—ฌ์ „ํžˆ F#๋ณด๋‹ค ์‹œ๋„๋Ÿฝ์ง€๋งŒ ํ˜„์žฌ์˜ ๊ด€์ ์—์„œ ๋ณด๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Fabulous ๋ฐ/๋˜๋Š” C#๊ณผ F# ๊ฐ„์— ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉ๋˜๋Š” ํŒจํ„ด์€ ๋ฌด์—‡์ด๋ฉฐ ๋ฌด์—‡์ด ๋‹ฌ๋ผ์•ผ ํ•ฉ๋‹ˆ๊นŒ? ํ†ตํ•ฉ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ MVU ์ž์ฒด๊ฐ€ ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ ๋˜๋Š” ์•ฑ ๋ชจ๋ธ์ด๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ด ์ „์ฒด ์ ‘๊ทผ ๋ฐฉ์‹์—์„œ ํŠนํžˆ ์–ธ์–ด๋ณ„ ํ•ญ๋ชฉ์ด ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@TimLariviere ๋Š” ์ตœ๊ทผ Fabulous๋ฅผ ๋ฐœ์ „์‹œํ‚ค๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€


๊ทธ๊ฑด ๊ทธ๋ ‡๊ณ : ์ž‘๋…„์— XF + C# + MVVM๊ณผ XF + F# + MVU๋ฅผ 1:1๋กœ ๋น„๊ตํ–ˆ๋Š”๋ฐ ๊ฒฐ๊ณผ๋Š” ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•˜์—ฌ ์—ฌ๊ธฐ ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

.NET MAUI๊ฐ€ MVU์ธ์ง€ ์•„๋‹Œ์ง€ ๋งํ•˜๊ธฐ์—๋Š” ๋„ˆ๋ฌด ์ด๋ฅด๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

MAUI๊ฐ€ ๊ฒฐ๊ตญ MVU๊ฐ€ ๋ ์ง€ ์—ฌ๋ถ€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ด๋ฏธ ๋งŽ์€ ํ˜ผ๋ž€์„ ์•ผ๊ธฐํ•œ ๋ฐœํ‘œ ๋ธ”๋กœ๊ทธ์˜ ์ƒ˜ํ”Œ์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚˜๋Š” ์ €์ž๊ฐ€ ์•„์ง MVU๋ฅผ ์‹ค์ œ๋กœ ์กฐ์‚ฌํ•˜์ง€ ์•Š์•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. "C# MVU"์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•œ๋‹ค๊ณ  ํ•ด์„œ ์ด๊ฒƒ์ด ๋” ๋‚˜์•„์ง€๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

@aspnetde ๋ฐ @forki์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ์ค‘ ๋ˆ„๊ตฌ๋„ MAUI/XF์šฉ ํ˜œ์„ฑ์—์„œ ์˜๊ฐ์„ ๋ฐ›์€ C# DSL์„ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ฃผ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. .

์ด๊ฒƒ์€ ๋‚ด๊ฐ€ ์ง์ ‘ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜๊ณผ ๋ฌธ์ œ์— ๋Œ€ํ•ด ๊ณ„์†ํ•ด์„œ ์งˆ๋ฌธํ•ด ์˜จ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๊ด€๋ จ๋œ ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์ด MVVM ๋ฐ MVU์™€ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ํŒจํ„ด์— ๋Œ€ํ•ด ์ฝ์–ด๋ณด๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ฆ‰, MVVM ์œ„์— MVU๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๊ฒƒ์ธ์ง€๋Š” ์—ฌ์ „ํžˆ ์˜๋ฌธ์ž…๋‹ˆ๋‹ค.

C# MVC ๋˜๋Š” C# MVVM์ด๋ผ๋Š” ๋ง์„ ๋“ค์–ด๋ณธ ์ ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์˜ˆ, C# ๋˜๋Š” XAML ๋’ค์— MVVM ๋˜๋Š” MVU์™€ ๊ฐ™์€ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์ด ์˜ค๋Š” ๊ฒƒ์ด ์ด์ƒํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ด์•ผ๊ธฐํ•˜๋Š” ๋” ๊ด‘๋ฒ”์œ„ํ•œ ๊ฐœ๋ฐœ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ ์ค‘์—์„œ ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ ์›ํ•˜๋Š” ์ˆ˜์˜ ์กฐํ•ฉ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๋ถ„๋ช…ํžˆ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜๋„๋Š” "C# MVVM"์ด "XAML MVVM"๊ณผ ๊ตฌ์กฐ์ ์œผ๋กœ ๋‹ค๋ฅด๋‹ค๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์กฐํ•ฉ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜์ด ์ „์ฒด์ ์œผ๋กœ ์•ฝ๊ฐ„ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ๊ฐ€ .NET MAUI์—์„œ MVU๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€ ๋…ผ์˜ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ์—ฌ๊ธฐ์—์„œ ๋” ์ƒ์‚ฐ์ ์ธ ๋…ผ์˜๋Š” ๋‹จ์ผ ์ œํ’ˆ ๋‚ด์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜๊ณผ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ๋ฌด์—‡์ด๋ผ๊ณ  ๋ถ€๋ฅด๊ณ  ๋ ˆ์ด๋ธ”์„ ์ง€์ •ํ•˜๋ฉฐ ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๊ฒƒ์ด ์—ฌ๊ธฐ์—์„œ ๋Œ€๋ถ€๋ถ„์˜ ์˜๊ฒฌ์˜ ๋ฐฉํ–ฅ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋งŽ์€ ์˜์‚ฌ์†Œํ†ต์„ ํ•˜๊ณ  ์žˆ๊ณ  ๋‚ด๊ฐ€ ์‹ค์ œ๋กœ ๋ช…ํ™•์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ํ˜ผ๋ž€์„ ์ผ์œผํ‚ค์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด์— ๋Œ€ํ•œ ๊ท€ํ•˜์˜ ์˜๊ฒฌ์„ ์ง„์‹ฌ์œผ๋กœ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ด๋ฏธ ๋งŽ์€ ํ˜ผ๋ž€์„ ์•ผ๊ธฐํ•œ ๋ฐœํ‘œ ๋ธ”๋กœ๊ทธ์˜ ์ƒ˜ํ”Œ์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ๋ธ”๋กœ๊ทธ์— ๋Œ€ํ•œ ๋‚˜์˜ ๊ณตํ—Œ์ด์—ˆ๊ณ  ๊ทธ๊ฒƒ์ด ๋‹น์‹ ์„ ์œ„ํ•ด ๋งŒ๋“  ํ˜ผ๋ž€์— ๋Œ€ํ•ด ์‚ฌ๊ณผ๋“œ๋ฆฝ๋‹ˆ๋‹ค. Elm๊ณผ @aspnetde ์˜ ๋ธ”๋กœ๊ทธ์— ๋งํฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ "์ด๊ฒƒ์ด ๋ฐ”๋กœ MVU์ž…๋‹ˆ๋‹ค"๋ผ๊ณ  ์ž˜๋ชป ๊ณ„์‚ฐํ–ˆ์œผ๋ฉฐ ๊ธฐ์กด MVU ๊ฒฝํ—˜๊ณผ ๊ธฐ๋Œ€๊ฐ€ ์žˆ๋Š” ๋ถ„๋“ค์—๊ฒŒ ์ฝ”๋“œ ์กฐ๊ฐ์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ๋น„์ค‘์„ ์ฐจ์ง€ํ• ์ง€ ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€/์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€์— ๋Œ€ํ•ด.

๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚˜๋Š” ์ €์ž๊ฐ€ ์•„์ง MVU๋ฅผ ์‹ค์ œ๋กœ ์กฐ์‚ฌํ•˜์ง€ ์•Š์•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ฃผ์ œ์— ๋Œ€ํ•ด ๊ด‘๋ฒ”์œ„ํ•œ ๋Œ€ํ™”์™€ ํ† ๋ก ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์ •ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์ €๋„ ๊ทธ๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š์œผ๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ๊ทธ๊ฒƒ์ด ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๊ฒƒ์ธ์ง€ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

@dersia ํ•ด๊ฒฐํ•ด์•ผ ํ•  ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์„ ํƒ๊ถŒ์„ ์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. MVVM ์œ„์— ์žˆ๋Š” MVU๊ฐ€ ๋ฌด์—‡์„ ํ•ด๊ฒฐํ•˜๋Š”์ง€ ๋ฌป๋Š”๋‹ค๋ฉด ๋‚˜๋Š” ์ „ํ˜€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์š”๊ตฌ๋˜๊ฑฐ๋‚˜ ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋ ค๊ณ  ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.

#28 ๋ฐ #66์—์„œ ์ œ์•ˆ๋œ ๋ฆฌํŒฉํ† ๋ง์€ ๋ถ€๋ถ„์ ์œผ๋กœ ๋ Œ๋”๋Ÿฌ ๊ตฌํ˜„์—์„œ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ๋ฐ MVVM ๊ด€๋ จ ์‚ฌํ•ญ์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ MVU๋ฅผ ์„ ํƒํ•˜๋ฉด MVVM์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฝ”๋“œ ์กฐ๊ฐ์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ๋ฌด๊ฒŒ๋ฅผ ๊ฒฌ๋”œ์ง€ ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทผ๋ฐ ์ € ๊ณ ๊ธฐ ๋งž์ฃ ? ๊ทธ๋ฆฌ๊ณ  ๋ผ๋ฒจ๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š์•„ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.

@davidortinau

์šฐ๋ฆฌ๊ฐ€ ๋ฌด์—‡์ด๋ผ๊ณ  ๋ถ€๋ฅด๊ณ  ๋ ˆ์ด๋ธ”์„ ์ง€์ •ํ•˜๋ฉฐ ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๊ฒƒ์ด ์—ฌ๊ธฐ์—์„œ ๋Œ€๋ถ€๋ถ„์˜ ์˜๊ฒฌ์˜ ๋ฐฉํ–ฅ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋งŽ์€ ์˜์‚ฌ์†Œํ†ต์„ ํ•˜๊ณ  ์žˆ๊ณ  ๋‚ด๊ฐ€ ์‹ค์ œ๋กœ ๋ช…ํ™•์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ํ˜ผ๋ž€์„ ์ผ์œผํ‚ค์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด์— ๋Œ€ํ•œ ๊ท€ํ•˜์˜ ์˜๊ฒฌ์„ ์ง„์‹ฌ์œผ๋กœ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

์ œ ์ชฝ์—์„œ ์ถ”๊ฐ€ํ•  ๋‚ด์šฉ์ด ๋‚จ์•„ ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ œ ์ž…์žฅ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•œ ๊ฒƒ ๊ฐ™์•„์š” :-). MVU๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์—ด๋ฆฐ ๋ฌธ์„ ๋ฐ€๊ณ  ๋‚˜๊ฐˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐœํ‘œ ๊ฒŒ์‹œ๋ฌผ๊ณผ Comet ์ €์žฅ์†Œ์˜ ์Šค๋‹ˆํŽซ์„ ๋ณด๊ณ  ์ถ”์ธกํ•  ์ˆ˜ ์žˆ๋Š” ๋‚ด์šฉ์ด๋ผ๋ฉด ์ž์œ ๋กญ๊ฒŒ ๊ทธ๋ ‡๊ฒŒ ํ•˜์‹ญ์‹œ์˜ค. ๊ทธ๋Ÿฌ๋‚˜ MVU๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒƒ์€ _์ œ๋ฐœ_ ์ค‘์ง€ํ•˜์‹ญ์‹œ์˜ค.

๊ฐ์‚ฌ ํ•ด์š”.

Don์ด ์ด ์Šค๋ ˆ๋“œ์—์„œ ์–ธ๊ธ‰๋˜์—ˆ๋“ฏ์ด :-) - CC: @dsyme

์™œ ์ด๊ฒƒ์ด MVU๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š”์ง€ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ํ›Œ๋ฅญํ•œ ํŒจ๋Ÿฌ๋‹ค์ž„์ผ ์ˆ˜ ์žˆ๊ณ  ์—ฌ๊ธฐ์—์„œ ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ํŒจ๋Ÿฌ๋‹ค์ž„์— ์ ํ•ฉํ•˜๊ณ  ํ˜ผ๋™ํ•˜์ง€ ์•Š๋Š” ์ ์ ˆํ•œ ์šฉ์–ด๋ฅผ ์ƒ๊ฐํ•ด๋‚ด์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๊นŒ?

@aspnetde ์˜†์— ๋ฌด์—‡์ด ๋‚จ์•˜์Šต๋‹ˆ๊นŒ? ๋งŽ์€ ๊ฒƒ ๊ฐ™์•„์š” :).
๋‚˜๋Š” ๋‹น์‹ ์˜ ๋…ผ๋ฌธ์˜ ์ผ๋ถ€๋ฅผ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ข‹์•„ํ–ˆ๋‹ค๊ณ  ๋งํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ Don Sym์—์„œ F#์— ๋Œ€ํ•œ ์ฑ…์„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด ๊ฐ„๊ฒฐํ•˜์ง€๋งŒ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๊ฐ€๋…์„ฑ์€ ๊ฐœ๋ฐœ ์ˆ˜๋ช… ์ฃผ๊ธฐ์—์„œ ๋งค์šฐ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ๋ฐ ๋งŽ์€ ์‹œ๊ฐ„์„ ํ• ์• ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์žฌ๊ท€๋Š” ์“ฐ๊ธฐ ์ „์šฉ์ž…๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ์ž‘์„ฑํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๊ฑฐ์˜ ์•„๋ฌด๋„ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(regexp์™€ ์œ ์‚ฌ).
๊ณผ๊ฑฐ์— ํšŒ์‚ฌ์—์„œ ํ”„๋กœํ† ํƒ€์ดํ•‘/์—ฐ๊ตฌ ์‹œ๊ฐ„ ๋™์•ˆ Angular์™€ ํ•จ๊ป˜ Redux๋ฅผ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜ํ”„ ์—˜๋ฏธ์‰ฌ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๊นŒ? ์†Œ์ค‘ํ•œ ๊ฒฝํ—˜์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•ด์•ผ ํ•˜๋ฉฐ ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ •ํ™•ํžˆ ์ƒํƒœ๊ฐ€ ๊ฐ‘์ž๊ธฐ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ์ „์ฒด ์Šคํƒ์„ ๊ธฐ์–ตํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.
๋‚˜๋Š” ๋ถˆ๋ณ€์„ฑ์˜ ์ด์ ์„ ์ดํ•ดํ•˜์ง€๋งŒ ํ˜„์‹ค ์„ธ๊ณ„๋Š” ๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ๊ฐ‘์ž๊ธฐ ํ…Œ๋””๋ฒ ์–ด์˜ ๋จธ๋ฆฌ๋ฅผ ์ฐข์€ Erik Meijer์˜ ํ”„๋ ˆ์  ํ…Œ์ด์…˜์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ œ๊ฐ€ ์ง€์ ํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ์€: ์šฐ๋ฆฌ์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ์‚ฌ๊ณ ๋Š” ์ด๋Ÿฌํ•œ ํŒจ๋Ÿฌ๋‹ค์ž„์— ๋ฐ˜๋Œ€๋˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๊นŒ? ๋‹น์‹ ์˜ ๊ฒฝํ—˜์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์ €๋Š” XAML/C#/MVVM์— ๋Œ€ํ•œ ๊ฒฝํ—˜์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— Don Syme์ด XAML์„ ๋ถˆํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.
๋‚ด ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด ๊ด€์‹ฌ์‚ฌ(UI, ํ”„๋ ˆ์  ํ…Œ์ด์…˜, ๋น„์ฆˆ๋‹ˆ์Šค ๋“ฑ ๋…ผ๋ฆฌ)๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ DSL(C# ๋งˆํฌ์—…)๊ณผ MVU๊ฐ€ ์žฅ๊ธฐ์ ์œผ๋กœ ์ฝ”๋“œ ํ’ˆ์งˆ์„ ๊ฐœ์„ ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฒฝํ—˜์ด ์—†๊ฑฐ๋‚˜ ๊ด€์‹ฌ์ด ์—†๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์ฑ…์ž„์„ ํ˜ผํ•ฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. MVU ํŒจํ„ด์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ดํ•ดํ•˜๋ ค๋ฉด ๋” ๋งŽ์€ ๊ฒฝํ—˜์ด ํ•„์š”ํ•˜์ง€๋งŒ ์ด ๋‘ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ๋ชจ๋‘ ์‹œ๋„ํ–ˆ๊ณ  ์ „์ฒด ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋งค์šฐ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์ตœ๋Œ€ํ•œ ๋งŽ์ด ๊ณต์œ ํ•ด์ฃผ์„ธ์š”. @aspnetde ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

(๋ชจ๋‘) ์ดํ•ดํ•ด ์ฃผ์…”์„œ ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@davidortinau ์•„๋งˆ๋„ ์—ฌ๊ธฐ์— ์˜คํ•ด๊ฐ€ ๋งก๊น๋‹ˆ๋‹ค . ๋‚˜๋Š” ๋‹จ์ง€ ์šฐ๋ฆฌ๊ฐ€ ๋ฌผ๊ฑด์˜ ์ด๋ฆ„์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ง€์–ด์•ผ ํ•œ๋‹ค๊ณ  ๋งํ•˜๋ ค๊ณ  ํ–ˆ์„ ๋ฟ์ž…๋‹ˆ๋‹ค. ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ ๋ถ„์•ผ์˜ ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์€ ์ด๋ฆ„์„ ์ง“๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์–ด๋ ค์šด ์ผ ์ค‘ ํ•˜๋‚˜๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ, ์ด๋ฏธ ์ด๋ฆ„์ด ์ž˜ ์ •์˜๋œ ๊ฒƒ์ด ์žˆ๋‹ค๋ฉด ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒƒ์— ๋Œ€ํ•ด ๊ทธ ์ด๋ฆ„์„ ์žฌ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Miss Communication ์ž˜๋ชป๋œ
์ด ๊ฒฝ์šฐ ์ž˜๋ชป๋œ ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ˆ˜์ •๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ์ด ํ”„๋กœ์ ํŠธ์—์„œ
) MVU๊ฐ€ ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ๋‚ด์šฉ์˜ ์ž˜๋ชป๋œ ์ด๋ฆ„์ž„์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.
b) ์—ฌ๊ธฐ์—์„œ ์„ค์ •ํ•˜๋ ค๋Š” ๊ฒƒ์„ ์„ค๋ช…ํ•˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ์šฉ์–ด๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด
๊ทธ๋Ÿฐ ๋‹ค์Œ c) ๋ชจ๋“  ์‚ฌ๋žŒ์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์ƒˆ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ์—ฌ์ „ํžˆ ๋Œ์•„๊ฐ€์„œ ๊ณ ์น  ์ˆ˜ ์žˆ๋Š” ์ง€์ ์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•ฉ์‹œ๋‹ค. ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋Š” ์ตœ์•…์˜ ์ƒํ™ฉ์€ XF/๋งˆ์šฐ์ด ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ MVU๋ฅผ ๋‹ค๋ฅธ ์„ธ๊ณ„์™€ ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ์ดํ•ดํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฆ‰, ๋‚˜๋Š” MVU์˜ ์—ด๋ ฌํ•œ ํŒฌ์ด๋ฉฐ MVVM๋„ ์‚ฌ๋ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Comet์—์„œ์™€ ๊ฐ™์ด ์œ ์ฐฝํ•œ MVVM ์ ‘๊ทผ ๋ฐฉ์‹(์•„์ง ๋” ๋‚˜์€ ์ด๋ฆ„์€ ์—†์Šต๋‹ˆ๋‹ค)๊ณผ ์ง€๊ธˆ๊นŒ์ง€ ์ œ์‹œ๋œ ๊ฒƒ์ด ํ›Œ๋ฅญํ•˜๊ณ  ๋„์›€์ด ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง€์›ํ•˜๊ณ  ์ด๋ฆ„์„ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

ํŽธ์ง‘: ๋ฏธ์Šค ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์ด ๋Œ€ํšŒ์—์„œ ํƒˆ๋ฝํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋ถˆ๋ณ€์„ฑ์˜ ์ด์ ์„ ์ดํ•ดํ•˜์ง€๋งŒ, ํ˜„์‹ค ์„ธ๊ณ„๋Š” ๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ๊ฐ‘์ž๊ธฐ ํ…Œ๋””๋ฒ ์–ด์˜ ๋จธ๋ฆฌ๋ฅผ ์ฐข๋Š” Erik Meijer์˜ ํ”„๋ ˆ์  ํ…Œ์ด์…˜์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

@tomasfabian ์ด๊ฒƒ์€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์„ธ์ƒ์„ ์ผ๋ จ์˜ ์‚ฌ๊ฑด์œผ๋กœ ๋ณด๊ธฐ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ์‹ค์ œ๋กœ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค(์—ฌ๊ธฐ์„œ ์ด๋ฒคํŠธ ์†Œ์‹ฑ ๋…ผ์˜๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค).
ํ…Œ๋””๋ฒ ์–ด์—๊ฒŒ ์ผ์–ด๋‚œ ์ผ์€ ๊ทธ ์ƒํƒœ์— ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ์˜ ์ด๋ฒคํŠธ๋Š” "๋จธ๋ฆฌ๊ฐ€ ์ฐข์–ด์ง„" ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ๋ฐœ์ƒํ•œ ์ผ์„ ์‹คํ–‰ ์ทจ์†Œํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋จธ๋ฆฌ๋ฅผ ํ…Œ๋””๋กœ ๋˜๋Œ๋ฆฌ๋ ค๋ฉด "๋ชธ์— ๋จธ๋ฆฌ๋ฅผ ๊ฟฐ๋งค๊ธฐ"๋ผ๋Š” ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ˜‰

FP ๋ฐ MVU์˜ ์ด์ ์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜๋Š” ๊ฒƒ์€ ์—ฌ๊ธฐ์—์„œ ์ฃผ์ œ์—์„œ ๋ฒ—์–ด๋‚œ IMHO์ž…๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์ž˜๋ชป๋œ ์˜์‚ฌ ์†Œํ†ต๊ณผ ์ •ํ™•ํ•œ ์ด๋ฆ„ ์ง€์ • ๊ฐ€๋Šฅ์„ฑ์— ๊ด€ํ•œ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

@isaacabraham ์•„๋งˆ๋„ ๋‹น์‹ ์ด ์˜ณ์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์‚ฌ๊ณผํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฑด ๋‚ด ์ž˜๋ชป์ด์•ผ. ๋„ค์ด๋ฐ์ด ์ค‘์š”ํ•˜๋‹ค๋Š” ๊ฑด ์•Œ์ง€๋งŒ ํ•œํŽธ์œผ๋กœ๋Š” 'MVU๊ฐ€ ์ƒ๊ฐํ•œ ๊ฒƒ๊ณผ ๋‹ค๋ฅผ ์ˆ˜๋„ ์žˆ๋‹ค'๋Š” ์ œ๋ชฉ์ด ๋ฌธ์ œ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฆ„ ์ง“๋Š” ๊ฒƒ๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๊ด‘๋ฒ”์œ„ํ•œ ์ฃผ์ œ๊ฐ€ ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.
๊ณ ๋งˆ์›Œ์š”, ํ† ๋งˆ์Šค

@tomasfabian MVU, FP ๋˜๋Š” ๊ทธ ๋ฐ–์˜ ๋ชจ๋“  ๊ฒƒ์˜ ์žฅ๋‹จ์ ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ฒŒ ๋˜์–ด ๋งค์šฐ ๊ธฐ์ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋“  ๊ฐ€์ƒ์ด๋“  ๐Ÿ˜Š ์ด๊ฒƒ์ด ์ ์ ˆํ•œ ํฌ๋Ÿผ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

@davidortinau
์–ธ์–ด ๊ธฐ๋Šฅ ๋ฐ ์•„ํ‚คํ…์ฒ˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ œ์•ˆ์„ ๋“œ๋ฆฌ๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

* new ํ‚ค์›Œ๋“œ ๋ฐ ๊ธฐํƒ€ ๊ตฌ๋ฌธ ๋…ธ์ด์ฆˆ.
Dart๋‚˜ Kotlin๊ณผ ๋‹ฌ๋ฆฌ C#์—๋Š” ํ•„์ˆ˜ new ํ‚ค์›Œ๋“œ๊ฐ€ ์˜์›ํžˆ ๋ถ™์–ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ ํƒ ์‚ฌํ•ญ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ํŒŒ์ผ๋ณ„ ์˜ตํŠธ์ธ ์ง€์‹œ๋ฌธ์œผ๋กœ๋„ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด์ž ์ธ๊ธฐ ์—†๋Š” ์ œ์•ˆ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ทธ ๋Œ€์‹ ์— ์ตœ์†Œํ•œ ํ•ต์‹ฌ ์ง‘ํ•ฉ์— ๋Œ€ํ•ด ์ƒ์„ฑ์ž๋ฅผ ๋ž˜ํ•‘ํ•˜๊ณ  ์ดˆ๊ธฐํ™” ์ „์šฉ ์†์„ฑ(์žˆ๋Š” ๊ฒฝ์šฐ)์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ณต์‹(์œ ์ง€ ๊ด€๋ฆฌ๋˜๋Š”) ์ •์  ํด๋ž˜์Šค(๋˜๋Š” MAUI ๋ทฐ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋‹น ์ •์  ํด๋ž˜์Šค)๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MAUI ๋ณด๊ธฐ ๊ฐœ์ฒด. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ทฐ ์ฝ”๋“œ .cs ํŒŒ์ผ์˜ ๋งจ ์œ„์— using static ์ง€์‹œ๋ฌธ์„ ๋„ฃ์€ ๋‹ค์Œ new ๊ตฌ๋ฌธ ๋…ธ์ด์ฆˆ ์—†์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด C# ๋ณด๊ธฐ ๊ธฐ๋Šฅ์˜ ์–ด์ˆ˜์„ ํ•จ๊ณผ ๋…ธ์ด์ฆˆ๊ฐ€ ์•ฝ๊ฐ„ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด๋Ÿฌํ•œ ์ •์  ๋ฉ”์„œ๋“œ ์ƒ์„ฑ์ž ๋ž˜ํผ๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ž๋™ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ(Xamarin.Forms๊ฐ€ CSharpForMarkup๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋„๋ก ๋น„์Šทํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.) MAUI ํ”„๋กœ์ ํŠธ.

๋˜ํ•œ MVU/Comet/CSharpForMarkup ๋ณด๊ธฐ ํ•จ์ˆ˜์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํฐ ํ‘œํ˜„์‹ ํŠธ๋ฆฌ์—์„œ ๊ตฌ๋ฌธ ํ˜ผ๋ž€์ด๋‚˜ ๋…ธ์ด์ฆˆ๋ฅผ ์ค„์ด๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” C# ์–ธ์–ด ์ œ์•ˆ์€ ํฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. C#9๋Š” MVU์˜ M ๋ฐ U ๋ถ€๋ถ„์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์ด์™€ ๊ด€๋ จํ•˜์—ฌ ๋จผ ๊ธธ์„ ๊ฐ”์ง€๋งŒ V ๋ถ€๋ถ„์€ ์—ฌ์ „ํžˆ โ€‹โ€‹๊ตฌ๋ฌธ์ƒ ๊ณจ์นซ๊ฑฐ๋ฆฌ์ž…๋‹ˆ๋‹ค.

* ํ™•์žฅ ์†์„ฑ *
"extension-everything" ์ œ์•ˆ์ด ํ˜„์žฌ ๋ณด๋ฅ˜ ์ค‘์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ MVVM-with-C#-markup(์˜ˆ: Xamarin.Forms๊ฐ€ ์žˆ๋Š” CSharpForMarkup)์— ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ํ•œ ๊ฐ€์ง€๋Š” ํ™•์žฅ ์†์„ฑ์ž…๋‹ˆ๋‹ค. CSharpForMarkup์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ๋„์šฐ๋ฏธ๋Š” ํ™•์žฅ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•ด์•ผ ํ–ˆ์ง€๋งŒ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ํ™•์žฅ ์†์„ฑ(๊ฐœ์ฒด ์ด๋‹ˆ์…œ๋ผ์ด์ €์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ)์ด ํ›จ์”ฌ ๋” ์ข‹์•„ ๋ณด์ž…๋‹ˆ๋‹ค.

// Instead of this:
public View Body() =>
    new Widget() {
        BuiltInProperty = "initial value",
    }.SetExtensionProperty("initial value");

// the extension property could be included in the object initializer:
public View Body() ->
    new Widget() {
        BuiltInProperty = "initial value",
        ExtensionProperty = "initial value",
    };

์ด๋Š” ๋งˆํฌ์—…์šฉ C#์ด ์žˆ๋Š” MVVM์—์„œ์™€ ๊ฐ™์ด ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๋ทฐ ๊ฐœ์ฒด ํŠธ๋ฆฌ์—๋งŒ ์‹ค์ œ๋กœ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. MVU ๋˜๋Š” ๊ธฐํƒ€ ๊ธฐ๋Šฅ์  UI ์•„ํ‚คํ…์ฒ˜์˜ ๊ฒฝ์šฐ ๋ทฐ ๊ฐœ์ฒด๊ฐ€ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ์ ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ์œ ์ฐฝํ•œ ํ™•์žฅ ๋ฐฉ๋ฒ•์ด ๋” ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

* ์ƒํƒœ ๊ด€๋ฆฌ์— ๋Œ€ํ•ด ๋œ ๋…๋‹จ์ (๋˜๋Š” ์›ํ•˜๋Š” ๊ฒฝ์šฐ ๋‚ฎ์€ ์ˆ˜์ค€)์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. *
Xamarin.Forms ์œ„์— MVU๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์žˆ์–ด ๊ฐ€์žฅ ํฐ ์žฅ๋ฒฝ ์ค‘ ํ•˜๋‚˜๋Š” ๋‘ ๊ฐ€์ง€ ํ•„์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ”Œ๋žซํผ๋ณ„ ํ‘œํ˜„ ๋“ฑ...). ๊ทธ๋ฆฌ๊ณ  ๋‘ ๋ฒˆ์งธ ์กฐ๊ฐ์€ ๋ถ€๋ถ„ diff ๋“ฑ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ diff๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํฌํ•จํ•˜์—ฌ ๋ทฐ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ๊ฐ’๊ณผ ๋‹ค๋ฅธ ๋ฐ˜ํ™˜ ๊ฐ’ ๊ฐ„์˜ ์ฐจ์ด์ ์„ ์ฐพ์•„ ํ—ค๋น„๊ธ‰ ํ”Œ๋žซํผ๋ณ„ ๋ทฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๋Š” diffing ์—”์ง„์ž…๋‹ˆ๋‹ค...

MAUI๊ฐ€ ์ด์ œ ์ด ๋‘ ๊ฐ€์ง€ ํ•„์ˆ˜ ์š”์†Œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ ๊ฐ™๊ตฐ์š”. ํ›Œ๋ฅญํ•ฉ๋‹ˆ๋‹ค! ๊ทธ๋Ÿฌ๋‚˜ MVU ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์ผ๋ถ€๊ฐ€ MVU ๋˜๋Š” ์œ ์‚ฌํ•œ "๊ธฐ๋Šฅ์ " UI ์•„ํ‚คํ…์ฒ˜๋ณด๋‹ค MVVM์— ๋” ๊ฐ€๊น๋‹ค๊ณ  ๋งํ•˜๋Š” ๋…๋‹จ์ ์ธ ์ƒํƒœ ๊ด€๋ฆฌ ๋ฐฉ์‹๊ณผ ์ ์–ด๋„ ํ‘œ๋ฉด์ ์œผ๋กœ๋Š” ๋งค์šฐ ๋ฐ€์ ‘ํ•˜๊ฒŒ ๊ด€๋ จ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์€ ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋‘ ๊ฐ€์ง€ ํ•„์ˆ˜ ์š”์†Œ(๊ฐ€๋ฒผ์šด ๋ณด๊ธฐ ๊ฐœ์ฒด ๊ทธ๋ž˜ํ”„ ๋ฐ ํšจ์œจ์ ์ธ diffing ์—”์ง„)๋ฅผ ์œ ์ง€ํ•˜๊ณ  MVU ๋˜๋Š” Comet์ด ์œ„์— ํšจ์œจ์ ์œผ๋กœ ๊ณ„์ธตํ™”๋  ์ˆ˜ ์žˆ๋Š” ๋” ๋‚ฎ์€ ์ˆ˜์ค€์˜ ๊ตฌ์„ฑ ์š”์†Œ ์‹œ์Šคํ…œ๊ณผ ๊ฒฐํ•ฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์„ ํƒ. ์–ด์ฉŒ๋ฉด ๊ทธ๊ฒƒ์ด ์ด๋ฏธ ๋ชฉํ‘œ์ด๊ณ  ๋‚ด๊ฐ€ ๋ณด์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ์ผ๊นŒ์š”? ๊ทธ๋ ‡๋‹ค๋ฉด ์ตœ์†Œํ•œ ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋ณธ ์˜ˆ๋ฅผ ํ†ตํ•ด ์ด์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ๋…ผ์˜๋ฅผ ๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

@aspnetde ์™œ ๊ฒŒ์‹œ๋ฌผ์„ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๊นŒ?

@tomasfabian

๋‚ด ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด [MVVM]์€ ๊ด€์‹ฌ์‚ฌ(UI, ํ”„๋ ˆ์  ํ…Œ์ด์…˜, ๋น„์ฆˆ๋‹ˆ์Šค ๋“ฑ)๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๋„ค, ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ์ €๋Š” MvvmCross๋กœ ๋นŒ๋“œ๋œ ๋Œ€๊ทœ๋ชจ Xamarin.iOS ๋ฐ Xamarin.Android ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์ข‹์€ ๊ฒฝํ—˜์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚  ๋‚˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋ณด๋‹ค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ›จ์”ฌ ๋” ์„ ํ˜ธํ•˜์ง€๋งŒ, ๊ทธ ๋ชจ๋“  ํ”„๋กœ์ ํŠธ(์ผ๋ถ€๋Š” 6์ž๋ฆฌ LOC๊ฐ€ ํฌํ•จ๋จ)๊ฐ€ ๊ธฐ์ˆ ์ ์œผ๋กœ๋‚˜ ๋น„์ฆˆ๋‹ˆ์Šค ๊ด€์ ์—์„œ ์„ฑ๊ณตํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

MVVM์€ ํŠนํžˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ™•์žฅํ•  ๋•Œ ์ข‹์€ ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ๋ชจ๋†€๋ฆฌ์Šค๋ฅผ ์ถœํ•˜ํ•ด์•ผ ํ•˜๋Š” ๋ชจ๋ฐ”์ผ์—์„œ๋Š” ์•ฑ์ด ์ผ์ • ํฌ๊ธฐ๋ฅผ ๋„˜์œผ๋ฉด ๋…๋ฆฝ์ ์ธ ๋ชจ๋“ˆ๋กœ ๋ฆฌํŒฉํ† ๋งํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ํŒจ๋Ÿฌ๋‹ค์ž„([MVU])์— ๋Œ€ํ•œ ์šฐ๋ฆฌ์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ์‚ฌ๊ณ ๊ฐ€ ์•„๋‹๊นŒ์š”? ๋‹น์‹ ์˜ ๊ฒฝํ—˜์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๋‚˜๋Š” ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜์ง€ ์•Š๋Š”๋‹ค. ์Šคํ† ๋ฆฌ์ง€์šฉ Redux์— ๋Œ€ํ•œ ๊ฒฝํ—˜์„ ํ™œ์šฉํ•˜๊ณ  ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ด์ ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ณด์‹ญ์‹œ์˜ค. ์–ธ๋œป๋ณด๊ธฐ์—๋Š” ๋” ๋ณต์žกํ•ด ๋ณด์ด์ง€๋งŒ ๋‚ด ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด ์ดํ•ดํ•˜๊ณ  ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. @forki๊ฐ€ ์ข…์ข… ์ง€์ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์ด ํ•ญ์ƒ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๊ฑฐ์˜ ์ง€๋ฃจํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ DSL(C# ๋งˆํฌ์—…)๊ณผ MVU๊ฐ€ ์žฅ๊ธฐ์ ์œผ๋กœ ์ฝ”๋“œ ํ’ˆ์งˆ์„ ๊ฐœ์„ ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

MVU์™€ MVVM์€ ์„œ๋กœ ๋‹ค๋ฅธ ์žฅ์ ์ด ์žˆ์ง€๋งŒ ๋‘˜ ๋‹ค ์„œ๋กœ ๋‹ค๋ฅธ ๋‹จ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

MVVM ํ”„๋กœ์ ํŠธ๊ฐ€ ์„ฑ๊ณต์ ์ด์—ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์šฐ๋ฆฌ ํŒ€๊ณผ ๋‚˜๋Š” ๋””๋ฒ„๊น…์— ๋Œ€ํ•ด ๋จธ๋ฆฌ๋ฅผ ์žƒ์—ˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ํ•œ ํ”„๋กœ์ ํŠธ์—์„œ ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ์ง€์ ํ•œ ๋ฐ”์™€ ๊ฐ™์ด ์ƒˆ๋กœ์šด ํŒ€์›์˜ ๊ฒฝํ—˜ ๋ถ€์กฑ๊ณผ ์˜คํ•ด๋กœ ์ธํ•ด ๋ณต์žก์„ฑ์„ ๊ฒช๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ์—„๊ฒฉํ•˜๊ฒŒ ์ ์šฉ๋  ๋•Œ MVU์—์„œ๋Š” ๊ทธ๋Ÿด ๊ฐ€๋Šฅ์„ฑ์ด ์ ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด MVU๊ฐ€ ์ž‘๋™ ๋ฐฉ์‹์˜ ๊ฒฝ๊ณ„๋ฅผ ๋„ˆ๋ฌด ์ข๊ฒŒ ์ •์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ๊ฒฝ๊ณ„๋ฅผ ๊นจ๊ณ  ๋‹ค๋ฅธ ๋ฐฉ์‹๋ณด๋‹ค ์ž˜๋ชป๋œ ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์ด ๊ฑฐ์˜ ๋” ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

MVU์˜ ๊ฒฝ์šฐ ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ: ์Šค์ผ€์ผ๋ง. ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๋‹จ์ผ ํ”„๋กœ๊ทธ๋žจ์„ ์ง€์ง€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ์—ฌ๊ธฐ์— ํšŒ์˜์ ์ž…๋‹ˆ๋‹ค(์—ฌ๋Ÿฌ ํ”„๋กœ๊ทธ๋žจ/๋ชจ๋“ˆ์ด ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค). ๋‘ ๋ฒˆ์งธ: ๋ฐ”๋กœ ์ง€๊ธˆ Fabulous์™€ ๊ฐ™์€ ๊ฒƒ์ด Xamarin.Forms ์œ„์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ iOS/Android ์œ„์— ์žˆ๋Š” ์ถ”์ƒํ™” ๊ณ„์ธต ์œ„์— ์žˆ๋Š” ์ถ”์ƒํ™” ๊ณ„์ธต ์œ„์— ์žˆ๋Š” ์ถ”์ƒํ™” ๊ณ„์ธต์ž…๋‹ˆ๋‹ค. ์—„์ฒญ๋‚œ ๋ณต์žก์„ฑ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ฌด๋„ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๋Š” ๋ฒ„๊ทธ๋ฅผ ํ•ด๊ฒฐํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์ถ”์ƒํ™” ๊ณ„์ธต(Xamarin.Forms)์ด ๋ณ€๊ฒฝ๋  ๋•Œ ํ•˜๋‚˜์˜ ์ถ”์ƒํ™” ๊ณ„์ธต(Fabulous)์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ๋„ ๋‹ค์†Œ ์ง€๋ฃจํ•˜๊ณ  ๋ถˆ์พŒํ•œ ์ž‘์—…์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์ด ๋‚ด๊ฐ€ MAUI์— ๋Œ€ํ•œ ํฐ ๊ธฐํšŒ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. ์ €๋Š” ์†”์งํžˆ Fabulous ๋ฉ”์ธํ…Œ์ด๋„ˆ๋“ค์ด ์—ฌ๊ธฐ์—์„œ Microsoft์™€ ํž˜์„ ํ•ฉ์น˜๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” ์กฐ์ง์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„๋“ค์ด ๊ณผ๊ฑฐ์— ๊ทธ๋žฌ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ Microsoft๊ฐ€ ๊ทธ๊ฒƒ์„ ๋ง์น˜์ง€ ์•Š๊ธฐ๋ฅผ ์ •๋ง๋กœ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋„๋งˆ

์š”์ „์— ๊ณต์‹ ๋ฐœํ‘œ๋ฅผ ์ฝ์—ˆ์„ ๋•Œ MVU๋กœ ํ‘œ์‹œ๋œ ๋‚ด์šฉ์— ๋†€๋ž์Šต๋‹ˆ๋‹ค.

readonly State<int> count = 0;

[Body]
View body() => new StackLayout
{
    new Label("Welcome to .NET MAUI!"),
    new Button(
        () => $"You clicked {count} times.",
        () => count.Value ++)
    )
};

๋‚ด๊ฐ€ ์•„๋Š” ํ•œ ์ด๊ฒƒ์€ MVU๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค . ๋‚˜๋Š” ์ด๋ฏธ ์—ฌ๊ธฐ ์— ์™œ ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ƒ๊ฐ ์„ ์ ์—ˆ์Šต๋‹ˆ๋‹ค .

๋‚ด๊ฐ€ ์•Œ๊ธฐ๋กœ๋Š” Xamarin.Forms ์œ„์— MVU๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ๋‚˜์ค‘์— Fabulous ๊ฐ€ ๋œ ๊ฒƒ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ 2018๋…„ ๋ช‡ ๋‹ฌ์„ ๋ณด๋‚ธ Don Syme ๋Š” ์ข€ ๋” ์™ธ๊ต์  ์ด์ง€๋งŒ ๊ฒฐ๋ก ์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ, ๋‚ด ์š”์ ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

  • C#์ด๋“  F#์ด๋“  ์ƒ๊ด€์—†์ด ์‹ค์ œ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์„ ๊ตฌํ˜„ํ–ˆ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค. Fabulous ๋’ค์— ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋‹ค๊ฐ€๊ฐ€๋Š” ๊ฒƒ์ด ์—ฌ๊ธฐ์—์„œ ์‹œ์ž‘๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๊ฒƒ์— ๊ด€์‹ฌ์ด ์—†์ง€๋งŒ ํ˜„์žฌ Comet ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๋ช…ํ™•ํ•œ ๋น„์ „์ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น "์•ฑ ๋ชจ๋ธ"์— ๋” ์ ์ ˆํ•œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค. ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐœ๋ช…ํ•˜์‹ญ์‹œ์˜ค. ์ด๋ฆ„์„ MSMVU๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ฌด์—‡์ด๋“ . ๊ทธ๋Ÿฌ๋‚˜ ์˜ค๋ Œ์ง€๋ฅผ ์œ„ํ•ด ์‚ฌ๊ณผ๋ฅผ ํŒ”์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๊ฑด๋ฐฐ!

์™œ ์ด๋ฆ„์„ MSMVU๋กœ ์ง€์ •ํ• ๊นŒ์š”? ํ˜œ์„ฑ์€ MVU์˜€์œผ๋ฉฐ ์•ž์œผ๋กœ๋„ ๊ทธ๋Ÿด ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งˆ์šฐ์ด๋Š” MVU์ž…๋‹ˆ๋‹ค.

.NET MAUI๊ฐ€ MVU์ธ์ง€ ์•„๋‹Œ์ง€ ๋งํ•˜๊ธฐ์—๋Š” ๋„ˆ๋ฌด ์ด๋ฅด๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

MAUI๊ฐ€ ๊ฒฐ๊ตญ MVU๊ฐ€ ๋ ์ง€ ์—ฌ๋ถ€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ด๋ฏธ ๋งŽ์€ ํ˜ผ๋ž€์„ ์•ผ๊ธฐํ•œ ๋ฐœํ‘œ ๋ธ”๋กœ๊ทธ์˜ ์ƒ˜ํ”Œ์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚˜๋Š” ์ €์ž๊ฐ€ ์•„์ง MVU๋ฅผ ์‹ค์ œ๋กœ ์กฐ์‚ฌํ•˜์ง€ ์•Š์•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. "C# MVU"์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•œ๋‹ค๊ณ  ํ•ด์„œ ์ด๊ฒƒ์ด ๋” ๋‚˜์•„์ง€๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ์–ด๋–ค ํ˜ผ๋ž€๋„ ์ผ์œผํ‚ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ผ๋ถ€ ์‚ฌ๋žŒ๋“ค์€ C#์ด MVU๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— SwiftUI(Comet์ด ๋Œ€๋ถ€๋ถ„์˜ ์˜๊ฐ์„ ์–ป์Œ)๋Š” ๋ช…์‹œ์ ์ธ ์ง€์นจ์ด ์—†์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ํŒจํ„ด์„ MVVM์ด๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ MVU์— ๋Œ€ํ•œ ์–ธ๊ธ‰์„ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

@TimLariviere https://github.com/Clancey/Comet#key -concepts
๊ธฐ๋ณธ์ ์œผ๋กœ Comet์€ ๊ทธ๊ฒƒ์„ MVU๋ผ๊ณ  ๋ถˆ๋ €๊ณ  ์ด๋ฏธ MVU์˜ ์ด์ „ ์ •์˜์— ์žˆ๋Š” ๋ฉ”์‹œ์ง€ ๋ฃจํ”„์˜ ์š”์ ์„ ๋†“์น˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— SwiftUI(Comet์ด ๋Œ€๋ถ€๋ถ„์˜ ์˜๊ฐ์„ ์–ป์Œ)๋Š” ๋ช…์‹œ์ ์ธ ์ง€์นจ์ด ์—†์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ํŒจํ„ด์„ MVVM์ด๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฒŒ์‹œ๋ฌผ์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์— ์žˆ๋Š” ์˜ˆ์ œ๋ฅผ ๋ณด๋ฉด ํ‹€๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. https://nalexn.github.io/clean-architecture-swiftui/

ํ•˜์ง€๋งŒ MVU์— ๋Œ€ํ•œ ์–ธ๊ธ‰์„ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ ๊ฒŒ์‹œ๋ฌผ์—์„œ๋„ ์ด์— ๋Œ€ํ•ด ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค(SwiftUI + Redux = TEA์˜ ์กฐํ•ฉ์œผ๋กœ). ์ดํ›„ "Clean Architecture"๋กœ ์ด์ƒํ•˜๊ฒŒ ์ „ํ™˜๋˜๊ณ  ์žˆ์ง€๋งŒ ๐Ÿ˜„

์—ฌ๊ธฐ์—์„œ ์–ธ๊ธ‰๋˜์—ˆ์œผ๋ฏ€๋กœ ๋ช‡ ๊ฐ€์ง€๋งŒ ๋ง์”€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

  • MAUI๋Š” ํ›Œ๋ฅญํ•˜๊ณ  ์•„ํ‚คํ…์ฒ˜๋กœ์„œ์˜ MVU์— ๋Œ€ํ•ด ๋ฐฐ์šฐ๋Š” ๊ฒƒ์€ ์‚ฌ๋žŒ๋“ค์ด MAUI๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

  • ๋‹จ์–ด์— ์–ฝ๋งค์ด๊ธฐ ์‰ฝ๊ณ , ์ด ๋‹จ๊ณ„์—์„œ ์šฐ๋ฆฌ ๋ชจ๋‘ ์ˆจ์„ ์‰ฌ๊ณ  ๊ฑฑ์ •ํ•˜์ง€ ์•Š์œผ๋ ค๊ณ  ๋…ธ๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ๋˜๋Š” ๋‹จ์–ด๋ฅผ ์กฐ์ •ํ•  ์‹œ๊ฐ„์ด ์ถฉ๋ถ„ํ•˜๊ณ  ์ •ํ™•ํ•œ ์šฉ์–ด์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „๋‹ฌ๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋“ค์—ˆ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ Elm์€ "MVU"์˜ ๊พธ๋ฐˆ์ด ์—†๊ณ  ํ•œ์ •๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ด ๋ช…์‹œ์  ๋ฉ”์‹œ์ง€, ๋ช…์‹œ์  ์—…๋ฐ์ดํŠธ, ๊ธฐ๋Šฅ์  ๋ชจ๋ธ, ๊ธฐ๋Šฅ์  ๋ทฐ ์žฌ๊ณ„์‚ฐ ๋ฐ ์ฐจ๋“ฑ ์—…๋ฐ์ดํŠธ๋ฅผ ์˜๋ฏธํ•œ๋‹ค๋Š” ๊ฒƒ์„ ํ™•๋ฆฝํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ MVU ์—๋Š” ๋งŽ์€

  • ๋‚˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ด ๋ถ„์•ผ์— ๋Œ€ํ•ด ๋งค์šฐ ๊ฐ•ํ•œ ์‹ ๋…๊ณผ ์˜๊ฒฌ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๊ณ  ๋งค์šฐ ๊ฐœ์ธ์ ์œผ๋กœ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์–ด๋–ค ๊ฒƒ์ธ์ง€ ์•Œ๊ณ  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ๋””์ž์ธ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ณต๊ฐ„์˜ ๋ชจ๋“  ์ง€์ ์—๋Š” ์žฅ๋‹จ์ ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ์ตœ๊ณ ์˜ ๊ธฐ์ˆ ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋ชจ๋“  ์‚ฌ๋žŒ์ด ํ•จ๊ป˜ ์‹œ๋„ํ•˜๊ณ , ์‚ฌ์šฉํ•˜๊ณ , ๋ฐฐ์šฐ๊ณ , ๊ณต์œ ํ•˜๊ณ , ํ˜‘๋ ฅํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

@dsyme
Comet/MAUI ์•„ํ‚คํ…์ฒ˜์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ์šฉ์–ด๋Š” ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„(๋˜๋Š” UDF)์˜ ๋ณ€ํ˜•์ด์ง€๋งŒ MVU ์ž์ฒด๊ฐ€ UDF์˜ ๋งค์šฐ ํŠน์ •ํ•œ ๋ณ€ํ˜•์ด๊ธฐ ๋•Œ๋ฌธ์— MVU๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. MAUI/Comet์€ ํ™•์‹คํžˆ UDF ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์ ํ•ฉํ•˜์ง€๋งŒ(SwiftUI์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ) MVU ํ”„๋ ˆ์ž„์›Œํฌ๋กœ๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. UDF์—๋Š” MVU, Flux, Redux, React ๋“ฑ ์—ฌ๋Ÿฌ ๋ณ€ํ˜•์ด ์žˆ์ง€๋งŒ MVU๊ฐ€ ์ „ํ˜€ ์•„๋‹ ๋•Œ Comet MVU๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์€ ์ž˜๋ชป๋œ ์˜์‚ฌ์†Œํ†ต์ž…๋‹ˆ๋‹ค.

MVU์™€ ๋‹ฌ๋ฆฌ Model์€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๋ฉฐ View ํ•จ์ˆ˜์˜ ์ฝ”๋“œ์— ์˜ํ•ด ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋Œ์—ฐ๋ณ€์ด๊ฐ€ ๊ด€์ฐฐ๋˜๊ณ  ๋ทฐ๋Š” ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๋Œ์—ฐ๋ณ€์ด์— ๋ฐ˜์‘ํ•ฉ๋‹ˆ๋‹ค. ๋ทฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ ๋‹จ๋ฐฉํ–ฅ์ด์ง€๋งŒ ์—…๋ฐ์ดํŠธ ๊ธฐ๋Šฅ, ๋ฉ”์‹œ์ง€ ๋ฐ ๋ฉ”์‹œ์ง€ ๋””์ŠคํŒจ์นญ์ด ์—†์œผ๋ฏ€๋กœ MVU๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. MVVM์˜ ๋‹จ๋ฐฉํ–ฅ ๋ณ€ํ˜•์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค.

@JeroMiya ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์šฉ์–ด์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

@dsyme ์ด์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ์–ธ๊ธ‰์€ ์—†์ง€๋งŒ React ์ดˆ๊ธฐ, ํŠนํžˆ React ์ž์ฒด์™€ Redux ๋ฐ Flux์™€ ๊ฐ™์ด ๋“ฑ์žฅํ•œ ์ดˆ๊ธฐ ํŒจํ„ด ๋ช‡ ๊ฐ€์ง€์™€ ๊ด€๋ จํ•˜์—ฌ ์ฒ˜์Œ ์‚ฌ์šฉ๋œ ์šฉ์–ด๋ฅผ ๋“ฃ๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งŽ์€ UDF ๋ณ€ํ˜•(๋Œ€๋ถ€๋ถ„ React ๊ณต๊ฐ„์— ์žˆ์Œ)์„ ์„ค๋ช…ํ•˜๋Š” ๊ธฐ์‚ฌ๋ฅผ ๊ธฐ์–ตํ•˜์ง€๋งŒ ์ง€๊ธˆ์€ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ฆ‰, ํ˜•์‹ ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋ณด๊ธฐ๊ฐ€ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ์ƒํƒœ ์ €์žฅ ๊ฐœ์ฒด ํŠธ๋ฆฌ์ธ ๊ฒƒ๊ณผ๋Š” ๋Œ€์กฐ์ ์œผ๋กœ ๋ชจ๋ธ์˜ ๊ธฐ๋Šฅ์ธ ๋ณด๊ธฐ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…์— ๋” ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. UDF ๊ฐœ๋…์€ ๋ชจ๋ธ์ด ์–ด๋–ป๊ฒŒ ์—…๋ฐ์ดํŠธ๋˜๋Š”์ง€ ๋˜๋Š” ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜๋“œ์‹œ ์ง€์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. MVU๋Š” UDF ๊ฐœ๋…์„ ๋ทฐ ์ž์ฒด๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋ธ ์—…๋ฐ์ดํŠธ ํ”„๋กœ์„ธ์Šค๊นŒ์ง€ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ MVU์—์„œ๋Š” ๋ชจ๋ธ๋„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์œผ๋ฉฐ UI ์ƒํƒœ ๋ณ€๊ฒฝ์€ ์ƒˆ ๋ณด๊ธฐ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ์ƒˆ ๋ชจ๋ธ์„ ์ƒ์„ฑํ•˜๋Š” ๋ช…๋ น์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ƒˆ๋กœ์šด ๊ฐœ๋…์€ ์•„๋‹™๋‹ˆ๋‹ค. React ์ด์ „์—๋„ Asp.Net MVC, Rails, ์‹ฌ์ง€์–ด PHP์™€ ๊ฐ™์€ ๋Œ€๋ถ€๋ถ„์˜ ์„œ๋ฒ„ ์ธก ์›น ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๊ธฐ์ˆ ์ ์œผ๋กœ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. React๊ฐ€ ๋“ฑ์žฅํ•˜๊ธฐ ์ „์—๋Š” ์ฃผ๋ฅ˜ SPA ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํด๋ผ์ด์–ธํŠธ ์ธก UI ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ผ๋ฐ˜์ ์ด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

@dsyme ์ด์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ์–ธ๊ธ‰์€ ์—†์ง€๋งŒ React ์ดˆ๊ธฐ, ํŠนํžˆ React ์ž์ฒด์™€ Redux ๋ฐ Flux์™€ ๊ฐ™์ด ๋“ฑ์žฅํ•œ ์ดˆ๊ธฐ ํŒจํ„ด ๋ช‡ ๊ฐ€์ง€์™€ ๊ด€๋ จํ•˜์—ฌ ์ฒ˜์Œ ์‚ฌ์šฉ๋œ ์šฉ์–ด๋ฅผ ๋“ฃ๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งŽ์€ UDF ๋ณ€ํ˜•(๋Œ€๋ถ€๋ถ„ React ๊ณต๊ฐ„์— ์žˆ์Œ)์„ ์„ค๋ช…ํ•˜๋Š” ๊ธฐ์‚ฌ๋ฅผ ๊ธฐ์–ตํ•˜์ง€๋งŒ ์ง€๊ธˆ์€ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ฆ‰, ํ˜•์‹ ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋ณด๊ธฐ๊ฐ€ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ์ƒํƒœ ์ €์žฅ ๊ฐœ์ฒด ํŠธ๋ฆฌ์ธ ๊ฒƒ๊ณผ๋Š” ๋Œ€์กฐ์ ์œผ๋กœ ๋ชจ๋ธ์˜ ๊ธฐ๋Šฅ์ธ ๋ณด๊ธฐ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…์— ๋” ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. UDF ๊ฐœ๋…์€ ๋ชจ๋ธ์ด ์–ด๋–ป๊ฒŒ ์—…๋ฐ์ดํŠธ๋˜๋Š”์ง€ ๋˜๋Š” ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜๋“œ์‹œ ์ง€์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. MVU๋Š” UDF ๊ฐœ๋…์„ ๋ทฐ ์ž์ฒด๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋ธ ์—…๋ฐ์ดํŠธ ํ”„๋กœ์„ธ์Šค๊นŒ์ง€ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ MVU์—์„œ๋Š” ๋ชจ๋ธ๋„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์œผ๋ฉฐ UI ์ƒํƒœ ๋ณ€๊ฒฝ์€ ์ƒˆ ๋ณด๊ธฐ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ์ƒˆ ๋ชจ๋ธ์„ ์ƒ์„ฑํ•˜๋Š” ๋ช…๋ น์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ƒˆ๋กœ์šด ๊ฐœ๋…์€ ์•„๋‹™๋‹ˆ๋‹ค. React ์ด์ „์—๋„ Asp.Net MVC, Rails, ์‹ฌ์ง€์–ด PHP์™€ ๊ฐ™์€ ๋Œ€๋ถ€๋ถ„์˜ ์„œ๋ฒ„ ์ธก ์›น ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๊ธฐ์ˆ ์ ์œผ๋กœ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. React๊ฐ€ ๋“ฑ์žฅํ•˜๊ธฐ ์ „์—๋Š” ์ฃผ๋ฅ˜ SPA ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํด๋ผ์ด์–ธํŠธ ์ธก UI ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ผ๋ฐ˜์ ์ด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

@JeroMiya ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ œ๊ฐ€ MVU๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
MVU๋ฅผ ์ตœ์ƒ์˜ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์˜ˆ์‹œํ•˜๋Š” ๊ฐ€์žฅ ์˜ค๋ž˜๋˜๊ณ  ์—ฌ์ „ํžˆ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์ค‘ ํ•˜๋‚˜๊ฐ€ MS Excel์ด๋ผ๊ณ  ๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

@dsyme ๊ท€ํ•˜์˜ ์˜๊ฒฌ์„ ์ฝ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. MAUI๋ฅผ ๋…ผ์˜๋œ ์•„ํ‚คํ…์ฒ˜(MVVM์ด ์žˆ๋Š” CSharpForMarkup)์˜ ์šฉ์–ด๋กœ ์–ธ๊ธ‰ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๋Š๋‚Œ์ด ๋“ญ๋‹ˆ๋‹ค.
์ด๊ฒƒ์ด MAUI๊ฐ€ ์ดํ•ดํ•˜๋Š” ๋ฐ”๊ฐ€ ์•„๋‹˜์„ ๋ช…ํ™•ํžˆ ํ•ด์ฃผ์„ธ์š”.
๋‚ด๊ฐ€ ์ดํ•ดํ•œ ๋ฐ”์— ๋”ฐ๋ฅด๋ฉด MAUI๋Š” ๋ฏธ๋ž˜์˜ ์–ด๋Š ์‹œ์ ์—์„œ XF๋ฅผ ๋Œ€์ฒดํ•  ๋‹ค์Œ MS ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ํ”„๋ ˆ์ž„์›Œํฌ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์™€ ๋Œ“๊ธ€์ด ์ง„ํ–‰๋˜๋Š” ๋ฐฉ์‹์ด ์ •๋ง ๋งˆ์Œ์— ๋“ญ๋‹ˆ๋‹ค. ์ฐธ์—ฌํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ์šฐ๋ฆฌ๋Š” MAUI์— ๋Œ€ํ•œ ๊ฐ€๋Šฅํ•œ ํ’๋ฏธ๋กœ ๋ชจ๋“  ๋‹ค๋ฅธ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์„ค์ •ํ•˜๊ณ  ๋ช…๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@dersia ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! CSharpForMarkup์— ๋Œ€ํ•œ ์ œ ๊ฒฝํ—˜์— ๋Œ€ํ•œ ์ฐธ๊ณ  ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. MVVM๋ณด๋‹ค ์•ฝ๊ฐ„ ๋‚ฎ์€ ์ˆ˜์ค€์ž…๋‹ˆ๋‹ค. C# ๋งˆํฌ์—…์„ ๋ณด๋‹ค ๊ฐ„์†Œํ™”๋˜๊ณ  ๋ณด๊ธฐ ์ข‹๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ํ™•์žฅ ๋ฉ”์„œ๋“œ ๋ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ ์ง‘ํ•ฉ์ด ๋” ๋งŽ์Šต๋‹ˆ๋‹ค. ViewModel ๋ฐ”์ธ๋”ฉ์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“œ๋Š” ๋„์šฐ๋ฏธ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— MVVM ํŒจํ„ด์„ ํ™•์‹คํžˆ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฒฐ๊ตญ ViewModel ๋Œ€์‹  Redux์—์„œ ๋ชจ๋“  ๋ทฐ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋๋‚ฉ๋‹ˆ๋‹ค. ๋ณด๊ธฐ ์†์„ฑ์„ ์ƒํƒœ ์„ ํƒ๊ธฐ์— ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ™•์žฅ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. Func<StateType, ChildStateType> Redux ์ƒํƒœ ์ €์žฅ์†Œ์˜ Select ๋ฐ DistinctUntilChanged ์—ฐ์‚ฐ์ž์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. Observable<StateType> . ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์€ ์•„๋‹ˆ์ง€๋งŒ ์ง€๊ธˆ Fabulous์™€ ๊ฐ™์€ UI ๊ฐœ์ฒด ํŠธ๋ฆฌ ๋น„๊ต ๋ฐ โ€‹โ€‹๋ณด๊ธฐ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์„ฑ์ˆ™ํ•œ ๋ฐฉ๋ฒ•์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

์–ผ๋งˆ ์ „ REST ๊ฒฝ์ฐฐ์€ ์šฐ๋ฆฌ ๋ชจ๋‘๊ฐ€ REST๋ผ๊ณ  ๋ถ€๋ฅด์ง€ ๋ง์•„์•ผ ํ•  ๊ฒƒ์„ ๋ชฉ๊ตฌ๋ฉ์œผ๋กœ ๋ฐ€์–ด ๋„ฃ์œผ๋ ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚ ์—๋„ ๋ชจ๋‘๊ฐ€ ๊ทธ๊ฒƒ์„ REST๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ ์šฐ๋ฆฌ ๋ชจ๋‘๋Š” ์—ฌ์ „ํžˆ ์‚ด์•„ ์žˆ๊ณ  ๊ฑด๊ฐ•ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ˜‰

@bitbonk REST ์ปค๋ฎค๋‹ˆํ‹ฐ๋Š” ์ ์  ๋” ๋งŽ์€ ๊ฒƒ๋“ค์ด ํ˜ผํ•ฉ๋˜๋ฉด์„œ ์ ์  ๋” ์“ธ๋ชจ ์—†๊ฒŒ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ์šฉ์–ด๋ฅผ ํฌ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์€ ์ด์ œ "ํ•˜์ดํผ๋ฏธ๋””์–ด(hypermedia)"๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ REpresentational State Transfer๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚  REST๋Š” "SOAP ์•„๋‹˜" ๋˜๋Š” "JSON over HTTP"๋งŒ์„ ์˜๋ฏธํ•˜๋ฉฐ ๋‘˜ ๋‹ค ํ•ต์‹ฌ ์•„์ด๋””์–ด๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์„ฑ๊ณตํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ ๋Œ“๊ธ€ ์ž‘์„ฑ์ž๋Š” MVU๊ฐ€ ๊ฐ™์€ ์šด๋ช…์„ ๋งž์ดํ•˜์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

@davidortinau @tomasfabian , ์•„์ง MAUI์—์„œ MVU์˜ ์˜ˆ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์˜ค๋Š˜ ๋ฐค์— ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ ์—์„œ WinForms์— ๋Œ€ํ•ด ๋น„์Šทํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰

@JeroMiya ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์šฉ์–ด์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

@dsyme , ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด React Flux์—์„œ ์‹œ์ž‘๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๊ทธ๋“ค์€ ๊ฒŒ์ž„ ์•„ํ‚คํ…์ฒ˜, ์ฆ‰ Doom 3๋ฅผ ๊ฐ€๋ฆฌ์ผฐ ์Šต๋‹ˆ๋‹ค. ์ œ ์ƒ๊ฐ์—๋Š” ์ด๊ฒƒ์ด ์ฒ˜์Œ ๋ฐœํ‘œ๋˜์—ˆ์„ ๋•Œ

๋‹ค์Œ์€ C# ์˜ˆ์ œ์— ๋Œ€ํ•œ ์ €์˜ ์‹œ๋„์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ์˜ˆ์ œ๋กœ ์ด๊ฒƒ์„ ์‹œ๋„ํ•  MAUI๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ€ ์—†์ž–์•„์š”? ์–ด์จŒ๋“  ์ด๊ฒƒ์€ ์•„์ด๋””์–ด์˜ ๋Œ€๋žต์ ์ธ ๋ฒˆ์—ญ์ž…๋‹ˆ๋‹ค.

using Model = int;

interface IMsg {}
sealed class Increment : IMsg {}

Func<Model> init() => 0;

Func<IMsg, Model, Model> update = (IMsg msg, Model model) =>
{
    return msg switch
    {
        Increment _ => model + 1,
        _ => throw new NotImplementedException()
    };
};

Func<Model, Action<IMsg>, View> view =
    (Model model, Action<IMsg> dispatch) => new StackLayout
    {
        new Label("Welcome to .NET MAUI!"),
        new Button(
            () => $"You clicked {model} times.",
            () => dispatch(new Increment())
        )
    };

// Program should be defined as part of MAUI and is used to start the flow.
// This should listen for messages, run the `update`, re-compute the `View`, then re-render.
var program = new Program<Model, IMsg>(init, update, view);

๋ณด๊ธฐ ๋ถ€๋ถ„์„ ์ œ์™ธํ•˜๊ณ  ๋น„์Šทํ•œ ๊ฒƒ์„ ํ•œ ๋ฒˆ ๊ฐ„๋‹จํžˆ

์ €๋Š” MVU๋ฅผ ์ฒ˜์Œ ์ ‘ํ–ˆ๊ณ  ์—ฌ๋Ÿฌ๋ถ„ ์ค‘ ๋งŽ์€ ๋ถ„๋“ค์— ๋น„ํ•ด ์‚ฌ์šฉ ๊ฒฝํ—˜์ด ๊ฑฐ์˜ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ MVU ๊ฐœ๋…์€ ํ™•์‹คํžˆ ๋‚ด ๊ด€์‹ฌ์„ ๋Œ์—ˆ๊ณ  ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ฆ๊ธฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. C# ๊ฐœ๋ฐœ์ž๋“ค์ด MVU ํŒจํ„ด ๊ฐœ๋ฐœ์— ๋„์›€์ด ๋˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋ฐ›๊ฒŒ ๋˜์–ด ๋งค์šฐ ๊ธฐ์ฉ๋‹ˆ๋‹ค.

MAUI MVU๊ฐ€ ์ผ๋ฐ˜์ ์ธ MVU๊ฐ€ ์•„๋‹ˆ๋ฉฐ SwiftUI์˜ ์˜ํ–ฅ์ด ํฌ๋‹ค๋Š” ๋ฐ ์ „์ ์œผ๋กœ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฑ…์˜ ์ฃผ์š” ์ €์ž์ธ Clancey Himeslef๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ์„ธ์…˜์—์„œ ์ด ์ ์„ ๋งค์šฐ ๋ถ„๋ช…ํ•˜๊ฒŒ ๋ฐํ˜”์Šต๋‹ˆ๋‹ค. Redux๊ฐ€ MVU์˜ ์˜ํ–ฅ์„ ๋งŽ์ด ๋ฐ›์œผ๋ฉฐ SwiftUI, Flutter ๋ฐ ๊ธฐํƒ€ ๋งŽ์€ ํ”„๋ ˆ์ž„์›Œํฌ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ๊ทธ๋“ค ์ค‘ ๋ˆ„๊ตฌ๋„ ์ˆœ์ˆ˜ํ•œ MVU๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ ๋ชจ๋‘๋Š” ์ด๋Ÿฌํ•œ ๋ชจ๋“  ํ”„๋ ˆ์ž„์›Œํฌ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์ด MVU๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๊ฒƒ์„ ์ฐธ์กฐํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ๋ถ€ํ„ฐ 1๋…„ ๋ฐ˜ ํ›„์— ์ถœ์‹œ๋  ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋ธ”๋กœ๊ทธ ์ œ๋ชฉ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹ญ์‹œ์˜ค.

๊ทธ๋ฆฌ๊ณ  ์‚ฌ๋žŒ๋“ค์ด ์ด ๋ธ”๋กœ๊ทธ ์ œ๋ชฉ์— ๋Œ€ํ•ด ํ™”๋ฅผ ๋‚ด๊ณ  ์žˆ๋‹ค๊ณ  ๋งํ•˜๋ฉด. ๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋“ค์— ๋Œ€ํ•ด ์ •๋ง๋กœ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ปค๋ฎค๋‹ˆํ‹ฐ๋Š” ์—ฌ์ „ํžˆ ๊ณ„์†๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์—๋„ˆ์ง€๋ฅผ ์‚ฌ์šฉํ•ฉ์‹œ๋‹ค. ์ž‘์€ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ๋„ˆ๋ฌด ๊ฑฑ์ •ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ ๋ชจ๋‘๋Š” ์ด๋Ÿฌํ•œ ๋ชจ๋“  ํ”„๋ ˆ์ž„์›Œํฌ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์ด MVU๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๊ฒƒ์„ ์ฐธ์กฐํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.

๊ฐœ, ๋ง, ๊ณ ์–‘์ด ๋ฐ ์นจํŒฌ์ง€๋Š” ๋ชจ๋‘ ์„œ๋กœ ๋งค์šฐ ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. ์ด์ œ๋ถ€ํ„ฐ๋Š” ๋ชจ๋‘ ๊ณ ์–‘์ด๋ผ๊ณ  ๋ถ€๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

:) ๊ธ€์Ž„, ๋‹น์‹ ์€ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ•œ ๊ฐ€์ง€ ๋ง์”€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ณ ์–‘์ด, ํ˜ธ๋ž‘์ด, ํ‘œ๋ฒ” ๋“ฑ์€ ๊ณ ์–‘์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹น์‹ ์ด ๊ทธ๊ฒƒ์„ ๊ฐ€์ ธ ์™€์„œ ๊ธฐ์ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ๊ฐ€ ๋ฐ”๋กœ ๊ทธ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

@aspnetde : Thomas, ๋งํ•œ ๋ชจ๋“  ๊ฒƒ. ๊ท€ํ•˜์˜ ์›๋ž˜ MVU ๋ธ”๋กœ๊ทธ๋Š” ๊ฐœ๋…์„ ๋งค์šฐ ๋ช…ํ™•ํ•˜๊ณ  ์ •ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๋Š” ์ตœ๊ณ ์˜ ๊ธฐ์‚ฌ ์ค‘ ํ•˜๋‚˜๋ผ๊ณ  ๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์œผ๋กœ๋ถ€ํ„ฐ ์ƒ๋‹นํ•œ ๊ฒƒ์„ ๋ฐฐ์› ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

@ libin85 ์ •ํ™•ํžˆ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ์‹ค์ œ๋กœ ํ•œ ๋ฒ”์ฃผ์— ์†ํ•˜๋Š” ๊ฒƒ๋“ค์„ ์—ด๊ฑฐํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒƒ๋“ค์€ ๋ฌด์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. MAUI ์ƒ˜ํ”Œ์„ MVU ๋ฒ”์ฃผ์— ๋„ฃ์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ์นจํŒฌ์ง€๋ฅผ ๊ณ ์–‘์ด ๋ฒ”์ฃผ์— ๋„ฃ์Šต๋‹ˆ๋‹ค.

๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๋ณด๊ธฐ์™€ ๊ฐ™์€ MVU ๊ตฌํ˜„๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฉ”์‹œ์ง€ ๋ฃจํ”„๊ฐ€ ์—†๊ณ  ๋ช…์‹œ์ ์ธ ์—…๋ฐ์ดํŠธ ๊ธฐ๋Šฅ์ด ์—†๋‹ค๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ถ„๋ช…ํ•œ ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋ธ์€ View์—์„œ ์ง์ ‘ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์‚ฌ๋žŒ๋“ค์ด MVU๋ฅผ ์ƒ๊ฐํ•ด๋ƒˆ์„ ๋•Œ ๋ช…์‹œ์ ์œผ๋กœ ์›ํ•˜์ง€ ์•Š์•˜๋˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ผ๋ถ€ ์–ธ์–ด์—์„œ๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด MVU๊ฐ€ ๋“ฑ์žฅํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์ด ๋Œ€์ค‘ํ™” ๋œ ์ด์œ . ์ด์ œ MVU ์ •์˜์—์„œ ํ•ด๋‹น ์†์„ฑ์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒฝ์šฐ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@forki : ๋‚˜๋Š” ๋‹น์‹ ์ด ๋งํ•œ ๊ฒƒ์— ๋ฐ˜๋Œ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์šฐ๋ฆฌ๊ฐ€ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์˜ ์ œ๋ชฉ์ด ์•„๋‹ˆ๋ผ ์ปค๋ฎค๋‹ˆํ‹ฐ๋กœ์„œ ๋…ผ์˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ๋งˆ์ง€๋ง‰ ๋Œ“๊ธ€์—์„œ ์ œ๊ธฐํ•œ ์š”์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒŒ ์ œ ์š”์ ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋…ผ์˜ํ•  ๊ธ์ •์ ์ธ ๊ฒƒ์ด๋ฉฐ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ด๋ฅผ ํ†ตํ•ด ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ ์ด๋ฆ„์ด ๋” ์ค‘์š”ํ•œ ์ธก๋ฉด์—์„œ ์ฃผ์˜๋ฅผ ์‚ฐ๋งŒํ•˜๊ฒŒ ํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š” ์•ฝ๊ฐ„์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚ด๊ฐ€ ๊ทธ๊ฒƒ์„ ๊บผ๋‚ธ ์ด์œ ๋Š” ๊ฐœ์ธ์ ์œผ๋กœ MAUI๋ฅผ ์ƒ์‹์ด ๊ฒฐ๊ตญ ๊ณตํ†ต์ ์œผ๋กœ ํ•ฉ์˜๋œ ํ•ด๊ฒฐ์ฑ…์œผ๋กœ ์ด๋„๋Š” ๊ณต๋™์ฒด์˜ ๋…ธ๋ ฅ์œผ๋กœ ๋ณด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋น„๊ณต๊ฐœ ๊ฒฐ์ •์ด ๋‚ด๋ ค์ง€๋Š” Microsoft ์ œํ’ˆ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‚ด ๋ฌธ์ œ๋ฅผ ์ œ๊ธฐํ•˜๊ธฐ ์œ„ํ•ด ๊ณ ๊ฐ์œผ๋กœ์„œ ์—ฌ๊ธฐ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ ๋ชจ๋‘๋Š” ์ด๋Ÿฌํ•œ ๋ชจ๋“  ํ”„๋ ˆ์ž„์›Œํฌ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์ด MVU๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

@ libin85 ๋‚˜๋Š” ์ด๊ฒƒ์ด ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. MVU๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ MVP ๋˜๋Š” Model View Presenter์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์ผ๋ จ์˜ ์ œ์•ฝ ์กฐ๊ฑด์ž…๋‹ˆ๋‹ค. MVVM์€ ํ”„๋ฆฌ์  ํ„ฐ๊ฐ€ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์ด ์žˆ๋Š” ViewModel์ด๋ผ๋Š” ์ ์—์„œ ๋‹ค๋ฅธ ๋ฐฉํ–ฅ์„ ์ทจํ•˜๋Š” ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. MVP ์ž์ฒด๋Š” MVC์˜ ์ œํ•œ๋œ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์ด ๋ชจ๋‘ MVC, ์‹ฌ์ง€์–ด MVP์˜ ํ›„์†์ด๋ผ๊ณ  ํ•ด๋„ ๊ณผ์–ธ์ด ์•„๋‹Œ ๊ฒƒ ๊ฐ™์ง€๋งŒ, MVU๊ฐ€ SwiftUI, Flux ๋“ฑ์— ์ ์šฉ๋œ๋‹ค๋Š” ๊ฒƒ์€ MVU๋ฅผ ๋ฌด์˜๋ฏธํ•œ ์šฉ์–ด๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ ์ด๋ฆ„์ด ๋” ์ค‘์š”ํ•œ ์ธก๋ฉด์—์„œ ์ฃผ์˜๋ฅผ ์‚ฐ๋งŒํ•˜๊ฒŒ ํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š” ์•ฝ๊ฐ„์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

์•„๋‹ˆ์š”, ์ด๋ฆ„์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ์˜๋ฏธ๋ฅผ ํ™•๋ฆฝํ•˜๊ณ  ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ๋…ผ์˜ํ•œ REST๋„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. REST๋Š” ๋„ˆ๋ฌด ๋‚จ์šฉ๋˜์–ด ๋งˆ์ผ€ํŒ… ์ „๋ฌธ ์šฉ์–ด ์™ธ์—๋Š” ๋” ์ด์ƒ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํŠนํžˆ MAUI์˜ "MVU"๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋‚ด์šฉ์— ๋Œ€ํ•œ ๊ธฐ์กด ์šฉ์–ด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ MVU์— ๊ทธ๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— MAUI "MVU"๋Š” MVVM ์˜ต์…˜์— ๋Œ€ํ•œ ์ข‹์€ ๋Œ€์•ˆ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. REST์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์œ ์šฉํ•˜๊ณ  ์ข‹์€ ๊ฒƒ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ •์˜์ ์ธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ž˜ ์ •์˜๋˜๊ณ  ํ™•๋ฆฝ๋œ ํŒจํ„ด์—์„œ ๋ถ„๋ช…ํžˆ ๋ฒ—์–ด๋‚˜๋Š” ๋Œ€์•ˆ์œผ๋กœ ์ด๋ฆ„์„ ํ˜ผ๋™ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ๊ฒฐ๊ตญ MVU๋Š” _๋˜ํ•œ_ MVVM ๋ฐ Comet ์˜ต์…˜์— ๋Œ€ํ•œ ์ข‹์€ ๋Œ€์•ˆ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— MAUI "MVU"๋Š” MVVM ์˜ต์…˜์— ๋Œ€ํ•œ ์ข‹์€ ๋Œ€์•ˆ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. REST์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์œ ์šฉํ•˜๊ณ  ์ข‹์€ ๊ฒƒ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ •์˜์ ์ธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ •์˜์—์„œ ๋ถ„๋ช…ํžˆ ๋ฒ—์–ด๋‚˜๋Š” ๋Œ€์•ˆ์œผ๋กœ ์ด๋ฆ„์„ ํ˜ผ๋™ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

์ „์ฒด ํ™•์ธ.

์™œ ์ด๋ฆ„์„ MSMVU๋กœ ์ง€์ •ํ• ๊นŒ์š”? ํ˜œ์„ฑ์€ MVU์˜€์œผ๋ฉฐ ์•ž์œผ๋กœ๋„ ๊ทธ๋Ÿด ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งˆ์šฐ์ด๋Š” MVU์ž…๋‹ˆ๋‹ค.

@saint4eva ๊ทธ๋“ค์€ "ํŒ๋งค"๋˜์ง€๋งŒ ์ •์˜์ƒ MVU๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ ์ด๋ฆ„์ด ๋” ์ค‘์š”ํ•œ ์ธก๋ฉด์—์„œ ์ฃผ์˜๋ฅผ ์‚ฐ๋งŒํ•˜๊ฒŒ ํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š” ์•ฝ๊ฐ„์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

์•„๋‹ˆ์š”, ์ด๋ฆ„์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ์˜๋ฏธ๋ฅผ ํ™•๋ฆฝํ•˜๊ณ  ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ๋…ผ์˜ํ•œ REST๋„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. REST๋Š” ๋„ˆ๋ฌด ๋‚จ์šฉ๋˜์–ด ๋งˆ์ผ€ํŒ… ์ „๋ฌธ ์šฉ์–ด ์™ธ์—๋Š” ๋” ์ด์ƒ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํŠนํžˆ MAUI์˜ "MVU"๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋‚ด์šฉ์— ๋Œ€ํ•œ ๊ธฐ์กด ์šฉ์–ด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ MVU์— ๊ทธ๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— MAUI "MVU"๋Š” MVVM ์˜ต์…˜์— ๋Œ€ํ•œ ์ข‹์€ ๋Œ€์•ˆ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. REST์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์œ ์šฉํ•˜๊ณ  ์ข‹์€ ๊ฒƒ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ •์˜์ ์ธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ž˜ ์ •์˜๋˜๊ณ  ํ™•๋ฆฝ๋œ ํŒจํ„ด์—์„œ ๋ถ„๋ช…ํžˆ ๋ฒ—์–ด๋‚˜๋Š” ๋Œ€์•ˆ์œผ๋กœ ์ด๋ฆ„์„ ํ˜ผ๋™ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ๊ฒฐ๊ตญ MVU๋Š” _๋˜ํ•œ_ MVVM ๋ฐ Comet ์˜ต์…˜์— ๋Œ€ํ•œ ์ข‹์€ ๋Œ€์•ˆ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‹น์‹ ์ด ๋งํ•œ ๋Œ€๋ถ€๋ถ„์— ๋™์˜ํ•˜์ง€๋งŒ "๋งˆ์šฐ์ด MVU"๋Š” ์—ฌ์ „ํžˆ ๋‚˜์˜๊ณ  ํ˜ผ๋ž€ ์Šค๋Ÿฝ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ "๋งˆ์šฐ์ด MVP" ๋˜๋Š” MVC๋กœ ๊ฐˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ์ž‘๋™ํ•˜๋ฉฐ MVU๋ณด๋‹ค ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์— ํ‘œ์‹œ๋œ ๋‚ด์šฉ์— ๋” ๊ฐ€๊น์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ํŽธ์ง‘:
์ œ์•ˆ๋œ ๋ฒ„์ „์ด ์–ด๋””์— ์žˆ๋Š”์ง€์กฐ์ฐจ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‚ด ๋ง์€ MVVM์˜ ๋…ผ๋ฆฌ๋Š” ViewModel์— ์žˆ๊ณ  MVU๋Š” ์—…๋ฐ์ดํŠธ ๊ธฐ๋Šฅ ๋‚ด์— ์žˆ๊ณ  MVP๋Š” Presenter์— ์žˆ๊ณ  MVC๋Š” Controller์— ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ฒƒ์ด ์‚ฌ๋Š” ๋ทฐ๊ฐ€ ์žˆ์„๊นŒ์š”? ์•„๋‹ˆ๋ฉด ๋ณด๊ธฐ, ๋…ผ๋ฆฌ ๋ฐ ๋ชจ๋ธ์„ ์ œ๊ณตํ•˜๋Š” ๋„๋ฉ”์ธ ๋ชจ๋ธ์— ์˜ํ•ด ๋ช…๋ช…๋œ ์ผ๋ถ€ ํด๋ž˜์Šค์— ๋ชจ๋‘ ์กด์žฌํ•ฉ๋‹ˆ๊นŒ? ๋ชจ๋ธ์€ ๋ณ„๋„์˜ ํด๋ž˜์Šค(์œ ํ˜•) ๋˜๋Š” ๋ ˆ์ฝ”๋“œ์—ฌ์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๋‚˜๋Š” ์ด๊ฒƒ์ด ๋‚˜๋ฅผ ์œ„ํ•œ ์ฃผ์š” ๊ณ ์ถฉ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด "์ œ์‹œ"๋˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋‹จ์„œ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—…๋ฐ์ดํŠธ, ๋ชจ๋ธ ๋ฐ ๋ณด๊ธฐ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ MAUI๋Š” ์ง€๊ธˆ๊นŒ์ง€ ๋…ผ์˜๋œ ํŒจํ„ด๋ณด๋‹ค ์•ฝ๊ฐ„ ๋‚ฎ์€ ์ˆ˜์ค€์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ๋‹ค๋ฅธ ํŒจํ„ด์˜ ๋ชจ๋ธ(๋˜๋Š” ์ƒํƒœ) ๋ฐ ๋ณด๊ธฐ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ(์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ๋‹ค์†Œ ๋…๋‹จ์ ์ด๊ธด ํ•˜์ง€๋งŒ).

์˜ˆ๋ฅผ ๋“ค์–ด State<T> ์˜ T ๊ฐ€ ViewModel๊ณผ ์œ ์‚ฌํ•œ ํด๋ž˜์Šค์ด๊ณ  ๋ณ„๋„์˜ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ํด๋ž˜์Šค ์„ธํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด MVVM๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋‹จ๋ฐฉํ–ฅ๋ณด๊ธฐ.

๋ฐ˜๋ฉด์— Redux์™€ ์œ ์‚ฌํ•œ ์ƒํƒœ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์„ ์ถ”๊ฐ€ํ•˜๊ณ  Redux ์ƒํƒœ ๋ชจ๋ธ์„ T in State<T> ํ•˜๋ฉด ๊ฒฐ๊ตญ MVU์— ๋งค์šฐ ๊ฐ€๊นŒ์šด ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. , Elm/Fabulous์™€ ๊ฐ™์€ ๊ธฐ์กด MVU๋งŒํผ ์™„์ „ํžˆ ํ†ตํ•ฉ๋˜์ง€๋Š” ์•Š์•˜์ง€๋งŒ. Fabulous๊ฐ€ Xamarin.Forms์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ MVU ํ”„๋ ˆ์ž„์›Œํฌ ๋’ค์— MAUI ๋ณด๊ธฐ๋ฅผ ์ˆจ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

MAUI๋ฅผ ํ†ตํ•ด MVC ๋˜๋Š” MVP ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋Œ€๋žต์ ์ธ ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋กœ ๋ณด๊ธฐ ๊ธฐ๋Šฅ์— "์ž‘์—…"์„ ๋…ธ์ถœํ•˜๋Š” ๋ณ„๋„์˜ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๋ฉด ์•„๋งˆ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด MAUI ํ™•์ธ ๋Œ€ํ™” ์ƒ์ž๊ฐ€ ์žˆ๊ณ  "์ปจํŠธ๋กค๋Ÿฌ" ํด๋ž˜์Šค์— "ClickOK" ๋ฉ”์„œ๋“œ์™€ "ClickCancel" ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. MAUI ๋ณด๊ธฐ๋Š” ๋ณด๊ธฐ์—์„œ ์ƒˆ ๋ชจ๋ธ์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ๋ชจ๋ธ์„ ๋ณ€๊ฒฝํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋กœ ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

@JeroMiya ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ํ™•์‹คํžˆ Redux ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด MVU์— ๋” ๊ฐ€๊นŒ์›Œ์ง€๊ณ  ์•„ํ‚คํ…์ฒ˜๋ฅผ ํ›จ์”ฌ ๋œ ๋น„ํŒ์ ์œผ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” React-Redux, React-Hooks, ReactiveX ๋ฐ ์ตœ๊ทผ Blazor Apps :heart: Fluxor :heart: ์˜ ํ–‰๋ณตํ•œ ์‚ฌ์šฉ์ž์ž…๋‹ˆ๋‹ค. @mrpmorris ๊ฐ€ ์ด ๋Œ€ํ™”์— ๊ธฐ์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ C# ์˜ˆ์ œ์— ๋Œ€ํ•œ ์ €์˜ ์‹œ๋„์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ์˜ˆ์ œ๋กœ ์ด๊ฒƒ์„ ์‹œ๋„ํ•  MAUI๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ€ ์—†์ž–์•„์š”? ์–ด์จŒ๋“  ์ด๊ฒƒ์€ ์•„์ด๋””์–ด์˜ ๋Œ€๋žต์ ์ธ ๋ฒˆ์—ญ์ž…๋‹ˆ๋‹ค.

using Model = int;

interface IMsg {}
sealed class Increment : IMsg {}

Func<Model> init() => 0;

Func<IMsg, Model, Model> update = (IMsg msg, Model model) =>
{
    return msg switch
    {
        Increment _ => model + 1,
        _ => throw new NotImplementedException()
    };
};

Func<Model, Action<IMsg>, View> view =
    (Model model, Action<IMsg> dispatch) => new StackLayout
    {
        new Label("Welcome to .NET MAUI!"),
        new Button(
            () => $"You clicked {model} times.",
            () => dispatch(new Increment())
        )
    };

// Program should be defined as part of MAUI and is used to start the flow.
// This should listen for messages, run the `update`, re-compute the `View`, then re-render.
var program = new Program<Model, IMsg>(init, update, view);

Microsoft ์ƒ˜ํ”Œ์—์„œ๋ณด๋‹ค ์—…๋ฐ์ดํŠธ์— ๋” ๋งŽ์€ ์„ฑ๋Šฅ ๋น„์šฉ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ? ์ด ๋ชจ๋ธ์—์„œ๋Š” MS ์ƒ˜ํ”Œ์—์„œ์™€ ๋‹ฌ๋ฆฌ ๋ชจ๋“  UI ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ์ƒˆ ๋ณด๊ธฐ๊ฐ€ ์ธ์Šคํ„ด์Šคํ™”๋˜๋ฉฐ ๊ธฐ์กด ๋ณด๊ธฐ ์š”์†Œ๋Š” ์ œ์ž๋ฆฌ์— ๋‘๊ณ  ๋ ˆ์ด๋ธ” ๊ฐ’๋งŒ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค(์žฌ -์‚ฌ์ด์ง• ๋น„์šฉ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Œ).

์ด ์ฐจ์ด์ ์€ ์ด๋ฆ„ ์ง€์ •์— ๋Œ€ํ•œ ์ด ํ† ๋ก ์„ ์ด๋„๋Š” ํ•ต์‹ฌ ์ฐจ์ด์  ์ค‘ ํ•˜๋‚˜์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ „ํ†ต์ ์œผ๋กœ ์ •์˜๋œ MVU ์•„ํ‚คํ…์ฒ˜์— UI๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค๋ฅธ ๊ธฐ์ˆ ์ด ์žˆ๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ๊ธฐ์ˆ ์ด ๋‹ค์Œ ์ˆ˜์ค€์—์„œ ๊ตฌํ˜„๋˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ๋ Œ๋”๋ง ์—”์ง„?

@markmccaigue ์„ฑ๋Šฅ ๊ด€๋ จ: ์ข…์ข… MVU ์‹œ์Šคํ…œ์—๋Š” ๊ฐ€์ƒ ๋ณด๊ธฐ(๋˜๋Š” html์˜ ๊ฒฝ์šฐ ๊ฐ€์ƒ DOM)์™€ ๋‹ค์–‘ํ•œ ์—”์ง„์ด ํ•จ๊ป˜ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ DOM์„ ๊ฐ€์ƒ DOM๊ณผ ๋น„๊ตํ•œ ํ›„ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” DOM์— ํŒจ์น˜๋ฅผ ์ ์šฉํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํŠนํžˆ ๋ถˆ๋ณ€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ์ž‘์—…ํ•˜๋Š” ๊ฒฝ์šฐ ์ผ๋ฐ˜์ ์œผ๋กœ ๋งค์šฐ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š”!!

๋‚˜๋Š” ์ง€๊ธˆ์ด ๋ฌธ์ œ๋ฅผ ๋‹ซ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค .. ๋‚˜๋Š” ์ด๊ฒƒ์„ ํ† ๋ก ํ•˜๊ณ  ์‹ถ์ง€๋งŒ github๋Š” ๊ทธ๊ฒƒ์„ ์ž‘๋™์‹œํ‚ค๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค :-/

์ด ๋Œ€ํ™”๋ฅผ ๊ณ„์†ํ•˜๊ณ  ์‹ถ์€ ์‚ฌ๋žŒ์ด ์žˆ์œผ๋ฉด ํ† ๋ก  ํ•ญ๋ชฉ์„ ๋งŒ๋“  ๋‹ค์Œ ์ด ๋ฌธ์ œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰