WPF 질문

안녕하세요 WPF에 대해서 공부하고 있습니다. 마땅히 질문할 곳이 없어 검색하던 중 닷넷 이라는 싸이트를 알게 되었으며
다양한 지식을 가지신 분들이 활동하는 곳이여서 도움을 얻고자 이렇게 질문을 드립니다.

  1. MVVM은 Model, View, ViewModel 로 구성이 되어 있는데.

View 에서는 ViewModel에 있는 속성을 바인딩을 하게 되고 View는 ViewModel의 프로젝트를 참조하되 ViewModel은 View 프로젝트를 참조하지 않도록 해야 된다고 이해하고 있습니다.

View와 ViewModel의 개념은 어느정도 이해가 되는데
(View에서는 Binding 작업을 통해서 ViewModel에서 변경될 값을 연결하고
ViewModel에서 변경되는 점을 확인하는 것)

ex) WPF winform에서 button을 생성하고 동작 로직을 구현하려 할때 view 화면에서 click 이벤트를 통해 버튼이 동작하도록 했는데 MVVM에서는 ViewModel에 버튼 동작 이벤트(ICommad)를 구현하고 View와 Binding을 통해 동작하도록 구현을 하는건가요?

  1. Model의 역할에 대해서는 이해가 잘되지 않습니다.

  2. MVVM에서 구현해야하는 인터페이스에는 Inotifypropertychange가 꼭 필요하다고 이해하고 있습니다.
    이유는 DataBinding이 되면 View에서 수정한 데이터가 자동으로 Model의 데이터로 변경도 되고, Model 데이터를 변경 시 자동으로 View에서의 데이터가 변경되어야 하기 때문에 PropertyChange 이벤트를 선언해야 한다고 이해하고 있습니다.

Inotifyproerty change의 역할? 기능이 잘 이해가 되지 않습니다.
(변화가 있다면 UI에 알려주는 역할 이렇게만 이해하고 있습니다.)

MVVM에서 Inotifyproperty는 Model에 구현되어야 하나요?

4.이론적으로 얕게 이해가 갈듯 하지만 MVVM 실습파일, 예제 소스 코드들을 보면 잘 이해가 되지 않습니다.
private int num=1;

    public int Num
    {
        set
        {
            num = value;
            Num2 = value * 2;
            OnPropertyChanged("Num");

        }
        get
        {
            return num;
        }
    }

위의 코드처럼 public 변수인 Num을 통해서 외부에서 private 변수인 num으로 접근은 (이해한 내용)
왜 Public과 Private으로 구분을 짓는지 이해가 되지 않습니다.

4개의 좋아요

MVVM이 아니라 OOP로 먼저 접근하시면 될 거 같습니다.

Model이라는 게 그냥 OOP에 나오는 객체에요.

자기 자신을 구성하는 데이터를 프로퍼티로 갖고 있고,

자기 자신의 동작을 메서드로 갖고 있는 의인화 된 전자세계의 인간입니다.

자기가 할 일은 자기가 처리해야하는 능동적인 객체입니다. (책임 주도 설계)

그런 객체가 UI에 표현해주기 위해서는 자기 자신이 변경되었다는 Notify를 UI에 제공해줘야 합니다.

UI에 내가 변경되었다는 알람이 필요없다면 안해줘도 되는 것이죠.

그 제공하는 방법이 INotifyPropertyChanged 인터페이스이고, WPF 앱이 시작하게되면

제가 알기로는 WPF의 XAML이 로딩되는 과정인 Visual Tree가 로딩되고, 리소스가 로딩되고 하는 여러 초기화 과정에서

XAML의 Binding이 걸려있는 객체들에 관해서 Binding 클래스를 이용한 바인딩을 시도하고, 이 객체들이 INotifyPropertyChanged가 구현되어 있다면 UI로 업데이트 하겠다는 신호인 것으로 이해하고 있습니다.

내가 바인딩 할 재료만 소스로 구현만 해두면 WPF가 알아서 XAML을 로딩하는 과정에서 끌어다가 자동으로 바인딩 해주는 것이죠

즉, UI로 업데이트가 필요한 객체에 대해서만, INotifyPropertyChanged를 구현해주시면 될 거 같다고 생각합니다.

