VB :: For Beginners

MVVM I – MVVM 패턴에 대한 기본 개념.

들어가기 전에…

MVVM 의 약자는 Model-View-ViewModel 이라는 사실은 MVVM 에 대해 한번 쯤 검색해보신 경험이 있으신 분들이라면 알고 계실 것으로 사료됩니다.

MVVM 은 WPF (Windows Presentation Foundation) 와 Silverlight 의 아키텍처 중 하나로 2005 년 Microsoft 의 John Gossman 이 블로그에 해당 기술 자료들을 공개적으로 집필하면서부터 알려지게 되었습니다.

디자이너가 작업한 인터페이스 (실질적인 사용자들이 눈으로 볼 수 있는 페이지) 가 View 에 해당하고, Database 와 통신하는 역할을 Model 이 담당하며 둘 사이에서 View 와는 Binding 이나 Command 로 연결하고 Model 과는 데이터를 주고 받는 역할을 담당하는 녀석이 ViewModel 이라고 이해하시면 되는데요,

이러한 정도의 설명만으로는 도무지 의미와 필요성에 대해 이해하기가 어려울 수 있으므로 인터넷 검색을 통해 찾아보거나, 제가 재구성한 다음의 도식들을 살펴보도록 합시다.

 

MVVM Chart

 

Unit Tests 라는 개념이 추가로 표시되었지만, 앞에서 언급해드린 의미들을 쉽게 이해하실 수 있도록 도표로 나타낸 것에 불과합니다.

 

IC416621

 

개념은 똑같이 적용됩니다만, UI events, PropertyChanged events, Model change event, ViewModel data, Update, Read 등의 데이터들이 이동한다는 것을 눈여겨두도록 합시다.

더불어, 아래 도표에서는 ViewModel 에서 다루어지는 요소들이 Collections / Properties / ICommands 라는 것이고, 일반적으로 UI 에 해당하는 View 는 디자이너가 담당하고, ViewModel 과 Model 은 개발자가 담당하는 영역으로 표시되어 있는데요, 이 부분도 함께 눈여겨두도록 합시다.

 

MVVM Infographic

 

당연히, 여러분이 개발자이시고, MVVM 을 충분히 익혀서 능숙하게 다루게 된다고 가정하더라도 개인적으로든 회사 업무로든 저러한 모든 부분들을 혼자서 담당하고 있으며, 그렇게 될 것이라는 사실을 잘 아시고 계실 것입니다, 다만 언제까지나 소규모의 개발 혹은 프로젝트만 다룰 수만은 없으므로 조금 규모가 있는 방대한 프로젝트의 경우 일반적으로 저렇게 나누어 협업한다는 사실만 알아두시고 넘어가시는 편을 권장합니다.

상단의 도식들을 아무리 들여다보시더라도 왜 저런 요소들이 필요하며, 왜 저렇게 번거롭게 코드를 짜야 하는지 이해가 가지 않으시는 분들이 계신다면,
앞서 눈여겨보았던 단어들…

[UI events, PropertyChanged events, Model change event, ViewModel data, Update, Read, Collections / Properties / ICommands]

이러한 각 요소들이 무엇이며 어떻게 코딩하고 동작하는지 원리를 이해하신다면 MVVM 이 무엇인지 확실하게 개념을 잡으실 수 있습니다.

 

Windows Form App 프로젝트에서 예제 만들어보기

이제 MVVM 에 대한 개념들을 차근차근 짚어나가기에 앞서, 항상 해 오던 다소 귀찮은 코딩을 해 보도록 하겠습니다.

팀장님이 퇴근할 무렵 자리 옆으로 걸어오시더니 프린트 된 기획서 한 장을 내밀어주셨습니다.

“자네, 이번에 회사에서 출판사들과 협의 하에 E-Book Reader 앱을 기획했는데 내용은 추후 e-mail 로 보내줄테니 일단 이렇게 동작하도록 앱 하나 개발해줄 수 있겠나?”

 

EBookProjectPlan

 

“엥? 기획서라고요? 이건 뭐 프로젝트 문서도 아니고 A4 용지 한장에 컨트롤 몇 개 그리신게…”

“어서, 퇴근시간 얼마 남지 않았으니 급하다.”

“일단 알겠습니다…”

 

1. 급한만큼, 일단 Visual Studio 를 실행하여 [새 프로젝트] 를 하나 생성합니다.
[Windows Forms App] 프로젝트이며 이름은 [WinFormEBookSample] 로 합니다.

 

MVVM-Fundamentals-001

 

2. 아래와 같이 프로젝트와 함께 텅 비어있는~ Form 하나가 화면에 표시되는데요,

 

MVVM-Fundamentals-002

 

