AvaloniaUI x ReactiveUI ์‚ฌ์šฉ ํ›„๊ธฐ

Xamarin, MAUI๋Š” ์•„๋‹ˆ์ง€๋งŒ ํฌ๋กœ์Šค ํ”Œ๋žซํผ์ด๋ผ ์—ฌ๊ธฐ์— ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ๋‚ด ํ”„๋กœ๊ทธ๋žจ์ด๋ผ ์ด๋ฏธ์ง€ ๋ฐ ์†Œ์Šค๋ฅผ ๊ณต๊ฐœํ•˜์ง€ ๋ชปํ•˜๋Š” ์  ์–‘ํ•ด ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.


์‚ฌ๋‚ด CCU(Concurrent connected User) ๋ชจ๋‹ˆํ„ฐ๋ง ํ”„๋กœ๊ทธ๋žจ์„ AvaloniaUI 0.10.18 ๋ฒ„์ „๊ณผ Community Toolkit 8 ๋ฒ„์ „์œผ๋กœ ์ž‘์—…์„ ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.

AvaloniaUI(์ดํ•˜ Avalonia)๋ฅผ 0.10.18 ๋ฒ„์ „์„ ์„ ํƒํ–ˆ๋˜ ์ด์œ ๋Š”, ํ˜„์žฌ Avalonia 11.0.0-Preview ๋ฒ„์ „์—์„œ Community Toolkit 8์ด ๋นŒ๋“œ ์—๋Ÿฌ๋ฅผ ๋ƒˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด๋ฒˆ์— Avalonia๋ฅผ 11 preview2 ๋ฒ„์ „์œผ๋กœ ์˜ฌ๋ฆฌ๋ฉด์„œ Reactive UI๋„ ํ•จ๊ป˜ ๊ฐ™์€ ๋ฒ„์ „์œผ๋กœ ์ ์šฉํ•ด๋ดค์Šต๋‹ˆ๋‹ค.

Reactive UI๋ฅผ ๊ณต๋ถ€ํ–ˆ๋˜ ๊ฒฝํ—˜์„ ๋ฉ”๋ชจ ํ–ˆ์—ˆ๋Š”๋ฐ ์›๋ณธ์„ ๊ณต์œ ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

