Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

C#으로 Azure Redis Cache 마스터하기: 단계별 실전 가이드

소개

Azure Redis Cache는 오픈 소스 인메모리 Redis 캐시를 기반으로 하는 서비스로, 웹 앱이 백엔드 데이터 원본의 데이터를 캐시에 담아두고 캐시에서 웹 페이지를 빠르게 제공함으로써 애플리케이션 성능을 크게 향상시킬 수 있습니다. 이번 단계별 튜토리얼에서는 웹 애플리케이션에서 Azure Redis Cache를 활용하는 방법을 자세히 알아보겠습니다.

Azure Redis Cache란 무엇인가?

현대의 애플리케이션은 대부분 방대한 양의 데이터를 처리합니다. 데이터베이스에서 데이터를 조회할 때는 일반적으로 해당 테이블을 찾아 결과를 가져온 뒤 사용자에게 반환하는 과정을 거치는데, 요청이 몰리면 성능이 눈에 띄게 저하됩니다. 이러한 문제를 해결하려면 자주 변경되지 않는 데이터를 캐시에 저장해 두고 불필요한 데이터베이스 요청을 줄이는 것이 효과적입니다.

Redis Cache는 Key-Value 형식으로 데이터를 캐시 메모리에 저장하고 조회하여 애플리케이션 성능을 높이는 데 활용되는 오픈 소스 인메모리 데이터베이스입니다. Azure Redis Cache는 뛰어난 보안성, 낮은 지연 시간, 높은 처리량을 제공하는 기능이 풍부한 관리형 서비스입니다.

그럼 C#으로 Redis Cache를 구현하는 방법을 살펴보겠습니다.

1단계. Azure 포털에 로그인한 후 Databases >> Redis Cache 메뉴로 이동합니다.

2단계. 새로운 Redis Cache 인스턴스를 생성합니다.

3단계. 생성된 Redis Cache에 연결하기 위한 액세스 키(Access Keys)를 확인합니다.

C#으로 Azure Redis Cache 마스터하기: 단계별 실전 가이드

StackExchange.Redis 설치

4단계. 다음 명령어를 실행하여 StackExchange.Redis NuGet 패키지를 설치합니다.

Install-Package StackExchange.Redis

이제 Redis Cache에 데이터를 저장하고 조회하는 코드를 작성해 보겠습니다. 앞서 Azure Document DB CRUD 작업 코드를 다룬 적이 있으니, 아직 읽지 않으셨다면 먼저 해당 글을 확인해 보시길 권장합니다. Document DB CRUD 코드가 준비되어 있다는 전제하에 여기에 Redis Cache를 추가로 구현해 보겠습니다.

5단계. 이전 글과 마찬가지로 appsettings.dev.json 파일에 Redis Cache 연결 문자열을 추가합니다.

C#으로 Azure Redis Cache 마스터하기: 단계별 실전 가이드

6단계. Config.cs 클래스에 RedisCache 속성을 하나 더 추가하여 appsettings.dev.json 파일에서 Redis Cache 연결 문자열 값을 읽어오도록 합니다.

