Study/C#

C# WPF에서 MVC 디자인 패턴 연습 예제 구현하기

13.d_dk 2021. 1. 25. 22:51
728x90
반응형

MVC란 무엇일까?

 MVC를 설명하기 전 간단하게 디자인 패턴에 대해서 설명해보고자 한다. 소프트웨어를 제작함에 있어 디자인 패턴이란 어떻게 설계하여 코드들을 작성할 것인지에 대한 방법들이다. 소프트웨어마다 ‘사용자가 누구인가?’, ‘어떤 상황에서 사용되는 소프트웨어인가?’ 등에 따라서 작성된 코드들을 배치하고 엮어 동작할지 조금씩 다르다. 엑셀과 같은 소프트웨어를 만들 때, 소프트웨어가 잘 동작하기 위해 코드를 엮는 방법과 효율적으로 코드를 작성하는 방법이 있을 수 있다. 반면에, 웹 기반에서 동작되는 소프트웨어는 이와 다른 방법이 있을 수 있다. 이러한 방법을 패턴화하여 개발자들이 소프트웨어를 설계하고 코드를 작성할 때 하나의 형식으로 의사소통을 할 수 있다. 이것이 소프트웨어의 디자인 패턴이다. 

 여러 디자인 패턴 중 하나가 MVC이다. MVC는 모델(Model), 뷰(View), 컨트롤러(Controller)의 약자들의 조합으로 이름이 구성되어 있다. 어떤 소프트웨어를 설계할 때, MVC 패턴을 사용하자라고 한다면 코드들을 역할에 따라 모델, 뷰, 컨트롤러로 나누어 엮는다는 의미로 받아들일 수 있다.

 여기서 각각의 역할에 따라 구분된 모델, 뷰, 컨트롤러가 어떻게 서로 상호작용할 수 있는지 그림으로 표현해보았다.

사용자가 MVC로 구성된 프로그램을 동작시켰을 때, 내부 동작 다이어그램

 

 뷰의 역할은 사용자와 소통을 하는 부분이다. 사용자의 입력을 받아드리거나 필요한 출력을 해주는 역할을 담당한다. 다르게 표현하면 사용자의 입력을 컨트롤러에 전달하거나 출력에 필요한 데이터를 컨트롤러로부터 받는다.

 컨트롤러의 역할은 뷰와 모델 사이에서 조율을 하는 것이다. 여기서 조율은 모델의 데이터를 가져오거나 변경하는 기능을 수행하거나, 뷰에 데이터를 전달하거나 뷰에 대한 변경 요청을 하기도 한다.

 모델은 데이터를 저장하고 관리하는 부분이다. 컨트롤러가 데이터를 요청하면 데이터를 전달한다. 또는 컨트롤러가 가지고 있는 데이터에 대하여 변경을 요청하면 데이터를 변경하기도 한다. 

 

 MVC의 각 요소들이 어떤 역할을 하는지 살펴보았다. 그럼 왜 이렇게 역할로 구분하여 놓았을까? 이러한 이유는 아래와 같다.

  1. 각각의 역할에 나누어 코드를 작성하면 코드의 관리 및 유지보수가 용이하기 때문이다.
  2. 모델과 뷰의 강한 결합을 사전에 방지하여 확장성을 가지게 할 수 있다.

 1번을 좀 더 풀어서 설명해보자. 코드를 작성할 때 역할이 나뉘어 분류가 되어 있으므로 새로운 기능 및 기능을 수정할 때 코드를 추가하거나 수정하기 위해 접근하는 것이 편하다. 예를 들어서 기존 데이터를 조합한 새로운 데이터를 추가로 관리해야한다면 모델 부분에 코드를 추가하거나 수정하면 된다.

 2번을 풀어서 설명해보겠다. 뷰가 있는 코드 부분에 모델을 넣어서 코드를 같이 작성할 수도 있다. 하지만 이 경우 뷰와 모델이 서로 코드로써 엮여 강한 결합을 가지게 되고 코드의 수정 및 추가 등의 확장성이 떨어진다. 예를 들어 이 뷰에서 사용하는 모델 데이터를 다른 뷰에서 사용을 해야하는 경우를 생각해보자. 또는 뷰가 수정이 필요한 경우를 생각해보자. 같이 엮여 있는 뷰 내부의 모델 데이터에 문제가 생기지 않게 다른 뷰와 연결을 해야하는 문제가 생길 수 있다. 또 뷰를 수정해야하는 경우에도 내부의 모델 데이터를 수정할 필요가 있을지 모른다. 이러한 결합으로 생기는 문제를 컨트롤러라는 매개를 두어 분리를 해두면 추가하고 수정하는 것은 같 모델과 뷰에서 진행하되 연결에 해당하는 부분만 컨트롤러로 관리하면 되므로 확장성에서 큰 장점을 가질 수 있다.

 이러한 설명에서 언급한 예시를 그림으로 설명하면 아래와 같다.