Avalonia UI RxUI ๋ฉ”๋ชจ

  1. RxUI ๋ฌธ์„œ์— Command๋ฅผ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ Code-Behind๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋˜์–ด์žˆ์ง€๋งŒ, XAML์„ ํ†ตํ•ด ๋ฐ”์ธ๋”ฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  2. WhenActivated๋Š” View๋งˆ๋‹ค ํ•ด์ค˜์•ผํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค? (ํ™•์‹คํ•˜์ง€ ์•Š์Œ)
    View์˜ Code-Behind์—์„œ ๋ฐ”์ธ๋”ฉํ•˜์ง€ ์•Š๊ณ , XAML์—์„œ ๋ฐ”์ธ๋”ฉํ•  ๊ฒฝ์šฐ์—” ํ•„์š” ์—†๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

  3. ViewModel์˜ ํ™œ์„ฑํ™” ์‹œ์ ์ด ์–ด๋–ค ๋•Œ์ธ์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์œผ๋‚˜, ViewModel์—์„œ ํ™œ์„ฑํ™”๊ฐ€ ๋  ๋•Œ ์ด๋ฒคํŠธ ์บ์น˜ํ•˜๋ ค๋ฉด IActivatableViewModel ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์ค˜์•ผํ•œ๋‹ค.
    ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ViewModel์— ๊ตฌํ˜„ํ•˜๋ฉด WhenActivated๋ฅผ ViewModel์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ,
    ์ด ์ฝ”๋“œ ๋ธ”๋Ÿญ ์•ˆ์˜ ์ฝ”๋“œ๋Š” View ์ชฝ์—์„œ WhenActivated๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๊ฐ™์ด ํ˜ธ์ถœ๋œ๋‹ค.

  4. RxUI์—์„  ReactiveWindow์™€ Window๋ฅผ, ReactiveUserControl์™€ UserControl ์„ ํ˜ผ์šฉํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋ƒฅ ReactiveWindow, ReactiveUserControl์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํ†ต์ผํ•˜์ž.

  5. 4๋ฒˆ ๋•Œ๋ฌธ์— RxUI์—์„œ๋Š” View์™€ ViewModel์„ ์„œ๋กœ ์˜์กด์‹œํ‚ฌ ์ˆ˜ ๋ฐ–์— ์—†๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

  6. ์˜์กด์„ฑ ๋“ฑ๋ก์„ ํ•  ๋•Œ๋Š” Splat์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ๋ฌธ์„œ๋ณด๊ณ  ์ž˜ ๋”ฐ๋ผํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.
    ์•„๋ž˜ ๋ฌธ์„œ์— ์ ํ˜€์žˆ๋“ฏ, ์„œ๋น„์Šค๋ฅผ ๋“ฑ๋กํ• ๋•Œ๋Š” CurrentMutable์„ ์‚ฌ์šฉํ•˜๊ณ  ๊ฐ์ฒด๋ฅผ ๊บผ๋‚ด์˜ฌ ๋•Œ๋Š” Current๋ฅผ ์ด์šฉํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.
    reactiveui - Splat: Locator.Current vs Locator.CurrentMutable - Stack Overflow
    ๋‚˜์ฒ˜๋Ÿผ Generic Host๋ฅผ ์ด์šฉํ•  ๊ฒฝ์šฐ ์•„๋ž˜ ๋ฌธ์„œ๋Œ€๋กœ ํ•œ๋‹ค.
    splat/src/Splat.Microsoft.Extensions.DependencyInjection/README.md at main ยท reactiveui/splat ยท GitHub

  7. ViewModel์„ Splat์— ๋“ฑ๋กํ•  ๋•Œ๋Š” IViewFor ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•ด์„œ ํ•ด๋‹น ๋ทฐ๋ชจ๋ธ์ด ์–ด๋–ค ๋ทฐ์˜ ๋ทฐ๋ชจ๋ธ์ธ์ง€ ๊ฐ„์ ‘์ ์œผ๋กœ ์ง€์ •ํ•œ๋‹ค.
    IViewFor๋Š” ๋ฐ˜๋“œ์‹œ ํ•  ํ•„์š”๋Š” ์—†๊ณ , ViewModel์— ๋Œ€ํ•ด์„œ View๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ์žˆ์„ ๋•Œ Locator๋กœ ๋งค์นญํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ, Customํ•˜๊ฒŒ View์— ๋Œ€ํ•œ ViewModel์„ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
    ๋”ฐ๋ผ์„œ ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ํ•„์š”์—†๊ณ  Naming ๊ทœ์น™์„ ์ž˜ ๋”ฐ๋ฅธ๋‹ค๋ฉด ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
    ํŠน์ • View๋ฅผ ํ™•์žฅํ•˜์—ฌ ๊ทธ ํ™•์žฅ๋œ view์˜ ViewModel์„ ์ง€์ •ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ์‚ฌ์šฉ๋œ๋‹ค.

  8. Converter๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ๋„ IValueConverter ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‹ˆ๋ผ IBindingTypeConverter๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค. Converter ์˜ˆ์‹œ
    ์‚ฌ์‹ค IValueConverter๋กœ ๊ตฌํ˜„ํ•ด์„œ XAML์˜ ๋ฐ”์ธ๋”ฉ์ด ๊ฐ€๋Šฅํ•ด ๋ณด์ด์ง€๋งŒ,
    RxUI์˜ Code-Behind Binding์„ ํ•˜๋ฉด์„œ Converter๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด IBindingTypeConverter๋ฅผ ์ด์šฉํ•ด์•ผํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.
    ๊ทธ๋ฆฌ๊ณ  Locator.CurrentMutable.RegisterConstant(new MyCoolTypeConverter(), typeof(IBindingTypeConverter)); ์ด๋ ‡๊ฒŒํ•˜๋ฉด Splat์— ๋“ฑ๋กํ•ด์„œ IoC ๋ฐฉ์‹์œผ๋กœ๋„ ์ด์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.
    ํ•˜์ง€๋งŒ ์—ญ์‹œ, ์ผ๋ฐ˜์ ์ธ IValueConverter๋ฅผ ์ด์šฉํ•ด์„œ๋„ ํ”„๋กœ๊ทธ๋žจ์ด ๋™์ž‘ํ•˜๋Š”๋ฐ ์˜ค๋™์ž‘์€ ์—†๋‹ค.

  9. ๋ฐ์ดํ„ฐ ์˜์†์„ฑ์€ ์ผ์ข…์˜ ์บ์‹ฑ๊ธฐ๋Šฅ์ด๋‹ค. App์„ ๊ป๋‹ค๊ฐ€ ์ผœ๋„ ๋ฐ์ดํ„ฐ๊ฐ€ ์œ ์ง€๋˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. (์›๋ฆฌ๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ์Œ)
    DataContractAttribute์™€ DataMemberAttribute๋ฅผ ์ด์šฉํ•ด์„œ ์ €์žฅํ•œ ๊ฐ’์„ ์ง€์ •ํ•œ๋‹ค.

  10. WhenActivated ๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด WhenActivated๋ฉ”์„œ๋“œ์˜ Action ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ disposables์„ ์ด์šฉํ•˜์—ฌ View๊ฐ€ ์ œ๊ฑฐ๋ ๋•Œ View์™€ ์—ฐ๊ฒฐ๋œ ViewModel์˜ ๊ด€์ฐฐ๊ฐ€๋Šฅ Property์™€ ๊ด€์ฐฐ๊ฐ€๋Šฅ Command๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋‹ค.

  11. Interaction ํด๋ž˜์Šค๋Š” input viewmodel๊ณผ output viewmodel์„ ์ œ๋„ค๋ฆญ์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
    ์ด๊ฒƒ์€ ๋Œ€ํ™”์ฐฝ ๊ฐ™์€ UI์™€ ์ƒํ˜ธ์ž‘์šฉ์„ ํ•  ๋•Œ ์“ฐ์ด๋Š” ๊ฒƒ์œผ๋กœ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์—์„  DialogService๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ํ˜ธ์ถœํ•˜๋Š”๋ฐ, rxui์—์„œ๋Š” ViewModel๊ฐ„ ๊ด€๊ณ„๋ฅผ ๋งบ์–ด์ฃผ๊ณ 
    Interaction๊ฐ์ฒด์—์„œ Handle ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ input viewmodel์„ ๋„ฃ์–ด์„œ ํ˜ธ์ถœ ๋ฐฉํ–ฅ์œผ๋กœ ํ•˜๊ณ ์žˆ๋‹ค.
    Handle ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด Code-Behind์—์„œ ๊ตฌ๋…ํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
    ์œ„์˜ ๋ฐฉ๋ฒ•์€ Avalonia.MusicStore ์ƒ˜ํ”Œ ์•ฑ์˜ MainWindowViewModel์˜ BuyMusicCommand์—์„œ ShowDialog.Handle์„ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ,
    ๋‹ค์Œ ์ค„๋กœ ๋„˜์–ด๊ฐ€๊ธฐ ์ „ Handle ๋ฉ”์„œ๋“œ๋กœ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.
    MainWindow.axaml.cs์˜ DoShowDialogAsync ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ๋˜๋Š”๋ฐ ์ด๋Š” MainWindow์˜ ์ƒ์„ฑ์ž์—์„œ ViewModel์˜ Interaction ๊ฐ์ฒด์ธ ShowDialog์˜ ๊ตฌ๋…๋ฉ”์„œ๋“œ๋กœ
    DoShowDialogAsync๋ฅผ ๋“ฑ๋กํ•ด๋†จ๊ธฐ๋•Œ๋ฌธ์ด๋‹ค.
    ํด๋ž˜์Šค๊ฐ„์˜ ๊ด€๊ณ„๊ฐ€ ์ฝ”๋“œ๋กœ ๋ช…์‹œ๋˜์–ด์žˆ์–ด์„œ ์ง๊ด€์ ์ด๋‹ค.

  12. ๋ฐ˜๋ณต๋œ ์ž‘์—…์ด๋‚˜ ๋ฌด๊ฑฐ์šด ์ž‘์—…์˜ ๊ฒฝ์šฐ ์Šค์ผ€์ฅด๋ง์„ ์ด์šฉํ•˜๋ฉด ๋˜๋ฉฐ ์•„๋ž˜ ๊ธ€์— ์ž˜ ๋‚˜ํƒ€๋‚˜ ์žˆ๋‹ค.
    | An advanced, composable, reactive model-view-viewmodel framework
    ์•„๋ž˜ ๊ธ€์„ ๋ณด๋ฉด Invoke๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ RxUI ๋ฐฉ์‹์œผ๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๋‹ค.
    | An advanced, composable, reactive model-view-viewmodel framework

  13. ๋ฐ˜๋ณต๋œ ๊ฐ’์ด ํ™•์ธ๋  ๊ฒฝ์šฐ ์ค‘๋ณต ์ œ๊ฑฐ๋Š” DistinctUntilChanged ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

  14. Subscribe ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ์— ์–ด๋–ค ์ž‘์—…์ด ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๊ตฌ๋…์— ๋“ฑ๋กํ•œ Action ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ToProperty๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด
    ๋ฐ์ดํ„ฐ๋ฅผ ํŠน์ • ํ”„๋กœํผํ‹ฐ๋กœ ์  ์ˆ˜๋„ ์žˆ๋‹ค.

  15. WhenAny ๋ฉ”์„œ๋“œ๋Š” ํŠน์ • ์†์„ฑ๊ฐ™์€ ๊ฒƒ๋“ค์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ๊ทธ๊ฒƒ์ด UI์— ๋…ธํ‹ฐ ๋˜๋Š” ๊ฒƒ๊ณผ ๋ณ„๊ฐœ๋กœ ๋งค๋ฒˆ ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด WhenAny๊ฐ€ ์—†๋Š” ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์€ ์ด๋ฒคํŠธ ์–ด๊ทธ๋ฆฌ๊ฒŒ์ดํ„ฐ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๋ฉ”์„ธ์ง€๋กœ ํŠน์ • ์†์„ฑ์„ ๊ตฌ๋…ํ•˜๊ณ  ๋ฉ”์„ธ์ง€๋ฅผ ๋˜์ง€๋ฉด
    ๊ทธ ๋ฉ”์„ธ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณณ์—์„œ ์ด๊ฒƒ์ €๊ฒƒ ์ž‘์—…์„ ํ•ด์•ผํ•˜๋Š” ๋ถ€๋ถ„์ธ๋ฐ, RxUI์—์„œ๋Š” WhenAny์—์„œ ๋ฉ”์‹ ์ € ๋Œ€์‹ ์— ์ž‘์—…์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
    ๋ฌผ๋ก  RxUI์—๋„ ๋ฉ”์‹ ์ € ๊ธฐ๋Šฅ์ด ์กด์žฌํ•˜๊ธดํ•˜์ง€๋งŒ WhenAny ๊ธฐ๋Šฅ์ด ๋”์šฑ ์„ ํ˜ธ๋˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
    | An advanced, composable, reactive model-view-viewmodel framework
    ๋˜ํ•œ ์•„๋ž˜์˜ ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•˜๋ฉด ๋ฉ”์„ธ์ง•์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.
    | An advanced, composable, reactive model-view-viewmodel framework


  • ํ˜„์žฌ ์‹ค์‹œ๊ฐ„์œผ๋กœ CCU ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ ์˜์†์„ฑ์ด ๋”ฐ๋กœ ํ•„์š”์—†๋‹ค. ํ•„์š”ํ•˜๋‹ค๋ฉด ํ”„๋กœ๊ทธ๋žจ ํ™”๋ฉด์„ ์ค‘์•™์— ๋„์šฐ๋Š” ์˜ต์…˜์ •๋„ ๋‚˜์ค‘์— ์ƒ๊ฐํ•ด๋ณด๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

  • Avalonia MVVM Template์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ์ตœ์‹  ๋ฒ„์ „์ธ Avalonia UI 11 Preview 2 ๋ฒ„์ „์œผ๋กœ ์ง„ํ–‰ํ•  ๋•Œ Nuget์—์„œ Avalonia.Themes.Fluent ์˜ ์ถ”๊ฐ€ ๋‹ค์šด๋กœ๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ๋‹ค์šด๋กœ๋“œ ํ•˜์ง€ ์•Š์œผ๋ฉด ๋นŒ๋“œ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. Template์— ์•ˆ ๋“ค์–ด ์žˆ์–ด์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉฐ ์ถ”ํ›„ ๊ฐœ์„ ๋  ๊ฒƒ ๊ฐ™๋‹ค.

  • ํ˜„์žฌ ReactiveUI์˜ ViewLocator ๋ฐฉ์‹์ด ์•„๋‹Œ AvaloniaUI์˜ ViewLocator๋กœ View๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์žˆ๋Š”๋ฐ ๋‚˜์ค‘์— IRoutingViewModel์„ ์‚ฌ์šฉํ•œ ReactiveUI์˜ Routing ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.
    Advanced Avalonia+ReactiveUI+Routing example ยท Issue #3605 ยท AvaloniaUI/Avalonia ยท GitHub
    ๋ฌผ๋ก  AvaloniaUI์˜ MVVM Template์˜ ๊ธฐ๋ณธ ViewLocator๋กœ๋„ ์ž˜ ๋™์ž‘ํ•œ๋‹ค.

  • ReactiveUI์˜ ๊ณต์‹ ๋ฌธ์„œ์—๋„ ๋‚˜์™€์žˆ๋“ฏ, MessageBus๋Š” ์ตœํ›„์˜ ์ˆ˜๋‹จ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ํ•œ๋‹ค.
    ์‹ค์ œ๋กœ ๋‚ด๊ฐ€ ํ•ด๋ณด๋‹ˆ๊นŒ ๊ฐ€๋น„์ง€๊ฐ€ ์—„์ฒญ๋‚˜๊ฒŒ ๋‚˜์˜ค๋ฉด์„œ ํ”„๋กœ๊ทธ๋žจ์ด ๋А๋ ค์ง€๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๋‹ค.
    ์ปค๋ฎค๋‹ˆํ‹ฐ ํˆดํ‚ท์œผ๋กœ ํ–ˆ์„ ๋•Œ๋Š” ๊ทธ๋Ÿฌ์ง€๋Š” ์•Š์•˜์—ˆ๋Š”๋ฐ, ReactiveUI๊ฐ€ ์ž๋™ํ™”ํ•˜๊ณ , ์ถ”์ƒํ™”๋ฅผ ๋งŽ์ด ํ•ด๋†“์€ ๊ฒƒ ๋•Œ๋ฌธ์— ์ค‘๊ฐ„ ์ž„์‹œ๊ฐ์ฒด๊ฐ€ ๋งŽ์ด ์ƒ์„ฑ๋˜์–ด Messaging์ด ๋ฐฉํ•ด๋ฐ›๋Š” ๋А๋‚Œ์ด๋‹ค.
    ๋”ฐ๋ผ์„œ ๊ฐœ๋ฐœ ๋งค์ปค๋‹ˆ์ฆ˜์„ RxUI ๋ฐฉ์‹์— ๋งž๊ฒŒ ๋ฐ”๊ฟ”์•ผํ•œ๋‹ค.