궁금하신 내용에 대해서 chatgpt 를 이용하시면 더욱 도움이 되실 거 같습니다.

8개의 좋아요

→ 네, 보통은 ICommand의 속성을 바인딩 처리 하여 버튼 클릭, 활성/비활성 에 대한 처리를 컨트롤 합니다.
하지만 OnClick 이벤트 핸들러를 통해서 구현해도 됩니다. 다만 이렇게 되면 View의 비하인드 코드에
코드 기술을 해야 하는데 이때 순수하게 View 관련 참조만 되어야 합니다.

코드 상으로 ViewModel에 직접 접근하여 처리해도 되지만 best practice는 아닙니다.

이런 경우 바인딩을 통해 접근하는 것이 좋고 가장 좋은 best practice는
View와 ViewModel 사이에 강력한 커플링을 없애고 외부로 부터 ViewModel이 주입되는 것이 가장 좋긴 합니다.

(단 View가 Model을 참조 한다면 그것은 MVVM 위배 설계 입니다.)

→ 모델은 데이터 정보를 저장(VO), 데이터 전달 용도(DTO), DB 테이블과 매핑 용도(DAO) 등
관련 클래스라고 보시면 됩니다. 즉 데이터 관련의 비즈니스 로직이 포함된 객체 입니다.

→ INotifyPropertyChanged 는 바인딩 처리 되어 있는 View에게 데이터 변경 통보 역할을 하게 되는 인터페이스 입니다.
값 변경시 PropertyChanged 이벤트를 발생시키면
WPF 내부적으로 View에 바인딩되어 있는 바인딩 path 표현식 기반으로 내부 리플렉션 등을 통해 새로운 데이터를 가져와 값을 갱신 시켜 줍니다.

→ 네 필요하다면 Model에도 INotifyPropertyChanged 구현이 적용 될 수 있습니다.

→ private 맴버 필드를 보통 Backing 필드라고 불리우는데 통상 값 변경시 OnPropertyChanged 처리를 하기 위해서 속성을 추가로 구현 하는 것 입니다.

private 맴버 필드 선언 없이 바로 public의 get/set 속성 만으로도 바인딩은 가능합니다.

하지만 값이 변경 되었는지 여부는 View에서 알 수 없고, 경우에 따라 이런 바인딩 처리는 메모리 누수의 원인이 되기도 합니다.

이런 부분은 다음 글을 참고하세요
(WPF) 잘못된 바인딩 사용에 의한 메모리 누수 - Arooong Blog (arong.info)

이러한 코드가 길어지고 귀찮다면 community toolkit 같은 라이브러리를 사용해서 코드를 간략화 하는 방법도 있습니다.

10개의 좋아요
  1. 아마 글로 읽고 경험하지 않아서 오는 괴리감? 같은거라고 생각합니다.
    Binding이 된 Property에 Inotifypropertychange의 구현 유무에 따라,
    Binding 값이 변했을 때 UI가 어떻게 다른지 확인 해보시면 될 것 같아요.
    Inotifypropertychange가 구현 된 경우 Binding된 값이 변하면 UI에 실시간으로 적용 될 겁니다.
    그렇지 않은 경우 UI 변동이 없습니다.
5개의 좋아요
  1. MVVM에서 버튼을 구성하는 방법
    알고 계신게 맞습니다. View에서 버튼을 만들고 ViewModel에서는 ICommand를 통해 버튼의 입력을 확인합니다.
    자세한 예제는 ICommand예제를 확인 하시면 되겠습니다.

  2. Model의 역할
    Model은 쉽게 생각하면 데이터라고 생각하시면 편합니다.
    제가 만약 어떤 프로그램의 Log부분을 제작한다고 한다면 ‘Log경로가 Model에 들어가는 데이터다’ 라고 생각해주시면됩니다.

  3. MVVM에서 INotifypropertyChanged의 역할
    View, ViewModel, Model 이름에서 알 수 있듯이, ViewModel은 View와 Model을 이어주는 다리역할을 합니다. Model이 변경되는것을 View는 알 수 없기 때문에 View가 알기위해서 ViewModel이 알람역할을 해줍니다. 그때 필요한 인터페이스가 INotifypropertyChanged입니다.
    → 해당 인터페이스 구현은 원하는 클래스에서 구현되고, ViewModel에있는 속성에서 사용합니다.

  4. 속성, 필드
    필드는 일반적으로 private, 속성은 일반적으로 public으로 구현합니다.
    그 이유는 다른 클래스들이 함부로 필드에 접근 할 수 없도록 외부에서 필요한 필드만 public 속성으로 구현해 보안 강화 및 실수를 예방합니다.