MVC 패턴에서 코드 수정 작업의 예시
MVC 패턴로 작성되지 않은 코드에서 새로운 코드를 추가하는 예시
MVC 패턴으로 작성된 코드에서 새로운 코드를 추가하는 예시

 

 

MVC 패턴을 C# WPF를 통해 구현해보기

 MVC를 이해하기 위해 예제로 구현해보자 한다. 예제는 C#의 WPF를 사용하여 visual studio 2012로 솔루션을 제작하였다. 예제는 버튼을 눌었을 때, 텍스트를 출력하는 라벨의 테스트를 바꾸어보는 예제이다. 여기서 각각의 프로그램 요소와 코드의 요소들을 MVC로 각각의 역할을 나누어 보면 아래의 그림과 같다. 

MVC를 구현해보기 위한 예제의 설계 다이어그램

 

 예제의 동작을 하나하나 나누어 설명해보겠다. 입력 버튼 1을 클릭하면 문자열 데이터 컨트롤러에 데이터를 요청한다. 이후 컨트롤러는 문자열 데이터를 확인한다. 컨트롤러는 확인한 문자열 데이터를 가져와서 뷰의 출력 라벨에 전달한다. 이를 그림으로 표현하면 아래와 같다.

MVC를 구현해보기 위한 예제의 동작 흐름 다이어그램

 

 MVC로 코드들을 작성하기 위해 솔루션의 프로젝트에서 코드를 작성하는 부분을 분리하였다. 뷰를 효율적으로 구성하기 위해서 유저 컨트롤을 따로 분리하여 두었다. 프로젝트의 디렉토리 및 코드의 구성은 아래와 같다.

예제를 구현하기 위한 Visual studio에서 솔루션의 구성

 

 먼저 모델에 해당하는 클래스(StringData)를 보자. 매우 간단하게 작업을 하였으며 이 클래스는 문자열 변수(StrData)를 하나 가지고 있다. 객체 생성(StringData()) 시 이 데이터를 초기화한다. 설명한 모델 클래스의 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace WPFWithMVC.Models
{
    class StringData
    {
        public string StrData = null;
 
        public StringData()
        {
            StrData = "";
        }
 
    }
}
 
cs

 

 다음은 컨트롤러에 해당하는 클래스(StringDataControl)이다. 먼저 이 클래스는 각 버튼의 동작에 따라 필요한 데이터를 문자열 데이터 클래스(_stringData1, _stringData2)로 정의하였다. 이 컨트롤러 클래스는 객체 생성 시 문자열 데이터 클래스를 생성하고 값을 저장한다. 뷰에서 데이터를 요청하였을 때 처리하기 위한 함수(DoActionStrData(object sender, EventArgs e))가 정의되어 있으며, 이러한 데이터를 전달하기 위한 이벤트 핸들러(Event handler) 변수(SendStrData)를 가지고 있다. 이 컨트롤러에 해당하는 클래스의 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using WPFWithMVC.Models;
 
namespace WPFWithMVC.Controls
{
    class StringDataControl
    {
        private StringData _stringData1 = null;
        private StringData _stringData2 = null;
 
        public StringDataControl()
        {
            _stringData1 = new StringData();
            _stringData2 = new StringData();
 
            _stringData1.StrData = "data1";
            _stringData2.StrData = "data2";
        }
 
        public EventHandler SendStrData = null;
 
