연습: WPF 애플리케이션에서 애플리케이션 데이터 캐싱

캐싱을 사용하면 빠른 액세스를 위해 데이터를 메모리에 저장할 수 있습니다. 데이터에 다시 액세스할 때 애플리케이션은 원래 소스에서 검색하는 대신 캐시에서 데이터를 가져올 수 있습니다. 이 경우 성능과 확장성이 향상됩니다. 또한 캐싱을 사용하면 데이터 소스를 일시적으로 사용할 수 없는 경우에도 데이터를 사용할 수 있습니다.

.NET Framework는 .NET Framework 애플리케이션에서 캐싱을 사용할 수 있도록 하는 클래스를 제공합니다. 이러한 클래스는 System.Runtime.Caching 네임스페이스에 있습니다.

참고

System.Runtime.Caching 네임스페이스는 .NET Framework 4의 새로운 기능입니다. 이 네임스페이스는 모든 .NET Framework 애플리케이션에서 캐싱을 사용할 수 있도록 합니다. 이전 버전의 .NET Framework에서는 캐싱을 System.Web 네임스페이스에서만 사용할 수 있었기 때문에 ASP.NET 클래스에 대한 종속성이 필요했습니다.

이 연습에서는 WPF(Windows Presentation Foundation) 애플리케이션의 일부로 .NET Framework에서 사용할 수 있는 캐싱 기능을 사용하는 방법을 보여 줍니다. 연습에서는 텍스트 파일의 내용을 캐시합니다.

이 연습에서 수행할 작업은 다음과 같습니다.

  • WPF 애플리케이션 프로젝트 만들기.

  • .NET Framework 4에 대한 참조 추가.

  • 캐시 초기화.

  • 텍스트 파일의 내용이 포함된 캐시 항목 추가.

  • 캐시 항목에 대한 제거 정책을 제공합니다.

  • 캐시된 파일의 경로를 모니터링하고 모니터링되는 항목의 변경 내용을 캐시 인스턴스에 알립니다.

사전 요구 사항

이 연습을 완료하려면 다음 사항이 필요합니다.

  • Visual Studio 2010

  • 적은 양의 텍스트가 포함된 텍스트 파일입니다. (메시지 상자에 텍스트 파일의 내용을 표시합니다.) 연습에 설명된 코드는 다음 파일로 작업한다고 가정합니다.

    c:\cache\cacheText.txt

    그러나 이 연습에서는 텍스트 파일을 사용하고 코드를 약간 변경할 수 있습니다.

WPF 애플리케이션 프로젝트 만들기

먼저 WPF 애플리케이션 프로젝트를 만듭니다.