=>
제가 처음 MVVM을 공부할 때 도움 되었던 블로그 첨부 드립니다.

객체지향, OOP

9개의 좋아요

답변주셔서 감사합니다.
제가 질문글을 올리고 공부해서 조금 이해한 토대로 작성을 해봤는데
Model = 어플리케이션에 사용되는 데이터와 그 데이터들을 처리

ViewModel = 중개자비슷한 역할(다리 역할)

View에 입력이 들어오면 View가 참조하고 있는 ViewModel에서 Binding된 객체를 찾아 업데이트
ViewModel에서는 InotifyProertyChange로 Model에 참조되어 있는 객체를 찾아 실시간으로 변경

-View 와 ViewModel은 Binding

-ViewModel 과 Model은 InotifyPropertyChange

View = 사용자에게 보여지는 UI

맞게 이해한걸까요?

3개의 좋아요

큰 도움 주시고 유익한 정보 알려주셔서 감사합니다.

1개의 좋아요

이것은 아닙니다

1개의 좋아요

위에 디모이님이 말씀해주신것처럼 ViewModel과 Model은 INotifypropertyChanged 이건 아니고

저 인터페이스를 구현해 Model이 변경됐다고 ViewModel이 View에게 알람을 울려준다고 생각하시면되겠습니다.

상세히 들어가면 다르게 표현될거같긴한데 그냥 딱 직관적이게 간단히 표현하자면 아래와 같이 표현할 수 있을것 같습니다.

View : UI
ViewModel : UI - Model(Data)의 처리를 위한 연결
Model : Data

실제로 INotify를 인터페이스가 구현된 예제를 보시면 이해하시기 훨씬 편하실것 같네요
https://blog.naver.com/goldrushing/220987878473
이 블로그는 따라하면서 배우기 좋으니 이것도 도움이 될것 같네요

3개의 좋아요

Bantree님이 알려주신 링크의 아래 글도 INotifypropertyChanged 관련 설명이 잘되어있네요.
공유드려요 ~!
https://blog.naver.com/goldrushing/220988712849

2개의 좋아요

답변주셔서 감사합니다. 어느정도 개념을 파악하는데 있어 큰 도움이 되었습니다.
추가로 질문이 있는데 Inotifypropertychanged 이벤트를 발생 시키려 할 때
Private 으로 선언 후에 Public에서 변경 동작을 알리는 것 같은데
private과 public이 뭔지는 알고는 있지만 왜
private과 public으로 선언을 하는지 잘 이해가 가질 않습니다…

2개의 좋아요

객체지향 관점에서 값(필드) 의 변경은 외부에서 직접 하지 않도록 하는 것이 좋습니다. 왜냐하면 객체 자신이 수정된 값을 인식하지 못하게 되면서 객체의 동작이 오동작 할 수 있기 때문입니다.

이것은 일종의 개발 패턴으로 권장하는 것입니다.

또한 값은 곧 상태인데 외부에 상태를 알리고 싶지 않을 때도 있습니다.
간단히 예를 들어서…

밥먹고, 공부하고, 일하는 상태는 알게 하고 싶은데
화장실 간 상태는 모르게 하고 싶을때 (굳이 화장실 갔다고 상태를 알리고 싶지는 않겠지요…)

내부의 상태는 private 필드로 모두 가지되, 외부의 상태는 화장실 간 상태는 감추는 형식입니다.

이 예에서도 유사한 원칙이 적용되는데

직접적인 상태 (private field) 는 감추고 알리고자 하는 상태 (public property) 는 노출 하는 원칙에 해당합니다.

5개의 좋아요

답변 감사합니다!

3개의 좋아요

디모이님의 설명을 보시고 객체지향에서의 캡슐화 부분을 한번 찾아보시면 추가적인 도움이 될 것 같습니다. 화이팅!

4개의 좋아요