๋ฐ˜์‘ํ˜•

์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ MVC ํŒจํ„ด์— ๋Œ€ํ•ด ์†Œ๊ฐœ๋ฅผ ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.
[Design Pattern] MVC(Model-View-Controller) ํŒจํ„ด ์ด์•ผ๊ธฐ #1

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” MVC ํŒจํ„ด์„ ์ ์šฉํ•œ ์œˆํผ(WinForm) ์˜ˆ์ œ๋ฅผ ์†Œ๊ฐœํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

MVC ํŒจํ„ด์„ ์ ์šฉํ•œ ์ „ํ™”๋ฒˆํ˜ธ๋ถ€ ํ”„๋กœ๊ทธ๋žจ

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

์˜ˆ์ œ ์ฝ”๋“œ๋Š” '์ „ํ™”๋ฒˆํ˜ธ๋ถ€'๋ฅผ ์˜ˆ์‹œ๋กœ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜๊ณ , ์กฐํšŒํ•˜๊ณ , ์ œ๊ฑฐํ•˜๋Š” ๊ฐ„๋‹จํ•œ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๋ฐ์ดํ„ฐ์˜ ์ถ”๊ฐ€์™€ ์ œ๊ฑฐ, ๊ฐฑ์‹ ์ด ์ด๋ฃจ์–ด์ง€๋Š”๋ฐ ์ด๊ฒƒ์„ MVC ํŒจํ„ด์„ ์ ์šฉํ•˜์—ฌ ์—ญํ• ๋ณ„๋กœ ๋‚˜๋ˆ„์—ˆ๋‹ค๊ณ  ์ดํ•ดํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

์˜ˆ์ œ ์ฝ”๋“œ ๋™์ž‘

MVC ๊ตฌ์กฐ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ชจ๋ธ์—๋Š” ์‚ฌ๋žŒ์˜ ์ •๋ณด๊ฐ€ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๊ณ , ๋ทฐ์—๋Š” ์‚ฌ๋žŒ ๋ชฉ๋ก๊ณผ ์ƒ์„ฑ / ์ œ๊ฑฐ / ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ„ํŠผ๊ณผ ํ…์ŠคํŠธ ๋ฐ•์Šค๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ์ปจํŠธ๋กค๋Ÿฌ๋Š” ์ค‘๊ฐ„์— ์œ„์น˜ํ•˜์—ฌ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. 

MVC ์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ ๋‹ค์ด์–ด๊ทธ๋žจ

์ฝ”๋“œ ์„ค๋ช…

์ฝ”๋“œ๋Š” ๋ชจ๋ธ / ์ปจํŠธ๋กค๋Ÿฌ / ๋ทฐ ๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์€ ๋ฉ”์ธ ํ”„๋กœ๊ทธ๋žจ ์ˆœ์œผ๋กœ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ œ ์ฝ”๋“œ์˜ UML์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ UML

๋ชจ๋ธ(Model)

Customer ํด๋ž˜์Šค์— ID์™€ Name, Phone, Address ์ •๋ณด๋ฅผ get/set ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

namespace MVCPattern.Model
{
    public class Customer
    {
        public Customer(string id, string name, string phone, string address)
        {
            _id = id;
            _name = name;
            _phone = phone;
            _address = address;
        }
        string _id;
        public string ID
        {
            get { return _id; }
            set { _id = value; }
        }
        string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        string _phone;
        public string Phone
        {
            get { return _phone; }
            set { _phone = value; }
        }
        string _address;
        public string Address
        {
            get { return _address; }
            set { _address = value; }
        }
    }
}

์ปจํŠธ๋กค๋Ÿฌ(Controller)

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

namespace MVCPattern.Controller
{
    public interface IView
    {
        void setController(Controller controller);
        void clearList();
        void addCustomer(Customer customer);
        void removeCustomer(Customer customer);
        void updateListWithCustomer(Customer customer);
        string getSelectedCustomerID();
        void setSelectedCustomer(Customer customer);
        string Name { get; set; }
        string Address { get; set; }
        string Phone { get; set; }
        string ID { get; set; }
        bool isModify { set; }
    }
}

์ปจํŠธ๋กค๋Ÿฌ์—๋Š” ์œ„์— ์ •์˜ํ•œ ๋ทฐ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋ชจ๋ธ์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Customer ์ •๋ณด๊ฐ€ View์— ๋„˜๊ธฐ๊ฑฐ๋‚˜ View์˜ ์ •๋ณด๊ฐ€ Customer๋กœ ๋„˜๊ธฐ๊ฑฐ๋‚˜, Customer ๋ชฉ๋ก์„ ์—…๋ฐ์ดํŠธํ•˜๊ฑฐ๋‚˜, Customer๋ฅผ ์ถ”๊ฐ€/์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ๋“ฑ ๋ชจ๋“  ๊ธฐ๋Šฅ์ด ์ปจํŠธ๋กค๋Ÿฌ์— ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

namespace MVCPattern.Controller
{
    public class Controller
    {
        IView _view = null;
        IList _customers = null;
        Customer _selectedCustomer;

        public Controller(IView view, IList customers)
        {
            _view = view;
            _customers = customers;
            view.setController(this);
        }
        
        private void updateView(Customer customer)
        {
            _view.ID = customer.ID;
            _view.Name = customer.Name;
            _view.Phone = customer.Phone;
            _view.Address = customer.Address;
        }