WPF 애플리케이션을 만들려면

  1. Visual Studio를 시작합니다.

  2. 파일 메뉴에서 새로 만들기를 클릭한 다음, 새 프로젝트를 클릭합니다.

    새 프로젝트 대화 상자가 표시됩니다.

  3. 설치된 템플릿에서 사용하려는 프로그래밍 언어(Visual Basic 또는 Visual C#)를 선택합니다.

  4. 새 프로젝트 대화 상자에서 WPF 애플리케이션을 선택합니다.

    참고

    WPF 애플리케이션 템플릿이 표시되지 않으면 WPF를 지원하는 .NET Framework 버전을 대상으로 지정해야 합니다. 새 프로젝트 대화 상자의 목록에서 .NET Framework 4를 선택합니다.

  5. 이름 텍스트 상자에 프로젝트 이름을 입력합니다. 예를 들어 WPFCaching을 입력할 수 있습니다.

  6. 솔루션용 디렉터리 만들기 확인란을 선택합니다.

  7. 확인을 클릭합니다.

    WPF 디자이너가 디자인 보기에서 열리고 MainWindow.xaml 파일이 표시됩니다. Visual Studio는 내 프로젝트 폴더, Application.xaml 파일 및 MainWindow.xaml 파일을 만듭니다.

.NET Framework 대상 지정 및 캐싱 어셈블리에 대한 참조 추가

기본적으로 WPF 애플리케이션은 .NET Framework 4 클라이언트 프로필을 대상으로 합니다. WPF 애플리케이션에서 System.Runtime.Caching 네임스페이스를 사용하려면 애플리케이션이 .NET Framework 4(.NET Framework 4 클라이언트 프로필이 아님)를 대상으로 지정해야 하며 네임스페이스에 대한 참조를 포함해야 합니다.

따라서 다음 단계는 .NET Framework 대상을 변경하고 System.Runtime.Caching 네임스페이스에 대한 참조를 추가하는 것입니다.

참고

.NET Framework 대상을 변경하는 절차는 Visual Basic 프로젝트와 Visual C# 프로젝트에서 다릅니다.

Visual Basic에서 대상 .NET Framework를 변경하려면 다음을 수행합니다.

  1. 솔루션 탐색기에서 프로젝트 이름을 마우스 오른쪽 단추로 클릭한 다음, 속성을 클릭합니다.

    애플리케이션의 속성 창이 표시됩니다.

  2. 컴파일 탭을 클릭합니다.

  3. 창의 맨 아래에서 고급 컴파일 옵션...을 클릭합니다.

    고급 컴파일러 설정 대화 상자가 표시됩니다.

  4. 대상 프레임워크(모든 구성) 목록에서 .NET Framework 4를 선택합니다. (.NET Framework 4 클라이언트 프로필을 선택하지 마세요.)

  5. 확인을 클릭합니다.

    대상 프레임워크 변경 대화 상자가 표시됩니다.

  6. 대상 프레임워크 변경 대화 상자에서 를 클릭합니다.

    프로젝트가 닫혔다가 다시 열립니다.

  7. 다음 단계에 따라 캐싱 어셈블리에 대한 참조를 추가합니다.

    1. 솔루션 탐색기에서 프로젝트 이름을 마우스 오른쪽 단추로 클릭한 다음, 참조 추가를 클릭합니다.

    2. .NET 탭을 선택하고 System.Runtime.Caching을 선택한 다음, 확인을 클릭합니다.

Visual C# 프로젝트에서 대상 .NET Framework를 변경하려면 다음을 수행합니다.

  1. 솔루션 탐색기에서 프로젝트 이름을 마우스 오른쪽 단추로 클릭한 다음, 속성을 클릭합니다.

    애플리케이션의 속성 창이 표시됩니다.

  2. 애플리케이션 탭을 클릭합니다.

  3. 대상 프레임워크 목록에서 .NET Framework 4를 선택합니다. (.NET Framework 4 클라이언트 프로필을 선택하지 마세요.)

  4. 다음 단계에 따라 캐싱 어셈블리에 대한 참조를 추가합니다.

    1. 참조 폴더를 마우스 오른쪽 단추로 클릭한 다음, 참조 추가를 클릭합니다.

    2. .NET 탭을 선택하고 System.Runtime.Caching을 선택한 다음, 확인을 클릭합니다.

WPF 창에 단추 추가

다음으로, 단추 컨트롤을 추가하고 단추의 Click 이벤트에 대한 이벤트 처리기를 만듭니다. 나중에 단추를 클릭하면 텍스트 파일의 내용이 캐시되고 표시되도록 코드를 추가합니다.

단추 컨트롤을 추가하려면 다음을 수행합니다.

  1. 솔루션 탐색기에서 MainWindow.xaml 파일을 두 번 클릭하여 엽니다.

  2. 도구 상자공통 WPF 컨트롤 아래에서 Button 컨트롤을 MainWindow 창으로 끕니다.

  3. 속성 창에서 Button 컨트롤의 Content 속성을 캐시 가져오기로 설정합니다.

캐시 초기화 및 항목 캐싱

다음으로, 다음 작업을 수행하는 코드를 추가합니다.

  • 캐시 클래스의 인스턴스를 만듭니다. 즉, 새 MemoryCache 개체를 인스턴스화합니다.

  • 캐시에서 HostFileChangeMonitor 개체를 사용하여 텍스트 파일의 변경 내용을 모니터링하도록 지정합니다.

  • 텍스트 파일을 읽고 해당 콘텐츠를 캐시 항목으로 캐시합니다.

  • 캐시된 텍스트 파일의 내용을 표시합니다.

캐시 개체를 만들려면 다음을 수행합니다.

  1. MainWindow.xaml.cs 또는 MainWindow.Xaml.vb 파일에 이벤트 처리기를 만들려면 방금 추가한 단추를 두 번 클릭합니다.

  2. 파일 맨 위에(클래스 선언 전) 다음 Imports(Visual Basic) 또는 using(C#) 문을 추가합니다.

    using System.Runtime.Caching;
    using System.IO;
    
    Imports System.Runtime.Caching
    Imports System.IO
    
  3. 이벤트 처리기에서 다음 코드를 추가하여 캐시 개체를 인스턴스화합니다.

    ObjectCache cache = MemoryCache.Default;
    
    Dim cache As ObjectCache = MemoryCache.Default
    

    ObjectCache 클래스는 메모리 내 개체 캐시를 제공하는 기본 제공 클래스입니다.

  4. 다음 코드를 추가하여 filecontents라는 캐시 항목의 내용을 읽습니다.

    Dim fileContents As String = TryCast(cache("filecontents"), String)
    
    string fileContents = cache["filecontents"] as string;
    
  5. 다음 코드를 추가하여 filecontents라는 캐시 항목이 있는지 확인합니다.

    If fileContents Is Nothing Then
    
    End If
    
    if (fileContents == null)
    {
    
    }
    

    지정된 캐시 항목이 없는 경우 텍스트 파일을 읽고 캐시에 캐시 항목으로 추가해야 합니다.

  6. if/then 블록에서 다음 코드를 추가하여 캐시 항목이 10초 후에 만료되도록 지정하는 새 CacheItemPolicy 개체를 만듭니다.

    Dim policy As New CacheItemPolicy()
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0)
    
    CacheItemPolicy policy = new CacheItemPolicy();
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0);
    

    제거 또는 만료 정보가 제공되지 않는 경우 기본값은 InfiniteAbsoluteExpiration입니다. 즉, 절대 시간에만 기반하여 캐시 항목이 만료되지 않습니다. 대신 메모리 압력이 있을 때만 캐시 항목이 만료됩니다. 항상 절대 또는 슬라이딩 만료를 명시적으로 지정하는 것이 좋습니다.

  7. if/then 블록 내부와 이전 단계에서 추가한 코드에 따라 다음 코드를 추가하여 모니터링하려는 파일 경로에 대한 컬렉션을 만들고 텍스트 파일의 경로를 컬렉션에 추가합니다.

    Dim filePaths As New List(Of String)()
    filePaths.Add("c:\cache\cacheText.txt")
    
    List<string> filePaths = new List<string>();
    filePaths.Add("c:\\cache\\cacheText.txt");
    

    참고

    사용하려는 텍스트 파일이 c:\cache\cacheText.txt가 아닌 경우 사용할 텍스트 파일의 경로를 지정합니다.

  8. 이전 단계에서 추가한 코드에 따라 다음 코드를 추가하여 캐시 항목에 대한 변경 모니터 컬렉션에 새 HostFileChangeMonitor 개체를 추가합니다.

    policy.ChangeMonitors.Add(New HostFileChangeMonitor(filePaths))
    
    policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));
    

    HostFileChangeMonitor 개체는 텍스트 파일의 경로를 모니터링하고 변경이 발생하는 경우 캐시에 알립니다. 이 예제에서는 파일 내용이 변경되면 캐시 항목이 만료됩니다.

  9. 이전 단계에서 추가한 코드에 따라 다음 코드를 추가하여 텍스트 파일의 내용을 읽습니다.

    fileContents = File.ReadAllText("c:\cache\cacheText.txt") & vbCrLf & DateTime.Now.ToString()
    
    fileContents = File.ReadAllText("c:\\cache\\cacheText.txt") + "\n" + DateTime.Now;
    

    캐시 항목이 만료되는 시기를 확인할 수 있도록 날짜 및 시간 타임스탬프가 추가됩니다.

  10. 이전 단계에서 추가한 코드에 따라 다음 코드를 추가하여 파일 내용을 캐시 개체에 CacheItem 인스턴스로 삽입합니다.

    cache.Set("filecontents", fileContents, policy)
    
    cache.Set("filecontents", fileContents, policy);
    

    이전에 만든 CacheItemPolicy 개체를 매개 변수로 전달하여 캐시 항목을 제거하는 방법에 대한 정보를 지정합니다.

  11. if/then 블록 뒤에 다음 코드를 추가하여 메시지 상자에 캐시된 파일 콘텐츠를 표시합니다.

    MessageBox.Show(fileContents)
    
    MessageBox.Show(fileContents);
    
  12. 빌드 메뉴에서 WPFCaching 빌드를 클릭하여 프로젝트를 빌드합니다.