        public void DoActionStrData(object sender, EventArgs e)
        {
            string key = sender as string;
            string senderStr = "";
 
            switch (key)
            {
                case "A":
                    if (_stringData1 != null)
                    {
                        senderStr = _stringData1.StrData;
                    }
                    break;
                case "B":
                    if (_stringData2 != null)
                    {
                        senderStr = _stringData2.StrData;
                    }
                    break;
            }
 
            if (SendStrData != null) { SendStrData(senderStr, EventArgs.Empty); }
        }
    }
}
 
cs

 

 아래는 뷰의 UI에서 사용한 유저 컨트롤들의 xaml 및 코드 비하인드이다. 데이터 바인딩 및 각종 설명은 생략한다.

    • Actionbutton (xaml; xaml.cs)
1
2
3
4
5
6
7
8
9
10
11
12
13
<UserControl x:Class="WPFWithMVC.UIComponents.ActionButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="70" d:DesignWidth="150"    
             x:Name="ActBtn">
    <Grid>
        <Button Foreground="Black" FontSize="20" FontFamily="Roboto" Content="{Binding ActionBtnTextStr, ElementName=ActBtn}" Click="Button_Click"/>
    </Grid>
</UserControl>
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace WPFWithMVC.UIComponents
{
    /// <summary>
    /// ActionButton.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class ActionButton : UserControl
    {
        public ActionButton()
        {
            InitializeComponent();
        }
 
        public string ActionBtnTextStr
        {
            get { return (string)GetValue(ActionBtnTextStrProperty); }
            set { SetValue(ActionBtnTextStrProperty, value); }
        }
        public static readonly DependencyProperty ActionBtnTextStrProperty =
            DependencyProperty.Register("ActionBtnTextStr"typeof(string), typeof(ActionButton), new UIPropertyMetadata(""));
 
        public event RoutedEventHandler Click;
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Click(this, e);
        }
    }
}
 
cs

 

  • MainTextLabel (xaml; xaml.cs)
1
2
3
4
5
6
7
8
9
10
11
12
13
<UserControl x:Class="WPFWithMVC.UIComponents.MainTextLabel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="150" d:DesignWidth="400"    
             x:Name="MainTxtLbl">
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
        <Label Foreground="Black" FontSize="60" FontFamily="Roboto" Content="{Binding MainTextLblStr, ElementName=MainTxtLbl}"/>
    </Grid>
</UserControl>
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace WPFWithMVC.UIComponents
{
    /// <summary>
    /// MainTextLabel.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainTextLabel : UserControl
    {
        public MainTextLabel()
        {
            InitializeComponent();
        }
 
        public string MainTextLblStr
        {
            get { return (string)GetValue(MainTextLblStrProperty); }
            set { SetValue(MainTextLblStrProperty, value); }
        }
        public static readonly DependencyProperty MainTextLblStrProperty =
            DependencyProperty.Register("MainTextLblStr"typeof(string), typeof(MainTextLabel), new UIPropertyMetadata(""));
    }
}
 
cs

 

  • SubTextLabel (xaml; xaml.cs)
1
2
3
4
5
6
7
8
9
10
11
12
13
<UserControl x:Class="WPFWithMVC.UIComponents.SubTextLabel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="300"    
             x:Name="SubTxtLbl">
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
        <Label Foreground="Black" FontSize="30" FontFamily="Roboto" Content="{Binding SubTextLblStr, ElementName=SubTxtLbl}"/>
    </Grid>
</UserControl>
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace WPFWithMVC.UIComponents
{
    /// <summary>
    /// SubTextLabel.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class SubTextLabel : UserControl
    {
        public SubTextLabel()
        {
            InitializeComponent();
        }
 
        public string SubTextLblStr
        {
            get { return (string)GetValue(SubTextLblStrProperty); }
            set { SetValue(SubTextLblStrProperty, value); }
        }
        public static readonly DependencyProperty SubTextLblStrProperty =
            DependencyProperty.Register("SubTextLblStr"typeof(string), typeof(SubTextLabel), new UIPropertyMetadata(""));
    }
}
 