        private void updateCustomer(Customer customer)
        {
            customer.ID = _view.ID;
            customer.Name = _view.Name;
            customer.Phone = _view.Phone;
            customer.Address = _view.Address;
        }

        public void LoadView()
        {
            _view.clearList();
            foreach (Customer customer in _customers)
                _view.addCustomer(customer);

            _view.setSelectedCustomer((Customer)_customers[0]);
        }

        public void SelectedCustomer(string selectedCustomerId)
        {
            foreach (Customer customer in this._customers)
            {
                if (customer.ID == selectedCustomerId)
                {
                    _selectedCustomer = customer;
                    updateView(customer);
                    _view.setSelectedCustomer(customer);
                    this._view.isModify = false;
                    break;
                }
            }
        }
        public void AddNewCustomer()
        {
            _selectedCustomer = new Customer("", "", "", "");
            updateView(_selectedCustomer);
            _view.isModify = true;
        }

        public void RemoveCustomer()
        {
            string id = this._view.getSelectedCustomerID();
            Customer customerToRemove = null;

            if (id != "")
            {
                foreach (Customer customer in _customers)
                {
                    if (customer.ID == id)
                    {
                        customerToRemove = customer;
                        break;
                    }
                }

                if (customerToRemove != null)
                {
                    int index = _customers.IndexOf(customerToRemove);
                    _customers.Remove(customerToRemove);
                    _view.removeCustomer(customerToRemove);

                    if (index > -1 && index < _customers.Count)
                    {
                        _view.setSelectedCustomer((Customer)_customers[index]);
                    }
                }
            }
        }

        public void Register()
        {
            updateCustomer(_selectedCustomer);
            if (!_customers.Contains(_selectedCustomer))
            {
                _customers.Add(_selectedCustomer);
                _view.addCustomer(_selectedCustomer);
            }
            else
            {
                _view.updateListWithCustomer(_selectedCustomer);
            }
            _view.setSelectedCustomer(_selectedCustomer);
            _view.isModify = false;
        }
    }
}

๋ทฐ(View)

๋ทฐ์—๋Š” View Interface์™€ ๋ฒ„ํŠผ ๋ฐ ๋ฆฌ์ŠคํŠธ ๋ทฐ ์ด๋ฒคํŠธ๊ฐ€ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๊ธด ๊ด€๊ณ„๋กœ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ํ•˜๋‹จ์— ์ฒจ๋ถ€๋œ ์˜ˆ์ œ ํŒŒ์ผ์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

namespace MVCPattern.View
{
    public partial class MainForm : Form, IView
    {
        MVCPattern.Controller.Controller _controller;
        public MainForm()
        {
            InitializeComponent();
        }
        public void setController(MVCPattern.Controller.Controller controller)
        {
            _controller = controller;
        }

        public void clearList() {...}

        public void addCustomer(Customer customer) {...}

        public void updateListWithCustomer(Customer customer) {...}
        
        public void removeCustomer(Customer customer) {...}
        
        public string getSelectedCustomerID() {...}
        
        public void setSelectedCustomer(Customer customer) {...}
                       
        private void buttonRemoveCustomer_Click(object sender, EventArgs e)
        {
            _controller.RemoveCustomer();
        }

        private void buttonRegister_Click(object sender, EventArgs e)
        {
            _controller.Register();
        }

        private void listViewCustomer_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listViewCustomer.SelectedItems.Count > 0)
                _controller.SelectedCustomer(listViewCustomer.SelectedItems[0].Text);
        }

        private void buttonNewCustomer_Click(object sender, EventArgs e)
        {
            _controller.AddNewCustomer();
        }
    }
}

ํ”„๋กœ๊ทธ๋žจ ๋ฉ”์ธ

๋ฉ”์ธ์—์„œ ๋ทฐ์™€ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ, ๋ทฐ์™€ ๋ฐ์ดํ„ฐ๋ฅผ ์ธ์ž๋กœ ๋„˜๊น๋‹ˆ๋‹ค.

namespace ExamMVC
{
    static class Program
    {
        /// <summary>
        /// ํ•ด๋‹น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฃผ ์ง„์ž…์ ์ž…๋‹ˆ๋‹ค.
        /// </summary>
        [STAThread]
        static void Main()
        {
            MainForm form = new MainForm();

            // Add some dummy data
            IList users = new ArrayList();
            users.Add(new Customer("1", "๊น€์ฒ ์ˆ˜", "010-1234-5678", "์„œ์šธ์‹œ ๊ฐ•๋™๊ตฌ"));
            users.Add(new Customer("2", "์ด์ˆ˜์ง€", "010-0000-1111", "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ"));
            users.Add(new Customer("3", "์ตœ์ˆ˜์ •", "010-2222-3333", "์„œ์šธ์‹œ ๊ฐ•์„œ๊ตฌ"));
            users.Add(new Customer("4", "๋ฐ•์žฌ์ˆ˜", "010-4444-5555", "์„œ์šธ์‹œ ๊ฐ•๋ถ๊ตฌ"));

            Controller controller = new Controller(form, users);
            controller.LoadView();
            form.ShowDialog();
        }
    }
}

์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ฒจ๋ถ€๋œ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

ExamMVC.zip
0.76MB

๋ฐ˜์‘ํ˜•