3. 일단 Panel 컨트롤을 선택하여 드래그 앤 드롭 해 놓고, Dock 속성의 설정 값을 [Bottom] 으로 조정해둡니다.

 

MVVM-Fundamentals-003

 

4. Button 두 개와 Label 하나도 드래그 앤 드롭하여 아래와 같이 배치하고, Label 의 AutoSize 속성을 [False] 값으로, BorderStyle 속성을 [FixedSingle] 값으로 각각 설정하여 줍니다.

 

MVVM-Fundamentals-004.png

 

5. 상단에 Panel 하나를 더 드래그하여 Dock 속성의 설정 값을 [Top] 으로 변경합니다.

 

MVVM-Fundamentals-005.png

 

6. 방금 Form 상단으로 삽입한 패널에 [ComboBox] 컨트롤을 드래그 하여 도서 제목이 표시될 공간을 만들어 준 후, Dock 속성 값을 [Fill] 로, 도서 제목이 표시될 ComboBox 의 DropDownStyle 속성을 [DropDownList] 값으로 각각 변경하시고, Items 속성 맨 우측의 […] 버튼을 클릭합니다.

 

MVVM-Fundamentals-006

 

7. 새로운 String Collection Editor 창이 표시되면 도서 제목들을 입력합니다.

 

MVVM-Fundamentals-007

 

8.  Form 중앙에는 TextBox 컨트롤을 배치하시고, Dock 속성은 [Fill] 값으로, TextBox 의 Multiline 과 ReadOnly 속성을 모두  [True] 값으로 변경합니다.

 

MVVM-Fundamentals-008.png

 

9. Button 컨트롤의 Text 속성을 각각 [-], [+] 로 수정합니다.

 

MVVM-Fundamentals-009

 

10. 그리고 Button 컨트롤 두 개를 각각 더블 클릭하여 이벤트를 생성하여 코딩을 시작합니다.

 

MVVM-Fundamentals-010

숫자를 입력받을 Number 라는 Property  (속성) 를 생성하시고, 이 속성을 기반으로 버튼 이벤트에 코딩을 시작합니다.
마이너스 (-) Button 을 클릭할 경우 숫자를 하나 감소시킵니다.
플러스 (+) Button 을 클릭할 경우 숫자를 하나 증가시킵니다.
Number Property (속성) 의 Set 부분은 숫자가 변경될 때 Label1의 텍스트도 변경되도록 구현되어 있습니다.

 

11. 생성자에 실행 시 초기화 될 내용을 넣어줍니다.
Label1 의 값을 보여주기 위해 Number = 1 을 다시 대입했습니다.
그리고 현재 설정된 숫자의 내용을 내용에 해당하는 Text 박스에 보여주는 함수를 호출해줍니다.

SetPageContents 는 Parameter 로 들어온 숫자에 해당하는 페이지 내용을 뿌려주는 단순한 함수입니다. [+] 버튼과 [-] 버튼에도 이 함수를 호출해줍니다. 버튼이 클릭되면 증가되거나 감소된 숫자의 내용이 표시됩니다.

 

MVVM-Fundamentals-011

 

12.  음… 잘 되는군….
이라고 생각하던 찰나에 팀장님께서 다가와,
“100 페이지로 갈려면 플러스 [+] Button 을 100 번 누를거야?”
“키보드로 숫자를 입력할 수 있도록 숫자 표시 부분을 TextBox 로 바꿔.!! 당장”
이라고 하면서  담배를 한 대 피시러 가셨습니다.

 

MVVM-Fundamentals-012

 

13. 기분은 다소 언짢았지만… 이 정도는 아무것도 아니죠 ^^!! Label을 삭제하고 TextBox 로 대체합니다.

 

MVVM-Fundamentals-013

 

14. 삭제한 “Label1” 이라는 컨트롤이 더 이상 존재하지 않으므로 다시 디버깅 및 빌드를 수행하면 다음과 같이 오류가 발생하게 됩니다.

 

MVVM-Fundamentals-014

 

15. 기존의 코드에 존재하던 Label1 의 명칭을 TextBox2 로 변경합니다.
그럼 오류가 해결되고 아래와 같이 잘 실행되는 모습을 확인할 수 있습니다.
그럼 이번에는 키보드로 숫자를 입력받아 페이지 내용이 바뀌도록 하는 기능을 추가해야겠죠? ^^

 

MVVM-Fundamentals-015

MVVM-Fundamentals-016

 

16. TextBox2 컨트롤에 대한 이벤트 속성 창을 열어서 TextChanged 이벤트를 더블 클릭합니다.

 

MVVM-Fundamentals-017

 

