{"id":42925,"date":"2024-11-13T22:28:15","date_gmt":"2024-11-13T22:28:15","guid":{"rendered":"https:\/\/atmokpo.com\/w\/?p=42925"},"modified":"2024-11-26T06:34:25","modified_gmt":"2024-11-26T06:34:25","slug":"mvvm-8-%ec%9c%a0%eb%8b%9b-%ed%85%8c%ec%8a%a4%ed%8a%b8%ec%99%80-mvvm-mocking%ec%9d%84-%ed%86%b5%ed%95%9c-dependency-injection-%ea%b8%b0%eb%b0%98%ec%9d%98-%ed%85%8c%ec%8a%a4%ed%8a%b8-%ed%99%98","status":"publish","type":"post","link":"https:\/\/atmokpo.com\/w\/42925\/","title":{"rendered":"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95"},"content":{"rendered":"<article>\n<p>\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc5d0\uc11c \ud14c\uc2a4\ud2b8\ub294 \ud544\uc218 \uc694\uc18c\uc774\uba70, \ud2b9\ud788 MVVM (Model-View-ViewModel) \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\ub294 WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc720\ub2db \ud14c\uc2a4\ud2b8\uc758 \ud544\uc694\uc131\uc774 \ub354\uc6b1 \uac15\uc870\ub429\ub2c8\ub2e4. \ubcf8 \ud3ec\uc2a4\ud2b8\uc5d0\uc11c\ub294 MVVM \ud328\ud134\uc744 \uae30\ubc18\uc73c\ub85c \ud55c WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc720\ub2db \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uacfc Mocking\uc744 \ud1b5\ud55c Dependency Injection(DI) \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc790\uc138\ud788 \uc124\uba85\ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>1. MVVM \uc544\ud0a4\ud14d\ucc98 \uc18c\uac1c<\/h2>\n<p>MVVM \ud328\ud134\uc740 WPF\uc640 \uac19\uc740 \ub370\uc774\ud130 \ubc14\uc778\ub529\uc744 \uc0ac\uc6a9\ud558\ub294 \uae30\uc220\uc5d0 \uc774\uc0c1\uc801\uc778 \uc544\ud0a4\ud14d\ucc98\uc785\ub2c8\ub2e4. \uc774 \ud328\ud134\uc740 \uc138 \uac00\uc9c0 \uc8fc\uc694 \uad6c\uc131 \uc694\uc18c\ub85c \ub098\ub258\uba70, \uac01 \uad6c\uc131 \uc694\uc18c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc5ed\ud560\uc744 \uc218\ud589\ud569\ub2c8\ub2e4.<\/p>\n<ul>\n<li><strong>Model:<\/strong> \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \ub370\uc774\ud130 \uad6c\uc870\ub97c \uc815\uc758\ud558\uace0, \ub370\uc774\ud130\uc640 \uad00\ub828\ub41c \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc744 \ucc98\ub9ac\ud569\ub2c8\ub2e4.<\/li>\n<li><strong>View:<\/strong> \uc0ac\uc6a9\uc790 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud45c\ud604\ud558\uba70, \uc0ac\uc6a9\uc790\uc640 \uc0c1\ud638\uc791\uc6a9\uc744 \ub2f4\ub2f9\ud569\ub2c8\ub2e4.<\/li>\n<li><strong>ViewModel:<\/strong> View\uc640 Model \uac04\uc758 \uc0c1\ud638\uc791\uc6a9\uc744 \uc870\uc815\ud558\uace0, View\uc5d0 \ud544\uc694\ud55c \ub370\uc774\ud130\ub97c \uc81c\uacf5\ud569\ub2c8\ub2e4.<\/li>\n<\/ul>\n<h2>2. \uc720\ub2db \ud14c\uc2a4\ud2b8\uc758 \uc911\uc694\uc131<\/h2>\n<p>\uc720\ub2db \ud14c\uc2a4\ud2b8\ub294 \uac01 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uad6c\uc131 \uc694\uc18c\uac00 \uae30\ub300\ud55c \ub300\ub85c \uc791\ub3d9\ud558\ub294\uc9c0 \ud655\uc778\ud558\uae30 \uc704\ud574 \uac1c\ubcc4\uc801\uc73c\ub85c \uac80\uc99d\ud558\ub294 \ud504\ub85c\uc138\uc2a4\uc785\ub2c8\ub2e4. WPF\uc640 MVVM \uc544\ud0a4\ud14d\ucc98\uc5d0\uc11c\ub294 ViewModel\uc758 \ub3d9\uc791\uc744 \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\uba70, \uc774\ub97c \ud1b5\ud574 UI\uc640 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ubd84\ub9ac\ub97c \uac80\uc99d\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc720\ub2db \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uc5bb\ub294 \uc774\uc810\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4:<\/p>\n<ul>\n<li>\ubc84\uadf8 \uc870\uae30 \ubc1c\uacac<\/li>\n<li>\ucf54\ub4dc \ubcc0\uacbd \uc2dc \uc548\uc815\uc131 \ud655\ubcf4<\/li>\n<li>\uc2e0\ub8b0\ud560 \uc218 \uc788\ub294 \ub9ac\ud329\ud1a0\ub9c1 \uac00\ub2a5<\/li>\n<li>\ubb38\uc11c\ud654\ub41c \ucf54\ub4dc<\/li>\n<\/ul>\n<h2>3. Testing Framework \ubc0f Mocking Library<\/h2>\n<p>\uc720\ub2db \ud14c\uc2a4\ud2b8\ub97c \uc27d\uac8c \uc218\ud589\ud558\uae30 \uc704\ud574 \ub2e4\uc591\ud55c Testing Framework\uacfc Mocking Library\uac00 \uc874\uc7ac\ud569\ub2c8\ub2e4. \ub300\ud45c\uc801\uc73c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \ub3c4\uad6c\ub4e4\uc774 \uc788\uc2b5\ub2c8\ub2e4:<\/p>\n<ul>\n<li><strong>xUnit:<\/strong> \uacbd\ub7c9\ud654\ub41c \uc720\ub2db \ud14c\uc2a4\ud2b8 \ud504\ub808\uc784\uc6cc\ud06c.<\/li>\n<li><strong>NUnit:<\/strong> .NET\uc758 \uac15\ub825\ud55c \uc720\ub2db \ud14c\uc2a4\ud2b8 \ud504\ub808\uc784\uc6cc\ud06c.<\/li>\n<li><strong>Moq:<\/strong> \uac04\ub2e8\ud558\uace0 \uc720\uc5f0\ud55c Mocking Framework.<\/li>\n<\/ul>\n<h2>4. Dependency Injection(DI)\uc758 \uac1c\ub150<\/h2>\n<p>Dependency Injection\uc740 \uac1d\uccb4 \uc9c0\ud5a5 \uc124\uacc4 \uc6d0\uce59 \uc911 \ud558\ub098\ub85c, \ud074\ub798\uc2a4\uac00 \ud544\uc694\ud55c \uc758\uc874\uc131\uc744 \uc678\ubd80\uc5d0\uc11c \uc8fc\uc785\ubc1b\ub3c4\ub85d \ud558\uc5ec \uc758\uc874\uc131\uc744 \uc904\uc774\uace0, \ucf54\ub4dc\uc758 \ud14c\uc2a4\ud2b8 \uc6a9\uc774\uc131\uc744 \ub192\uc785\ub2c8\ub2e4. MVVM \uc544\ud0a4\ud14d\ucc98\uc5d0\uc11c DI\ub294 \uc8fc\ub85c ViewModel\uc758 \uc758\uc874\uc131\uc744 \uad00\ub9ac\ud558\ub294 \ub370 \uc0ac\uc6a9\ub429\ub2c8\ub2e4.<\/p>\n<h3>4.1. DI \ucee8\ud14c\uc774\ub108<\/h3>\n<p>DI\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 DI \ucee8\ud14c\uc774\ub108\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc73c\uba70, \ub300\ud45c\uc801\uc73c\ub85c <code>Microsoft.Extensions.DependencyInjection<\/code>\uc640 <code>Autofac<\/code>\uac00 \uc788\uc2b5\ub2c8\ub2e4. DI \ucee8\ud14c\uc774\ub108\ub294 \uac1d\uccb4\uc758 \uc0dd\uba85\uc8fc\uae30\ub97c \uad00\ub9ac\ud558\uace0, \ud544\uc694\uc5d0 \ub530\ub77c \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ud558\ub294 \uc5ed\ud560\uc744 \ud569\ub2c8\ub2e4.<\/p>\n<h2>5. MVVM\uc744 \ud65c\uc6a9\ud55c \uc720\ub2db \ud14c\uc2a4\ud2b8 \uc0ac\ub840<\/h2>\n<p>\uc774\uc81c \uc2e4\uc81c MVVM \uad6c\uc870\uc758 WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc608\uc2dc\ub85c \ub4e4\uc5b4 \uc720\ub2db \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\ubcf4\uaca0\uc2b5\ub2c8\ub2e4. \uac04\ub2e8\ud55c Todo List \uc5b4\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc608\ub85c \ub4e4\uc5b4\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h3>5.1. Model \uc815\uc758<\/h3>\n<pre><code>public class Todo\n{\n    public string Title { get; set; }\n    public bool IsCompleted { get; set; }\n}\n<\/code><\/pre>\n<h3>5.2. ViewModel \uc815\uc758<\/h3>\n<pre><code>public class TodoViewModel : INotifyPropertyChanged\n{\n    private ObservableCollection<todo> _todos;\n    public ObservableCollection<todo> Todos\n    {\n        get { return _todos; }\n        set\n        {\n            _todos = value;\n            OnPropertyChanged(nameof(Todos));\n        }\n    }\n\n    public TodoViewModel()\n    {\n        Todos = new ObservableCollection<todo>();\n    }\n\n    public void AddTodo(string title)\n    {\n        Todos.Add(new Todo { Title = title, IsCompleted = false });\n    }\n\n    public event PropertyChangedEventHandler PropertyChanged;\n\n    protected void OnPropertyChanged(string propertyName)\n    {\n        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n    }\n}\n<\/todo><\/todo><\/todo><\/code><\/pre>\n<h3>5.3. \uc720\ub2db \ud14c\uc2a4\ud2b8 \ud074\ub798\uc2a4 \uc815\uc758<\/h3>\n<pre><code>public class TodoViewModelTests\n{\n    [Fact]\n    public void AddTodo_ShouldAddTodoToCollection()\n    {\n        \/\/ Arrange\n        var viewModel = new TodoViewModel();\n        string todoTitle = \"Test Todo\";\n\n        \/\/ Act\n        viewModel.AddTodo(todoTitle);\n\n        \/\/ Assert\n        Assert.Single(viewModel.Todos);\n        Assert.Equal(todoTitle, viewModel.Todos.First().Title);\n    }\n}\n<\/code><\/pre>\n<h2>6. Mocking\uc744 \ud1b5\ud55c \ud14c\uc2a4\ud2b8<\/h2>\n<p>Mocking\uc744 \uc0ac\uc6a9\ud558\uba74 \uc678\ubd80 \uc758\uc874\uc131\uc774 \uc788\ub294 \uac1d\uccb4\ub97c \ub300\uccb4\ud558\uc5ec \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc608\ub97c \ub4e4\uc5b4, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc5f0\uacb0\uc774\ub098 \uc678\ubd80 API \ud638\ucd9c \ub4f1\uc744 Mock\uc73c\ub85c \ub300\uccb4\ud558\uc5ec \ud14c\uc2a4\ud2b8 \ud658\uacbd\uc744 \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<h3>6.1. Repository Pattern\uacfc Mocking<\/h3>\n<p>Todo List \uc571\uc5d0\uc11c Repository Pattern\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ub97c \uad00\ub9ac\ud55c\ub2e4\uace0 \uac00\uc815\ud574\ubcf4\uaca0\uc2b5\ub2c8\ub2e4. Todo \ub370\uc774\ud130\ub97c \uad00\ub9ac\ud558\ub294 <code>ITodoRepository<\/code> \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code>public interface ITodoRepository\n{\n    void Add(Todo todo);\n    IEnumerable<todo> GetAll();\n}\n<\/todo><\/code><\/pre>\n<h3>6.2. ViewModel\uc744 Mocking\ud560 \uacbd\uc6b0<\/h3>\n<pre><code>public class TodoViewModelWithMockedRepo\n{\n    private readonly ITodoRepository _todoRepository;\n    private ObservableCollection<todo> _todos;\n\n    public ObservableCollection<todo> Todos\n    {\n        get { return _todos; }\n        private set\n        {\n            _todos = value;\n            OnPropertyChanged(nameof(Todos));\n        }\n    }\n\n    public TodoViewModelWithMockedRepo(ITodoRepository todoRepository)\n    {\n        _todoRepository = todoRepository;\n        Todos = new ObservableCollection<todo>(_todoRepository.GetAll());\n    }\n\n    public void AddTodo(string title)\n    {\n        var todo = new Todo { Title = title, IsCompleted = false };\n        _todoRepository.Add(todo);\n        Todos.Add(todo);\n    }\n}\n<\/todo><\/todo><\/todo><\/code><\/pre>\n<h3>6.3. Mocking\uc744 \uc774\uc6a9\ud55c \uc720\ub2db \ud14c\uc2a4\ud2b8<\/h3>\n<pre><code>public class TodoViewModelWithRepoTests\n{\n    [Fact]\n    public void AddTodo_ShouldCallAddOnRepo()\n    {\n        \/\/ Arrange\n        var mockRepo = new Mock<itodorepository>();\n        var viewModel = new TodoViewModelWithMockedRepo(mockRepo.Object);\n        string todoTitle = \"Mocked Todo\";\n\n        \/\/ Act\n        viewModel.AddTodo(todoTitle);\n\n        \/\/ Assert\n        mockRepo.Verify(repo =&gt; repo.Add(It.IsAny<todo>()), Times.Once);\n    }\n}\n<\/todo><\/itodorepository><\/code><\/pre>\n<h2>7. \uacb0\ub860<\/h2>\n<p>\uc5ec\uae30\uae4c\uc9c0 WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c MVVM \ud328\ud134\uc744 \ud65c\uc6a9\ud55c \uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uc558\uc2b5\ub2c8\ub2e4. \uc774\ub7ec\ud55c \ud328\ud134\uacfc \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uba74 \ucf54\ub4dc\uc758 \uc720\uc9c0 \uad00\ub9ac\uc131\uacfc \ud14c\uc2a4\ud2b8 \uc6a9\uc774\uc131\uc744 \uadf9\ub300\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ud2b9\ud788, WPF\uac00 \uc81c\uacf5\ud558\ub294 \ub370\uc774\ud130 \ubc14\uc778\ub529 \uae30\ub2a5\uacfc \uacb0\ud569\ud558\uc5ec MVVM \uad6c\uc870\ub97c \ud1b5\ud574 \uace0\ud488\uc9c8\uc758 \uc18c\ud504\ud2b8\uc6e8\uc5b4\ub97c \uac1c\ubc1c\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>8. \ucc38\uace0 \uc790\ub8cc<\/h2>\n<ul>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/testing\/unit-testing-with-dotnet-test\">Microsoft Docs &#8211; unit testing with dotnet test<\/a><\/li>\n<li><a href=\"https:\/\/xunit.net\/\">xUnit.net<\/a><\/li>\n<li><a href=\"https:\/\/nunit.org\/\">NUnit<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/moq\/moq4\">Moq GitHub Repository<\/a><\/li>\n<\/ul>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc5d0\uc11c \ud14c\uc2a4\ud2b8\ub294 \ud544\uc218 \uc694\uc18c\uc774\uba70, \ud2b9\ud788 MVVM (Model-View-ViewModel) \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\ub294 WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc720\ub2db \ud14c\uc2a4\ud2b8\uc758 \ud544\uc694\uc131\uc774 \ub354\uc6b1 \uac15\uc870\ub429\ub2c8\ub2e4. \ubcf8 \ud3ec\uc2a4\ud2b8\uc5d0\uc11c\ub294 MVVM \ud328\ud134\uc744 \uae30\ubc18\uc73c\ub85c \ud55c WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc720\ub2db \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uacfc Mocking\uc744 \ud1b5\ud55c Dependency Injection(DI) \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc790\uc138\ud788 \uc124\uba85\ud558\uaca0\uc2b5\ub2c8\ub2e4. 1. MVVM \uc544\ud0a4\ud14d\ucc98 \uc18c\uac1c MVVM \ud328\ud134\uc740 WPF\uc640 \uac19\uc740 \ub370\uc774\ud130 \ubc14\uc778\ub529\uc744 \uc0ac\uc6a9\ud558\ub294 \uae30\uc220\uc5d0 \uc774\uc0c1\uc801\uc778 \uc544\ud0a4\ud14d\ucc98\uc785\ub2c8\ub2e4. &hellip; <a href=\"https:\/\/atmokpo.com\/w\/42925\/\" class=\"more-link\">\ub354 \ubcf4\uae30<span class=\"screen-reader-text\"> &#8220;[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[39],"tags":[],"class_list":["post-42925","post","type-post","status-publish","format-standard","hentry","category-wpf-"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95 - \ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/atmokpo.com\/w\/42925\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95 - \ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8\" \/>\n<meta property=\"og:description\" content=\"\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc5d0\uc11c \ud14c\uc2a4\ud2b8\ub294 \ud544\uc218 \uc694\uc18c\uc774\uba70, \ud2b9\ud788 MVVM (Model-View-ViewModel) \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\ub294 WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc720\ub2db \ud14c\uc2a4\ud2b8\uc758 \ud544\uc694\uc131\uc774 \ub354\uc6b1 \uac15\uc870\ub429\ub2c8\ub2e4. \ubcf8 \ud3ec\uc2a4\ud2b8\uc5d0\uc11c\ub294 MVVM \ud328\ud134\uc744 \uae30\ubc18\uc73c\ub85c \ud55c WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc720\ub2db \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uacfc Mocking\uc744 \ud1b5\ud55c Dependency Injection(DI) \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc790\uc138\ud788 \uc124\uba85\ud558\uaca0\uc2b5\ub2c8\ub2e4. 1. MVVM \uc544\ud0a4\ud14d\ucc98 \uc18c\uac1c MVVM \ud328\ud134\uc740 WPF\uc640 \uac19\uc740 \ub370\uc774\ud130 \ubc14\uc778\ub529\uc744 \uc0ac\uc6a9\ud558\ub294 \uae30\uc220\uc5d0 \uc774\uc0c1\uc801\uc778 \uc544\ud0a4\ud14d\ucc98\uc785\ub2c8\ub2e4. &hellip; \ub354 \ubcf4\uae30 &quot;[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95&quot;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/atmokpo.com\/w\/42925\/\" \/>\n<meta property=\"og:site_name\" content=\"\ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8\" \/>\n<meta property=\"article:published_time\" content=\"2024-11-13T22:28:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-11-26T06:34:25+00:00\" \/>\n<meta name=\"author\" content=\"root\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@bebubo4\" \/>\n<meta name=\"twitter:site\" content=\"@bebubo4\" \/>\n<meta name=\"twitter:label1\" content=\"\uae00\uc4f4\uc774\" \/>\n\t<meta name=\"twitter:data1\" content=\"root\" \/>\n\t<meta name=\"twitter:label2\" content=\"\uc608\uc0c1 \ub418\ub294 \ud310\ub3c5 \uc2dc\uac04\" \/>\n\t<meta name=\"twitter:data2\" content=\"1\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/atmokpo.com\/w\/42925\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/atmokpo.com\/w\/42925\/\"},\"author\":{\"name\":\"root\",\"@id\":\"https:\/\/atmokpo.com\/w\/#\/schema\/person\/91b6b3b138fbba0efb4ae64b1abd81d7\"},\"headline\":\"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95\",\"datePublished\":\"2024-11-13T22:28:15+00:00\",\"dateModified\":\"2024-11-26T06:34:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/atmokpo.com\/w\/42925\/\"},\"wordCount\":96,\"publisher\":{\"@id\":\"https:\/\/atmokpo.com\/w\/#organization\"},\"articleSection\":[\"WPF \uac1c\ubc1c\"],\"inLanguage\":\"ko-KR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/atmokpo.com\/w\/42925\/\",\"url\":\"https:\/\/atmokpo.com\/w\/42925\/\",\"name\":\"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95 - \ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8\",\"isPartOf\":{\"@id\":\"https:\/\/atmokpo.com\/w\/#website\"},\"datePublished\":\"2024-11-13T22:28:15+00:00\",\"dateModified\":\"2024-11-26T06:34:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/atmokpo.com\/w\/42925\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/atmokpo.com\/w\/42925\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/atmokpo.com\/w\/42925\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\ud648\",\"item\":\"https:\/\/atmokpo.com\/w\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/atmokpo.com\/w\/#website\",\"url\":\"https:\/\/atmokpo.com\/w\/\",\"name\":\"\ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/atmokpo.com\/w\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/atmokpo.com\/w\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/atmokpo.com\/w\/#organization\",\"name\":\"\ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8\",\"url\":\"https:\/\/atmokpo.com\/w\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/atmokpo.com\/w\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/atmokpo.com\/w\/wp-content\/uploads\/2024\/11\/logo.png\",\"contentUrl\":\"https:\/\/atmokpo.com\/w\/wp-content\/uploads\/2024\/11\/logo.png\",\"width\":400,\"height\":400,\"caption\":\"\ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8\"},\"image\":{\"@id\":\"https:\/\/atmokpo.com\/w\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/bebubo4\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/atmokpo.com\/w\/#\/schema\/person\/91b6b3b138fbba0efb4ae64b1abd81d7\",\"name\":\"root\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/atmokpo.com\/w\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/708197b41fc6435a7ce22d951b25d4a47e9e904270cb1f04682d4f025066f80c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/708197b41fc6435a7ce22d951b25d4a47e9e904270cb1f04682d4f025066f80c?s=96&d=mm&r=g\",\"caption\":\"root\"},\"sameAs\":[\"http:\/\/atmokpo.com\/w\"],\"url\":\"https:\/\/atmokpo.com\/w\/author\/root\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95 - \ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/atmokpo.com\/w\/42925\/","og_locale":"ko_KR","og_type":"article","og_title":"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95 - \ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8","og_description":"\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc5d0\uc11c \ud14c\uc2a4\ud2b8\ub294 \ud544\uc218 \uc694\uc18c\uc774\uba70, \ud2b9\ud788 MVVM (Model-View-ViewModel) \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\ub294 WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc720\ub2db \ud14c\uc2a4\ud2b8\uc758 \ud544\uc694\uc131\uc774 \ub354\uc6b1 \uac15\uc870\ub429\ub2c8\ub2e4. \ubcf8 \ud3ec\uc2a4\ud2b8\uc5d0\uc11c\ub294 MVVM \ud328\ud134\uc744 \uae30\ubc18\uc73c\ub85c \ud55c WPF \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc720\ub2db \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uacfc Mocking\uc744 \ud1b5\ud55c Dependency Injection(DI) \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd\uc744 \uad6c\ucd95\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc790\uc138\ud788 \uc124\uba85\ud558\uaca0\uc2b5\ub2c8\ub2e4. 1. MVVM \uc544\ud0a4\ud14d\ucc98 \uc18c\uac1c MVVM \ud328\ud134\uc740 WPF\uc640 \uac19\uc740 \ub370\uc774\ud130 \ubc14\uc778\ub529\uc744 \uc0ac\uc6a9\ud558\ub294 \uae30\uc220\uc5d0 \uc774\uc0c1\uc801\uc778 \uc544\ud0a4\ud14d\ucc98\uc785\ub2c8\ub2e4. &hellip; \ub354 \ubcf4\uae30 \"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95\"","og_url":"https:\/\/atmokpo.com\/w\/42925\/","og_site_name":"\ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8","article_published_time":"2024-11-13T22:28:15+00:00","article_modified_time":"2024-11-26T06:34:25+00:00","author":"root","twitter_card":"summary_large_image","twitter_creator":"@bebubo4","twitter_site":"@bebubo4","twitter_misc":{"\uae00\uc4f4\uc774":"root","\uc608\uc0c1 \ub418\ub294 \ud310\ub3c5 \uc2dc\uac04":"1\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/atmokpo.com\/w\/42925\/#article","isPartOf":{"@id":"https:\/\/atmokpo.com\/w\/42925\/"},"author":{"name":"root","@id":"https:\/\/atmokpo.com\/w\/#\/schema\/person\/91b6b3b138fbba0efb4ae64b1abd81d7"},"headline":"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95","datePublished":"2024-11-13T22:28:15+00:00","dateModified":"2024-11-26T06:34:25+00:00","mainEntityOfPage":{"@id":"https:\/\/atmokpo.com\/w\/42925\/"},"wordCount":96,"publisher":{"@id":"https:\/\/atmokpo.com\/w\/#organization"},"articleSection":["WPF \uac1c\ubc1c"],"inLanguage":"ko-KR"},{"@type":"WebPage","@id":"https:\/\/atmokpo.com\/w\/42925\/","url":"https:\/\/atmokpo.com\/w\/42925\/","name":"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95 - \ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8","isPartOf":{"@id":"https:\/\/atmokpo.com\/w\/#website"},"datePublished":"2024-11-13T22:28:15+00:00","dateModified":"2024-11-26T06:34:25+00:00","breadcrumb":{"@id":"https:\/\/atmokpo.com\/w\/42925\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/atmokpo.com\/w\/42925\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/atmokpo.com\/w\/42925\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\ud648","item":"https:\/\/atmokpo.com\/w\/en\/"},{"@type":"ListItem","position":2,"name":"[MVVM] 8.\uc720\ub2db \ud14c\uc2a4\ud2b8\uc640 MVVM, Mocking\uc744 \ud1b5\ud55c Dependency Injection \uae30\ubc18\uc758 \ud14c\uc2a4\ud2b8 \ud658\uacbd \uad6c\ucd95"}]},{"@type":"WebSite","@id":"https:\/\/atmokpo.com\/w\/#website","url":"https:\/\/atmokpo.com\/w\/","name":"\ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8","description":"","publisher":{"@id":"https:\/\/atmokpo.com\/w\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/atmokpo.com\/w\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/atmokpo.com\/w\/#organization","name":"\ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8","url":"https:\/\/atmokpo.com\/w\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/atmokpo.com\/w\/#\/schema\/logo\/image\/","url":"https:\/\/atmokpo.com\/w\/wp-content\/uploads\/2024\/11\/logo.png","contentUrl":"https:\/\/atmokpo.com\/w\/wp-content\/uploads\/2024\/11\/logo.png","width":400,"height":400,"caption":"\ub77c\uc774\ube0c\uc2a4\ub9c8\ud2b8"},"image":{"@id":"https:\/\/atmokpo.com\/w\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/bebubo4"]},{"@type":"Person","@id":"https:\/\/atmokpo.com\/w\/#\/schema\/person\/91b6b3b138fbba0efb4ae64b1abd81d7","name":"root","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/atmokpo.com\/w\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/708197b41fc6435a7ce22d951b25d4a47e9e904270cb1f04682d4f025066f80c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/708197b41fc6435a7ce22d951b25d4a47e9e904270cb1f04682d4f025066f80c?s=96&d=mm&r=g","caption":"root"},"sameAs":["http:\/\/atmokpo.com\/w"],"url":"https:\/\/atmokpo.com\/w\/author\/root\/"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/posts\/42925","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/comments?post=42925"}],"version-history":[{"count":1,"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/posts\/42925\/revisions"}],"predecessor-version":[{"id":42926,"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/posts\/42925\/revisions\/42926"}],"wp:attachment":[{"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/media?parent=42925"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/categories?post=42925"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/atmokpo.com\/w\/wp-json\/wp\/v2\/tags?post=42925"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}