[ClouDeveloper News – Azure Edition] 2016년 12월 22일

클라우드 컴퓨팅을 중심으로 관련된 여러 기술과 업계 소식을 매주 전하는 ClouDeveloper News를 시작합니다. 파일럿 프로그램으로 구상하여 운영 중에 있으며 추후 여러 피드백과 의견 수렴을 통하여 프로그램의 틀을 갖추어 나갈 예정이오니 많은 관심과 구독을 부탁드립니다.

이번주 포커스/주요 소식

  • New Azure Logic Apps innovation – general availability of cloud-based Enterprise Integration Pack
    • Azure Logic App에서 클라우드 기반의 엔터프라이즈 시스템 연동 기능을 사용할 수 있게 되었습니다. 그중에서도, 이번에 새로 출시된 기능에는 EDI 문서 송수신에 관련된 기능이 포함됩니다.
  • Microsoft Azure Storage Import/Export Announcements
    • Azure Storage 가져오기/내보내기 기능이 정삭 출시되었습니다. 디스크 단위로 데이터를 가져오거나 내보내는 서비스와 해당 플랫폼 별로 실제 데이터 송수신 작업을 처리하는 에이전트 도구도 같이 출시되었습니다.
  • SQL Server next version Community Technology Preview 1.1 now available
    • SQL Server의 차세대 버전의 프리뷰 릴리즈가 Windows와 Linux 용으로 업데이트되어 출시되었습니다. 레드햇 7.3과 우분투 16.10에서의 실행을 지원하게 되었고, 데이터 가져오기 원본 데이터 소스로 MySQL을 사용할 수 있게 개선된 것을 포함, 다수의 개선 사항이 추가되었습니다.
  • AzCopy 5.1.1 Release
    • AzCopy 명령줄 유틸리티를 사용하여 BLOB 저장소 컨테이너 상의 데이터를 고속으로, 효율적으로 가져오거나 저장소로 업로드하는 기능을 수행하고, SDK를 이용하여 추가 개발하지 않고 스크립트 수준에서 자동화 로직을 개발하는데 활용할 수 있습니다. 이번 5.1.1 버전에서는 오픈 소스로 공개된  Azure Storage Data Movement Library 의 기능을 채택하도록 프로그램을 업데이트한 것이 주된 변경 사항입니다.
  • Introducing Microsoft R Server 9.0
    • Microsoft R Server 9.0이 출시되었습니다.

Azure 서비스 공지 사항

아티클, 기고

새로운 제품 및 서비스

활용 및 노하우

웹 캐스트

서드파티 소식

 

 

ClouDeveloper 페이스북 페이지에 댓글로 의견을 남겨주시면 뉴스 발행 및 각종 정보 전달에 반영하도록 하겠습니다. 고맙습니다.

의견 남기기: https://fb.com/cloudeveloper

Azure BLOB 저장소 레시피 – 모바일 홈페이지 만들기

안녕하세요. Windows Azure MVP 남정현입니다.


Windows Azure를 가지고 무엇을 할 수 있을까? 이 점에 대해서 궁금해하시는 많은 분들을 위하여 레시피 강좌 시리즈를 지속적으로 업로드하려고 합니다.


이번에 소개해드리려고 하는 내용은 요즈음 유행하는 HTML5 기반의 앱과 관련된 내용입니다. 서버의 렌더링을 필요로하지 않고 스스로 동작할 수 있는, 마치 앱과 같은 특성을 지닌 지능적인 HTML 페이지를 Windows Azure BLOB Storage위에서 호스팅하는 방법입니다.


사실 지금 소개해드리려는 내용은 굉장히 간단한 내용이지만, 활용하기에 따라서는 굉장히 유용한 레시피가 될 수 있습니다. 이벤트나 행사 웹 사이트와 같이 단순하지만 기간 내에 액세스가 폭증하는 페이지들을 호스팅해야 하는 요구 사항이 종종 있는데 이럴 때 활용하시면 일을 매우 단순하게 만들 수 있습니다.


정적 웹 사이트에 담을 내용 준비하기


정적 웹 사이트란 문자 그대로 웹 디자이너가 작업을 끝마친 시안 형태의 웹 페이지에서부터 ASP, PHP, ASP.NET, CGI, Python, Perl 등 생각할 수 있는 서버측 구성 요소를 하나도 들여오지 않고 jQuery나 Dojo 같은 자바스크립트 프레임워크들, 그리고 외부의 Open API만을 활용해서 온전하게 작동하는 웹 앱에 이르기까지 운영해야 할 서버 측의 비용을 고려하지 않고 만들 수 있는 모든 종류의 웹 사이트 및 웹 앱을 뜻합니다. 자바스크립트 세계의 발전에 따라 정적 웹 사이트의 의미도 크게 확장되었다고 볼 수 있습니다.


여기서는 jQuery Mobile을 이용하여 만든 간단한 웹 사이트를 Windows Azure Storage를 이용해서 호스팅하도록 해보겠습니다. 소개하는 내용이 아니더라도 여러분이 손수 만든 개인 모바일 홈페이지도 괜찮고 무엇이든 시험해볼 수 있는 것이면 됩니다.



  • 준비물 1: CloudBerry Client for Windows Azure BLOB Storage (Pro 버전 대신 Freeware를 설명합니다.)

  • 준비물 2: jQuery Mobile 패키지 파일

  • 준비물 3: 여러분이 올릴 간단한 웹 페이지 파일 및 이미지 파일

CloudBerry Client for Windows Azure BLOB Storage 설치하기


CloudBerry Client는 여러 종류의 Windows Azure BLOB Storage 클라이언트 중 다루기 쉽고 간편한 인터페이스를 제공하는 무료 클라이언트입니다. CloudBerry Client는 Windows Azure 이외에도 KT UCLOUD Biz Storage 클라이언트와 같은 OpenStack Client도 지원합니다.



http://www.cloudberrylab.com/ 웹 사이트에 방문하시면 메인 페이지에 CloudBerry Explorer Freeware라는 이름의 다운로드 링크 컬렉션이 보일 것입니다. 여기서 for Windows Azure를 선택하여 이번 레시피에서 설명하는데 필요한 도구를 다운로드하고 설치합니다.


프리웨어이지만 사용자 등록을 권하는 부분이 있는데, 지속적으로 이 도구를 사용하게 될 것을 감안하여 재량껏 등록하여 사용하기 바랍니다. 등록하지 않고 진행해도 사용에는 큰 지장은 없을 것입니다.


설치 후 아래와 같이 프로그램이 나타나는지 확인합니다.



계정 정보 등록하기


새로운 계정 정보를 등록하려면 아래 그림과 같이 File 메뉴의 Azure Blob Storage Accounts 메뉴를 선택합니다.



아래와 같이 대화 상자가 나타날 것입니다. Add 버튼을 클릭합니다.



아래와 같이 계정 정보 입력 대화상자가 나타나는지 확인합니다.




  • Display name: 이 프로그램 상에서 나타낼 항목 이름으로 자유롭게, 알아보기 쉬운 이름으로 입력합니다.

  • Account: Windows Azure 저장소의 ID를 입력합니다. URL을 보면 <계정 이름>.blob.core.windows.net와 같은 형태로 구성되어있는데 여기서 <계정 이름>에 해당하는 ID를 입력합니다.

  • Shared Key: Windows Azure 관리 포털에서 나타나는 이 저장소에 대한 Shared Key를 입력합니다. Primary Key나 Secondary Key 중 하나를 입력하면 됩니다. 보안 향상을 위하여, 서비스 구성을 위해 활용하는 Key와는 다른 여분의 Key를 이곳에 설정하는 것이 좋습니다. 이렇게 하여 불시에 이 Key를 갱신하여 유출 사고 등에 유연하게 대처할 수 있게 됩니다.

  • Use SSL: SSL 통신을 사용할 지의 여부를 결정합니다.

  • Development Storage: 실제 서비스가 아니라 Windows Azure Storage Emulator로 연결할 경우 이 항목을 체크합니다.

계정 정보를 확인하려면 http://manage.windowsazure.com/ 으로 이동하여 저장소 계정 화면에 대한 대시 보드를 아래와 같이 확인합니다. 그 다음 하단의 도구 모음에서 Manage Keys 버튼을 클릭합니다.



아래와 같이 모달 대화 상자가 나타나면 Storage Account Name을 복사하시고, Primary Access Key 또는 Secondary Access Key 중 하나를 복사하여 위의 대화 상자에 입력하도록 합니다.



모든 설정이 완료되면 Test Connection 버튼을 클릭하여 연결이 잘 되는지 확인합니다. 연결에 성공하면 아래와 같이 대화 상자가 나타날 것입니다.



jQuery Mobile 패키지 준비하기


기본적으로 jQuery Mobile 패키지 파일을 CDN에서 받아서 이용하는 방법이 편리합니다. 이렇게 하면 jQuery Mobile 다운로드에 관한 트래픽을 우리쪽 서버가 아닌 다른 위치의 CDN으로 분산시킬 수 있으므로 트래픽 관련 비용 절감에 도움이 되기도 합니다. 여기서는 jQuery Mobile 패키지를 우리쪽 서버에 업로드하는 것을 기준으로 예제를 만들어 보도록 하겠습니다.


http://jquerymobile.com/download/ 웹 페이지에 접속하여 아래와 같이 Latest Stable Release를 찾아 JavaScript와 CSS 파일 패키지를 Minified Version으로 다운로드하기 바랍니다. 링크를 클릭하면 저장이 아니라 파일이 열리는 동작으로 다운로드가 발생할 수 있으므로 링크를 오른쪽 버튼으로 클릭하고 다른 이름으로 저장 기능을 사용하여 저장하기 바랍니다.



그리고 jQuery Mobile이 필요로하는 jQuery 라이브러리 파일도 가져와야 합니다. http://jquery.com/download/ 웹 페이지에 접속하여 아래와 같이 Minified Version을 다운로드합니다.



NOTE: 최근에 릴리즈한 1.9.x 버전의 경우 jQuery Mobile과 호환성 문제가 있을 수 있으므로 1.8.x 릴리즈를 다운로드해야 할 수 있습니다. 1.9.x 버전이 작동하지 않을 경우 1.8.x 버전을 사용하여 진행할 수 있습니다.


컨테이너를 만들고 권한 설정하기


이제 컨테이너를 만들고 여기에 파일을 업로드할 차례입니다. 다시 CloudBerry Storage Explorer로 되돌아가서 오른쪽 패널의 Source 드롭 다운 상자에서 방금 추가한 계정을 선택하여 접속을 시도합니다. 



Windows Azure Storage는 전통적인 웹 호스팅 환경과는 다르며, 기본적으로 1계층의 컨테이너만을 지원합니다. 그리고 컨테이너보다 더 깊이있는 레벨의 폴더 계층을 형성하려면 올리는 파일의 이름에 경로 구분을 위한 문자 (‘/’)를 포함시켜 폴더처럼 보이게 하는 방법을 사용하게 됩니다.


API에서 폴더를 탐색한다는 것은 이러한 특성에 따라 실제 폴더로 스택 자료 구조를 이용해서 탐색하는 방식이 아니라, Where Clause를 이용할 때 사용할 수 있는 Prefix Matching 기법을 사용하게 됩니다. 즉, 같은 Prefix를 보유하는 컨테이너 내의 파일들은 논리적으로 같은 폴더에 있는 것으로 취급이 가능합니다.


컨테이너를 만들기 위해서는 아래 그림과 같이 오른쪽 편의 도구 모음을 클릭합니다.



아래와 같이 대화 상자가 나타나면 컨테이너의 이름을 입력하고 권한을 설정합니다.



위의 권한들에 대해 각각 내용을 살펴보면 다음과 같습니다.



  • Full public read access: 이 컨테이너의 URL로 접속하면 컨테이너 안에 무슨 파일이 들어있는지 목록을 조회할 수 있는 기능과 더불어 모든 파일에 대해 다운로드 기능을 제공함을 의미합니다.

  • Public read access for blobs only: 이 컨테이너의 URL로 접속하면 권한이 없다는 오류 메시지가 나타나고, 대신 이 컨테이너 안의 정확한 파일의 URL을 알고 있는 경우 해당 파일은 다운로드가 가능함을 의미합니다.

  • No public read access: 컨테이너이든 그 안에 들어있는 파일이든 인증을 거치지 않고는 읽을 수 없도록 보호함을 의미합니다.

위의 세 가지 옵션 중에서 지금 우리가 선택하려는 것은 두 번째 옵션으로, 정적 웹 호스팅에서 어떤 파일이 들어있는지 사용자가 확인할 필요 없이 개별 URL에 대해서만 안다면 자동으로 모든 서비스가 제공되므로 파일에 대해서만 공개하도록 만들 것입니다.


파일 업로드하기