Number Property  (속성) 에는 TextBox2.Text를 자동으로 변경하는 원칙이 이미 코드에 포함되어 있으므로 TextBox2 의 Text 를 직접적으로 변경할 경우 영향을 받지 않도록 iNum 부분을 직접 변경하고 SetPageContents 만 호출하여 페이지 내용을 뿌려줍니다.

 

17.  이제 입력한 페이지로 바로 갈 수 있는 기능이 구현되어 오류 없이 실행됩니다.

 

MVVM-Fundamentals-018

 

그런데… 담배 한대를 피고 오신 팀장님께서, 다시 들어오셔서
“어이! 너 개발자 맞아? TextBox2 가 뭐냐? 나중에 다른 개발자가 코드보고 바로 바로 수정할 수 있겠어?”
“이름 규칙 프로젝트 규칙에 맞게 수정해야지! 에헴.”
하고 다시 돌아갔다.

짜증이 밀려옵니다. 진작 말씀하시지…
어쨌든 수정해야겠죠… ㅠ_ㅠ!

 

18. 컨트롤 이름 값을 모두 명확하게 수정하는 작업을 진행하고…

 

MVVM-Fundamentals-019

 

19. 이벤트 이름 역시도 모두 컨트롤 이름 값과 일치하도록 수정합니다.

 

MVVM-Fundamentals-021.png

 

20. 이전에 작성했던 모든 코드를 모드 이름이 바뀌어 새로 생성된 코드로 이동시켜 줍니다.
(휴… Ctrl + C, Ctrl + V 없었으면 어쩔 뻔 했을꼬…)
라고 생각하는 순간 사장실에서 나오던 팀장님이 또 한 마디 하시고 가셨습니다.
“이번에 베타 (BETA) 버전으로 공개할거라 50 페이지까지만 볼 수 있도록 기능 수정해야겠는데?”
(헐… ㅠㅠ)
“네 알겠습니다.”

 

MVVM-Fundamentals-022

 

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Imports System.Windows.Forms

Partial Public Class Form1
Inherits Form
Private iNum As Integer = 1

Private Property Number() As Integer
Get
Return iNum
End Get
Set
iNum = Value
Label1.Text = iNum.ToString()
End Set
End Property

Private Sub SetPageContents(Number As Integer)
TextBox1.Text = String.Format("고객님께서는 현재 {0} 페이지를 보시고 계십니다.", Number)
End Sub

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Number = 1
SetPageContents(Number)
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Number -= 1
SetPageContents(Number)

CheckEnabled()
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Number += 1
SetPageContents(Number)

CheckEnabled()
End Sub

Private Sub TxtNumber_TextChanged(sender As Object, e As EventArgs)
Dim iInputValue As Integer = Convert.ToUInt16(Label1.Text)
If iInputValue >= 1 AndAlso iInputValue <= 50 Then
iNum = iInputValue
SetPageContents(iNum)
CheckEnabled()
Else
MessageBox.Show("1 ~ 50 페이지 까지만 입력 가능합니다.", "WinFormEBookSample", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Sub

Private Sub CheckEnabled()
If Number = 50 Then
AddButton.Enabled = False
Else
AddButton.Enabled = True
End If

If Number = 1 Then
RemoveButton.Enabled = False
Else
RemoveButton.Enabled = True
End If
End Sub
End Class

 

CheckEnable()이라는 함수를 생성하시고,
1 ~ 10 조건에 맞춰 플러스 [+] 버튼과 마이너스 [-] 버튼의 Enable 속성을 조정하여
손으로 페이지를 입력했을 때 처리 까지 꼼꼼하게 생각해서 재구성합니다.

이제 모든 작업을 완료했으니 테스트를 해 봐야겠죠?
F5 키를 누르고 시작!!!

첫 (1) 페이지에서는 더 이상의 감소가 불가능하므로 마이너스 [-] 버튼이 비활성화됩니다.

 

MVVM-Fundamentals-023

 

마지막 (50) 페이지에서는 더 이상의 감소가 불가능하므로 플러스 [+] 버튼이 비활성화됩니다.

 

MVVM-Fundamentals-024

 

키보드로 50 페이지 이상의 값을 입력할 경우, MessageBox 를 띄우고 동작하지 않도록…!

 

MVVM-Fundamentals-025

 

다시 팀장님 오셔서 또 업무 주시기 전에 얼른 퇴근해버려야겠습니다… ㅠㅠ

여기까지, 간단하게 MVVM 의 구조를 살펴보는 시간을 가져보았고, 작은 E-Book 샘플 앱을 만들면서 여러가지 짜증나는 상황도 설정해 보았습니다. 다음 시간에는 MVVM 패턴에 대해 조금 더 자세히 알아보도록 하겠습니다.

게시글이 이해하시는데 조금이나마 도움이 되셨기를 바라며,
오늘도 좋은 하루 보내시기 바랍니다! 고맙습니다.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s