While this class is provided because it is sometimes necessary, the MessageBus should be used only as a last resort . The MessageBus is effectively a global variable , which means it is subject to memory and event leaks, and furthermore, the detached nature of MessageBus means that itโ€™s a goto whose destination is invisible. It also encourages bad design as many people will directly proxy View events to the ViewModel layer, which makes them not particularly ViewModelly.

  • ๋งํฌ๋ฅผ ๋ณด๋ฉด Program.cs์— ์žˆ๋Š” UseReactiveUI() ๋ฉ”์„œ๋“œ๋ฅผ ์“ฐ๋ฉด RxApp.MainThreadScheduler๋ฅผ AvaloniaScheduler.Instance๋กœ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.
    ์‹ค์ œ๋กœ UseReactiveUI ๋ฉ”์„œ๋“œ๋ฅผ ๋””์ปดํŒŒ์ผํ•ด๋ณด๋ฉด ๊ทธ๋Ÿฐ ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
    ๊ทธ๋Ÿฐ๋ฐ ์ดํ•ด๊ฐ€ ์•ˆ๊ฐ€๋Š” ๊ฒƒ์€ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ์‹œ์ ์— RxApp.MainThreadScheduler๋ฅผ ํ™•์ธํ•˜๋ฉด System.Reactive.Concurrency.DefaultScheduler ๊ฐ€ ๋“ค์–ด์žˆ๋‹คโ€ฆ
    ๋”ฐ๋ผ์„œ RxApp.MainThreadScheduler๋ฅผ ์“ฐ๋Š” ๊ณณ์—๋Š” ์•„์ง์€ AvaloniaScheduler.Instance๋กœ ํ•ด์•ผํ•  ๊ฒƒ ๊ฐ™๋‹ค.

  • Quartz๋„ Splat Generic Host์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, ์ด์œ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ์ „ํ˜€ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜๋‹ค.