여기서는 정적 웹 호스팅을 간단하게 테스트해볼 목적으로 1계층 컨테이너 안에 같은 파일들을 넣어보려고 합니다. 여러분의 컴퓨터에서 아래와 같이 파일을 준비하시면 됩니다.



그리고 위의 index.html 파일의 소스 코드는 아래와 같습니다.


[#M_더보기|접기|<!DOCTYPE html>
<html>
    <head>
        <meta charset=”utf-8″ />
        <meta name=”viewport” content=”width=device-width, initial-scale=1″ />
        <meta name=”apple-mobile-web-app-capable” content=”yes” />
        <meta name=”apple-mobile-web-app-status-bar-style” content=”black” />
        <title>
        </title>
        <link rel=”stylesheet” href=”jquery.mobile-1.2.0.min.css” />
        http://jquery-1.8.3.min.js
        http://jquery.mobile-1.2.0.min.js
       
            try {

    $(function() {


    });


  } catch (error) {
    console.error(“Your javascript has an error: ” + error);
  }
       
    </head>
    <body>
       

<

div id=”page1″>
           

               

                    Seoul
               

           

           

               

                    Welcome!
               

                https://maps.googleapis.com/maps/api/staticmap?center=서울&zoom=14&size=288×200&sensor=false” width=”288″ height=”200″ />
           

           

<

div>
               

                   

                           

  •                            
                                    Seoul
                               

                           
  •                        

  •                             http://www.google.co.kr/” data-transition=”fade” data-theme=”” data-icon=””>
                                    Google
                               
                           
  •                        

  •                             http://m.naver.com/” data-transition=”fade” data-theme=”” data-icon=””>
                                    NAVER
                               
                           
  •                    

               

            </div>
        </div>
    </body>
</html>

_M#]

이제 위의 소스 코드를 Azure Blob Storage로 업로드합니다. 아래와 같이 파일이 업로드된 것을 확인합니다.



결과 확인하고 QR코드로 만들어 배포하기


이제 마지막으로 올라간 파일이 잘 작동하는지 확인할 차례입니다. 위의 파일들 중 index.html 파일을 오른쪽 버튼으로 클릭하여 URL을 확인합니다.



아래와 같이 대화 상자가 나타나면 Copy to clipboard 버튼을 클릭하여 주소를 복사하고 웹 브라우저에서 열어보도록 합니다. (혹은 Open link 버튼을 눌러도 됩니다.)



웹 브라우저에서 아래와 같이 잘 나타나는지 확인합니다.



이제 이 URL을 QR코드로 만들기 위하여 http://qr.naver.com/ 으로 접속하여 QR코드를 만들면 모바일 웹 사이트 구축이 완료됩니다.


더 나아가기


만약 폴더 구조를 유지하면서 파일 업로드를 하기 원한다면, Storage Explorer에서는 폴더를 직접 생성하는 기능이 없지만, 미리 로컬에서 만든 폴더째로 한꺼번에 업로드하면 자동으로 폴더를 생성하게 됩니다.


그리고 Windows Azure CDN 노드를 추가하면 이 상태 그대로 CDN 서비스를 받을 수 있습니다. CDN 엣지 노드 형성은 2013년 2월 현재 신규 포털이 아닌 구 버전의 포털 http://windows.azure.com/ 에서 관리할 수 있습니다.

A Lap around cloud computing – 1인 1근두운 시대

이전 글: [Windows Azure Platform/A Lap around Cloud Computing] – A Lap around cloud computing – 지금이 여러분의 이력서를 새로 쓸 시간 



뜬금없이 근두운 이야기가 무엇인가 하고 놀라는 분들이 있으리라 생각한다. 이해가 빠른 분들이 계실 것이므로 단도직입적으로 말하면, 필자가 의도한 그대로, Cloud Computing 이야기를 하고자 했던 것이다. 우리의 머릿속 한 구석에 큰 존재감을 과시하며 차지하고 있는 전설 속 원숭이 손오공의 근두운을 IT 세상에서는 누구나 하나씩 다 가지고 있는 것이다.


여러분이 사용하고 싶어하는 근두운의 종류 또한 다양하다. 그래서 앞서 설명했던 Windows Live, Windows Server 기반 Private Cloud, Office 365가 있었고, 오늘은 마지막으로 개발자와 IT 전문가들의 관점에서 적극적으로 검토해 볼 가치가 있고 든든한 파트너 역을 맡아줄 Windows Azure Platform이라는 근두운을 이야기해볼 생각이다.


IT 관리자의 관점에서 보는 Windows Azure Platform


PDC08에서 처음 소개된 Windows Azure Platform은 전적으로 개발자의 역할을 중시했던 플랫폼이었다. 이는 PDC09, 그리고 PDC 2010 직전까지도 지속되었고 꾸준히 그 색을 더해 나가고 있던 과정이었다. 하지만 PDC 2010에서 처음으로 세간에 루머로만 떠돌던 VM Role이 공식적으로 사용 가능하게 베타 서비스로 출시되었고 이에 따라 IT 관리자들의 관점에서도 Windows Azure Platform을 활용할 수 있는 기회가 대폭 늘어나게 되었다.


Windows Azure Platform이 IT 관리자들에게 제공하는 주요 이점은 한 마디로 정리하면 기존의 IT 자산과 맞물려 사용할 수 있는 다양한 기회를 제공한다는 점이다. Microsoft의 Public Cloud는 모든 것을 Cloud로 올려야 한다고 말하지 않는다. 대신, 네트워크 수준에서의 통합부터 시작하여 Cloud 내부 및 외부에서 발생할 수 있는 문제를 다양한 방법으로 해결할 수 있도록 도와준다.


Windows Azure의 VM Role은 On-Premise 시스템을 분리 해체하는 작업을 거치지 않고 곧바로 Windows Azure 데이터센터에 서버를 올려놓는 방법이다. 기존에 먼저 소개된 Web Role 및 Worker Role과 달리 Windows Server 2008 R2 운영 체제 전체를 하나의 완전한 Role로 채택하여 사용할 수 있는 기법으로, 여러분이 기존에 어떤 라이선스를 가지고 있던지 관계없이 Windows Azure VM Role 라이선스로 전환할 수 있도록 해준다.


매우 이상적인 이야기처럼 들릴 수도 있지만 사실 중요한 문제가 두 가지가 있다. 라이선스에 관한 것이 있고, 또 다른 하나는 기술적인 구성 상의 문제이다. 다음의 표에 대략적인 내용을 언급해두었다.
































구성 요소 및 역할


변경 방향


3rd Party Software


Plan A: Public Cloud 호환 라이선스로 재계약


Plan B: 기존 서버를 유지하고, Windows Azure Connect로 네트워크 통합 / 단 Traffic 추가로 인한 변동 사항은 해당 공급자와 재 협상 필요


3rd Party Software Data


SQL Server Embedded DB


è MDF 및 LDF 파일을 SQL Server에 연결하고, 해당 DB를 SQL Azure로 이관해야 함


è MDB 파일이나 ACCDB 파일의 경우 SQL Server로 이관 후 SQL Azure로 이관해야 함


기타 데이터베이스


è 기존 서버를 유지하고, Windows Azure Connect로 네트워크 통합


SQL Server


Plan A: SQL Azure로 부분/전체 Migration


Plan B: 관계 지향적이지 않고 대용량 DB가 필요한 경우 Windows Azure Table Storage 사용


Plan C: 기존 서버를 유지하고, Windows Azure Connect로 네트워크 통합


Exchange Server


Plan A: Office 365로 부분/전체 Migration


Plan B: 기존 서버를 유지하고, Windows Azure Connect로 네트워크 통합


SharePoint Online


Plan A: Office 365로 부분/전체 Migration


Plan B: 기존 서버를 유지하고, Windows Azure Connect로 네트워크 통합


Lync Online


Plan A: Office 365로 부분/전체 Migration


Plan B: 기존 서버를 유지하고, Windows Azure Connect로 네트워크 통합


Active Directory


AD DS, AD LDS 모두 기존의 On-Premise 시스템을 Windows Azure Connect를 경유하여 활용하는 것이 최선


 


라이선스에 관한 문제의 본질은 다음과 같다. Windows Azure Compute를 통해서 서비스가 실행되면, Service Level Agreement (SLA) 계약 이행을 위하여 기본적으로 VM을 1대 이상 사용하는 것을 전제로 한다. 최소 1대만을 유지하도록 설정해도 상관은 없지만, 필연적으로 사용량이 증가하고 서비스를 위하여 배치된 VM들의 상태가 바빠지는 것이 감지되면 자동적으로 Fabric Controller가 원본 VM 이미지를 복제하여 새로운 VM을 복제하기 시작한다. 이것이 의미하는 바는 단순하다. 물리적인 Instance의 수가 자동으로 늘어나므로 그 안에 포함된 3rd Party 소프트웨어에 대한 라이선스도 같이 계산되어야 하고, 그것이 CPU 기반 라이선스이든 연결 개수 기반 라이선스이든 상관이 없는 것이다. 양쪽 라이선스 모두 있는 그대로 (as-is) 해석을 한다면 Public Cloud 내에서는 상식을 넘는 금액을 요구할 수 밖에 없다.


이를 해결하기 위해서는 해당 소프트웨어 공급자가 Public Cloud에 대응되는 사용량 – 또는 – 사용 시간 기반 라이선스를 지원해야 하며, 대다수의 경우 이를 지원하지 않을 것이므로 이러한 소프트웨어를 포함하는 서버를 On-Premise 환경에 배치하고, 이들 서버에 대한 종속성을 지니는 별도의 VM Role, Web Role, Worker Role 만을 Windows Azure에 게시한 후 Windows Azure Connect로 상호 연동을 가능하게 만드는 것이 최선이다.


기술적인 문제의 본질은 다음과 같다. 주로 데이터베이스에 대한 부분과 관련이 깊은데, Windows Azure가 SLA 이행을 위하여 VM을 복제하고, 복제된 VM들의 목록을 기준으로 Load Balancer를 구현하는 것은 매우 바람직한 일이다. 그러나 기존의 서버 모델은 개별 서버가 데이터베이스까지 서버 내에 같이 포함하고 있는 경우가 많은데 여기에 대한 적당한 조치를 취하지 않고 그대로 VM Role로 전환하는 경우 우스꽝스러운 문제가 발생한다. 접속할 때 마다 데이터베이스의 내용이 달라지는 일이 발생하는 것이다. 이를 해결하기 위해서는 사용 중인 데이터베이스의 종류를 파악하는 것이 중요한데, SQL Server로 이관이 가능한 범주 안에 있는 데이터베이스들은 우선 SQL Server로 이관한 후, 이를 SQL Azure로 다시 이관하는 작업이 필요하다. 그리고 기존 응용프로그램들도 SQL Azure를 데이터 소스로 사용할 수 있도록 일부 수정이 필요하다.


SQL Azure로 이관하는 것을 누구나 쉽게 검토해볼 수는 있다. 그러나 생각 외로 만만찮은 문제들이 쌓여있다. 기존에 사용하던 자료 형식 중 CHAR, VARCHAR, TEXT와 같이 유니코드와 호환되지 않는 문자열 자료 형식들은 이관 후 CJK 문자 세트로 구성된 데이터가 소실되므로 NCHAR, NVARCHAR, NTEXT로 업그레이드해야 한다는 부분이 있다. 날짜와 시간의 경우 이관 이전과 이관 이후의 시간대 설정 차이가 있으므로 데이터 일관성에 문제가 있을 수 있다는 점이다. 드문 경우이지만, .NET 어셈블리는 SQL Azure에 설치할 수 없으므로 이와 관련된 기능을 사용하는 경우 SQL Azure로 이관하기 전 적당한 Wrapper나 Agent를 따로 개발해야 한다. 또, 기존의 응용프로그램이 데이터베이스 연결을 헤프게 사용하는 경향이 있다면 SQL Azure 입장에서는 예고 없이 연결을 차단시킬 수 있다는 점도 숙지해야 한다. SQL Azure 서비스 자체는 공유 환경에서 실행되므로 SQL Server 인프라와는 비교할 수 없이 엄격한 정책 준수를 요구하는데, 사실 이 때문에 낭패를 보는 경우가 많다. 이런 모든 문제들을 극복하기 위해서, 데이터베이스 역시 특별한 이슈가 없다면 Windows Azure Connect를 사용하여 기존 On-Premise 환경과 구분선 없이 밀착시키는 것이 좋을 수 있다.


사실 지금 언급한 내용들만 이야기해도 Cloud로 이관하는 것보다는 이관하지 않는 것이 더 좋은 것처럼 들린다. 그래서, IT 관리자 입장에서는 무리해서 기존의 인프라를 Cloud로 이관하기 보다, 기존의 인프라나 IT 자산으로는 충당할 수 없는 새로운 영역을 Cloud를 통해 개발하고 확보하는 방법을 새로 익히는 것이 좋다. 그런 맥락에서, IT 관리자들은 Cloud 환경에 최적화된 VM-Role을 개발하는 방법을 익히고, VM-Role이 Windows Azure Connect를 통하여 기존의 Active Directory Domain Controller에 참가하도록 시스템을 구성하거나, 웹 상에서의 클레임 기반 인증을 구현할 목적으로 Active Directory Federation Services (AD FS)와 Windows Azure AppFabric Access Control을 같이 활용하는 방안을 모색하는 것이 바람직하다.


응용프로그램 개발자 관점에서 보는 Windows Azure


원래부터 그러했지만 Windows Azure는 개발자들을 위한 Cloud 플랫폼이었다. 여러 서비스들이 있지만 각각의 역할을 하나씩 소개하려 한다.


Windows Azure Compute: Windows Azure 데이터센터에서 여러분의 응용프로그램을 Hosting할 수 있도록 해주며, IIS를 활용하여 웹 응용프로그램을 실행할 수 있도록 해주는 Web Role, WCF, Socket, C, C++, Python 등 Win32 기반 시스템에서 사용 가능한 모든 종류의 응용프로그램을 실행할 수 있도록 해주는 Worker Role, 그리고 VHD 기반 이미지를 이용하여 Windows Server 2008 R2 OS를 실행할 수 있도록 해주는 VM Role을 하나의 서비스 안에서 다양한 방법으로 조합하여 실행할 수 있는 서비스이다. Windows Azure SDK에서는 VM Role을 제외한 Web Role과 Worker Role 에뮬레이터가 기본 제공된다.


Windows Azure Storage: 대용량의 데이터를 고속으로 처리할 수 있도록 해주는 특별한 저장소로, HTTP 및 HTTPS 프로토콜을 기반으로 상호 작용할 수 있기 때문에 플랫폼이나 위치에 제약이 없다. 저장소의 유형으로는, 단순 파일 저장 및 대용량 파일의 Paging 연산을 지원하는 BLOB 저장소, 행과 열의 대규모 집합 및 고속 인덱싱을 지원하는 테이블 저장소, 고속 메시지 입력 및 출력을 지원하는 큐 저장소로 구분된다. 저장소의 범주에 속하지는 않으나, Windows Azure Compute 상의 Role들이 Win32 API를 사용하여 파일 입력과 출력 연산을 수행할 수 있도록 해주는 Cloud Drive API가 Windows Azure Storage Emulator와 함께 제공된다.


Windows Azure CDN: 대한민국 및 아시아 권역에서 빠른 속도를 자랑하는 새로운 CDN 서비스 역시 Windows Azure Platform 안에 있다. 기본적으로는 Windows Azure Blob Storage에서 공개 권한으로 설정한 Block BLOB에 대해 CDN 서비스를 사용할 경우 자동으로 Mirroring이 된다. 최근 업데이트에서는 Windows Azure Storage가 아닌, 동적으로 API를 사용하여 특정 Contents를 CDN 서비스를 통해 Mirroring할 수 있게 업데이트되었고, 더불어 HTTPS도 지원하기 시작하였다.


Windows Azure AppFabric: 대규모 서비스 운영에 필요한 주요 서비스 컴포넌트 5가지를 제공하는 온라인 서비스로, Windows Server AppFabric의 기술을 바탕으로 하지만 외부에 드러나는 모습은 많이 다르다.



Windows Azure 초창기부터 지속적으로 제공되어왔던 Service Bus는 Point-to-Point 연결을 구현하는 Tunneling Mechanism을 제공한다. WCF 기술을 기반으로 하며, 서버 역할을 수행하는 WCF 호스트가 Service Bus와 연결을 맺은 뒤, WCF 클라이언트는 직접 WCF 호스트에 접근하지 않는 대신, 암호화된 연결을 사용하는 Service Bus로 방향을 바꾸어 접속을 시도하는 방식이다. 이러한 방식이 유용한 이유는, 방화벽의 존재 여부와 관계없이 네트워크 계층에 일관성이 없는 서로 다른 환경 사이를 완벽하게 연결시켜주기 때문이다.



Access Control 서비스는 또 한 번 업데이트를 준비 중에 있다. 처음 발표된 Access Control은 특정 도메인이나 기관이 운영하는 Active Directory 인프라를 기반으로 인터넷 상에서 클레임 기반 인증을 구현하기 위한 목적으로 처음 소개되었다. 인터넷 서비스를 상대로 클레임 기반 인증을 수행하는 것이기 때문에, 인트라넷 환경과는 달리 수시로 Traffic이 발생하며, 뿐만 아니라 신뢰성도 매우 중요하기 때문에 Azure AppFabric Access Control이 유용하다. 그리고 조만간 대대적인 업데이트를 통하여 Windows Live ID, Yahoo, Google, Facebook 등의 Social Networking Platform을 인증 수단으로 사용할 수 있게 되어 한층 더 폭넓은 활용 가능성을 제공한다.


Cache 서비스는 Server 버전의 AppFabric Cache를 Cloud 버전으로 제공하는 것으로, Cache를 위한 인프라를 직접 구축하지 않으면서, 같은 API, 같은 기술을 사용할 수 있는 것이 장점이다. Windows Azure Storage와 SQL Azure를 AppFabric Cache 원본으로 지정하여 사용할 경우 시간과 비용을 획기적으로 절약할 수 있다. 그리고 올해 연중으로 BizTalk Server와의 연계를 고려한 AppFabric Integration 서비스와 함께 Cloud Computing 전반을 통솔하고 제어할 수 있는 AppFabric Composite App 역시 출시될 예정에 있다.


물론 아직 부족한 서비스들도 있다. 그렇지만 이 정도 수준의 서비스라고 한다면 누구나 원하는 서비스를 제약 없이 구현해 볼 수 있지 않을까? 프로그래밍 언어나 개발 도구에 관계없이, 그리고 여러분이 실행하는 프로그램의 위치와 무관하게 말이다. 다시 강조하지만, Microsoft의 Public Cloud는 다른 Cloud Platform들처럼 강제 이주를 논하지 않는다. 모든 것은 여러분의 결정에 따라 움직이며, 매번 적절한 솔루션은 Microsoft에 의해서이든 오픈 소스 커뮤니티에 의해서이든 쓰여지고 업그레이드되어 나가고 있다. Microsoft가 말하는 Cloud Power의 진가를 확인하고 싶다면 지금 곧 Windows Azure Platform으로 떠나보자.


더 많은 정보가 필요하다면 Windows Azure 홈페이지 (http://www.windowsazure.com/)와 더불어 Windows Azure Café (http://cafe.naver.com/wazure), 그리고 .NET 기반 소프트웨어 개발을 위하여 Visual Studio 2010 한국 공식 팀 블로그 (http://www.vsts2010.net/)을 자주 찾아주기 바란다.


글쓴이 이력




  • Blog: http://7d5.32b.myftpupload.com / E-MAIL: rkttu@rkttu.com / Twitter: @rkttu


  • Windows Azure MVP (2011) / Visual C# MVP (2009-2010)


  • ㈜코아뱅크 코아기술연구소 (http://www.corebank.net) 연구원 재직 중


  • Windows Azure Café SYSOP (http://cafe.naver.com/wazure)


  • Visual Studio 2010 Team Blog (http://www.vsts2010.net) 집필진 활동 중

CloudBerry Explorer for Microsoft Azure Storage

최근에 저는 Windows Azure Storage를 관리 목적으로 편리하게 활용할 수 있는 유틸리티를 찾아 나섰습니다. 그 동안 소개했던 myazurestorage의 경우 웹 브라우저의 기능 상 한계때문에 큰 파일을 올리거나 복잡한 작업을 하기에는 부족한 부분이 많았습니다. 또한 예제 형태로 제공되던 다양항 유형의 관리 도구들 역시 미약한 부분들이 많았습니다. 그러던 중 가장 사용하기 쉽고 편리하면서도, 기본적인 모든 기능을 무료로 제공하는 멋진 유틸리티 하나를 찾았습니다. 바로 CloudBerry Explorer for Microsoft Azure Storage입니다. 원래는 Amazon S3를 위한 버전을 먼저 출시했던 제품이지만 클라우드와의 상관관계성을 반영하여 Microsoft Azure Storage에 대한 버전도 추가로 출시하였습니다.

기본적으로는 Windows Commander와 유사한 사용자 인터페이스를 가지고 있으며 양쪽을 Side-by-Side로 살펴보면서 탐색할 수 있는 기능을 제공합니다. API를 가지고 작업할 때와는 달리, 적당한 MIME TYPE을 자동으로 유추하여 지정하는 기능도 제공하고, CloudBerry Explorer에서 가장 핵심적인 기능인 동기화 기능을 제공하므로 많은 수의 파일을 업로드할 때 매우 유용하게 사용할 수 있습니다.





아직 Azure Storage의 모든 기능들을 제공하는 것은 아니지만 이 글을 쓰는 시점 이후로 추가될 것으로 예정한 기능들은 다음과 같습니다. 아래와 같은 기능들이 더 추가되면 더 나은 관리 도구로서 거듭날 수 있을 것입니다.

조건부 헤더 설정
접근 권한 목록 (ACL) 편집을 지원
서버 Timeout 지원 
컨테이너와 BLOB에 대한 메타데이터 관리 지원 
Microsoft PowerShell 연동을 통한 자동화 지원
Azure CDN에 대한 기능 지원 

CloudBerry Explorer는 Windows XP 이후부터 사용이 가능하고, Microsoft .NET Framework 2.0 이상이 시스템에 설치되어있어야 합니다. 상용 버전의 경우, 차이점 비교, 고급 동기화 기능 등을 제공하므로 더 복잡한 작업을 수행하기 원하는 경우 소프트웨어 구입을 검토해보시는 것도 괜찮습니다. 무료 버전의 경우 제한 없이 사용 가능하며, http://cloudberrylab.com/?page=explorer-azure 에서 다운로드하실 수 있습니다. 🙂

Windows Azure BLOB Storage에 올린 파일을 Silverlight와 Flash에서 활용하려면?

Windows Azure BLOB Storage는 클라우드 기반의 저장소이지만 외부에서 사용하기에 무척 편리하고 유용한 HTTP 및 HTTPS 프로토콜을 기반으로 서비스가 제공됩니다. 대화형 서버 처리 엔진이 존재하지 않는다는 점만 제외하면 HTTP 기반의 서비스를 구축하기 위해서 필요한 모든 사항이 제공되며, 파일 이어받기, ETAG 처리 등 HTTP 프로토콜의 최신 사양들을 정확히 구현하고 있습니다.

최근에 저는 Windows Azure Platform의 Storage Service를 활용하면서 또 한 가지 좋은 정보를 얻을 수 있었습니다. Windows Azure Storage를 사용하면서 가장 필요한 것 중 하나는 RIA 응용프로그램과 충분히 활용하는 전략인데, 여기에는 Smooth Streaming 뿐만 아니라 일상적으로 활용 가능한 이미지, 사운드, 비디오, 텍스트 파일들도 포함될 수 있습니다. 그러나 익히 알려진대로 보안 상의 이유 때문에 RIA 플랫폼 자체적으로는 접근하려는 원격 웹 서버의 루트 경로 상에 반드시 매니페스트 파일이 존재해야 합니다. 하지만 일반적인 클라이언트나 API를 이용해서는 우리가 아는 루트 경로 상에 BLOB 객체를 올릴 수 없습니다. 어떻게 하면 좋을까요?

여기에 대한 답이 있습니다. Windows Azure Storage는 루트 경로에 대한 예약된 컨테이너 이름을 제공합니다. 바로 $root 인데, 최상위 컨테이너 중 $root라는 이름의 컨테이너를 생성하고 여기에 파일을 업로드하면 바깥에서 보기에 루트 경로에 올라온 것과 동일하게 취급됩니다. 여기에 RIA 응용프로그램이 필요로 하는, Adobe Flash의 경우 crossdomain.xml 파일, Microsoft Silverlight의 경우 clientaccesspolicy.xml 파일을 text/xml MIME 형식으로 정확히 지정하여 업로드하면 문제가 해결됩니다.

crossdomain.xml 파일과 clientaccesspolicy.xml 파일의 예제는 휴즈플로우의 CTO이신 이길복 MVP님의 블로그 아티클 (http://gilverlight.net/2888)을 참조하시면 되겠습니다.

Windows Azure 코드 샘플 컬렉션

Windows Azure 코드 샘플을 한 곳에 모아서 찾아보기 쉽게 만든 블로그 아티클이 있어서 올려봅니다. Windows Azure 실전 예제에 관심있으신 분들께 도움이 되셨으면 합니다. 🙂
예제 응용프로그램

아키텍처 및 디자인 예제

  • 코드 갤러리
    • 동적 스케일링 샘플 – 처리량에 대응하여 동적으로 인스턴스의 수가 늘어나고 줄어드는 것을 보여주는 다중 역할 샘플입니다: http://code.msdn.microsoft.com/azurescale
  • 본사 DPE 부서에서 작성한 예제
    • Project Riviera – 동적 스케일링 샘플에서 더 확장된 예제로, 윈도 애저 스토리지, Windows Workflow, 액티브 디렉터리 페더레이션 서비스, Patterns & Practices Enterprise Library 캐싱 및 로깅 응용프로그램 블럭, 윈도 라이브 ID 인증 등 엔터프라이즈 및 아키텍처에서 등장하는 기술들이 골고루 사용된 고급 샘플입니다: http://code.msdn.microsoft.com/riviera
  • Patterns & Practice – Windows Azure Platform을 위한 아티클이 새로 업데이트되고 있는 중입니다.

클레임 / 아이덴티티 예제

환경 설정

데이터 액세스 및 스토리지 예제

응용프로그램 배포

일반적인 내용들

로깅 및 운영 전략

기존 응용프로그램을 클라우드로 마이그레이션
서비스 버스 (AppFabric)
서비스 관리 API
SQL 애저
WCF (Windows Communication Foundation)
윈도 애저 스토리지

Windows Azure Update: myAzureStorage

지난번 글 (2010/08/23 – [Cloud] – Windows Azure Update: CloudStorageAccount 클래스 사용 시 주의 사항)에 이어서 오늘은 myAzureStorage.com에 대한 내용을 소개합니다.


사이트 바로 가기: http://www.myazurestorage.com/


Windows Azure Platform의 핵심 기능들 중에서, Hosting Service (Compute) 영역 만큼 많은 비중을 차지하고 핵심적인 기능을 담당하는 것이 Storage Service (Storage) 영역입니다. 하지만 Storage Service를 단지 http://windows.azure.com/ 에서 제공하는 웹 프론트엔드로만 관리하는데에는 모자르는 점이 많은데요, 이를 효과적으로 보완하고 좀 더 쉽게 관리할 수 있는 웹 사이트를 소개합니다. 바로 myAzureStorage.com (http://www.myazurestorage.com) 이라는 사이트입니다.


myAzureStorage는 SQL Azure Labs에서 공개한 Codename: Houston과는 별도로 독립적으로 런칭된 웹 서비스로, Windows Azure의 REST Management API를 기반으로 작성된 웹 기반 관리도구이며, 별도의 사용 요금이 없으므로 편리하게 활용할 수 있습니다.


myAzureStorage.com에 접속하면 아래와 같은 로그인 화면이 나타납니다. Windows Azure Platform이 노출하는 REST Service API와의 연결을 위하여 Windows Azure Storage의 계정 ID와 Primary Access Key를 묻는 것이며 이는 http://windows.azure.com/ 에서 Storage Service 항목에 나와있는 값을 대입하면 됩니다.



사이트에 로그인하고 나서는 아래 그림과 같이 Table, Queue, BLOB Storage에 대한 접근을 할 수 있게 되어있습니다. Table Storage의 경우 테이블 스키마를 정의하고 웹 상에서 직접 데이터를 검색할 수 있습니다.





테이블 관리 기능 외에도, 큐에 쌓여있는 메시지를 조회하거나, BLOB 컨테이너 내의 파일을 편집하거나 다운로드하거나, 외부 공개 권한 설정 등을 관리할 수도 있게 되어있습니다. 이 서비스는 Windows Azure REST API를 이용하여 관리하므로 실제 트랜잭션을 일으키는 것 이외에 단순 조회 및 관리는 Windows Azure Platform의 요금 정책에 관계없이 편리하게 이용할 수 있습니다.


Windows Azure Update: CloudStorageAccount 클래스 사용 시 주의 사항

안녕하세요. Visual C# MVP 남정현입니다. 지난번 Windows Azure Update (2010/07/29 – [Cloud] – Windows Azure Update: Microsoft Project Code-Named “Houston” CTP 1) 에 이어서 오늘은 Windows Azure Cafe 내에서 발견한 이슈에 대하여 소개하는 글을 올립니다. 이 글은 Windows Azure Tools for Visual Studio 버전 1.2에 적용되며 향후에 개선될 여지가 있는 부분으로 꼭 메모해두시면 좋을만한 부분입니다.


CloudStorageAccount 클래스에 대하여


Windows Azure Platform에서 사용하는 서비스의 유형 중에서, BLOB, Table, Queue를 다루기 위해서는 Windows Azure Storage 서비스를 신청하고 여기에 직접 접근하는 API를 호출해야 하는 데, 이 때 최초에 사용자 인증을 완료하기 위하여 제일 먼저 활용하는 클래스가 바로 CloudStorageAccount 클래스입니다. 이 클래스에는 다음과 같은 멤버들을 포함하고 있습니다.



  • [static] FromConfigurationSetting: Windows Azure의 Worker – 또는 – Web Role의 개별 환경 설정 파일에 들어있는 설정 파일로부터 Storage 연결 문자열을 가져와 CloudStorageAccount 객체를 생성하는 Factory Method입니다.

  • [static] Parse: 형식과 규칙에 맞는 연결 문자열이 있을 경우 문자열을 해석하여 CloudStorageAccount 객체를 생성하는 Factory Method입니다. 만약 분석에 실패할 경우 예외를 발생시킵니다.

  • [static] SetConfigurationSettingPublisher: Windows Azure Management API 등을 통해서 동적으로 설정 내역이 바뀌었을 경우 이를 전달하고 시스템 내부에 반영하는 통지 이벤트 처리기를 등록합니다.

  • [static] TryParse: 기본적으로 Parse 메서드와 하는 일이 동일하지만, 예외를 직접 던지지 않고 실패할 경우 반환값으로 false를 반환하도록 설계되어있어 조건문 만으로 예외 상황을 처리할 수 있도록 도와주는 도우미 메서드입니다.

위의 Static Member들 중에서도 특별히 굵게 강조 표시한 메서드 2개는, 기본적으로 제공되는 프로젝트 템플릿 상에 별도의 언급도 없으며, 이에 대한 구체적인 문서를 쉽게 발견하기 힘들지만, 이 글에서 소개하는 내용을 적용하지 않았을 경우 다음의 문제가 발생할 수 있습니다.



  • FromConfigurationSettings 메서드를 호출할 때 예외가 발생합니다.

  • FromConfigurationSettings 메서드를 사용하지 않기 위하여 Role의 자체적인 Configuration File을 사용하도록 구성한 경우 설정 변경을 위하여 매번 Role을 새로 업데이트해야 하는 비효율적인 상황에 직면할 수 있습니다.

문제 해결 방법


이러한 문제를 해결하고, Storage API의 설정이 매 순간 관리 도구에 의하여 편집되고 정확히 반영될 수 있도록 하려면 SetConfigurationSettingPublisher 정적 메서드를 호출하여 이벤트 핸들러를 하나만 지정하면 됩니다. 아래의 코드를 WebRole.cs 파일 – 또는 – WorkerRole.cs 파일의 내용 중 OnStart 메서드에 추가하시면 됩니다.


CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                string connectionString;


                if (RoleEnvironment.IsAvailable) [footnote]Windows Azure SDK Simulator 위에서 실행 중이거나 실제 Windows Azure Platform 위에서 실행 중일 때 이 Static Property의 반환값은 항상 True이며, 그 외에 단순히 일반 ASP.NET 웹 사이트로 기동 중일 때에는 항상 False가 됩니다.[/footnote]
                {
                    connectionString = RoleEnvironment.GetConfigurationSettingValue(configName); [footnote]관리 도구 등에 의하여 변경된 신규 설정값을 읽습니다.[/footnote]
                }
                else
                {
                    connectionString = System.Configuration.ConfigurationManager.AppSettings[configName];
                }


                configSetter(connectionString); [footnote]실제 설정이 반영되는 구간입니다.[/footnote]
            });


같이 보기: http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/6d79ca07-f53a-4110-af46-e4edc7e34e9b 


아래 그림은 적용 예시입니다.



감사합니다. 🙂


Hello Windows Azure / Twitter 스타일 방명록 만들기 #2

지난번 글 (2010/07/27 – [Cloud Development] – Hello Windows Azure / Twitter 스타일 방명록 만들기 #1)에 이어서 오늘 시간에는 ASP.NET MVC 2를 사용하는 Web Role 위에서 jQuery, jTemplate을 이용하여 기본적인 방명록 UI를 꾸며보고, 별 다른 Worker Role의 구현 없이 Windows Azure Table Storage를 경유하여 방명록의 글을 삽입, 삭제, 변경하는 기능을 구현해보기로 하겠습니다.


시작하기 전에 (2010.08.09 Update)


지난번 코드에서 누락되거나 교정될 필요가 있는 코드를 포함하여 업데이트를 할 부분이 있어 말씀을 전합니다. TwistDataSource.cs 파일의 내용을 다음과 같이 작성해야 하며, 지난번 코드에서 변경된 부분을 밑줄로 표시해두었습니다.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using System.Data.Services.Client;
using Microsoft.WindowsAzure.StorageClient;


namespace TwistBook.DataModel
{
    public class TwistDataSource
    {
        private static CloudStorageAccount storageAccount;
        private TwistDataServiceContext serviceContext;


        static TwistDataSource()
        {
            // 중요: 실제로 응용프로그램을 Cloud 환경에 배포할 때에는
            // Cloud Project 내의 다른 환경 설정 문자열을 이용하도록
            // 호출을 변경해야 합니다.
            storageAccount = CloudStorageAccount.DevelopmentStorageAccount;


            CloudTableClient.CreateTablesFromModel(
                typeof(TwistDataServiceContext),
                storageAccount.TableEndpoint.AbsoluteUri,
                storageAccount.Credentials);
        }


        public TwistDataSource()
        {
            this.serviceContext = new TwistDataServiceContext(storageAccount);
            this.serviceContext.RetryPolicy = RetryPolicies.Retry(
                3, TimeSpan.FromSeconds(1));
        }


        public DataServiceResponse Insert(TwistModel model)
        {
            this.serviceContext.AddObject(
                TwistDataServiceContext.TwistModelName,
                model);


            return this.serviceContext.SaveChangesWithRetries();
        }


        public IEnumerable<TwistModel> Select()
        {
            var results = from eachTwist in this.serviceContext.TwistModel
                          select eachTwist;


            var query = new CloudTableQuery<TwistModel>(
                results as DataServiceQuery<TwistModel>,
                RetryPolicies.Retry(3, TimeSpan.FromSeconds(1)));


            return query.Execute();
        }


        public DataServiceResponse Delete(TwistModel model)
        {
            // 이 부분의 코드가 삭제되었습니다.
            this.serviceContext.DeleteObject(model);
            return this.serviceContext.SaveChanges();
        }


        public DataServiceResponse Update(TwistModel model)
       
{
           
this.serviceContext.UpdateObject(model);
           
return this.serviceContext.SaveChanges();
        }

    }
}


Web Role 완성하기


1. ASP.NET MVC 2 응용프로그램의 특성을 잘 살리기 위하여 AJAX 기술을 활용하는 방식으로 예제를 설명하고자 합니다. 이를 위하여 필요한 것이 jQuery와 jTemplate 라이브러리인데, jQuery의 경우 ASP.NET MVC 2 프로젝트를 만들면 자동으로 아래의 Scripts 디렉터리에 1.4 버전이 번들링되어있으니 별도로 받으실 필요가 없습니다.



 


자바스크립트 라이브러리들의 경우, 근래 들어서는 4GL 개발 도구들의 영향으로 Debug Version과 Release Version 라이브러리를 각기 개별적으로 제공하는 경우가 늘었습니다. jQuery도 이러한 추세를 잘 따르고 있으며, 위의 화면에서 jquery-1.4.1-vsdoc.js 파일은 Debug 목적 + Visual Web Developer용 Intellisense 지원을 위한 버전이고, jquery-1.4.1.js 파일은 원래의 소스 코드가 있는 그대로 (as-is) 제공되는 버전입니다. 그리고 jquery-1.4.1.min.js 파일은 원래의 소스 코드에서 주석과 공백 제거, 변수명 최소화와 같은 Obfuscation Process를 포함한 Minified Process를 거친 전송에 최적화된 버전입니다.


자바스크립트 전송에 필요한 대역폭을 좀 더 아낄 필요가 있고, 접속하는 브라우저들이 모두 G-ZIP 압축 해제 기능을 지원한다는 점을 확신할 수 있다면, WSFU (Windows Service For Unix)나 Cygwin, GNU for Win32 등을 통해서 액세스할 수 있는 GZIP 압축 유틸리티를 이용하여 Minified Version을 GZIP 파일로 한 번 더 묶어서 이를 다운로드하도록 구성하는 것도 좋은 선택이 될 수 있습니다. WSFU는 http://www.microsoft.com/downloads/details.aspx?FamilyID=896c9688-601b-44f1-81a4-02878ff11778&DisplayLang=en 에서 다운로드 가능합니다.


2. jTemplate은 jQuery를 기반으로 만들어진 플러그인으로 HTML이나 XML 컨텐츠를 지정된 지시자에 맞추어 반복 생성하거나, 내용을 치환하거나, 수식을 계산하는 등의 복잡한 연산 작업을 가능하게 합니다. 특히 JSON (Java Script Object Notation) 기반의 데이터를 내려보내어줄 것이므로 이러한 기능은 필수적입니다. jTemplate은 http://plugins.jquery.com/project/jTemplates 에서 다운로드받으실 수 있고, 압축 파일을 다운로드받으면 아래와 유사한 형태로 나타납니다.



3. jquery-jtemplates.js 파일을 선택하여 ASP.NET MVC 2 프로젝트의 Scripts 디렉터리 아래로 복사합니다. jQuery 라이브러리와 같은 위치에 배치하여 불러오기 쉽도록 만들기 위한 선택입니다.



4. Visual Studio 솔루션 탐색기에서 방금 압축 해제한 jTemplate 라이브러리의 소스 코드를 추가해야 합니다. 솔루션 탐색기에서 Web Role 프로젝트 아래의 Scripts 디렉터리를 아래 그림과 같이 클릭하고 상단 도구 모음의 “모든 파일 표시” 버튼을 클릭하면 아직 등록되지 않은 jTemplate 라이브러리의 파일이 나타납니다.




 


5. jquery.jtemplates.js 파일을 오른쪽 버튼으로 클릭하고 “프로젝트에 포함” 메뉴를 클릭하면 솔루션의 일부로 편입됩니다. 이 때, jquery.jtemplates.js 파일을 오른쪽 버튼으로 클릭하고 속성 메뉴를 선택하여 나타나는 속성 창에서 빌드 작업이 “내용”으로 선택되어있는지 반드시 확인하여 주세요. “내용”으로 선택되어있지 않은 파일은 실제 배포 때 제외될 수도 있습니다.







6. 이제 마스터 페이지에 jQuery와 jTemplate 라이브러리를 추가해야 합니다. 여기서 마스터 페이지란 페이지 전반에 걸쳐서 기본 바탕이 되는 ASP.NET 사이트 수준의 골격 템플릿입니다. PowerPoint의 마스터 슬라이드와 비슷한 개념으로 이해해도 됩니다. 마스터 페이지는 Views 폴더 아래의 Shared 폴더 아래의 Site.Master 파일이며 아래와 같은 위치에 나타납니다.




7. Site.Master 파일을 열어서 아래와 같이 수정합니다. 원래 내용에서 수정된 부분을 굵게 표시하였으며 자세한 내용은 각주를 참조하여 주십시오.


<%@ Master Language=”C#” Inherits=”System.Web.Mvc.ViewMasterPage” %>


<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd“>
<html xmlns=”http://www.w3.org/1999/xhtml“>
<head runat=”server”>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″/>
    <title><asp:ContentPlaceHolder ID=”TitleContent” runat=”server” /></title>
    <link href=”<%= Url.Content(“~/Content/Site.css”) %>” rel=”stylesheet” type=”text/css” /> [footnote]기본으로 제공되는 템플릿 코드로부터 수정한 부분으로, 마스터 페이지는 처리 과정 도중에 해석되는 파일이지만 브라우저의 입장에서 서비스를 하는 페이지가 아니기 때문에, 기본으로 제공되는 경로인 ../../Content/Stie.css는 잘못 해석될 가능성이 있습니다.

이를 예방하기 위하여 Inline Expression을 사용하여 Url.Content 메서드로 정확한 경로를 다시 가져오도록 만든 것입니다.[/footnote]
    http://%=Url.Content( [footnote]기본으로 제공되는 템플릿 코드로부터 수정한 부분으로, 마스터 페이지는 처리 과정 도중에 해석되는 파일이지만 브라우저의 입장에서 서비스를 하는 페이지가 아니기 때문에, 기본으로 제공되는 경로인 ../../Content/jquery-1.4.1.min.js는 잘못 해석될 가능성이 있습니다.

이를 예방하기 위하여 Inline Expression을 사용하여 Url.Content 메서드로 정확한 경로를 다시 가져오도록 만든 것입니다.[/footnote]
    http://%=Url.Content( [footnote]이번 시간에 JSON 기반의 데이터를 표현하기 위하여 사용할 jTemplate 라이브러리를 여기에서 지정합니다. 앞의 URL들과 마찬가지의 방법을 사용하여 정확하게 경로가 참조될 수 있도록 만들어줍니다.[/footnote]

</head>


<body>
   

<

div class=”page”>


       

<

div id=”header”>
           

               

내 MVC 응용 프로그램

           

             
           

               
           

           
           

        </div>


       

<

div id=”main”>
           


           

        </div>
    </div>
</body>
</html>


8. 웹 페이지를 위한 기본 준비는 끝났습니다. 이제 Twitter Style의 방명록을 입력받을 수 있고 보여줄 수 있는 서비스를 만들기 위하여 서비스의 중심이 되는 Controller를 구성해보도록 하겠습니다. 편의를 위하여 HomeController를 편집하도록 하겠습니다. 솔루션 탐색기에서 TwistBook.WebRole 프로젝트의 Controllers 폴더 아래의 HomeController.cs 파일을 아래 그림과 같이 선택하여 엽니다.




9. ASP.NET MVC에서 컨트롤러 내에서 Public 접근자로 노출된 각각의 Method는 이전의 ASP.NET Web Form에 비유하였을 때 개별 처리기 (ASHX 파일)에서 웹 페이지를 결정하여 내보내는 것과 같은 개념으로 최초에 사용자가 페이지에 접근할 때나, 페이지의 FORM 태그로부터 응답이 되돌아온 시점에서 모두 사용이 가능합니다. 이러한 특성을 바탕으로, HomeController는 그 자체로 API의 역할을 수행할 수 있으며 역으로 페이지를 렌더링하기 위한 컨텐츠 단위로서의 역할도 수행이 가능합니다.


HomeController.cs 파일의 내용을 아래와 같이 수정합니다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using TwistBook.DataModel;


namespace TwistBook.WebRole.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public HomeController()
            : base()
        {
        }


        public ActionResult Index()
        {
            ViewData[“Message”] = “Windows Azure 방명록 예제”;
            return View(“Index”); [footnote]기본 Index 메서드에서는 return View(); 로 호출하였지만, 다른 Controller Method에서 이 메서드를 호출하게 되는 경우, Index View가 아닌 Controller 그 자신의 View를 찾도록 기본 설계가 구성되어있기 때문에, 이를 방지하고 재 사용하기 쉬운 형태로 만들기 위해 특별히 “Index”라는 뷰 이름을 찾도록 명시한 것입니다.[/footnote]
        }


        [HttpPost] [footnote]POST 요청에 의해서만 메시지가 JSON 형식으로 내려가도록 구성하기 위한 것으로, 필요에 따라이 Attribute를 누락하고, 아래의 Json 메서드 호출에서 AllowGet 인자를 지정하면 GET 요청에 의해서도 조회 결과가 JSON으로 반환될 수 있습니다.[/footnote]
        public ActionResult RetrieveMessages()
        {
            var account = CloudStorageAccount.DevelopmentStorageAccount;
            var dataSource = new TwistDataSource();


            var results = from eachItem in dataSource.Select()
                          orderby eachItem.WrittenDate descending
                          select eachItem;


            return Json(results); [footnote]ActionResult 클래스를 상위 클래스로 두는 JSON Serialization Result 객체를 반환합니다.[/footnote]
        }


        [HttpPost]
        public ActionResult AddMessage(string name, string message, string imageUrl)
        {
            var account = CloudStorageAccount.DevelopmentStorageAccount;
            var dataSource = new TwistDataSource();
            dataSource.Insert(new TwistModel()
            {
                WriterName = name,
                WrittenDate = DateTime.Now,
                MessageBody = message,
                ImageUrl = imageUrl
            }); [footnote]데이터 삽입 직후 Commit 연산까지 한번에 처리하도록 설계된 메서드를 부르는 것입니다.[/footnote]


            return Index(); [footnote]중요: 이 함수의 결과로 나타나는 View가 AddMessage가 아니라 Index입니다.[/footnote]
        }


        public ActionResult UpdateMessage(string partitionKey, string rowKey) [footnote]동일한 메서드에 대한 오버로드이지만, GET 방식으로 호출될 수 있고, 인자를 2개를 받도록 구성되어있으므로 이 버전의 메서드에서는 View를 렌더링하는데 사용됩니다.[/footnote]
        {
            var account = CloudStorageAccount.DevelopmentStorageAccount;
            var dataSource = new TwistDataSource();
            var results = from eachItem in dataSource.Select()
                          where eachItem.PartitionKey == partitionKey
                          where eachItem.RowKey == rowKey
                          select eachItem;


            ViewData[“PartitionKey”] = partitionKey;
            ViewData[“RowKey”] = rowKey; [footnote]ViewData 컬렉션에 Update 동작을 구현하기 위해 필요한 정보를 다시 전달합니다. 나중에 View에서 이 정보를 참조하여 페이지를 렌더링하게 됩니다.[/footnote]


            if (results.Count() > 0)
            {
                var result = results.First();
                ViewData[“Name”] = result.WriterName;
                ViewData[“Message”] = result.MessageBody; [footnote]조회된 결과를 페이지 렌더링을 위하여 ViewData 컬렉션에 보관합니다.[/footnote]
            }


            return View();
        }


        [HttpPost]
        public ActionResult UpdateMessage(string partitionKey, string rowKey, string name, string message, string imageUrl) [footnote]동일한 버전의 UpdateMessage 메서드에 대한 오버로드이지만, POST 요청에만 동작하도록 설계된 버전의 Controller Method입니다.[/footnote]
        {
            var account = CloudStorageAccount.DevelopmentStorageAccount;
            var dataSource = new TwistDataSource();
            var results = from eachItem in dataSource.Select()
                          where eachItem.PartitionKey == partitionKey
                          where eachItem.RowKey == rowKey
                          select eachItem;


            if (results.Count() > 0)
            {
                var result = results.First();


                if (result != null)
                {
                    result.WriterName = name;
                    result.MessageBody = message;
                    result.WrittenDate = DateTime.Now;
                    result.ImageUrl = imageUrl;
                    dataSource.Update(result);
                    return View(“PopupUpdateView”); [footnote]편집을 마친 후, 미리 구성된 PopupUpdateView를 찾아 이동합니다. 이 뷰는 팝업창 형태로 열린 편집 창을 닫고, 팝업 창의 부모 (window.opener)를 새로 고침하도록 디자인된 뷰입니다.[/footnote]
                }
                else
                    return View(“PopupUpdateFailView”);
            }
            else
                return View(“PopupUpdateFailView”); [footnote]업데이트에 실패할 경우 보여줄 View를 지정합니다.[/footnote]
        }


        public ActionResult DeleteMessage(string partitionKey, string rowKey)
        {
            var account = CloudStorageAccount.DevelopmentStorageAccount;
            var dataSource = new TwistDataSource();
            var results = from eachItem in dataSource.Select()
                          where eachItem.PartitionKey == partitionKey
                          where eachItem.RowKey == rowKey
                          select eachItem;


            if (results.Count() > 0)
            {
                dataSource.Delete(results.First());
                return Index(); [footnote]데이터 삭제 후 Index 뷰를 다시 로드하도록 만들었습니다.[/footnote]
            }
            else
                return Index();
        }


        public ActionResult About()
        {
            return View();
        }
    }
}


10. 방명록의 기본 기능을 만들기 위하여 이제 Views 폴더 아래의 Home 폴더 아래의 Index.aspx 파일을 열어서 편집해야 합니다. 아래 그림과 같은 위치에 존재합니다.




<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage” %>


<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>
    홈 페이지
</asp:Content>


<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent” runat=”server”>
   
        $(document).ready(function () {
            $.ajax({
                type: ‘POST’, [footnote]XmlHttpRequest 객체를 이용하여 전송할 때 POST 방식으로 요청하는 것을 명시하고 있습니다.[/footnote]
                url: ”, [footnote]RetrieveMessages Controller Method를 정확히 찾을 수 있도록 전체 경로를 반환하는 함수를 사용하여 스크립트 위에 렌더링합니다.[/footnote]
                data: ‘{}’,
                contentType: ‘application/json; charset=utf-8’,
                dataType: ‘json’, [footnote]JSON 방식의 결과 집합이 필요함을 명시하고, JSON 방식으로 데이터를 받아들이도록 구성하고 있습니다.[/footnote]
                success: function (data) {
                    var targetDiv = $(‘#guestbookList’);  [footnote]jTemplate 엔진으로 치환된 내용을 렌더링할 대상 div element를 찾습니다.[/footnote]
                    targetDiv.setTemplate($(‘#templateContent’).html()); [footnote]기준이 되는 템플릿 컨텐츠를 로드합니다. 이스케이프 문자로 복잡하게 처리하지 않고 편리하게 다룰 수 있도록 만들기 위하여, JavaScript나 VBScript로 해석되지 않도록 처리한 별도의 SCRIPT element로부터 로드하도록 구성하였습니다.[/footnote]
                    targetDiv.processTemplate(data); [footnote]jTemplate 엔진을 이용하여 주어진 데이터를 통해 렌더링을 시작합니다.[/footnote]
                }
            });
        });
   
   
   
    {#foreach $T as record}
   

       
       

           

RT @{$T.record.WriterName} {$T.record.MessageBody}

           

{$T.record.WrittenDate} via cloud

            ?partitionKey={$T.record.PartitionKey}&rowKey={$T.record.RowKey}’, ‘editWindow’, ‘location=1,status=1,scrollbars=1,width=300,height=200’);”>편집
             | 
            ?partitionKey={$T.record.PartitionKey}&rowKey={$T.record.RowKey}” target=”_self”>삭제
       

       

   

    {#/for}
    [footnote]렌더링에 필요한 템플릿 코드가 이곳에 기술됩니다. 이 부분은 스크립트 태그 안에 있지만 스크립트 해석기에 의하여 처리되지는 않으며, 또한 시각적으로 드러나지도 않습니다. (as-is string으로 해석됩니다.)[/footnote]


    <h2><%= ViewData[“Message”] %></h2>
   

<

div>
       

                           { %> [footnote]메시지를 추가하기 위한 form 데이터를 구성하고 있습니다.[/footnote]
              
               [footnote]Controller Method의 name 매개 변수와 이름을 같게 지정합니다.[/footnote]
              


              
              
[footnote]Controller Method의 message 매개 변수와 이름을 같게 지정합니다.[/footnote]


                 [footnote]전송 버튼과 초기화 버튼이 trigger 역할을 하여 데이터를 전송하거나 리셋하는 역할을 합니다.[/footnote]
              

           
       

        <br /><br />
       

 [footnote]방명록 목록은 이 요소 아래에 rendering 될 것입니다.[/footnote]
    </div>
</asp:Content>


11. 방명록 내용을 편집하기 위한 팝업 창을 위한 뷰와, 댓글 편집이 끝난 뒤 취할 동작을 프로그래밍한 자바스크립트 코드를 위한 뷰는 Partial View로 디자인해야 합니다. 이 중에서 우선 방명록 항목 편집을 위한 Partial View를 추가하기 위해, 솔루션 탐색기에서 Views 디렉터리 아래의 Home 디렉터리를 오른쪽 버튼으로 클릭하고, View 추가 메뉴를 아래 그림과 같이 선택합니다.




12. View의 이름은 UpdateMessage로 지정하고, Partial View에 체크하여 아래 대화 상자와 같이 옵션을 구성한 후 확인 버튼을 클릭합니다.




13. UpdateMessage.ascx 파일의 내용을 다음과 같이 작성합니다.


<%@ Control Language=”C#” Inherits=”System.Web.Mvc.ViewUserControl<dynamic>” %>

           { %> [footnote]UpdateMessage의 POST 전송 대상을 찾아 업데이트 작업을 수행하도록 만듭니다.[/footnote]
      
       [footnote]링크에 의하여 GET 방식으로 전달된 매개 변수를 다시 렌더링하여 재사용합니다.[/footnote]


        
       [footnote]ViewData에 저장된 기존 데이터를 꺼내옵니다.[/footnote]
      


       [footnote]ViewData에 저장된 기존 데이터를 꺼내옵니다.[/footnote]
      


         [footnote]전송 버튼과 초기화 버튼이 trigger 역할을 하여 데이터를 전송하거나 리셋하는 역할을 합니다.[/footnote]
      

   


14. 이어서 솔루션 탐색기에서 Views 디렉터리 아래의 Home 디렉터리를 오른쪽 버튼으로 클릭하고, View 추가 메뉴를 11단계에서와 같이 선택합니다.



15. View의 이름은 PopupUpdateView로 지정하고, Partial View에 체크하여 아래 대화 상자와 같이 옵션을 구성한 후 확인 버튼을 클릭합니다.




16. PopupUpdateView.ascx 파일의 내용을 다음과 같이 작성합니다.


<%@ Control Language=”C#” Inherits=”System.Web.Mvc.ViewUserControl<dynamic>” %>

    try {
        window.close(); [footnote]팝업 창을 닫습니다.[/footnote]
        if (window.opener && !window.opener.closed) {
            window.opener.location.href = ”; [footnote]팝업 부모 창이 유효하다면, 정확한 Index View의 URL을 찾아 다시 로드하도록 만듭니다.[/footnote]
        }
    } catch (ex) {
    }


17. 이어서 솔루션 탐색기에서 Views 디렉터리 아래의 Home 디렉터리를 오른쪽 버튼으로 클릭하고, View 추가 메뉴를 11단계에서와 같이 선택합니다.




18. View의 이름은 PopupUpdateFailView로 지정하고, Partial View에 체크하여 아래 대화 상자와 같이 옵션을 구성한 후 확인 버튼을 클릭합니다.




19. PopupUpdateFailView.ascx 파일의 내용을 다음과 같이 작성합니다.


<%@ Control Language=”C#” Inherits=”System.Web.Mvc.ViewUserControl<dynamic>” %>
<h3>업데이트에 실패하였습니다.</h3>
<a href=”#” onclick=”window.close()”>창 닫기</a>


20. 기본적인 방명록 글 남기기와 조회 기능이 올바르게 작동하는지 확인하기 위하여 시뮬레이터를 디버그 모드로 시작해야 합니다. 일반적인 응용프로그램 개발 때와 마찬가지로 F5키를 눌러서 디버그 모드로 시뮬레이터에 패키지를 배포하고 디버거를 연결할 수 있습니다. 이 때, 아래 그림과 같은 오류 메시지가 나타나면 관리자 권한이 아닌 상태에서 Visual Studio를 시작한 것이므로 Visual Studio를 종료한 뒤 “개발 도구 시작하기 및 프로젝트 생성하기” Chapter의 1단계를 참고하여 관리자 모드로 Visual Studio를 다시 시작해야 합니다.




21. 아래의 그림들에서처럼 기능들이 정상적으로 진행된다면 우선 이번 시간에 진행할 기본 기능들에 대한 소개와 작업이 끝난 것입니다.





이번 Article을 작성하면서 발견한 Windows Azure SDK 1.2에 대한 문제 한 가지


좀 더 완성에 가까워질수록 해결될 문제들 중에 한 가지가 될 예정이긴 하겠습니다만 실습하는 도중 불편함이 예상되어 제가 발견한 문제를 블로그 아티클을 통하여 미리 공유하고자 합니다. 간혹 Windows Azure Local Storage의 Table Storage에 아래와 같이 MBCS (Multi-Byte Character Set) 문자가 포함된 데이터를 삽입하려고 할 때 별 다른 까닭없이 HTTP/404 오류가 나타나는 경우가 있습니다.



사용자 코드에서 System.Data.Services.Client.DataServiceRequestException이(가) 처리되지 않았습니다.
  Message=이 요청을 처리하는 동안 오류가 발생했습니다.
  Source=Microsoft.WindowsAzure.StorageClient
  StackTrace:
       위치: Microsoft.WindowsAzure.StorageClient.Tasks.Task1.get_Result()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: Microsoft.WindowsAzure.StorageClient.Tasks.Task1.ExecuteAndWait()
       위치: Microsoft.WindowsAzure.StorageClient.TaskImplHelper.ExecuteImplWithRetry[T](Func2 impl, RetryPolicy policy)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: Microsoft.WindowsAzure.StorageClient.TableServiceContext.SaveChangesWithRetries(SaveChangesOptions options)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: Microsoft.WindowsAzure.StorageClient.TableServiceContext.SaveChangesWithRetries()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: TwistBook.DataModel.TwistDataSource.Insert(TwistModel model) 파일 d:users남정현documentsvisual studio 2010ProjectsTwistBookTwistBook.DataModelTwistDataSource.cs:줄 42<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: TwistBook.WebRole.Controllers.HomeController.AddMessage(String name, String message, String imageUrl) 파일 d:users남정현documentsvisual studio 2010ProjectsTwistBookTwistBook.WebRoleControllersHomeController.cs:줄 44<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: lambda_method(Closure , ControllerBase , Object[] )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters)
       위치: System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: System.Web.Mvc.ControllerActionInvoker.&lt;&gt;c__DisplayClassd.&lt;InvokeActionMethodWithFilters&gt;b__a()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 위치: System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation)
  InnerException: System.Data.Services.Client.DataServiceClientException
       Message=<?xml version=”1.0″ encoding=”utf-8″ standalone=”yes”?>
<error xmlns=”http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“>
  <code>InvalidInput</code>
  <message xml:lang=”ko-KR”>One of the request inputs is not valid.</message>
</error>
       Source=System.Data.Services.Client
       StatusCode=400
       StackTrace:
            위치: System.Data.Services.Client.DataServiceContext.SaveResult.<HandleBatchResponse>d__1e.MoveNext()
       InnerException:






실제 Windows Azure 실행 환경에서는 이러한 현상이 나타나지 않는 것으로 보입니다. 추후, 이러한 문제점을 해결할 수 있는 방안이 발견되면 별도의 업데이트 소식을 통하여 정보가 전달될 수 있도록 하겠습니다. 예제를 기반으로 테스트 패브릭 위에서 테스트하시는 동안에는 Table Storage에 한글, 히라가나, 카타카나, 번체, 간체, 한자 등의 데이터가 들어가지 않는 범위에서 테스트가 필요할 것 같습니다.


다음 시간에는


다음 시간에는 각 Role이 어떤 방법으로 Windows Azure 환경에서 실행되는지, Web Role과 Worker Role이 Cloud Computing 환경에서 상호 작용하고 통신하는 방법을 본격적으로 소개하고, 오늘 만든 Web Role을 어떤 방식으로 수정하게 될 것이고, Worker Role이 어떤 방식으로 데이터를 교환하게 될 것인지를 보여드릴 예정입니다. 그리고 이번 시간에 언급하지 않은 BLOB Storage에 이미지를 저장하고 가져오는 방법에 대해서도 소개하겠습니다. 🙂


더운 여름 날씨에 건강 유의하시고, 활기찬 여름 보내시기 바랍니다. 감사합니다.


ps. Windows Azure Cafe (http://cafe.naver.com/wazure) 에서 2010년 8월 14일부터 본격적으로 Offline Study를 진행합니다. Windows Azure Platform의 학습에 관심있으신 개발자 여러분들의 많은 관심과 참여 부탁드리며, 아울러 Visual Studio 2010 공식 팀 블로그에서 Cloud Computing 관련 Article을 집필하실 열정적인 Blogger 여러분도 함께 모시고 있습니다. 이에 관련된 모든 상세한 내용은 Windows Azure Cafe를 통하여 저에게 연락 주시면 상세히 안내해드리겠습니다. 감사합니다. 🙂


Hello Windows Azure / Twitter 스타일 방명록 만들기 #1

꼭 읽어주세요: 이 글이 작성된 현 시점에 가장 최신 버전의 Azure Tools는 버전 1.2입니다. 이 강좌를 시작하시기 전에 Windows Azure Tools for Visual Studio를 1.2 버전으로 업그레이드하여 주십시오. 이전 버전을 설치하신 경우에는 SDK와 Tools를 모두 완전히 제거한 후 1.2 버전으로 새로 설치하여 주십시오. Windows Azure Tools for Visual Studio 1.2 한글판 다운로드는 http://www.microsoft.com/downloads/details.aspx?displaylang=ko&FamilyID=2274a0a8-5d37-4eac-b50a-e197dc340f6f 에서 가능합니다.


지난번 글 (2010/06/07 – [Cloud Development] – Hello Windows Azure / Understanding Windows Azure Development Process)에 이어서, 오늘부터는 Twitter 스타일 방명록 만들기 첫 번째 시간입니다. 이번 시간에는 Windows Azure 프로젝트를 만들고, 데이터 모델을 작성하고 파악하는 것을 실습 목표로 정의하고자 합니다.


빠르고 편리한 실습을 위하여, Visual Web Developer 2010 Express를 사용하여 실습하는 것을 기준으로 하겠습니다. Visual Studio 2010이 이미 설치되어있으신 경우 이를 이용하셔도 됩니다. 어떤 개발 도구를 사용하더라도 반드시 Windows Azure Tools for Visual Studio가 설치되어있어야 하며 설치 방법은 2010/06/03 – [Cloud Development] – Hello Windows Azure / Windows Azure 개발 환경의 구축 에서 소개하는 내용에 따라 완료하여 주시기 바랍니다.


개발 도구 시작하기 및 프로젝트 생성하기


1. Visual Web Developer 2010 Express (또는 Visual Studio 2010)를 권한 상승 시킨 상태에서 시작하도록 합니다. 아래의 그림을 참고하세요. 사용자 계정 컨트롤을 사용하고 있을 경우 별도의 경고 대화 상자가 나타날 수 있으며 실행하도록 선택하시면 됩니다.



2. Visual Web Developer 2010 Express가 실행되면 초기 화면에서 새 프로젝트 만들기 링크를 클릭합니다.



3. 아래에 표시된 대화 상자에서 왼쪽의 개발 범주를 Cloud로 선택하면 사용 가능한 프로젝트 템플릿 중에서 “Windows Azure 클라우드 서비스”가 나타납니다. 이 항목을 클릭하고, 프로젝트 이름을 원하는 이름 (여기서는 TwistBook이라고 하겠습니다.)을 지정한 후, “솔루션용 디렉터리 만들기”에 체크하고 “확인” 버튼을 클릭합니다.



 


특별히 솔루션용 디렉터리 만들기에 체크가 되어있는지를 확인하는 이유는, 이 옵션이 Windows Azure Tools로 생성되는 프로젝트의 특성 상 한 솔루션 안에 다수의 프로젝트가 만들어지기 때문에 이를 정확하게 분류하기 위하여 사용하는 옵션으로, 사용하도록 맞추어져있을 때 좀 더 소스 코드 관리가 편리하기 때문입니다.


4. 배포할 Windows Azure 응용프로그램 내에 배치될 Role의 종류와 유형을 설정하는 추가 프로젝트 마법사가 아래와 같이 나타납니다. (만약 아래 화면 대신 HTML 페이지로 안내 페이지가 나타나는 경우 Azure Tools가 올바르게 설치되지 않은 상태입니다.)




5. .NET Framework 4 역할 그룹과 클라우드 서비스 솔루션 그룹 사이의 두 개의 버튼을 이용하여 실제로 제작할 프로젝트의 유형을 설정하고 프로젝트의 이름까지 정할 수 있습니다. 우선 ASP.NET MVC 2 웹 역할 프로젝트 한 개와 작업자 역할 프로젝트 한 개를 추가하겠습니다.




6. 이제 각 프로젝트의 정확한 이름을 설정하기 위하여, 클라우드 서비스 솔루션 그룹 안에 추가된 프로젝트 중 MvcWebRole1 프로젝트 항목을 선택하면 연필 모양의 아이콘이 이름 옆에 나타납니다. 이를 클릭하면 아래와 같이 이름을 바꿀 수 있도록 편집 영역이 나타납니다. 이 예제에서는 다음과 같이 이름을 정하였습니다.


– MvcWebRole1 => TwistBook.WebRole
– WorkerRole1 => TwistBook.LinkProcessor


이름을 편집하고 나면 아래와 같은 화면이 되어있을 것입니다. 확인 버튼을 눌러 프로젝트를 생성합니다.




7. 프로젝트의 생성을 진행하다보면 Visual Studio 2010 Professional 이상의 버전에서는 다른 ASP.NET MVC 2 프로젝트와 마찬가지로 테스트 프로젝트를 만들것인지를 물어보는 대화 상자가 나타납니다. 빠른 설명과 간결한 진행을 위하여 테스트 프로젝트를 생성하지 않는 방향으로 이 예제에서는 진행하도록 하겠습니다. (필요하신 분들께서는 생성하셔도 됩니다.) Visual Web Developer 2010 Express Edition에서는 이러한 대화 상자가 따로 나타나지 않습니다.


8. 프로젝트 생성이 끝나면 아래와 같이 솔루션 탐색기에 총 3개의 프로젝트가 열거됩니다.




TwistBook 프로젝트는 Cloud Application 전체를 총괄하는 프로젝트이며, Cloud 환경에서 하나의 Application으로 분류됩니다. 이 프로젝트 안에 Web Role과 Worker Role이 다수 연결되는 구조로 되어있으며, 나중에 Cloud Service Package 파일 (CSPKG)로 컴파일될 때 이 프로젝트가 기준이 됩니다.


TwistBook.WebRole 프로젝트는 ASP.NET MVC 2를 사용하도록 프로젝트가 구성되어있으며 여기에 기본적인 트위터 스타일의 방명록 UI를 표시하거나 인증된 사용자로부터 메시지를 입력받아 Worker Role에게 처리를 위임하는 등의 작업을 수행하도록 코드를 구성할 것입니다.


그리고 TwistBook.LinkProcessor 프로젝트는 Web Role과는 따로 실행되는 개별적인 Role 인스턴스로서, Web Role에서 받아들이는 메시지 중 이미지 파일을 twitpic.com에 게시하여 짧은 URL을 받아온다거나, 본문에 있는 긴 URL을 짧게 만들어 받아오는것과 같이 처리량이 많이 몰렸을 경우 병목 현상을 일으킬 수 있는 기능만을 전담하도록 코드를 구성할 것입니다.


자료 구조 만들기


1. 클라우드 환경 내부 및 외부에서 기준이 될 모델 자료 구조를 만들기 위하여, 별도의 클래스 라이브러리를 작성하도록 하겠습니다. 솔루션 탐색기에서 솔루션 항목을 오른쪽 버튼으로 클릭하고 아래 그림처럼 새 프로젝트 추가 메뉴를 클릭합니다.




2. 일반적인 클래스 라이브러리 프로젝트를 하나 만듭니다. 이름은 TwistBook.DataModel로 지정하고, Cloud 환경 위에서 사용하도록 현재 지정된 .NET Framework 4와 동일한 빌드 타겟이 지정되어있는지 확인한 후 프로젝트를 생성합니다.



3. TwistBook.DataModel 프로젝트에 Windows Azure Table Storage에서 사용할 Data Context 클래스를 만들도록 하겠습니다.[footnote]이 샘플에서 Windows Azure Storage를 이용하는 방향으로 설명이 되어있지만, 실제로 여러분이 개발할 Windows Azure 서비스에서는 SQL Azure나 다른 곳에 배치되어있을 고가용성의 관계형 데이터베이스 시스템 (예: SQL Server 2008 R2)을 이용하는 것이 더 좋을 수 있습니다.[/footnote]


Data Context 클래스를 만들기 위해서는 Windows Azure SDK에서 제공하는 클래스 라이브러리 파일들을 TwistBook.DataModel 프로젝트 참조에 포함시켜야 합니다. 아래 그림과 같이 솔루션 탐색기에서 TwistBook.DataModel 프로젝트 아래의 참조 항목을 오른쪽 버튼으로 클릭하고 “참조 추가” 메뉴를 클릭합니다.




4. 참조 추가 대화 상자가 나타나면, .NET 탭을 클릭합니다. 이 과정에서 비동기적으로 Visual Studio가 관리하는 디렉터리 목록 내에 있는 모든 어셈블리들을 조사하여 실시간으로 리스트 박스에 추가합니다. 이 샘플에서 필요로 하는 SDK의 라이브러리가 목록에 나타나기까지 조금 시간이 걸릴 수 있으며 시스템마다 차이가 있을 수 있지만 약 1분 이내에 나타납니다.




5. 나타난 항목들 중에서 다음의 항목들을 찾아 키보드의 Ctrl 키를 누른채로 하나씩 클릭하면, 아래 그림과 같이 여러 대상을 선택하고 참조로 추가할 수 있습니다.


* System.Data.Services.Client
* Microsoft.WindowsAzure.StorageClient




6. 아래 그림과 같이 참조 목록이 구성되어있으면 준비가 다 된것입니다. 이제 본격적으로 코드 작성을 시작해 보도록 하겠습니다. 🙂




7. 기본으로 만들어진 클래스가 담겨있는 Class1.cs 파일의 내용을 아래와 같이 작성합니다. 코드에서 핵심이 되는 부분을 굵게 표시하였습니다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure.StorageClient; [footnote]Windows Azure SDK와 함께 제공되는 Table Storage를 위한 API가 포함되어있는 네임스페이스입니다.[/footnote]


namespace TwistBook.DataModel
{
    public class TwistModel : TableServiceEntity [footnote]TableServiceEntity 클래스를 상속받도록 자료 구조를 만들어야 SDK를 이용하여 Table Storage에 데이터를 저장하거나 가져올 수 있습니다.[/footnote]
    {
        public TwistModel()
        {
            DateTime current = DateTime.Now;
            PartitionKey = current.ToString(“yyyyMMdd”);
            RowKey = current.ToString(“hhmmss”); [footnote]TableServiceEntity 클래스의 기능을 적용하기 위하여 동일한 시그니처를 가진 생성자를 하나 만듭니다.

Table Storage의 접근 효율성을 위하여, 테이블은 여러 개의 파티션으로 구분됩니다. 이 샘플에서 파티션의 분리 단위로 “날짜”를 사용하였습니다.

그리고 파티션 내에서 각각의 Entity가 고유한 의미를 가질 수 있게 하기 위하여 Row Key를 사용하여 구분합니다.

Partiton Key와 Row Key가 더해져서 테이블 내에서는 이 Entity가 “유일할 수 있다”는 특성을 보장합니다.[/footnote]
        }


        public string WriterName { get; set; }
        public string MessageBody { get; set; }
        public DateTime WrittenDate { get; set; }
        public string ImageUrl { get; set; } [footnote]WriterName Property는 작성자의 이름, MessageBody Property는 메시지 본문, WrittenDate Property는 작성한 날짜와 시간을, ImageUrl Property는 같이 첨부하는 사진의 URL을 보관하는 목적으로 사용됩니다.

C# 3.0 이후로 지원되는 단축 Property Getter/Setter 선언으로 별도의 private 멤버 변수를 배치하지 않고 이와 같이 단순한 코드를 만들 수 있습니다.[/footnote]
    }
}


8. Class1.cs 파일의 이름을 클래스 이름과 동일하게 설정합니다. Windows 탐색기를 열지 않고, 아래의 그림에서처럼 솔루션 탐색기에서 직접 이름을 바꿀 수 있으며, Class1.cs 파일을 TwistModel.cs 파일로 이름을 변경합니다.




9. TwistBook.DataModel 프로젝트에 Windows Azure Table Storage에서 사용할 Data Context 클래스를 만들도록 하겠습니다. 새 항목을 프로젝트에 추가하기 위하여 아래 그림과 같이 솔루션 탐색기에서 TwistBook.DataModel 프로젝트 항목을 오른쪽 버튼으로 클릭하면 “추가” – “새 항목 추가” 메뉴가 나타나는데 이를 클릭하시면 됩니다.




10. 새 항목 추가 대화 상자에서 설치된 템플릿 영역에서 “Visual C# 템플릿”을 선택하고, 우측 목록에서 “클래스”를 선택합니다. 그리고 이름에 새로 추가할 클래스의 이름을 지정한 후 “추가” 버튼을 클릭합니다. 9단계와 10단계를 거쳐서 다음의 파일들을 추가로 생성합니다.


* TwistDataServiceContext.cs
* TwistDataSource.cs





11. 솔루션 탐색기 내의 TwistBook.DataModel 프로젝트 항목 아래에 다음 그림과 같이 구성이 되어있으면 정상적으로 추가가 된 것입니다.




12. 이제 TwistDataServiceContext.cs 파일을 열어서 다음과 같이 코드를 작성합니다. 코드에서 중요한 부분은 굵은 글씨로 표현하였고 여기에 따른 부가적인 설명을 각주로 붙였습니다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient; [footnote]Windows Azure SDK와 함께 제공되는 Table Storage를 위한 API가 포함되어있는 네임스페이스입니다.[/footnote]


namespace TwistBook.DataModel
{
    internal class TwistDataServiceContext : TableServiceContext [footnote]LINQ를 이용하여 손쉽게 데이터를 가져오거나 설정할 수 있도록 LINQ의 설정을 확장해주는 기본 추상 클래스입니다.[/footnote]
    {
        internal TwistDataServiceContext(CloudStorageAccount account)
            : base(account.TableEndpoint.AbsoluteUri, account.Credentials) [footnote]CSCFG 파일 상의 정보를 표현하는 객체인 CloudStorageAccount를 생성자에서 인자로 받아 이 객체를 초기화하고, Windows Azure Storage와의 연결을 초기화합니다.[/footnote]
        {
        }


        internal const string TwistModelName = “TwistModel”;


        public IQueryable<TwistModel> TwistModel [footnote]지연 실행을 목적으로 하는 질의 객체를 생성합니다. 지연 실행이란, 각각의 요소를 다룰 필요가 있을 때 식을 계산하고 평가하는 방식으로, 전체의 내용을 미리 메모리에 읽어들여서 처리하는 것과는 차이가 있습니다.

이 객체는 앞서 우리가 정의한 TwistModel 클래스를 트랜잭션의 단위로 사용하도록 SDK 내의 프레임워크에서 생성됩니다.[/footnote]
        {
            get { return this.CreateQuery<TwistModel>(TwistModelName); } [footnote]주의: 엔티티 클래스의 이름, ServiceContext에서 노출하는 프로퍼티의 이름, CreateQuery 메서드에 전달하는 테이블 명의 이름이 모두 같아야 혼선없이 올바르게 동작할 수 있음을 보증할 수 있습니다.[/footnote]
        }

    }
}


13. 이어서 TwistDataSource.cs 파일을 열어서 다음과 같이 코드를 작성합니다. 코드에서 중요한 부분은 굵은 글씨로 표현하였고 이에 따른 부가적인 설명을 각주로 붙였습니다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using System.Data.Services.Client;
using Microsoft.WindowsAzure.StorageClient; [footnote]LINQ to Azure Table Storage를 활용하는데에 필요한 클래스 및 원격 데이터 액세스에 필요한 클래스들이 굵게 강조 표시한 3개의 네임스페이스 안에 모두 포함되어있습니다.[/footnote]


namespace TwistBook.DataModel
{
    public class TwistDataSource
    {
        private static CloudStorageAccount storageAccount;
        private TwistDataServiceContext serviceContext;

        static TwistDataSource()
        {
            // 중요: 실제로 응용프로그램을 Cloud 환경에 배포할 때에는
            // Cloud Project 내의 다른 환경 설정 문자열을 이용하도록
            // 호출을 변경해야 합니다.
           storageAccount = CloudStorageAccount.DevelopmentStorageAccount; [footnote]현재는 실제 Windows Azure Storage 계정을 지정하지 않고 Local Development Storage 계정을 대신 지정합니다.[/footnote]

           CloudTableClient.CreateTablesFromModel(
                typeof(TwistDataServiceContext),
                storageAccount.TableEndpoint.AbsoluteUri,
                storageAccount.Credentials); [footnote]테이블 모델을 생성할 때 사용할 기준이 될 DataContext 클래스를 선택하고, 생성을 요청합니다. 이 때 접속할 대상 스토리지의 HTTP 주소와 자격 증명 정보도 한꺼번에 지정합니다.

또한, 이 작업은 TwistDataSource 클래스를 프레임워크에서 로드할 때 한 번만 발생할 수 있도록 유도하기 위하여 정적 생성자에 정의하였습니다. 테이블의 초기 구조를 할당하는 작업은 자주 일어날 필요가 없는 작업이기 때문에 성능 상의 이득을 위하여 이와 같이 작성합니다.[/footnote]
        }


        public TwistDataSource()
        {
            this.serviceContext = new TwistDataServiceContext(storageAccount); [footnote]서비스 객체를 초기화합니다. 앞에서 가져온 계정 정보를 사용하여 복원된 계정 정보 객체를 사용하여 초기화하고 있다는 점을 확인하십시오.[/footnote]
            this.serviceContext.RetryPolicy = RetryPolicies.Retry(
                3, TimeSpan.FromSeconds(1)); [footnote]혹시 있을지 모르는 장애에 대해 좀 더 완벽한 대비를 위하여, 재시도 정책을 설정할 수 있습니다. (이 부분은 매우 중요한 개념입니다.) 첫 번째 인자에는 재시도 횟수, 그리고 두 번째 인자에는 재시도 간격을 TimeSpan 객체를 이용하여 지정할 수 있습니다. 여기서는 처음 실패가 발생한 시점을 기준으로 3회 더 시도하며 각 시도 간격은 1초로 정합니다.[/footnote]

        }


        public DataServiceResponse Insert(TwistModel model)
        {
            this.serviceContext.AddObject(
                TwistDataServiceContext.TwistModelName,
                model); [footnote]전형적인 LINQ to Entity 서비스와 마찬가지로 AddObject를 이용하여 객체의 참조를 기반으로 새로운 데이터를 추가할 수 있습니다.[/footnote]


            return this.serviceContext.SaveChanges(); [footnote]트랜잭션 개념을 기본적으로 사용하므로 SaveChanges 메서드는 삽입, 변경, 삭제 작업이 있은 직후에는 반드시 병행되어야 합니다.[/footnote]
        }


        public IEnumerable<TwistModel> Select()
        {
            var results = from eachTwist in this.serviceContext.TwistTable
                          select eachTwist; [footnote]Windows Azure Table Storage에 전송할 Query를 지연된 실행을 위한 객체로 초기화합니다. 이 문장이 실행되었다고해서 곧바로 데이터가 수집되는 것은 아닙니다.[/footnote]


            var query = new CloudTableQuery<TwistModel>(
                results as DataServiceQuery<TwistModel>,
                RetryPolicies.Retry(3, TimeSpan.FromSeconds(1))); [footnote]Windows Azure Table Storage에 실제로 Query를 전송할 클라이언트 객체를 초기화하고, 이 객체의 재시도 정책도 추가로 정의할 수 있습니다. 여기서도 3회 재시도, 매 시도마다 1초 간격을 두기로 설정합니다.[/footnote]


            return query.Execute(); [footnote]비로소 이 부분에서야 실제 전송과 데이터 수집이 발생하게 됩니다.[/footnote]
        }


        public DataServiceResponse Delete(TwistModel model)
        {
            this.serviceContext.AttachTo(
                TwistDataServiceContext.TwistModelName,
                model, ““); [footnote]Table Storage에서 객체를 삭제할 때에는 삭제를 위하여 검색할 대상을 지정해야 하며 이 때 사용하는 것이 AttachTo 메서드입니다. 이 메서드를 이용하여 어떤 테이블에서 어떠한 유형의 데이터를 검색할 것인지를 서비스 객체에 지정합니다.[/footnote]


            this.serviceContext.DeleteObject(model);
            return this.serviceContext.SaveChanges();
        }
    }
}


Preface: ASP.NET MVC 2 Web Role에 대한 이해


다음 Article의 내용을 올리기 전에, ASP.NET MVC 2에 대한 이해를 돕기 위하여 간단한 단락 하나를 구성하였습니다. ASP.NET MVC 2는 Microsoft의 최신 웹 기술이 적용된 프레임워크로 Windows Azure 개발 환경에서 뿐만 아니라 일반적인 웹 사이트 개발에도 얼마든지 활용될 수 있는 유용한 프레임워크입니다.


TwistBook.WebRole 프로젝트의 노드를 솔루션 탐색기에서 살펴보면 아래와 같은 구성이 나타납니다. 이 구성은 전형적인 ASP.NET MVC 응용프로그램이며, 고전적인 웹 프로그래밍 모델에서와는 달리 직접 aspx 페이지를 부르지 않고 알기 쉬운 주소를 기반으로하는 것이 특징입니다. ASP.NET MVC 응용프로그램을 처음 접하시는 분들을 위하여 디렉터리 구조에 대한 설명을 잠시 말씀드립니다.




App_Data: ASP.NET 응용프로그램이 데이터베이스에 연결하기 위하여 필요한 각종 코드 및 데이터베이스 연결 설정 파일들을 보관하는 디렉터리이며, ASP.NET 2.0부터 존재해왔던 디렉터리입니다. 예외적으로 이 디렉터리에는 Microsoft Access 파일 (.mdb 또는 .accdb)이나 소규모 웹 사이트를 위한 Embedding 가능한 SQL 데이터베이스 파일 (.mdf 및 *.ldf)이 배치되기도 합니다.


Content: ASP.NET MVC 응용프로그램 전반에 걸쳐서 사용되는 공통적인 클라이언트측 구성 요소 (가령 CSS 스타일 시트, XSLT 스타일 시트, 이미지 파일, 오디오 파일 등)가 이 디렉터리에 저장됩니다. 이 디렉터리에 저장된 파일들은 중간 처리기에 의하여 해석되지 않는 고유한 경로를 유지할 수 있습니다.


[중요] Controllers: ASP.NET MVC 응용프로그램에서 “C”를 대표하는 구성 요소가 저장되는 디렉터리이며 백그라운드에서 웹 페이지를 그리거나, 웹 브라우저로부터 받아온 정보를 해석하거나, 가공하거나, 처리하는 제어 코드를 이곳에 배치합니다.


[중요] Models: ASP.NET MVC 응용프로그램에서 “M”을 대표하는 구성 요소가 저장되는 디렉터리이며 주로 Controller 간의 통신, 데이터베이스와의 통신, 클라이언트로의 통신 등에서 기본 단위가 되는 데이터나 모델을 표현하는 클래스 코드를 이곳에 배치합니다. 이곳에 배치되는 코드에는 로직이 포함되지 않는 것을 원칙으로하며, 이곳에 배치되는 클래스들의 성격을 일반적으로는 POCO [footnote]Plain Old CLR Object (Plain Old Java Object; POJO를 응용한 줄임말)[/footnote] – 또는 – PONO [footnote]Plain Old .NET Framework Object (Plain Old Java Object; POJO를 응용한 줄임말, POCO와 동일한 의미의 다른말)[/footnote] (http://en.wikipedia.org/wiki/Plain_Old_CLR_Object)로 이해하면 쉽습니다.


Scripts: Content 디렉터리와 유사한 성격의 디렉터리이지만 특별히 JavaScript 라이브러리들을 위하여 할당된 디렉터리로, ASP.NET MVC 2는 오픈 소스 기반의 JavaScript Framework인 jQuery를 기본으로 제공합니다. 만약 jQuery Plugin을 개발하였거나 사용하고자 하는 다른 Plugin이 있을 경우 – 또는 – jQuery 이외의 다른 JavaScript 라이브러리 (예: 네이버 jindo, script.aculo.us, Moo Tools, Google Web Toolkit, extJS, Dojo Toolkit, prototype, Yahoo! UI 등)를 이곳에 추가하면 됩니다.


[중요] Views: ASP.NET MVC 응용프로그램에서 “V”를 대표하는 구성 요소가 저장되는 디렉터리이며 주로 Controller에 어떤 데이터를 전달할 것인지를 사용자에게 대화형으로 묻거나, Controller에 의하여 발생한 출력 결과를 사용자에게 대화형으로 전달할 때 사용하는 컨텐츠 파일들이 여기에 저장됩니다. ASP.NET MVC 2에서는 Web Forms와 Script Tag Expression을 기반으로 하는 뷰 엔진을 기초로 합니다. [footnote]이 글을 작성하는 시점에서 ASP.NET MVC 3에서 기본으로 채택될 예정인 Razor View Engine이 새로 발표되었습니다. Razor View Engine은 Web Form을 대체하는 ASP.NET MVC 전용의 View Engine 시스템을 뜻합니다.[/footnote]


[중요] Global.asax: ASP.NET MVC에서 매우 중요한 구성 요소로 지금 작업하는 ASP.NET 응용프로그램이 ASP.NET MVC 엔진에 의하여 처리되어야 함을 지정하고 초기 설정을 구성하는 코드가 여기에 포함되어있습니다. 이 파일이 누락되거나 내용이 잘못되어있을 경우 ASP.NET MVC 응용프로그램으로서 동작하지 않음을 유의해야 합니다. 추가적으로 사이트 내에 다른 영역을 구성하거나, 다른 주소 패턴을 확장해야 할 경우에도 이 파일에 내용을 추가해야 설정이 적용됩니다.


[중요] Web.config: ASP.NET 응용프로그램의 환경 설정 파일로 역시 이 파일의 내용에 문제가 있거나 누락되어있을 경우 ASP.NET MVC 응용프로그램이 올바르게 동작하지 않을 수 있음을 주의해야 합니다.


[중요] WebRole.cs: ASP.NET 응용프로그램과는 무관하나, Windows Azure 환경에서 Web Role이 초기에 기동될 때 필요한 설정을 포함하고 있으며, 클라우드 컴퓨팅 환경에서의 실질적인 진입점이 됩니다. 이 클래스가 없을 경우 응용프로그램 실행에 문제가 있을 수 있습니다.


다음 시간에는


다음 시간에는 ASP.NET MVC 2 기반의 Web Role을 작성하고, 테이블 스토리지에서 실제로 데이터를 조회하거나 추가, 변경, 삭제하는 예시를 들어보도록 하겠습니다. 긴 강좌 읽어주셔서 감사하며, 즐거운 여름 휴가 되십시오. 감사합니다. 🙂


강좌에 대한 고칠 부분, 의견, 제안 등은 남정현의 클라우드 & 닷넷 블로그 (http://7d5.32b.myftpupload.com/), 트위터 (@rkttu), 전자 메일 (rkttu nospam rkttu dot com)을 통하여 항상 받고 있습니다. 언제든 의견 주시면 감사하겠습니다. 🙂