public class Config
{
 public DocDbConnectionString docDb { get; set; }
 public string RedisCache { get; set; }
}`
public class DocDbConnectionString
{
 public string EndPoint { get; set; }
 public string AuthKey { get; set; }
 public string Database { get; set; }
 public string Collection { get; set; }
}

7단계. program.cs 파일로 이동하여 Redis Cache를 위한 ConnectionMultiplexer를 추가합니다.

IDatabase cache = lazyConnection.Value.GetDatabase();
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
 string cacheConnection = configs.RedisCache;
 return ConnectionMultiplexer.Connect(cacheConnection);
});
public static ConnectionMultiplexer Connection
{
 get
 {
 return lazyConnection.Value;
 }
}

이제 Document DB에 문서를 생성할 때 Key를 기준으로 Redis Cache에도 함께 저장하고, 문서를 읽을 때는 해당 Key로 Redis Cache에 문서가 존재하는지 먼저 확인합니다. 캐시에 문서가 있다면 Document DB까지 접근할 필요 없이 바로 반환하면 되므로, 이를 통해 애플리케이션 성능을 크게 향상시킬 수 있습니다.

var collection = UriFactory.CreateDocumentCollectionUri(configs.docDb.Database, configs.docDb.Collection);
try
{
 // 직원 정보를 담은 JObject 생성
 Console.WriteLine("\nCreating document");
 JObject emp = new JObject();
 emp.Add("id", "V003");
 emp.Add("name", "virendra");
 emp.Add("address", "Indore");
 emp.Add("Country", "India");
 // DocumentDb에 문서 생성
 var createResponse = await Client.CreateDocumentAsync(collection, emp);
 var createdDocument = createResponse.Resource;
 Console.WriteLine("Document with id {0} created", createdDocument.Id);
 // "redisEmp3"라는 키로 JObject를 Redis 캐시에 저장
 var entryInRedis = await cache.StringSetAsync("redisEmp3", emp.ToString());
 Console.WriteLine("Document with key redisEmp3 stored into redis cache");
}
catch (Exception ex)
{
 throw ex;
}

8단계. 이번에는 Redis Cache에서 문서를 읽어보겠습니다.

// Redis Cache에서 문서 읽기
var empInRedis = await cache.StringGetAsync("redisEmp3");
if (!empInRedis.IsNullOrEmpty)
{
 Console.WriteLine("Read Document from RedisCache {0} : ", empInRedis);
}
// Redis Cache에 문서가 없으면 Document DB에서 읽기
if (empInRedis.IsNullOrEmpty)
{
 var readResponse = await client.ReadDocumentAsync(UriFactory.CreateDocumentUri(configs.docDb.Database, configs.docDb.Collection, "V001"));
 var readDocument = readResponse.Resource;
 Console.WriteLine("Read Document {0}: ", readResponse.Resource.ToString());
}

아래 화면은 Redis Cache에서 문서를 읽어오는 과정을 보여줍니다.

9단계. 다음은 Program.cs 클래스의 전체 코드입니다.

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using StackExchange.Redis;
using Microsoft.Azure.Documents.Client;
public class Program
{
 private static IConfiguration Configuration { get; set; }
 private static Config configs;
 private DocumentClient client;
 private IDatabase cache = lazyConnection.Value.GetDatabase();
 static void Main(string[] args)
 {
 // 구성 설정 초기화
 var builder = new ConfigurationBuilder()
 .SetBasePath(Directory.GetCurrentDirectory())
 .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: false, reloadOnChange: true);
 Configuration = builder.Build();
 configs = new Config();
 Configuration.Bind(configs);
 Program obj = new Program();
 obj.CRUDOperation().Wait();
 }
 // CRUD 작업
 private async Task CRUDOperation()
 {
 var collection = UriFactory.CreateDocumentCollectionUri(configs.docDb.Database, configs.docDb.Collection);
 try
 {
 // 직원 정보를 담은 JObject 생성
 Console.WriteLine("\nCreating document");
 JObject emp = new JObject();
 emp.Add("id", "V003");
 emp.Add("name", "virendra");
 emp.Add("address", "Indore");
 emp.Add("Country", "India");
 // 문서 생성
 var createResponse = await Client.CreateDocumentAsync(collection, emp);
 var createdDocument = createResponse.Resource;
 Console.WriteLine("Document with id {0} created", createdDocument.Id);
 // "redisEmp3" 키로 JObject를 Redis 캐시에 저장
 var entryInRedis = await cache.StringSetAsync("redisEmp3", emp.ToString());
 Console.WriteLine("Document with key redisEmp3 stored into redis cache");
 }
 catch (Exception ex)
 {
 throw ex;
 }
 // Redis 캐시에서 문서 읽기
 var empInRedis = await cache.StringGetAsync("redisEmp3");
 if (!empInRedis.IsNullOrEmpty)
 {
 Console.WriteLine("Read Document from RedisCache {0} : ", empInRedis);
 }
 if (empInRedis.IsNullOrEmpty)
 {
 // Document DB에서 문서 읽기
 var readResponse = await client.ReadDocumentAsync(UriFactory.CreateDocumentUri(configs.docDb.Database, configs.docDb.Collection, "V001"));
 var readDocument = readResponse.Resource;
 Console.WriteLine("Read Document {0}: ", readResponse.Resource.ToString());
 }
 }
 // Document 클라이언트 단일 인스턴스 생성 후 재사용
 public DocumentClient Client
 {
 get
 {
 if (client == null)
 {
 Uri endpointUri = new Uri(configs.docDb.EndPoint);
 client = new DocumentClient(endpointUri, configs.docDb.AuthKey, null, ConsistencyLevel.Session);
 client.OpenAsync();
 }
 return client;
 }
 }
 // Redis Cache 연결 설정
 private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
 {
 string cacheConnection = configs.RedisCache;
 return ConnectionMultiplexer.Connect(cacheConnection);
 });
 public static ConnectionMultiplexer Connection
 {
 get
 {
 return lazyConnection.Value;
 }
 }
}

이 글이 Azure Redis Cache를 이해하고 실제 프로젝트에 적용하는 데 도움이 되기를 바랍니다.