Windows Azure 개발: 간단한 방명록 만들기 [Step 2] / 소스 코드 수정

이전 글 보기> Windows Azure 개발: 간단한 방명록 만들기 [Step 1]


지난 글에 이어서, 오늘 글에서는 방명록의 Web Role 어플리케이션을 만드는 부분과 함께, Blob Storage의 사용 방법, 그리고 간단한 주의 사항 하나를 살펴보도록 하겠습니다.


 


Blob Storage는 Blob (Binary Large Object) 즉 일반 바이너리 파일을 저장할 수 있는 공간으로, 지난 글에서 살펴본 Table Storage와 더불어서 Storage 기능 중 하나로 제공되는 부분입니다. Blob Storage를 통하여, 방명록의 사진 첨부 기능을 구현해 보고자 합니다.


 


그리고, 우리가 특별히 제작할 Worker Role 어플리케이션은 클라우드 컴퓨팅 서비스에 특화된 기능에 관한 예시 하나를 보여줄 것입니다. 바로, 업로드한 방명록의 사진 크기를 적절한 썸네일 이미지로 변환하는 기능입니다. 개별적인 썸네일 이미지 변환 작업 하나하나는 큰 작업이 아닐 수 있지만, 이것이 동시에 많은 사용자들에 의하여 발생하는 작업이라고 가정한다면, 웹 서비스 입장에서는 굉장한 리소스 사용이 발생하게 될 것입니다.


 


지난번에 만든 GuestBook_Data 프로젝트를 확인한 후, Web Role로 등록된 ASP.NET 프로젝트의 Default.aspx 페이지를 열어서, 아래와 같이 디자인 타임 상에 ASP.NET 컨트롤들을 배치합니다. (Name 옆의 입력 필드의 인스턴스 명을 ‘NameTextBox’, Message 옆의 입력 필드의 인스턴스 명을 ‘MessageTextBox’, Photo 옆의 입력 필드의 인스턴스 명을 ‘FileUpload1’, 연필 모양의 이미지를 사용하는 이미지 버튼 필드의 인스턴스 명을 ‘SignButton’으로 하기로 합니다. 그리고, 처리 과정을 살펴보기 위하여, ASP.NET AJAX Timer 컴포넌트를 하나 추가하고, 이름을 ‘Timer1’으로 하기로 합니다.)


 



 


그리고 Default.aspx 페이지의 코드 비하인드를 엽니다. 그리고, 아래와 같이 네임스페이스 참조를 추가합니다.


 

using System.Net;
using GuestBook_Data;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;

 


코드 비하인드와 연결된 _Default 클래스의 멤버 변수로는 다음의 항목들을 추가합니다. Blob Storage와의 상태를 동기화하고 관리하기 위한 변수들입니다. 싱글턴 패턴으로 유지하기 위하여 모두 정적 인스턴스로 선언하였으며, storageInitialized 변수에는 초기화 여부를 관리하고, gate 변수는 스레드 이벤트 동기화를 관리하며, blobStorage 변수는 실제 Windows Azure Blob Storage에 대한 서비스를 포함하는 변수입니다.


 

private static bool storageInitialized = false;
private static object gate = new Object();
private static CloudBlobClient blobStorage;

 


SignButton의 Click 이벤트를 구현하여 핸들러를 추가한 후 아래와 같이 코드를 작성합니다. 이 이벤트 핸들러는, Windows Azure Blob Storage에 첨부한 사진 파일을 저장하고, 이전 글에서 작성한 모델을 바탕으로 Windows Azure Table Storage에 방명록의 글을 저장하는 역할을 수행합니다.


 

protected void SignButton_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
InitializeStorage();

// Windows Azure Blob Storage에 이미지를 저장합니다.
CloudBlobContainer container = blobStorage.GetContainerReference("guestbookpics");
string uniqueBlobName = string.Format("image_{0}.jpg", Guid.NewGuid().ToString());
CloudBlockBlob blob = container.GetBlockBlobReference(uniqueBlobName);
blob.Properties.ContentType = FileUpload1.PostedFile.ContentType;
blob.UploadFromStream(FileUpload1.FileContent);
System.Diagnostics.Trace.TraceInformation("Uploaded image '{0}' to blob storage as '{1}'", FileUpload1.FileName, uniqueBlobName);

// Windows Azure Table Storage에 새 항목을 추가합니다.
GuestBookEntry entry = new GuestBookEntry() { GuestName = NameTextBox.Text, Message = MessageTextBox.Text, PhotoUrl = blob.Uri.ToString(), ThumbnailUrl = blob.Uri.ToString() };
GuestBookEntryDataSource ds = new GuestBookEntryDataSource();
ds.AddGuestBookEntry(entry);

System.Diagnostics.Trace.TraceInformation("Added entry {0}-{1} in table storage for guest '{2}'", entry.PartitionKey, entry.RowKey, entry.GuestName);

}

NameTextBox.Text = “”;
MessageTextBox.Text = “”;

DataList1.DataBind();
}


 


Timer1 컴포넌트의 Tick 이벤트를 아래와 같이 구현하여, 타이머가 실행되어있을 동안 주기적으로 데이터 바인딩 상태를 확인하는 동작을 서술합니다.


 

protected void Timer1_Tick(object sender, EventArgs e)
{
DataList1.DataBind();
}

 


