자습서: Azure Functions 및 Azure Redis를 사용하여 쓰기 숨김 캐시 만들기
이 자습서에서는 Azure Managed Redis(미리 보기) 또는 Azure Cache for Redis 인스턴스를 쓰기 숨김 캐시로 사용하기 위한 것입니다. 이 자습서의 쓰기 숨김 패턴은 캐시에 쓰기가 SQL 데이터베이스(Azure SQL Database 서비스의 인스턴스)에 해당하는 쓰기를 트리거하는 방법을 보여 줍니다.
Azure Functions용 Redis 트리거를 사용하여 이 기능을 구현합니다. 이 시나리오에서는 Redis를 사용하여 인벤토리 및 가격 책정 정보를 저장하는 동시에 해당 정보를 SQL 데이터베이스에 백업하는 방법을 확인할 수 있습니다.
캐시에 작성된 새 항목이나 새 가격은 모두 데이터베이스의 SQL 테이블에 반영됩니다.
이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.
- 데이터베이스, 트리거 및 연결 문자열을 구성합니다.
- 트리거가 작동하는지 확인합니다.
- 함수 앱에 코드를 배포합니다.
필수 구성 요소
- Azure 구독 Azure 구독이 아직 없는 경우 무료 계정을 만듭니다.
- 이전 자습서의 완료, Azure Redis에서 Azure Functions 트리거 시작, 다음 리소스가 프로비전됨:
- Azure Managed Redis(미리 보기) 또는 Azure Cache for Redis 인스턴스
- Azure Functions 인스턴스
- Azure SQL 사용에 대한 실무 지식
- NuGet 패키지가 설치된 VS Code(Visual Studio Code) 환경 설정
새 SQL 데이터베이스를 만들고 구성합니다.
이 예제의 SQL 데이터베이스는 지원 데이터베이스입니다. Azure Portal을 통해 또는 원하는 자동화 방법을 통해 SQL 데이터베이스를 만들 수 있습니다.
SQL 데이터베이스를 만드는 방법에 대한 자세한 내용은 빠른 시작: 단일 데이터베이스 만들기 - Azure SQL Database를 참조하세요.
이 예제에서는 포털을 사용합니다.
데이터베이스 이름을 입력하고 새로 만들기를 선택하여 데이터베이스를 보관할 새 서버를 만듭니다.
SQL 인증 사용을 선택하고 관리자 로그인 및 암호를 입력합니다. 이러한 자격 증명을 저장하거나 기록해 두어야 합니다. 프로덕션 환경에서 서버를 배포하는 경우 대신 Microsoft Entra 인증을 사용합니다.
네트워킹 탭으로 이동하여 공용 엔드포인트를 연결 방법으로 선택합니다. 표시되는 두 방화벽 규칙에 대해 예를 선택합니다. 이 엔드포인트를 사용하면 Azure 함수 앱에서 액세스할 수 있습니다.
유효성 검사가 완료되면 검토 + 만들기를 선택한 다음 만들기를 선택합니다. SQL 데이터베이스에서 배포를 시작합니다.
배포가 완료되면 Azure Portal의 리소스로 이동하여 쿼리 편집기 탭을 선택합니다. 기록할 데이터를 보관하는 인벤토리라는 새 테이블을 만듭니다. 다음 SQL 명령을 사용하여 두 필드가 포함된 새 테이블을 만듭니다.
ItemName
은 각 항목의 이름을 나열합니다.Price
는 항목의 가격을 저장합니다.
CREATE TABLE inventory ( ItemName varchar(255), Price decimal(18,2) );
명령이 실행을 완료하면 Tables 폴더를 확장하여 새 테이블이 만들어졌는지 확인합니다.
Redis 트리거 구성
먼저 이전 자습서에서 사용한 것과 동일한 VS Code 프로젝트의 복사본을 만듭니다. 이전 자습서의 폴더를 RedisWriteBehindTrigger와 같은 새 이름으로 복사하고 VS Code에서 엽니다.
둘째, RedisBindings.cs 및 RedisTriggers.cs 파일을 삭제합니다.
이 예제에서는 pub/sub 트리거를 사용하여 keyevent
알림을 트리거합니다. 이 예제의 목표는 다음과 같습니다.
SET
이벤트가 발생할 때마다 트리거됩니다.SET
이벤트는 새 키가 캐시 인스턴스에 기록되거나 키 값이 변경될 때 발생합니다.SET
이벤트가 트리거되면 캐시 인스턴스에 액세스하여 새 키 값을 찾습니다.- SQL 데이터베이스의 인벤토리 테이블에 키가 이미 있는지 확인합니다.
- 그렇다면 해당 키 값을 업데이트합니다.
- 그렇지 않다면 키와 해당 값을 사용하여 새 행을 작성합니다.
트리거를 구성하려면 다음을 수행합니다.
System.Data.SqlClient
NuGet 패키지를 가져와서 SQL 데이터베이스와의 통신을 사용합니다. VS Code 터미널로 이동하여 다음 명령을 사용합니다.dotnet add package System.Data.SqlClient
RedisFunction.cs라는 새 파일을 만듭니다. RedisBindings.cs 및 RedisTriggers.cs 파일을 삭제했는지 확인합니다.
다음 코드를 복사한 후 RedisFunction.cs에 붙여넣어 기존 코드를 바꿉니다.
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Redis;
using System.Data.SqlClient;
public class WriteBehindDemo
{
private readonly ILogger<WriteBehindDemo> logger;
public WriteBehindDemo(ILogger<WriteBehindDemo> logger)
{
this.logger = logger;
}
public string SQLAddress = System.Environment.GetEnvironmentVariable("SQLConnectionString");
//This example uses the PubSub trigger to listen to key events on the 'set' operation. A Redis Input binding is used to get the value of the key being set.
[Function("WriteBehind")]
public void WriteBehind(
[RedisPubSubTrigger(Common.connectionString, "__keyevent@0__:set")] Common.ChannelMessage channelMessage,
[RedisInput(Common.connectionString, "GET {Message}")] string setValue)
{
var key = channelMessage.Message; //The name of the key that was set
var value = 0.0;
//Check if the value is a number. If not, log an error and return.
if (double.TryParse(setValue, out double result))
{
value = result; //The value that was set. (i.e. the price.)
logger.LogInformation($"Key '{channelMessage.Message}' was set to value '{value}'");
}
else
{
logger.LogInformation($"Invalid input for key '{key}'. A number is expected.");
return;
}
// Define the name of the table you created and the column names.
String tableName = "dbo.inventory";
String column1Value = "ItemName";
String column2Value = "Price";
logger.LogInformation($" '{SQLAddress}'");
using (SqlConnection connection = new SqlConnection(SQLAddress))
{
connection.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
//Form the SQL query to update the database. In practice, you would want to use a parameterized query to prevent SQL injection attacks.
//An example query would be something like "UPDATE dbo.inventory SET Price = 1.75 WHERE ItemName = 'Apple'".
command.CommandText = "UPDATE " + tableName + " SET " + column2Value + " = " + value + " WHERE " + column1Value + " = '" + key + "'";
int rowsAffected = command.ExecuteNonQuery(); //The query execution returns the number of rows affected by the query. If the key doesn't exist, it will return 0.
if (rowsAffected == 0) //If key doesn't exist, add it to the database
{
//Form the SQL query to update the database. In practice, you would want to use a parameterized query to prevent SQL injection attacks.
//An example query would be something like "INSERT INTO dbo.inventory (ItemName, Price) VALUES ('Bread', '2.55')".
command.CommandText = "INSERT INTO " + tableName + " (" + column1Value + ", " + column2Value + ") VALUES ('" + key + "', '" + value + "')";
command.ExecuteNonQuery();
logger.LogInformation($"Item " + key + " has been added to the database with price " + value + "");
}
else {
logger.LogInformation($"Item " + key + " has been updated to price " + value + "");
}
}
connection.Close();
}
//Log the time that the function was executed.
logger.LogInformation($"C# Redis trigger function executed at: {DateTime.Now}");
}
}
Important
이 예제는 자습서용으로 간소화되었습니다. 프로덕션용으로는 매개 변수화된 SQL 쿼리를 사용하여 SQL 삽입 공격을 방지하는 것이 좋습니다.
연결 문자열 구성
SQL 데이터베이스에 대한 연결 문자열을 포함하려면 local.settings.json 파일을 업데이트해야 합니다. SQLConnectionString
의 Values
섹션에 항목을 추가합니다. 파일은 다음 예제와 비슷합니다.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"redisConnectionString": "<redis-connection-string>",
"SQLConnectionString": "<sql-connection-string>"
}
}
Redis 연결 문자열 찾으려면 Azure Managed Redis 또는 Azure Cache for Redis 리소스의 리소스 메뉴로 이동합니다. 리소스 메뉴의 액세스 키 영역에 있는 문자열을 찾습니다.
SQL 데이터베이스 연결 문자열을 찾으려면 SQL 데이터베이스 리소스의 리소스 메뉴로 이동합니다. 설정에서 연결 문자열을 선택한 다음 ADO.NET 탭을 선택합니다. 문자열은 ADO.NET(SQL 인증) 영역에 있습니다.
암호는 자동으로 붙여넣어지지 않기 때문에 SQL 데이터베이스 연결 문자열의 암호를 수동으로 입력해야 합니다.
Important
이 예제는 자습서용으로 간소화되었습니다. 프로덕션용으로 Azure Key Vault를 사용하여 연결 문자열 정보를 저장하거나 SQL 인증에 Azure Microsoft Entra ID를 사용하는 것이 좋습니다.
프로젝트 빌드 및 실행
VS Code에서 실행 및 디버그 탭으로 이동하여 프로젝트를 실행합니다.
Azure Portal에서 Redis 인스턴스로 돌아가서 콘솔 단추를 선택하여 Redis 콘솔을 입력합니다. 다음의 몇 가지
SET
명령을 사용해 보세요.SET apple 5.25
SET bread 2.25
SET apple 4.50
Important
콘솔 도구는 아직 Azure Managed Redis에 사용할 수 없습니다. 대신 Redis-cli 또는 Redis Insight와 같은 도구를 사용하여 Redis 인스턴스에서 직접 명령을 실행하는 것이 좋습니다.
VS Code로 돌아가면 트리거가 등록됩니다. 트리거가 작동하는지 확인하려면 다음을 수행합니다.
Azure Portal에서 SQL 데이터베이스로 이동합니다.
리소스 메뉴에서 쿼리 편집기를 선택합니다.
새 쿼리의 경우 다음 SQL 명령으로 쿼리를 만들어 인벤토리 테이블에서 상위 100개 항목을 확인합니다.
SELECT TOP (100) * FROM [dbo].[inventory]
Redis 인스턴스에 기록된 항목이 여기에 표시되는지 확인합니다.
함수 앱에 코드 배포
이 자습서는 이전 자습서를 기반으로 합니다. 자세한 내용은 Azure 함수에 코드 배포를 참조하세요.
VS Code에서 Azure 탭으로 이동합니다.
구독을 찾아 확장합니다. 그런 다음 함수 앱 섹션을 찾아 확장합니다.
함수 앱을 길게 누르거나 마우스 오른쪽 단추로 클릭한 다음 함수 앱에 배포를 선택합니다.
연결 문자열 정보 추가
이 자습서는 이전 자습서를 기반으로 합니다. redisConnectionString
에 대한 자세한 내용은 연결 문자열 정보 추가를 참조하세요.
Azure Portal에서 함수 앱으로 이동합니다. 리소스 메뉴에서 환경 변수를 선택합니다.
앱 설정 창에서 새 필드로 SQLConnectionString을 입력합니다. 값에 연결 문자열을 입력합니다.
적용을 선택합니다.
개요 블레이드로 이동하고 다시 시작을 선택하여 새 연결 문자열 정보로 앱을 다시 시작합니다.
배포 확인
배포가 완료되면 Redis 인스턴스로 돌아가서 명령을 사용하여 SET
더 많은 값을 작성합니다. SQL 데이터베이스에도 표시되는지 확인합니다.
함수 앱이 제대로 작동하는지 확인하려면 포털의 앱으로 이동하여 리소스 메뉴에서 로그 스트림을 선택합니다. 여기에서 실행 중인 트리거와 SQL 데이터베이스에 대해 수행되는 해당 업데이트가 표시됩니다.
삭제하지 않고 SQL 데이터베이스 테이블을 지우려면 다음 SQL 쿼리를 사용하면 됩니다.
TRUNCATE TABLE [dbo].[inventory]
리소스 정리
이 문서에서 만든 리소스를 계속 사용하려면 리소스 그룹을 유지합니다.
그렇지 않고 리소스 사용을 완료하는 경우 요금이 부과되지 않도록 하려면 만든 Azure 리소스 그룹을 삭제하면 됩니다.
Important
리소스 그룹을 삭제하면 다시 되돌릴 수 없습니다. 리소스 그룹을 삭제하는 경우 그 안의 모든 리소스가 영구적으로 삭제됩니다. 잘못된 리소스 그룹 또는 리소스를 자동으로 삭제하지 않도록 해야 합니다. 유지하려는 리소스가 포함된 기존 리소스 그룹 내에서 리소스를 만든 경우 리소스 그룹을 삭제하는 대신 각 리소스를 개별적으로 삭제할 수 있습니다.
리소스 그룹을 삭제하려면
Azure Portal에 로그인한 다음, 리소스 그룹을 선택합니다.
삭제하려는 리소스 그룹을 선택합니다.
리소스 그룹이 많은 경우 필드 필터링... 상자를 사용하여 이 문서에 대해 만든 리소스 그룹의 이름을 입력합니다. 결과 목록에서 리소스 그룹을 선택합니다.
리소스 그룹 삭제를 선택합니다.
리소스 그룹 삭제를 확인하는 메시지가 표시됩니다. 리소스 그룹의 이름을 입력하여 확인한 다음, 삭제를 선택합니다.
잠시 후, 리소스 그룹 및 모든 해당 리소스가 삭제됩니다.
요약
이 자습서 및 Azure Redis 에서 Azure Functions 트리거 시작은 Azure 함수 앱에서 Redis 트리거 및 바인딩을 사용하는 방법을 보여 줍니다. 또한 Azure SQL Database에서 Redis를 쓰기 숨김 캐시로 사용하는 방법도 보여 줍니다. Azure Functions에서 Azure Managed Redis 또는 Azure Cache for Redis를 사용하는 것은 많은 통합 및 성능 문제를 해결할 수 있는 강력한 조합입니다.