cs

 

 다음은 뷰의 UI에 해당하는 xaml 코드이다. 위의 유저 컨트롤을 사용하여 버튼 2개와 텍스트 출력 라벨을 간단하게 배치하였다. 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<Window x:Class="WPFWithMVC.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:UIComponents="clr-namespace:WPFWithMVC.UIComponents"     
        Title="MainWindow" Height="700" Width="1200">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="450"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="150"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="150"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Grid Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left">
            <StackPanel>
                <UIComponents:MainTextLabel x:Name="mainLbl" HorizontalAlignment="Left" Margin="10, 5, 0, 0"/>
                <UIComponents:SubTextLabel x:Name="subLbl" HorizontalAlignment="Left" Margin="10, 5, 0, 0"/>
            </StackPanel>
        </Grid>
        <Grid Grid.Column="2" Grid.Row="0" Grid.RowSpan="2">
            <StackPanel>
                <UIComponents:ActionButton x:Name="btn1" Click="btn1_click"/>
                <UIComponents:ActionButton x:Name="btn2" Click="btn2_click"/>
            </StackPanel>
        </Grid>
    </Grid>
</Window>
 
cs

 

 다음은 뷰에 해당하는 UI의 코드 비하인드이다. 뷰에서 다루기 위한 문자열 변수가 정의되어 있다. 컨트롤러를 사용하기 위해 변수로 정의되어 있으며 이 컨트롤러에 문자열 데이터를 요청하기 위한 이벤트 핸들러 변수(_callStrData)가 정의되어 있다. 뷰의 UI에서 나타나는 텍스트를 초기화하는 코드가 _initText()에 정의되어 있으며, 컨트롤러와 이벤트 핸들러를 사용하기 위해 객체를 생성하고 초기화 하는 코드가 _init()에 정의되어 있다. 이후 문자열 데이터를 요청하는 함수들 (_callActA(), _callActB()) 과 데이터를 받기 위한 함수(_rcvStrData(object sender, EventArgs e)), 그리고 각 버튼을 눌렀을 때 수행되는 함수들(btn1_click(object sender, RoutedEventArgs e), btn2_click(object sender, RoutedEventArgs e))이 정의되어 있다. 이 코드들은 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace WPFWithMVC
{
    using Controls;
 
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        private StringDataControl _strCtrl = new StringDataControl();
        private EventHandler _callStrData = null;
        private string _strData = "";
 
        public MainWindow()
        {
            InitializeComponent();
            _initText();
        }
 
        private void _initText()
        {
            mainLbl.MainTextLblStr = "main";
            subLbl.SubTextLblStr = "sub";
 
            btn1.ActionBtnTextStr = "btn1";
            btn2.ActionBtnTextStr = "btn2";
 
            _init();
        }
 
        private void _init()
        {
            _callStrData += _strCtrl.DoActionStrData;
            _strCtrl.SendStrData += _rcvStrData;
        }
 
        private void _callActA()
        {
            if (_callStrData != null) { _callStrData("A"null); }
        }
 
        private void _callActB()
        {
            if (_callStrData != null) { _callStrData("B"null); }
        }
 
        private void _rcvStrData(object sender, EventArgs e)
        {
            string tmpStr = sender as string;
            _strData = tmpStr;
        }
 
        private void btn1_click(object sender, RoutedEventArgs e)
        {
            _callActA();
            mainLbl.MainTextLblStr = _strData;
        }
 
        private void btn2_click(object sender, RoutedEventArgs e)
        {
            _callActB();
            mainLbl.MainTextLblStr = _strData;
        }
    }
}
 
cs

 