그리고, ASP.NET의 메카니즘을 이용하여, 사용자의 입력이 되돌아 온 포스트 백 상태일 때 타이머를 켜도록 하여 백그라운드에서 비동기적으로 실행되는 Worker Role 어플리케이션의 상태를 확인할 수 있게 합니다.


 

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Timer1.Enabled = true;
}
}

 


이제, 프로그램 내에서 중요한 Windows Azure Storage와의 연결을 초기화하는 InitializeStorage 메서드를 구현합니다. 이 메서드는, 방명록의 “쓰기” 버튼을 호출할 때 마다 불리지만, 실제로 의미를 가지고 동작하는 것은 응용프로그램이 시작된 이후 최초 한 번이 됩니다.


 


private void InitializeStorage()
{
if (storageInitialized)
{
return;
}

lock (gate)
{
if (storageInitialized)
{
return;
}

try
{
  // read account configuration settings
  var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");

  // create blob container for images
  blobStorage = storageAccount.CreateCloudBlobClient();
  CloudBlobContainer container = blobStorage.GetContainerReference("guestbookpics");
  container.CreateIfNotExist();

  // configure container for public access
  var permissions = container.GetPermissions();
  permissions.PublicAccess = BlobContainerPublicAccessType.Container;
  container.SetPermissions(permissions);
}
catch (WebException)
{
  throw new WebException("Storage services initialization failure. "
      + "Check your storage account configuration settings. If running locally, "
      + "ensure that the Development Storage service is running.");
}

storageInitialized = true;

}
}


 


여기서 DataConnectionString은 응용프로그램 설정 (web.config이 아닙니다) 상의 연결 문자열로, 실제 Windows Azure Storage를 지정하거나, Windows Azure Tools의 Simulator와 연결하는 것 중 선택하여 완성해야 하는 항목입니다. 프로젝트 속성을 열어서 아래와 같이 설정할 수 있습니다.


 



 


위의 코드 상에서 DataConnectionString이라는 이름을 사용하였으므로, 같은 항목의 이름을 새로 입력하고, Type을 ConnectionString으로 설정한 후, Value 옆의 “…” 버튼 – 또는 – 도구 모음 상단의 “Add Settings” 버튼을 클릭합니다. 그러면 아래와 같은 세부 설정 창이 팝업으로 나타납니다.


 



 


“Use development storage”를 선택하면, 로컬 컴퓨터에 구축된 Storage를 사용하여 기능을 시험해볼 수 있으며, “Enter storage credentials”를 선택하면, 실제 Windows Azure Storage에 접속하는 것을 뜻하며, 입력해야 하는 항목들은 Windows Azure Portal 사이트에서 모두 확인할 수 있는 정보들입니다. 여기서는 첫 번째 항목을 선택하여 배포 전에 프로그램이 잘 동작하는지 점검하는 것으로 설정하겠습니다.


 


설정을 변경하고 나면 모두 저장 버튼을 눌러 프로젝트의 변경 사항을 저장합니다.


 


이제 마지막으로, Web Role 어플리케이션에서 화룡점정(?)이라고 할 수 있는 설정 전달 기능을, 기본으로 추가되어있는 WebRole.cs (또는 WebRole.vb) 파일 내에 코드를 추가해야 합니다. 아래와 같이 코드를 작성합니다.


 

public override bool OnStart()
{
DiagnosticMonitor.Start(“DiagnosticsConnectionString”);

// Restart the role upon all configuration changes
// Note: To customize the handling of configuration changes,
// remove this line and register custom event handlers instead.
// See the MSDN topic on “Managing Configuration Changes” for further details
// (http://go.microsoft.com/fwlink/?LinkId=166357).
RoleEnvironment.Changing += RoleEnvironmentChanging;

Microsoft.WindowsAzure.CloudStorageAccount.SetConfigurationSettingPublisher(( configName, configSetter) =>
{
configSetter(Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue(configName));
});

return base.OnStart();
}


 


노트: 개발 환경에서 테스트를 위하여 사용하는 DiagnosticMonitor.Start 메서드는 실제 Windows Azure 환경 위에서는 동작하지 않을 수 있습니다. 응용프로그램을 게시한 이후에 인스턴스의 상태가 Busy에서 머무르거나 Ready로 전환되지 않고 Stop으로 전환될 경우, 이 부분을 확인하여 DiagnosticMonitor 개체의 사용을 해제하거나, 정식 Windows Azure Storage 계정을 대체 지정하여야 합니다.


 


다음 Step에서는 방명록의 비동기 Worker Role을 작성하는 방법을 살펴보도록 하겠습니다. 감사합니다. 🙂

Windows Azure 개발: 간단한 방명록 만들기 [Step 2] / 소스 코드 수정”에 대한 2개의 생각

    • Windows Azure SDK와 Windows Azure Tools 자체는 현 시점에서 Microsoft IIS와 SQL Server의 기능을 강력하게 의존하고 있습니다. Mono 기반으로는 아직까지 Novell와 Microsoft 모두 공식적인 언급이 나와있지는 않은 상태입니다.

      대신, 리눅스나 맥 OS X 등에서 Windows Azure를 개발하기 위하여 Java, PHP 등의 다른 프로그래밍 언어를 선택하여 개발하는 것을 공식적으로 지원합니다. 또는, 가상 머신 어플라이언스를 활용하시어 Windows Vista 이상의 환경을 구축하여 사용하시는 것도 방법입니다.

      저 개인적으로는 빠른 시일 내에 Mono에서도 Windows Azure 응용프로그램을 제작할 수 있는 패키징 도구가 출시되었으면 하는 바람이 있습니다. 🙂

댓글 남기기