WPF 애플리케이션에서 캐싱 테스트

이제 응용 프로그램을 테스트할 수 있습니다.

WPF 애플리케이션에서 캐싱을 테스트하려면 다음을 수행합니다.

  1. Ctrl+F5를 눌러 애플리케이션을 실행합니다.

    MainWindow 창이 표시됩니다.

  2. 캐시 가져오기를 클릭합니다.

    텍스트 파일에서 캐시된 콘텐츠가 메시지 상자에 표시됩니다. 파일의 타임스탬프를 확인합니다.

  3. 메시지 상자를 닫은 다음, 캐시 가져오기를 다시 클릭합니다.

    타임스탬프는 변경되지 않습니다. 캐시된 콘텐츠가 표시됨을 나타냅니다.

  4. 10초 이상 기다린 다음, 캐시 가져오기를 다시 클릭합니다.

    이번에는 새 타임스탬프가 표시됩니다. 이는 정책에서 캐시 항목이 만료되도록 하고 캐시된 새 콘텐츠가 표시됨을 나타냅니다.

  5. 텍스트 편집기에서 만든 텍스트 파일을 엽니다. 아직 변경하지 마세요.

  6. 메시지 상자를 닫은 다음, 캐시 가져오기를 다시 클릭합니다.

    타임스탬프를 다시 확인합니다.

  7. 텍스트 파일을 변경한 다음, 파일을 저장합니다.

  8. 메시지 상자를 닫은 다음, 캐시 가져오기를 다시 클릭합니다.

    이 메시지 상자에는 텍스트 파일의 업데이트된 콘텐츠와 새 타임스탬프가 포함되어 있습니다. 이는 절대 시간 제한 기간이 만료되지 않았음에도 불구하고 파일을 변경할 때 호스트 파일 변경 모니터가 캐시 항목을 즉시 제거했음을 나타냅니다.

    참고

    제거 시간을 20초 이상으로 늘려 파일을 변경하는 데 더 많은 시간을 할애할 수 있습니다.