๊ทธ๋ฆฌ๊ณ  RxUI๋Š” ์•„๋‹ˆ๊ณ  Avalonia ๋ฌธ์ œ์ธ๋“ฏ ํ•œ๋ฐ, ๋งˆ์ง€๋ง‰์— ๋ฉ”๋ชจํ•œ ๊ฒƒ์ด ์™„์ „ํžˆ ๋“œ๋Ÿฌ๋‚œ ๋ฌธ์ œ๋Š” ์•„๋‹™๋‹ˆ๋‹ค.
์—ฌ์ „ํžˆ ๋น„๋™๊ธฐ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ž์ฃผ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์ €์˜ ๋ชจ๋‹ˆํ„ฐ๋ง ํ”„๋กœ๊ทธ๋žจ์—๋Š” ๋ณด๋Š” ๋ฐฉ๋ฒ•์˜ ๋ฉ”๋‰ด๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ ์žˆ์–ด์„œ ๊ทธ ๋ฒ„ํŠผ๋“ค์„ ๋ง‰ ํด๋ฆญํ•˜๋ฉด ๋ณด๋Š” ๋ฐฉ์‹์ด ๋งˆ๊ตฌ ๋ฐ”๋€Œ๋Š”๋ฐ,
UI์—์„œ ์—…๋ฐ์ดํŠธํ•  ๊ฒƒ์ด ๋งŽ์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ์ข…์ข… ๋‚ฉ๋‹ˆ๋‹ค. (๊ฐ€๋งŒํžˆ ์ผœ๋‘๋ฉด ๋ฌธ์ œ ์•ˆ๋‚จ)
ํ•˜์ง€๋งŒ ์ด ๋ถ€๋ถ„์€ ๊ฐœ์„ ๋  ๊ฒƒ์ด๋ผ๊ณ  ๋ฏฟ๊ณ  ์ง„ํ–‰ํ•ด์•ผํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. (๋ฌผ๋ก  Toolkit์„ 11๋ฒ„์ „์—๋„ ๋นŒ๋“œ ์—๋Ÿฌ ์—†์ด ์ง€์›ํ•ด์ค€๋‹ค๋ฉด RxUI๋ฅผ ์•ˆ์จ๋„ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๋ถ€๋ถ„์€ ์•„๋‹ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.)

7๊ฐœ์˜ ์ข‹์•„์š”