프로그램이 실행되고 사용자가 버튼을 누르면 어떻게 동작이 되는지 하나하나 살펴보자.

  1. 뷰(MainWindow)에 컨트롤러(StringDataControl) 객체를 생성한다.
  2. 컨트롤러(StringDataControl) 객체 내에서 모델(StringData) 객체들을 생성한다.
  3. 뷰의 이벤트 핸들러(_callStrData) 생성 및 이벤트 발생 시 동작할 컨트롤러(StringDataControl) 객체의 함수(DoActionStrData)를 연결한다.
    (뷰에서 모델의 데이터를 요청하기 위함, 컨트롤러에서 이를 요청 받았다면 이벤트 핸들러를 통해 데이터를 보내기 위함)
  4. 컨트롤러 객체의 이벤트 핸들러(SendStrData)에 이벤트 발생 시 동작할 뷰의 함수(_rcvStrData)를 연결한다.
    (컨트롤러에서 이벤트 핸들러를 통해 데이터를 보내 이벤트를 발생시키기 위함, 이에 대응하여 데이터를 받는 뷰의 함수가 실행하기 위함)
  5. 사용자가 버튼을 누른다.
  6. 뷰에서 모델의 데이터를 요청하는 이벤트(_callStrData)가 발생한다.
  7. 컨트롤러에서 이를 요청 받았으므로 이에 연결된 함수(DoActionStrData)를 실행한다.
  8. 컨트롤러에서 요청을 받은 문자열 데이터를 이벤트(SendStrData)를 발생시켜 보낸다. 
  9. 뷰에서 이 이벤트에 대응하여 데이터를 받는 함수(_rcvStrData)가 실행된다.
  10. 데이터를 뷰에서 사용하고자 하는 문자열 변수(_strData)에 저장한다.
  11. 이 변수(_strData)를 메인 라벨에 바인딩되어 있는 변수(mainLbl.MainTextLblStr)에 할당한다.
  12. 사용자가 보는 텍스트 출력 라벨의 텍스트가 변경된다.

 

이를 다이어그램으로 표현하면 아래의 그림과 같다.

이 그림에서 모델, 컨트롤러, 뷰가 노란색 점선으로 연결된 것을 볼 수 있다. 이는 느슨한 연결을 의미한다. 이 구조는 이러한 느슨한 연결로 쉬운 확장성을 가진다.

 

이러한 동작을 사용자가 버튼을 눌러 텍스트 레이블이 바뀌는 것을 아래의 그림에서 확인할 수 있다.

왼쪽의 초기 화면에서 btn1 또는 btn2를 눌렀을 때 오른쪽 화면과 같이 텍스트 레이블의 텍스트가 업데이트되는 것을 볼 수 있다.

 

Reference

  1. github.com/daegukdo/TIL/tree/master/02_C_sharp/019_WPF_MVC/WPFWithMVC
  2. blog.naver.com/jhc9639/220967034588
  3. ko.wikipedia.org/wiki/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4_%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4
  4. dailyheumsi.tistory.com/148
  5. opentutorials.org/course/697/3828
  6. dlucky.tistory.com/135
 

MVC 디자인 패턴 - 생활코딩

수업 소개 이미 CodeIgniter의 기본적인 골격인 Controller, Model, View를 살펴봤다. 이것들을 모아서 MVC라고 하는데 이번 시간에는 MVC에 대한 일반적인 정의를 간단히 알아보고, CodeIgniter에서는 MVC 패턴

opentutorials.org

 

[디자인 패턴 1편]. 디자인 패턴 개요

1. 디자인 패턴이란 디자인 패턴은 소프트웨어 공학론 안의 좋은 코드를 설계하기 위한 일종의 설계 디자인 방법론이다. 그렇다면 좋은 코드란 무엇인가? 좋은 코드란, 가독성, 간결함 등 여러

dailyheumsi.tistory.com

 

소프트웨어 디자인 패턴 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 소프트웨어 디자인 패턴(software design pattern)은 소프트웨어 공학에서 소프트웨어 디자인에서 특정 문맥에서 공통적으로 발생하는 문제에 대해 재사용 가능한 해

ko.wikipedia.org

 

[개발자 면접준비]#1. MVC패턴이란

​오늘은 개발자면접에 많이 나오기도 하는 MVC패턴에 대해서 알아보고자 합니다. 과연 MVC패턴이 무...

blog.naver.com

 

daegukdo/TIL

today I learned. Contribute to daegukdo/TIL development by creating an account on GitHub.

github.com

 

MVC 패턴의 이해

<출처 : http://flex2.egloos.com/2596672> 1. 이 글은 누구를 위한 무엇인가 본 글은 디자인 패턴에 대해 이해는 하고 있으나 실제 작업에서 어떻게 활용해야 하는지 부담을 느끼..

dlucky.tistory.com

 

 

 

 

 

 

 

반응형