코드 예

이 연습을 완료하면 만든 프로젝트의 코드가 다음 예제와 유사합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.Runtime.Caching;
using System.IO;

namespace WPFCaching
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {

            ObjectCache cache = MemoryCache.Default;
            string fileContents = cache["filecontents"] as string;

            if (fileContents == null)
            {
                CacheItemPolicy policy = new CacheItemPolicy();
                policy.AbsoluteExpiration =
                    DateTimeOffset.Now.AddSeconds(10.0);

                List<string> filePaths = new List<string>();
                filePaths.Add("c:\\cache\\cacheText.txt");

                policy.ChangeMonitors.Add(new
                    HostFileChangeMonitor(filePaths));

                // Fetch the file contents.
                fileContents = File.ReadAllText("c:\\cache\\cacheText.txt") + "\n" + DateTime.Now.ToString();

                cache.Set("filecontents", fileContents, policy);
            }
            MessageBox.Show(fileContents);
        }
    }
}
Imports System.Runtime.Caching
Imports System.IO

Class MainWindow

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Dim cache As ObjectCache = MemoryCache.Default
        Dim fileContents As String = TryCast(cache("filecontents"), _
            String)

        If fileContents Is Nothing Then
            Dim policy As New CacheItemPolicy()
            policy.AbsoluteExpiration = _
                DateTimeOffset.Now.AddSeconds(10.0)
            Dim filePaths As New List(Of String)()
            filePaths.Add("c:\cache\cacheText.txt")
            policy.ChangeMonitors.Add(New  _
                HostFileChangeMonitor(filePaths))

            ' Fetch the file contents.
            fileContents = File.ReadAllText("c:\cache\cacheText.txt") & vbCrLf & DateTime.Now.ToString()
            cache.Set("filecontents", fileContents, policy)
        End If
        MessageBox.Show(fileContents)
    End Sub
End Class

참고 항목