지난 아티클에서는 Phalanger와 PHP 사이에 차이점들이 있다고 말씀드렸습니다. 구체적으로 어떤 차이점들이 있을까요? 여러 프로그래밍 언어를 지원한다는 사실이 가장 큰 차이점이고 닷넷 기반 위에서 실행된다는 것이 구분되는 점이겠지만 이런 점을 차치하고 PHP 관점에서 차이점을 살펴본다면 지금 이야기하려는 토픽들에 대한 이야기가 빠질 수 없을 것입니다.

App_Code 폴더의 사용

Phalanger가 ASP.NET을 기반으로 하고 있기 때문에 자동으로 이어받는 특성으로, App_Code 폴더의 사용에 관한 부분이 있습니다. ASP.NET에서는 App_Code 폴더 안에 낱개 코드 파일들을 넣어두면 이것을 자동으로 웹 페이지의 서버 런타임에서 자유롭게 가져다쓸 수 있다고 하였는데, Phalanger도 마찬가지입니다. 웹 페이지를 렌더링하기 위한 목적이 아닌 공통이 되는 PHP 코드를 이 폴더에 넣어두기만 하면 자동으로 이 폴더에 속한 모든 PHP 코드들이 글로벌 문맥 상에서 사용 가능하게 활성화됩니다.

단, 조심해야 할 부작용이 하나 있다면 여기에 지나치게 많은 코드를 배치할 경우 컴파일 시간이 늘어나서 처음 사이트를 시작할 때 시간이 오래 걸리게 될 가능성이 있습니다. 안타깝게도 C나 C++처럼 병렬 컴파일은 아직 지원되지 않기 때문에 컴파일 시간이 오래 걸릴 경우 다양한 문제를 야기할 가능성이 있습니다.

php.ini와 같은 Global Configuration이 아닌 web.config에 의한 설정

PHP의 경우 설정을 변경하기 위해서는 PHP 전체의 설정을 주관하는 php.ini 파일을 업데이트하거나, PHP를 다시 컴파일하여 설치하는 번거로운 과정을 거쳐야만 모듈에 대한 설정이나 추가/제거가 가능했습니다. 하지만 Phalanger의 경우 현재 만들어진 응용프로그램 풀마다 다른 설정을 가지도록 구성할 수 있으므로 좀 더 자유도 높은 설정이 가능합니다. 이를 위해서 web.config 파일을 수정하고 저장하기만 하면 됩니다.

이러한 설정을 다루기 위해서는 phpNet이라는 XML 요소를 web.config에 지정해야 하는데, 그냥 지정할 수는 없고 반드시 적절한 처리기를 연결해주어야 합니다. web.config은 단순한 XML 파일이 아니라 닷넷 프레임워크가 직접 내용을 검사하고 분석하는 프로그램 코드의 일부이기 때문에 규칙을 준수하는 것이 매우 중요합니다.

phpNet 요소를 추가하려면 web.config에서 <configuration> 요소의 제일 첫 번째 노드로 아래 XML 조각이 배치되어야 합니다.

<configSections>
<section name="phpNet" type="PHP.Core.ConfigurationSectionHandler, PhpNetCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=0a8e8c4c76728c71" />
</configSections>

그 다음, 보기에 편리한 위치에 phpNet 요소를 추가합니다. 보통 아래의 코드 조각으로 최초 설정을 시작하면 무난합니다.

<phpNet>
<classLibrary>
  <add assembly="PhpNetClassLibrary, Version=3.0.0.0, Culture=neutral, PublicKeyToken=4af37afe3cde05fb" section="bcl" />
  <add assembly="PhpNetXmlDom, Version=3.0.0.0, Culture=neutral, PublicKeyToken=2771987119c16a03" section="dom"/>
</classLibrary>   
</phpNet>

php.ini 파일의 샘플 사본을 복사하여 php.ini 파일로 사용하던 것과 비슷한 접근 방법이지만 각 사이트 혹은 도메인 별로 따로 사용하는 web.config 파일 안에서 이러한 설정을 다루는 것이 중요한 차이점입니다. 그리고 무엇보다도 안심해도 좋은 것은 INI 파일처럼 프로그램이 잘못 다루게 될 가능성이 있는 파일이 아니라, XML의 형태로 설정 파일이 관리되므로 web.config 파일을 건드리는 다른 써드 파티 어플리케이션 때문에 Phalanger의 설정이 깨지거나 변형될 일이 거의 없다는 점입니다.

위의 기본 설정을 지정하면 Phalanger에서 기본적인 PHP API를 사용할 수 있으며, PHP5부터 기본으로 제공되는 SimpleXMLElement도 위의 설정으로 기본으로 활성화됩니다.

PHP/CLR의 사용

이제 위의 설정을 토대로 PHP/CLR을 활성화하여 닷넷 프레임워크의 기본 API를 Phalanger에서 즉시 호출하여 사용할 수 있습니다. 위의 <phpNet> 요소 아래에 다음의 XML 요소를 추가하면 됩니다.

<compiler>
  <set name="LanguageFeatures">
    <add value="PhpClr" />
  </set>
</compiler>

그리고 <classLibrary> 요소 아래에 .NET Framework 기본 어셈블리에 대한 레퍼런스를 추가합니다.

<classLibrary>
  <add assembly="mscorlib" />
  <add assembly="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <add assembly="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  <add assembly="PhpNetClassLibrary, Version=3.0.0.0, Culture=neutral, PublicKeyToken=4af37afe3cde05fb" section="bcl" />
  <add assembly="PhpNetXmlDom, Version=3.0.0.0, Culture=neutral, PublicKeyToken=2771987119c16a03" section="dom"/>
</classLibrary>

이제 새로 추가한 코드가 의도한대로 잘 작동하는지 살펴보기 위하여, 이미지 리사이징을 수행하는 샘플 코드를 Phalanger 위에서 실행하도록 PHP/CLR 기반으로 코드를 만들어보도록 하겠습니다. 이 코드는 http://wiki.php-compiler.net/Code_Samples/Resize_image 의 예제를 발췌하여 조금 변형한 것입니다.

<?php
use System\Drawing\Bitmap;
use System\Drawing\Graphics;
use System\Drawing\GraphicsUnit;
use System\Drawing\Rectangle;
use System\Web\HttpContext;

function resize_imageSysDraw($from,$wid,$hgt)
{
  $bmp = Bitmap::FromFile($from);
  $fmt = $bmp->RawFormat;
  $new = new Bitmap($wid, $hgt);
  $gr = Graphics::FromImage($new);
  $gr->DrawImage($bmp,
    new Rectangle(0,0,$wid,$hgt),
    new Rectangle(0,0,$bmp->Width, $bmp->Height),
    GraphicsUnit::Pixel);
  $gr->Dispose();
  $new->Save(HttpContext::$Current->Response->OutputStream, $fmt);
  $new->Dispose();
}

resize_imageSysDraw(realpath('Penguins.jpg'), 320, 240);
?>

PHP/CLR의 경우 여느 닷넷 언어들과 마찬가지로 네임스페이스에 속한 클래스에 대한 참조를 use 명령어로 지정하고 있으며, 정적 멤버에 대해서는 :: 연산자를, 객체 생성은 new 연산자를 사용하였습니다. resize_imageSysDraw 함수에서는 ASP.NET의 HttpContext를 가져와서 기본 출력 대신 비트맵 이미지를 내보내도록 만들었고 그 결과 아래와 같이 축소된 이미지가 렌더링되서 나타나게 됩니다.

Phalanger의 LINQ 지원

이제 마지막으로 PHP/CLR의 하이라이트라고 할 수 있는 LINQ 지원에 대해서 살펴보겠습니다. LINQ는 Microsoft Research에서 C# 언어의 확장 사양인 C-omega 언어의 일부로 개발 중이던 사양을 정규화하여 Production Spec으로 만든 것으로, C# 이외에 VB.NET에도 영향을 주었으며 Prism이나 지금 소개하는 Phalanger에서도 개념을 적극 채택하여 정규 사양으로 활용 중입니다. 그리고 F#은 이러한 접근을 더욱 드라마틱하게 활용하여 함수형 언어로 발전시키기도 하였습니다.

LINQ에 대해서 이야기하려면 책을 한 권 따로 만들어야할 만큼 방대합니다. 그래서 자세한 이야기는 하지 않고, LINQ 자체에 대해서 진지하게 학습하기 원한다면 LINQ 관련 국내외 도서들을 검토하기 바랍니다. 개인적으로는 "생각하는 C# LINQ"라는 책을 추천합니다. :-)

http://kangcom.com/sub/view.asp?sku=200809180001&mcd=571

LINQ는 한 마디로 이야기하면, 프로그래밍 코드를 한 방향에서만 바라보도록 뷰 포인트의 시각을 고정한 것과 같습니다. 본디, 어떤 연관성이 있는 데이터 집합을 접근하는 방법에는 여러 가지 방법이 있을 수 있지만 LINQ는 데이터가 어떤 순서로 들어있든, 어떤 형태로 연결되어있든 관계없이 데이터를 꺼내올 수 있도록 도와주는 Iterator 패턴의 한 형태인 Enumerator를 조금 독특하게 해석하였습니다.

Enumerator가 열거할 대상을 미리 정할 수 있도록 만들고, 열거할 때 조건을 지정하여 필요없는 데이터는 건너뛸 수 있게 해준다던지 이런 취지에서 해석을 한 것이 LINQ입니다. 그리고 Enumerator를 수정하게 되는 시점이 이미 메모리 상에 저장된 데이터 셋에 대한 작업인지, 아니면 아직 수신되지 않은 미지의 데이터 셋에 대한 작업인지에 따라서도 지연 실행이냐 즉시 실행이냐 이렇게 구분하기도 하구요. 그러면서도 항상 잃지 않는 것은 핵심은 Enumerator라는 사실이며, 이에 입각하여 배열이나 리스트같은 정규화된 자료 구조로 변환할 수 있는 길을 항상 열어놓아 최대한의 유연성을 부여하기도 합니다.

어렵게 들릴 수도 있지만 Enumerator를 수정할 수 있게 해준다는 컨셉은 생각보다 활용 폭이 넓은데, 가장 가까이 있는 예로는 SQL 쿼리가 될 수 있습니다. 처음의 아이디어는 SQL 쿼리를 이용하여 전체 데이터 셋보다 가능한 적게 데이터를 반환하여 네트워크 트래픽을 줄이고 빠르게 데이터를 검색할 수 있도록 최적화하자는 것에 있었을 것이며, 이것을 좀 더 프로그래밍 언어와 친화적으로 만들 방법을 모색한 끝에 LINQ to SQL이 나타나게 된 셈입니다. 그리고 이를 필두로 접근할 수 있는 모든 유형의 컬렉션에 대해서 이런 아이디어를 대입하여 현재는 오픈 소스를 찾아보면 정말 엄청나게 많은 LINQ provider들을 발견할 수 있을 정도입니다.

이렇게 독창적이고 전례없던 기술을 Phalanger에서도 이용할 수 있다는 것은 매우 좋은 일입니다. <phpNet> 요소에 대해 PHP-CLR을 활성화하도록 설정을 수정한 후 아래 코드를 테스트해보기 바랍니다.

<?php
$myarray = json_decode('[
    {"label":"foo","name":"baz"},
    {"label":"boop","name":"beep2"},
    {"label":"foo","name":"baz1"},
    {"label":"boop","name":"beep3"},
    {"label":"foo","name":"baz2"},
    {"label":"boop","name":"beep1"}
]', true);

$result =
from $myarray as $x
where $x['label'] == 'foo'
select $x['name'];

foreach ($result as $x) {
    print($x.'<br />');
}

print_r($result);

?>

json_decode라는 기본 PHP 함수를 이용하여 JSON을 PHP 연관 배열로 바꾸고, 이것을 LINQ로 조회한 다음, 그 결과를 foreach 문을 통해서 출력하도록 만들었습니다. C#이나 VB.NET의 LINQ와 약간 다른 점은, from 절에서 in 연산자 대신 as 연산자를 사용하고 in 연산자와는 도치되는 좌/우항 관계를 가집니다. 즉, [나열 변수] in [데이터 소스] 에서 [데이터 소스] as [나열 변수]로 바뀝니다. 그리고 이것은 foreach 문에도 동일하게 적용됩니다. 아래는 실행 결과입니다.

PHP, JSON, 그리고 LINQ가 한 자리에 모여 매우 재미있는 상호 작용을 이룬 것을 볼 수 있습니다. 이 정도면 닷넷에서의 웹 프로그래밍이 이전과는 제법 많이 달라질 수 있다는 것을 체감할 수 있을 것입니다.

다음번에는 Phalanger가 기존 PHP의 모듈들을 어떻게 다루고 관리하는지에 대한 상세한 내용을 살펴보도록 하겠습니다. 긴 글 읽어주셔서 감사합니다. :-)

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'Web Development > Phalanger' 카테고리의 다른 글

Phalanger와 PHP의 차이점들  (0) 2012/02/10
PHP x C# x VB.NET = ASP.NET  (0) 2012/02/08
Phalanger와 WebMatrix의 완벽한 만남  (1) 2012/02/06
PHP와 .NET의 완벽한 만남 - Phalanger  (0) 2012/02/04
Posted by Windows Azure MVP 남정현 (rkttu.com)

지난 아티클에 이어 오늘은 Phalanger를 이용하여 C#과 VB.NET 코드를 동시에 활용하는 예를 한 번 조명해보려고 합니다. 사실 이것이 Phalanger의 하이라이트라고 하여도 무방하지 않습니다. 기존의 C#과 VB.NET 로직을 재사용하면서도 Phalanger로 빠르고 가볍게 웹 페이지를 풀어나가는 방식은 여러모로 웹 개발에 가속을 붙여줄 것입니다.

계속 설명하기 전에, Phalanger가 ASP.NET 위에서 실행되기 때문에 적용되는 한 가지 특수한 규칙을 이야기할 것이 있습니다. 바로 미리 정해진 이름의 폴더인데, Bin, App_Code 폴더입니다. 그 외 많은 폴더들이 있지만 지금은 두 가지만 살펴보겠습니다.

앞에서 이야기한대로 ASP.NET은 닷넷 프레임워크를 기반으로 작동한다고 하였고, 닷넷 프레임워크는 언어의 종류와 무관하게 MSIL이라는 코드로 컴파일되서 나오는 DLL 파일들을 취급할 수 있습니다. 그렇게 만들어지는 DLL 파일들은 Bin 폴더에 파일을 넣어주면면 자동으로 참조가 활성화되서 해당 웹 사이트 안의 모든 닷넷 코드에서 클래스 라이브러리를 사용할 수 있게 됩니다. 단, 주의할 것은 이 폴더 안에 아무 DLL이나 넣을 수 있는 것은 아니며 반드시 닷넷으로 컴파일된 DLL만 포함시킬 수 있습니다.

그리고 이번 아티클에서 가장 핵심이 되는 기능을 제공하는 폴더인 App_Code 폴더는, 컴파일을 하려는 모듈에 대한 코드를 여기에 넣어서 모든 페이지에서 공유할 수 있습니다. 기본적으로 이 폴더에는 한 종류의 언어에 해당되는 파일들만 넣을 수 있고, 그외 다른 언어의 파일이 포함되면 아래 이미지와 같은 오류가 발생합니다. 하지만 제가 이전에 소개했던 약간의 추가 설정을 적용하면 App_Code 폴더에서 여러 프로그래밍 언어를 동시에 사용할 수 있습니다.

위와 같이 나타나는 문제를 해결하기 위하여, App_Code 폴더 자체에서 사용할 언어는 Phalanger로 정하고, App_Code 폴더 안의 두 번째 수준의 디렉터리들에 C#이나 VB.NET 같은 언어를 사용하기로 결정합니다. 그리고 web.config 파일에 다음과 같이 <system.web> 요소 아래에 하위 디렉터리가 존재한다는 것을 알려줍니다.

<system.web>
<globalization requestEncoding="utf-8" responseEncoding="utf-8" fileEncoding="utf-8" />
<compilation>
  <codeSubDirectories>
    <add directoryName="Cs" />
    <add directoryName="Vb" />
  </codeSubDirectories>
</compilation>
</system.web>

그리고 App_Code 폴더에 각각 Cs 폴더와 Vb 폴더를 만듭니다. 폴더 이름에서 바로 알 수 있듯이 각각 C#과 VB.NET 코드를 따로 보관할 수 있도록 하고, 위의 그림처럼 오류가 발생하지 않으면서 자동으로 C#과 VB.NET으로 만든 코드를 Phalanger에서 액세스할 수 있도록 하게 할 것입니다. 이것으로 준비는 모두 끝났으며 우리가 원하는대로 C#과 VB.NET 코드를 추가하기만 하면됩니다.

C# 코드

using System;
using System.Collections.Generic;
using System.Web;

/// <summary>
/// Summary description for ClassName
/// </summary>
public class ClassName
{
    public string Name { get; set; }
    public int Age { get; set; }
    public override string ToString() {
        return String.Format("Name: {0} / Age: {1:D3}", Name, Age);
    }
}

VB.NET 코드

Imports Microsoft.VisualBasic

Public Class ClassName2
    Public Content As String
End Class

그리고 중요한 부분이 있습니다. Phalanger가 서브 디렉터리에 있는 코드들을 컴파일하였을 때 각각 따로 만들게 될 코드 조각들을 인식할 수 있도록 최소한 1개 이상의 임의의 PHP 파일이 필요합니다. 이후 아티클에서 따로 설명하겠지만 Phalanger는 App_Code 폴더 안에 있는 PHP 파일을 모두 자동으로 include하는 동작을 가지고 있습니다. (이것이 이전의 Original PHP와는 다른 부분입니다.)

지극히 일상적이고도 당연한 클래스 선언을 담고 있는 파일을 각 디렉터리에 추가하였습니다. 이제 웹 매트릭스의 폴더 레이아웃은 아래 그림과 같은 형태가 되면 됩니다.

이제 마지막으로 index.php 코드를 아래와 같이 작성합니다. 아래와 같이 작성하면 정말 PHP에서 C#과 VB.NET 코드를 자동으로 불러올 수 있을까요? 기대됩니다. :-)

<?php       
// C#
$test1 = new ClassName();
$test1->Name = "남정현";
$test1->Age = 2012-1987;
print $test1->ToString().'<br />';
print get_class($test1).'<br />';

// VB.NET
$test2 = new ClassName2();
$test2->Content = '<strong>안녕하세요!!!</strong>'.'<br />';
print $test2->Content;
print get_class($test2).'<br />';

phpinfo();
?>

ClassName은 C#으로, ClassName2는 VB.NET으로 만든 코드입니다. PHP/CLR 확장의 도움으로 Name, Age, Content 프로퍼티에 문자열을 대입하고 있으며, print 문을 이용하여 웹 페이지 상에 문자열을 출력합니다. 그리고 get_class라는 기본 PHP 함수를 사용하여 클래스 형식명을 가져오는 일도 하려고 하는군요. 마지막으로는 phpinfo() 함수를 호출하여 Phalanger 및 서버 시스템에 대한 정보도 덤프로 출력합니다. 이제 이 페이지를 실행해보면 아래와 같이 나타나게 될 것입니다. :-)

훌륭합니다! C#과 VB.NET 컴파일러를 따로 부르는 일 없이 앉은 자리에서 한 번에 코드를 컴파일하고, 이것을 PHP에서 보기 좋게 가져다 쓰는 일까지 해냈습니다.

다음 아티클에서는 마지막으로 Phalanger만의 고유한 기능이라고 할 수 있는 자동 include에 대해서 마지막으로 이야기해볼까 합니다. Original PHP에서는 include나 include_once 같은 함수를 어떤 인과 관계에 따라서 포함하게 될 것인지, 그리고 순서에 대해서도 많은 고민을 해야 했지만 Phalanger는 이러한 부분에 대한 고민을 많이 덜어낼 수 있습니다. 그리고 그 중심에는 App_Code 폴더의 역할이 크다고 했는데요, 이 부분에 대해서 집중적으로 살펴보려고 합니다.

 

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'Web Development > Phalanger' 카테고리의 다른 글

Phalanger와 PHP의 차이점들  (0) 2012/02/10
PHP x C# x VB.NET = ASP.NET  (0) 2012/02/08
Phalanger와 WebMatrix의 완벽한 만남  (1) 2012/02/06
PHP와 .NET의 완벽한 만남 - Phalanger  (0) 2012/02/04
Posted by Windows Azure MVP 남정현 (rkttu.com)

요즈음 웹 개발에 있어서 하나의 중추적인 트렌드로 자리 잡은 것이 바로 모바일 웹 개발이다. 모바일 웹 개발이라고 하면 흔히 하는 생각으로 막연하다는 느낌부터 들 것이다. 1세대의 모바일 웹 개발은 확실히 HTML보다 가벼워야 했고 하드웨어의 제한 사항이 큰 편이었기 때문에 WML과 같은 메타 언어의 존재감이나 그 수요가 분명했다. 하지만 모바일 기기와 일반 PC의 사양 차이가 날이갈수록 좁혀짐은 물론 이제 모바일 기기가 경우에 따라서는 일반 PC나 랩톱 컴퓨터보다 훨씬 더 유용해지고 쓰임새가 많아지게 되면서 이런 구분이 모호해지게 된다.

필자 역시 모바일 웹 개발을 해야 할 필요성을 자주 느끼게 되었다. 당장 가지고 있는 스마트폰인 Windows Phone 7.1 (이름하여 망고폰)을 비롯해서 주변 지인들이 빠짐없이 가지고 있는 아이폰, 아이팟, 아이패드, 그리고 안드로이드 계열이나 크롬 북을 포함하여 상당히 많은 수의 브라우저들을 고려하는 모바일 웹 사이트가 필요했다. 물론 이들 모두 일정 수준 이상의 HTML5와 CSS3, 그리고 자바스크립트 렌더링 엔진을 갖추고 있긴 하지만 특유의 해상도 제한이나 성능 제한, 그리고 결정적으로 고밀도의 선택이 가능했던 마우스를 대신하여 터치 인터페이스에 최적화된, 이전보다 훨씬 둔감한 조작을 이해할 수 있는 인터페이스를 디자인해야 한다는 것이 난제가 되었다.

기존 웹 기술을 최대한 보존하면서도 검증된 프레임워크의 이점을 누릴 수 있는 방법이 없을까 고민하다가 아주 훌륭한 프레임워크를 테스트해보게 되었고 그 내용을 블로그를 통하여 간단하게 소개하고자 한다. 바로 jQuery Mobile이다.

jQuery Mobile과 jQuery의 차이점?

그냥 얼핏 듣기에 jQuery Mobile과 jQuery는 큰 차이점이 없어보인다. 오히려 어떻게 보면 jQuery의 축소 버전이 아닌가 하는 생각이 들 수도 있다. 하지만 이 둘 사이의 정확한 관계는, jQuery Core를 기반으로 만들어진 Extension이 jQuery Mobile이며, jQuery Mobile은 단순히 기능 집합을 축소한 것이 아니라 오히려 모바일 환경에 알맞도록 확장시킨 일종의 확장팩에 해당되는 개념이다.

사실, 여러분이 어떻게 jQuery Mobile을 사용하는가에 따라서 jQuery 특유의 자바스크립트 기술을 전혀 사용하지 않을 수도 있다. jQuery Mobile이 제공하는 몇 가지 규칙에 맞추어 웹 페이지를 프로그래밍한다면 나머지 시각 효과, 간단한 검색 기능, 심지어 대화 상자 기능까지 자동으로 jQuery Mobile이 알아서 처리해주기 때문이다.

jQuery Mobile을 가장 잘 활용할 수 있는 방법

이제까지 여러분은 자바스크립트 모듈을 어떤 방식으로 사용해왔는가? 대개는 웹 사이트 안에 들어가는 부속품 정도로 여기고 이것을 같은 웹 사이트 안에서 서비스하도록 구성하는 일이 많았다. 그리고 웹 서버에 대한 트래픽이나 부하가 일어나지 않도록 하기 위하여 적절한 Cache Timeout 설정을 사용하여 클라이언트가 jQuery 라이브러리를 지속적으로 재사용할 수 있는 방안을 적용해왔을 것이다.

그렇지만 기왕 최적화를 할 요량이면 밀어 붙일 수 있는 곳까지는 밀어붙여보는 것도 나쁘지 않을 것이다. jQuery는 물론 jQuery Mobile까지 여러분의 웹 서버가 아닌 곳으로 레퍼런스를 걸 수 있는 방법이 요즈음 유행하고 있다. 즉, CDN 서버를 이용하는 방식으로, jQuery를 비롯한 몇 가지 유명한 자바스크립트 및 공통적인 웹 자원들을 공개적으로 서비스하는 곳이 있고 이곳의 라이브러리를 가져다 쓰는 방식이다.

jQuery의 경우 jQuery 프로젝트 팀이 자체적으로 운영하는 CDN 서비스가 있으며, Microsoft의 ASP.NET AJAX CDN, 그리고 잘 알려진 Google의 CDN 서비스까지 모두 세 가지 유형의 CDN 서비스를 사용하여 jQuery 및 jQuery Mobile 자바스크립트 라이브러리를 개별 웹 페이지에 붙여넣을 수 있다.

CDN에 대해서 간단히 설명하면, CDN 네임스페이스 상의 특정한 URL에 대해서 요청이 발생하면 해당 리소스에 대한 사본을 CDN 네트워크 상에서 현재 위치로부터 가장 가깝거나 혹은 빠른 응답 속도를 보이는 서버로부터 데이터를 가져와 클라이언트로 내려보내는 서비스이다. 물론 이 과정을 수행할 수 있도록 하기 위하여 원본 서버가 필요하고 이 원본 서버로부터 데이터를 가져와서 네트워크 상에 고속으로 배포하는 작업은 필수적이다. 글로벌 CDN으로 불리는 서비스들은 당연히 이러한 CDN에 큰 비용을 투자할 수 있는, 그리고 전세계적인 네트워크 망을 보유할 수 있는 기업이어야 할 필요성이 있으며 이러한 기업으로는 대표적으로 Google과 Microsoft가 있는 셈이다.

Microsoft CDN을 이용하여 jQuery 시작하기

각각의 CDN 서비스들마다 자바스크립트를 제공하는 방법에는 차이점도 있고 장단점도 있지만 여기서는 Microsoft의 CDN 서비스를 사용하는 경우를 예로 들어 설명하고자 한다. 당연한 이야이기이지만 Microsoft CDN에서는 jQuery를 Visual Web Developer의 JavaScript Intellisense와 연계할 수 있는 vsdoc 버전의 자바스크립트 라이브러리를 CDN 버전으로 제공받을 수 있다. Microsoft CDN 서비스로부터 여러분이 가져오고 싶은 자바스크립트 코드를 카탈로그로부터 가져오기 위하여 아래 웹 사이트를 찾아볼 수 있다.

http://www.asp.net/ajaxlibrary/cdn.ashx

위의 웹 사이트에 구체적인 설명이 잘 나와있지만 이 웹 페이지에서는 여러분이 상황에 맞게 쓸 수 있도록 코드 조각을 정리하여 설명하려고 한다.

만약 여러분이 jQuery 1.5.1 버전을 http 버전 프로토콜로 연결하려고 하면 아래와 같이 <HEAD> 태그 내부에 Child Element로 기술하면 된다.

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.5.1.min.js" type="text/javascript"></script>

만약 HTTPS 기반 웹 사이트를 사용 중이고 여기서 CDN을 사용하려고 한다면 프로토콜 접두사만 바꾸면 HTTPS 버전의 CDN도 이용할 수 있다.

<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.5.1.min.js" type="text/javascript"></script>

만약 VSDOC 버전을 연결하려고 하면 아래와 같이 min 대신 vsdoc으로 이름을 바꾸면 된다.

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.5.1.vsdoc.js" type="text/javascript"></script>

jQuery UI를 사용하기 위해서는 CSS 파일, 이미지 파일, 그리고 자바스크립트 파일에 대한 참조가 필요한데, CSS 파일에 대한 참조만 정확하다면 이미지 파일들의 경로는 신경쓰지 않아도 된다. 그리고 jQuery UI는 jQuery를 기반으로 하는 프레임워크이므로 jQuery에 대한 참조가 필수이다. 그리고 테마는 여러분이 http://www.asp.net/ajaxlibrary/CDNjQueryUI1816.ashx 페이지에서 1.8.16 버전에 해당되는 미리 제공되는 테마 중에서 하나를 택하여 CSS 파일에 대한 참조만 정확히 지정하면 된다. 이런 설정을 바탕으로 jQuery UI를 CDN에서 가져올 때 Redmond 테마 버전으로 가져오고자 한다면 아래와 같이 코드 조각을 쓸 수 있다.

<link rel="stylesheet" href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/themes/redmond/jquery-ui.css" media="all" type="text/css" />
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>

그리고 jQuery Mobile을 사용하려 한다면 아래와 같이 작성한다.

<link rel="stylesheet" src="http://ajax.aspnetcdn.com/ajax/jquery.mobile/1.0/jquery.mobile-1.0.min.css" media="all" type="text/css" />
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.mobile/1.0/jquery.mobile-1.0.min.js" type="text/javascript"></script>

jQuery Mobile의 경우 HTML5 마크업을 사용하는 것이 중요하다. Custom Attribute에 대한 지원이 필수적이기 때문이다. 이 부분에 대한 설명은 다음 기회로 넘기기로 하겠다.

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

요즈음 클라우드 서비스들을 이용하다보면, Windows 서버 운영체제를 통해서 확장성있는 클라우드를 만들고자 하는 경우가 자주 있습니다. 일반적인 웹 사이트를 구축할 때에도 마찬가지이고, 당연히 KT UCLOUD나 Amazon과 같은 환경에서도 같은 노력이 뒷받침이 되어야 하지요. 그리고 제가 주 전공으로 하고 있는 Windows Azure 역시, 첫 배포 때에는 간과하기 쉬운 점이 바로 로드 밸런싱 환경이라는 점입니다.

이러한 로드밸런싱 환경을 만들때에는, 이전에 구축해본 경험이 없는 관리자가 개발자 입장에서는 상당히 어려운 문제에 봉착하게 될 가능성이 많습니다. 특히 요즈음 웹 환경에서는 당연하게 사용하는 세션이나 쿠키에 관련된 설정들이 로드밸런싱 환경에서 기대했던 것과 다르게 동작해서 좌절하는 경험을 많이들 하실텐데요, 제가 오늘 블로그에 올리는 것은 ASP.NET에 관한, 그리고 IIS 7에 관한 내용입니다. (PHP나 JSP 개발자분들께서도 공감하실 수 있는 부분이 있을 것입니다.)

로드밸런싱 환경을 잘 알고 구축할 수 있다면, 앞으로 나오게될 어떤 종류의 클라우드 서비스이든 관계없이 문제를 정확하게 해결할 수 있을 것입니다. 사실 클라우드 기반의 웹 서비스는 달리 표현하면, 기본 골자는 로드밸런싱에 기반을 두고 있는 것이고, 그 이후의 확장성 전략을 클라우드 솔루션으로 채우는 것과 같다고 말할 수 있습니다. (어떤 뼈대를 사용할 것인지는 전적으로 여러분들의 선택에 달린 것입니다.)

로드 밸런싱 환경이란?

로드 밸런싱 기술 자체는 상당히 오래된 것입니다. 이름에서 알 수 있듯이, 몰려오는 트래픽을 내부적으로 분산하여 특정 서버 컴퓨터로 연결이 몰려 서비스가 사용 불가 상태로 빠지는 것을 "지연"시키거나 "완화"시키는 것에 목적이 있습니다. 로드 밸런싱의 기술적 개념도는 다음과 같습니다. (이미지 출처: http://msdn.microsoft.com/en-us/library/ff650667.aspx)

다양한 상황에서 로드밸런싱이 쓰이겠지만 가장 일반적으로는 웹 환경에서 많이 쓰입니다. 연결을 오래 유지할 필요가 없으면서도, 짧은 시간 내에 빠른 연결 회전을 보이는 웹 프로토콜에서 가장 중요한 것은 바로 신속성인데, 분산 처리를 하지 않는 경우에는 필연적으로 서버 컴퓨터가 받아들일 수 있는 동시 연결 한계치에 금방 치닫게 됩니다. 그러나 로드 밸런싱을 정확히 사용하면 이러한 한계치에 치닫게 되는 속도가 로드 밸런싱에 참가하는 컴퓨터의 댓수만큼 반비례하게 됩니다. 그리고 이 때 하나의 웹 사이트를 위한 로드 밸런싱 서비스에 멤버로 참여하는 서버 컴퓨터들을 묶어서 "웹 팜"이라고 정의를 하는 것이지요. 더 일반적으로는 "서버 팜"이라고도 합니다.

잠시 다른 이야기로 넘어가자면, 요즈음 대두되는 클라우드 컴퓨팅은 관리 측면에서 봤을 때, 충분한 대역폭을 보장하는 연결과 매우 뛰어난 성능을 가진 로드 밸런서를 이용하여 연결을 분산하는 작업을 수행하는 것입니다. 그리고 웹 팜 안에 참여하는 컴퓨터의 유형에 있어서는 이전과 다른 점이 하나 있는데, 마치 구름과 같이 수축과 팽창을 자유자재로 한다는 것입니다. 물론 이런 수축과 팽창이 가능함은 내부적으로 가상화 솔루션을 이용했다거나 여기에 대응할 수 있는 알고리즘을 사용했다는 가정이 깔려있는 것입니다.

정말 완벽하고 정확하게 구축했다면, 적은 전원이나 자원 공급으로도 충분히 웹 팜이 유지가 될 수도 있고, 필요하다면 웹 팜의 크기가 엄청나게 커질 수도 있겠지요. 이걸 여러분이 관리하신다면 프라이빗 클라우드, 신뢰할 수 있는 IT 기업이 관리한다면 퍼블릭 클라우드가 된다고 보실 수 있겠습니다. 그러나, 클라우드 컴퓨팅이 만능약처럼 들릴 수 있는 부분이 있지만 정확히 알아야 할 것은 클라우드 컴퓨팅 역시 이 로드 밸런싱을 기초로 만들어지는 것이고, 여러분이 운영할 수 있는 한계에까지 트래픽이 몰리거나, 이런 일을 하는 IT 업체에게 지불할 수 있는 재정의 한계에까지 트래픽이 몰린다면 이것이 여러분이 생각할 수 있는 클라우드의 한계입니다. 무제한이라고 해서 값이 저렴하거나 무료에 수렴하는게 아님을 명확히 이해하고 있어야 합니다.

웹 로드 밸런싱을 위한 이야기

다시 본론으로 돌아와서, 웹을 로드 밸런싱할 수 있으려면 무엇을 검토해야 할까요? 가장 중요한 것은 웹 서버에 참여하는 각각의 컴퓨터 자체에는 "절대로" 컴퓨터의 고유한 정보를 가지고 있으면 안된다는 점입니다. 매우 단순한 이야기같지만 이러한 원칙을 지키지 않도록 설계되어있는 것이 지금 이 시점까지의 서버 컴퓨팅 기술들의 대다수의 원칙입니다. 간단한 예를 들어볼까요?

여러분이 일상적으로 사용하는, 웹을 통한 파일 업로드 기능을 담당하는 간단한 웹 앱이 있다고 가정해 보겠습니다. 이 웹 앱은 서버가 한 대 일때에는 참 쉽고 빠르게 설치해서 쓸 수 있었습니다. 당연히, 설치를 잘 했다면, 사용자가 웹 페이지를 방문해서 파일을 업로드하면 웹 서버가 그것을 알아보고 파일을 회수해서 하드 디스크 어딘가에 저장하겠지요. 그러나 시간이 지나서 이 웹 앱의 기능을 업그레이드하고 좀 더 많은 사용자들이 파일을 저장하고 다운로드할 수 있도록 만들어보고자 해서 로드 밸런싱 환경을 구축하여 베타 테스트를 시작했습니다. 그런데 어떤 문제들이 생겼을까요?

앞서 이야기한 기술적인 특성때문에, 사용자들은 분명히 조금전까지 파일을 업로드했었는데 페이지를 다시 와서보니 파일이 업로드되지 않은 상태로 페이지가 나와서 혼란스러워합니다. 혹은 파일을 어디로 빼돌린거냐며 분노하는 사람들도 있구요. 그래서 몇 번 F5키를 누르다보면 "어라?"하고 놀라게 됩니다. 조금 전에 업로드했던 파일이 다시 나타나니까요. 그러고나서 그 파일을 다운로드하려고 링크를 클릭하면 이번엔 또 다시 404 오류를 만납니다. 이제 사용자들은 이 서비스에 대해서 대단한 분노와 원성을 쏟아낼 것입니다. 서비스 상태에도 일관성이 없을 뿐 아니라 불안정한것 같다. 믿을 수 없다면서요.

이것이 일선 IT 현장에서 로드 밸런싱이나 클라우드를 처음 접목했을 때 겪는 "가장 흔하고 일반적인 장애"입니다. 더 안타까운 것은, 이것을 신 기술에 의한 책임으로 회피하고 문제시하는 것입니다. 문제의 본질을 정확히 알고 있다면 이렇게 말하는 것이 왜 잘못인지도 금방 알 수 있을 것입니다.

여기서 든 예제처럼, 이 웹 앱의 문제는 단순히 업로드한 파일을 자신의 컴퓨터에 저장하려고 했다는 데에 문제가 있습니다. 로드 밸런싱 멤버로 참여하는 컴퓨터가 자신의 상태를 중요하게 여기면, 다음번에 이어받는 다른 서버 컴퓨터의 입장에서는 이전에 그 컴퓨터가 무엇을 했는지 알 길이 없습니다. 그저, 찾고자 하는 내용이 없음을 이야기하는 수 밖에 없습니다. 이런 상황이 반복되면서 서비스 전체는 들어올때와 나갈때가 전혀 다른, 일관성이 없고 이상한 서비스가 되는 것입니다.

이 문제를 해결하기 위하여 어떻게 수정해야 할까요? 답은 간단합니다. 파일 저장소를 로드 밸런싱 멤버 컴퓨터 내부가 아닌, 여러 멤버 컴퓨터들이 같이 이용할 수 있는 공용 저장소로 바꾸는 것입니다. 가장 간단한 방법은 네트워크 UNC 경로로 이용할 수 있는 스토리지가 있을 수 있습니다.

여기서 궁금한 점이 하나 더 있는데, 그렇다면 로드 밸런싱에 의하여 애써 분산한 서비스가 다시 모이는 것이 아니냐고 반문할 수도 있습니다. 그런데 사실, 생각외로 사용자들이나 웹 크롤러와 같이 인터넷 상에서 발생하는 별 뜻없이 바쁘게 만드는 다양한 유형의 트래픽을 웹 팜 수준에서 한 번은 로드 밸런싱을 해주는 것 만으로도 실제 스토리지에 대한 요구 사항은 획기적으로 감소한다는 점입니다. 거기다, 역할 분담도 정확히 할 수 있으며 스토리지 자체에 대한 요구 사항이 폭증하는 것을 방지하기 위하여 기술적으로는 좀 더 복잡해질 수 있지만 캐싱 기능을 사용할 수도 있습니다. 이렇게 함으로서, 우리가 흔히 잘 아는 클라우드 서비스의 시작을 뗄 수 있게 됩니다.

기술적인 이야기 1 - 세션 처리 방법 바꾸기

그렇다면 IIS와 ASP.NET에서는 이런 이상한 상황을 예방하고 신뢰할 수 있는 서비스를 만들기 위해서 어떤 수정 사항을 반영해야 하는 것일까요? 제가 이제까지 인터넷 상으로 자료 조사를 해왔던 것은 모두 제각기 흩어져있는 정보들이었고 이것을 한 번에 취합할 수 있는 방법을 오늘 블로그 포스팅을 통하여 소개할까 합니다.

기본적으로 ASP.NET은 세션 처리를 IIS 프로세스 안에서 수행하도록 되어있습니다. 가장 동선도 짧고, 신속하게 반응하기 때문입니다. 그러나 로드 밸런싱 환경에서 이는 당연히 "채택하면 안되는" 기법입니다. 이 방법은 web.config 파일 안의 <sessionState> 요소에서 변경할 수 있는 부분으로, <configuration> 요소 아래의 <system.web> 요소 아래에서 없는 경우 새로 지정할 수 있습니다. <sessionState> 요소의 mode 속성의 값을 변경하면 됩니다. 지금 이야기한 부분은 mode 속성이 InProc으로 지정되어있거나, 아무것도 지정되어있지 않을 때 .NET Framework의 글로벌 web.config 설정을 바꾸지 않은 경우 기본으로 지정되는 설정입니다.

IIS 7에서 볼 수 있는 아래 그림과 같은 설정도 이 XML 파일의 수정을 텍스트 에디터 없이 수정하는 것입니다.

로드 밸런싱 환경에서 정상적으로 동작하는 웹 사이트를 만들기 위해서는 mode의 설정 값을 InProc 대신 StateServer나 SQLServer로 바꾸어야 하는데, 양쪽 값 모두 장단점이 있습니다. StateServer의 경우 기본적으로는 꺼져있는 ASP.NET State Service라는 NT 서비스가 제공하는 별도의 서버를 이용하는 방식이고, SQLServer는 이름에서 알 수 있듯이 실제 SQL Server를 사용하여 세션을 구현하는 방식입니다. 데이터베이스 서버의 성능이 세션을 모두 수용할 수 있을만큼 획기적으로 뛰어나거나, 세션 서버가 죽었다가 살아나도 로그아웃 처리가 안되게 한다던가, 혹은 여러 로드 밸런싱 사이트 사이에서 세션 공유를 안전하게 할 방법이 필요하다면 이 모드를 사용할 수 있습니다. 이에 비하여 StateServer는 별도의 SQL 서버 없이도 간편하게 구축할 수 있는 방법을 제공하긴 하지만, 세션 서버가 죽었다 살아날 경우 내용이 없어지는 휘발성 세션입니다.

양쪽 모드 모두 중요한 것은 멤버로 참여하는 웹 서버 컴퓨터 밖에 상태를 보관해야 한다는 것이 키 포인트로, 이것을 지키지 않고 멤버 컴퓨터 안에 이런 설정을 구축하면 전혀 나아지는 것이 없습니다. 그리고 당연한 이야기이지만 멤버 컴퓨터로 참여하는 모든 웹 서버가 같은 설정을 가지고 있어야 합니다.

StateServer와 SQLServer 모드를 구현하는 방법에 대한 자세한 내용은 아래 아티클을 참고하시면 되겠습니다.

http://msdn.microsoft.com/ko-kr/library/ms178586.aspx

기술적인 이야기 2 - ASP.NET 사이트 간에 립싱크 맞추기

세션을 공유하는 것 이외에, ASP.NET은 내부적으로 Machine Key라는 것을 사용합니다. Machine Key의 용도는 ASP.NET 안에서 참 다양한데, 가장 대표적으로는 클라이언트와 서버 사이에 쿠키 정보를 주고 받을 때 암호화하기 위한 수단으로 이용하는 것이 유명한 사례입니다. 쿠키를 이용한 취약점 공격은 웹 세계에서 너무나 당연한 공격 방식 중 하나이기 때문에 ASP.NET은 처음부터 이를 보완하기 위한 전략을 구현하고 있었습니다. 그러나 이것이 지금 와서 로드 밸런싱 환경이 되면서는 또 다른 어려운 문제로 바뀐 것입니다.

이 Machine Key라는 것 역시 서버 컴퓨터마다 고유하게 생성할 뿐 아니라, 매번 연결할 때 마다 다른 값을 생성하여 암호화에 사용합니다. 클라이언트 입장에서야, 서버가 "ABC"라는 쿠키를 주니까 "아 그렇구나. 나중에 돌려주면 서버가 날 알아보겠지?"하며 성실하게 반납합니다. 그런데 로드 밸런싱에 참여하는 A라는 서버 대신 C라는 서버가 이 쿠키를 받아들었을 때는 "이거 내것 아님" 하며 클라이언트에게 퇴짜를 놓습니다. 이것이 문제의 핵심인 것이죠.

이 문제를 해결하기 위해서는 아까전에 이야기한 주제보다 좀 더 많은 노력이 필요합니다. 생각보다, 보안을 완벽하게 유지하기 위하여 ASP.NET이 관리자들에게 요구하는 사항이 까다롭기 때문입니다. 이 Machine Key를 만들기 위해서는 별도의 생성 도구를 사용해야 합니다. 그러나 안타깝게도 이 도구를 구한다거나 만들 수 있으려면 개발자들의 조력이 좀 필요합니다. 그리고 개발자 본인들도 이런 방법을 찾아야 하기때문에 꽤나 귀찮습니다. Codeproject에 가면 이러한 방법을 자세히 설명한 아티클도 있습니다만 간단한 도구도 드리고, 코드 조각도 드리니 프로그램에 넣어 활용하시면 더 편리할 것입니다.

using System;
using System.Text;
using System.Security.Cryptography;

/* 중략 */

        public static string getRandomKey(int bytelength)
        {
            byte[] buff = new byte[bytelength];
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(buff);
            StringBuilder sb = new StringBuilder(bytelength * 2);
            for (int i = 0; i < buff.Length; i++)
                sb.Append(string.Format("{0:X2}", buff[i]));
            return sb.ToString();
        }

        public static string getASPNET20machinekey()
        {
            StringBuilder aspnet20machinekey = new StringBuilder();
            string key64byte = getRandomKey(64);
            string key32byte = getRandomKey(32);
            aspnet20machinekey.Append("<machineKey\n");
            aspnet20machinekey.Append(" validationKey=\"" + key64byte + "\"\n");
            aspnet20machinekey.Append(" decryptionKey=\"" + key32byte + "\"\n");
            aspnet20machinekey.Append(" validation=\"SHA1\" decryption=\"AES\"\n");
            aspnet20machinekey.Append("/>\n");
            return aspnet20machinekey.ToString();
        }

        public static string getASPNET11machinekey()
        {
            StringBuilder aspnet11machinekey = new StringBuilder();
            string key64byte = getRandomKey(64);
            string key24byte = getRandomKey(24);

            aspnet11machinekey.Append("<machineKey");
            aspnet11machinekey.Append(" validationKey=\"" + key64byte + "\"\n");
            aspnet11machinekey.Append(" decryptionKey=\"" + key24byte + "\"\n");
            aspnet11machinekey.Append(" validation=\"SHA1\"\n");
            aspnet11machinekey.Append("/>\n");
            return aspnet11machinekey.ToString();
        }

위의 코드를 사용하여 프로그램을 만들거나 ZIP 파일 안의 프로그램을 이용하여 값을 만들도록 하면 아래와 같은 XML 코드 조각을 얻을 수 있을 것입니다. 이 코드 조각을 각각의 서버에 들어있는 web.config에 지정하거나, 특정한 값만 인용하여 아래의 IIS 7 설정 아이콘에서 볼 수 있는 설정 도구를 통해서 직접 설정할 수도 있습니다.

<machineKey
 validationKey="FACBB6C89C44CB8BB7165FC4639BAA7267B...EF297D815E1BDD40E883E3451628CB95D34309"
 decryptionKey="4E95057676CC8DBA9AB...AACC1121B6B962E5AFA7849B0C82"
 validation="SHA1" decryption="AES"
/>

기술적인 이야기 3 - IIS에서 놓치면 안되는 것

ASP.NET을 가장 먼저 사용할 수 있게 된 웹 서버가 IIS이다보니 발생한 일종의 특성입니다만 여러 포럼에 걸쳐서 잘 언급되지 않는 문제점이 하나 있습니다. 바로 IIS에서 사용하는 사이트 ID 값을 통해서 정해지는 Application Path를 Machine Key와 같이 활용된다는 사실입니다. 웹 사이트 관리를 하다보면 로드 밸런싱에 참여하는 컴퓨터들을 다음과 같이 관리하게 되는 경우가 있습니다.

  • 서버 A에서는 기본 웹 사이트를 먼저 지우고 새 웹 사이트를 만들었다.
  • 서버 B에서는 새 웹 사이트를 먼저 만들고 기본 웹 사이트를 지웠다.

혹은 아래와 같은 경우도 있을 수 있습니다.

  • 서버 C에서는 사이트 A를 만들고 사이트 B를 만들었다.
  • 서버 D에서는 사이트 B를 만들고 사이트 A를 만들었다.

별 차이 없이 생각할 수 있지만, IIS에서는 이 경우 각각의 사이트들에 다른 ID 값을 부과하게 됩니다. 이 경우, 분명히 Machine Key를 동일하게 지정했음에도 불구하고 로드 밸런싱 환경에서 세션 상태가 일관성없게 변하는 문제를 만나게 됩니다. 제가 이번에 고민하게 된 부분도 바로 이 부분이었는데요, 이 문제를 해결하기 위해서는 IIS 7에서 전체 웹 사이트 목록에 나타나는 내용 중 다음의 ID 값이 멤버로 참여하는 웹 서버마다 차이가 있지 않은지 우선 검토해야 합니다.

위에있는 그림에서 빨간색으로 그린 부분이 서버 컴퓨터마다 차이가 있다면 이 값을 수정해주어야 합니다. 이 값을 수정하기 위해서는 수정할 사이트를 클릭하고, 고급 설정 링크를 아래 그림과 같이 클릭합니다.

이제 아래와 같은 팝업 대화 상자가 나타나면 강조 표시한 속성인 ID 값이 멤버로 참여하는 웹 서버 모두 같은 값을 가질 수 있도록 통일시켜줍니다.

확인 버튼을 누른 다음, ID 값이 바뀐 서버 컴퓨터에 한해서 IIS 전체를 재시작해주시거나 사이트 재시작을 시켜주시면 정상적으로 작동하게 될 것입니다.

Windows Azure 환경에서의 고려 사항

오늘 살펴본 내용은 IIS 7과 ASP.NET에 관한 부분이었지만, Windows Azure Platform의 경우에도 비슷한 문제가 있습니다. Windows Azure Platform에 VM Role로 웹 사이트를 게시를 하든, Web Role로 웹 사이트를 게시하든 세션을 사용하게 될 경우 비슷한 문제가 있을 수 있습니다.

다행히, Web Role을 이용한다면 내부적으로 사용하는 IIS에서 여러분이 몇 개의 웹 사이트를 추가적으로 구성하든 관계없이 같은 순서로 같은 ID를 사용하는 웹 사이트를 만들 것이므로 세 번째로 이야기한 ID 값 수정과 같은 작업은 할 필요가 없을 것입니다. 그러나 Machine Key에 대한 설정이나 세션 공유를 위한 설정은 SQL Azure를 이용한다거나, Worker Role에서 ASP.NET State Service 혹은 써드파티의 Session State Server를 이용해야 할 수 있습니다.

물론, 최근에 Windows Azure Platform의 일부로 Windows Azure AppFabric Cache가 새로 출시되기는 하였습니다만 상당히 이용 가격이 비싼 편입니다. (비싼만큼 확실한 성능을 제공합니다.) 로드 밸런싱 환경에서 특별한 문제를 일으키지 않는 일반적인 세션 공유가 필요하시다면 오늘 이야기한 주제를 응용한 Azure Project를 구축해보는 것도 의미가 있을 것입니다.

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

인터넷 검색 중에 아주 흥미로운 웹 캐스트를 하나 발견하였습니다. 닷넷 기반 응용프로그램 프레임워크 전문 개발 업체인 DevForce를 기반으로 하는 Prism Explorer와 이에 연관된 Northwind 샘플 데이터베이스를 기초로 하는 엔터프라이즈 응용프로그램을 Windows Azure Platform의 Windows Azure Compute와 SQL Azure Database로 마이그레이션하는 웹 캐스트입니다. 기본적으로 이 동영상은 DevForce 프레임워크의 클라우드에서의 활용 가능성 및 실리성을 설명하기도 하지만, 동시에 Windows Azure Platform에 대한 실질적인 예를 들어주는 좋은 사례라 생각하여 블로그에 백서와 동영상에 대한 링크를 첨부하였습니다.

백서 다운로드 (English Only): http://www.ideablade.com/PDF/DevForceInAzure.pdf
동영상 출처 (English Only): http://www.ideablade.com/Videos/PrismExToAzure/
홈페이지: http://www.ideablade.com/DevForceProductPlatform/DevForceInAzure.aspx

저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

이 글은 http://www.boutell.com/newfaq/misc/urllength.html 의 내용을 인용하여 서술한 것으로 2006년 이후로 바뀐 내용들이 반영되어있지 않은 것들이 많습니다. 덧붙일 의견이 있으시면 언제든 말씀해주시면 반영하겠습니다. :-)

http://www.w3.org/Protocols/rfc2616/rfc2616.html 에서 설명하는 사양에도 최대 URL 길이에 대한 내용은 언급이 되어있지 않습니다. 하지만 웹 개발을 하면서 누구나 한번즈음은 이런 부분에 대해서 고민을 하게 될 때가 있는데, 그러한 고민을 풀어줄만한 아티클이 있어 소개해 봅니다.

Browser Case No. 1: Microsoft Internet Explorer

http://support.microsoft.com/kb/q208427/ 에서 언급한 것 처럼 Microsoft Internet Explorer는 내부 WININET 헤더 파일 상의 정의를 충실히 따릅니다. URL이 가질 수 있는 최대 길이는 2083자이고, 이 중 프로토콜, 서버 이름 등을 제외한 순수 경로가 2048자까지 허용이 됩니다. 이 글을 작성했던 분의 테스트 결과에 따르면 URL 길이가 긴 경우 브라우저 차원에서 오류 페이지를 띄운다는 것으로 결과가 나왔다고 합니다.

Browser Case No. 2: Firefox

버전 1.5.x의 경우 시각적으로 주소 표시줄은 65536번째 글자 이후로는 주소를 더 표시하지 못한다고 합니다. 그러나 논리적으로 십만글자 이상의 URL도 정상적으로 처리하는 것으로 보이며, 현재 출시되는 Firefox의 경우 이러한 제약이 거의 없지 않겠는가 하는 예상을 해봅니다.

Browser Case No. 3: Safari

적어도 8만자까지는 잘 동작한다고 합니다. :-)

Browser Case No. 4: Opera

긴 URL에 관해서는 종결자라고 해도 틀림없겠네요. 무려 19만자까지, 그것도 인라인 편집이 아닌 여러 행 편집이 가능한 컨트롤로 확장까지 가능하다고 합니다. >_<

Web Server Case No. 1: Apache

기본적으로 약 4000자까지는 허용하지만 그 이후부터는 413 Entity too large 오류가 발생한다고 합니다. 그러나 근래 개발되는 RHEL 기반에서의 Apache는 문서 상으로 약 8000자 이상까지 지원한다고 합니다.

Web Server Case No. 2: Microsoft Internet Information Services (IIS)

기본적으로 16384자까지 지원하며 이는 Microsoft Internet Explorer의 경우와는 상반되는 동작입니다. 게다가 설정도 가능합니다. 특별한 제약은 없겠지만 너무 긴 URL을 받아들이는건 상식적이지 않겠지요.

Web Server Case No. 2-1: ASP.NET

웹 서버 이야기는 아닙니다만 IIS에서 독자적인 처리 규정을 가지고 있는 서버 기반 처리 엔진에 대한 이야기를 하나 하자면, ASP.NET의 이야기를 해야 할 것 같습니다. ASP.NET 3.5 SP1 (내부 ASP.NET 2.0) 까지는 Windows의 시스템 상수 _MAX_PATH가 정의하는 범위 만큼의 URL만을 IIS의 설정과는 관계없이 받아들일 수 있었지만 ASP.NET 4.0부터는 Web.config 파일의 httpRuntime 요소의 maxQueryStringLength 속성에 의하여 확장이 가능합니다.

Web Server Case No. 3: Perl의 HTTP::Daemon

기본적으로 8000자까지 지원합니다. POST 메서드로 수신하게 되는 데이터를 제외하고 순수 HTTP 헤더는 16384바이트까지 지원하며 이 중 헤더에 들어있을 URL에도 이러한 제약이 적용됩니다. 즉, 헤더에 전달되는 내용과의 상관관계도 감안해야하므로 헤더의 양이 많은 경우 8000자보다 안되게 지원이 될 수도 있습니다. 보통은 8000자 이상의 URL로 요청을 하는 경우 413 오류가 발생합니다. 이러한 제약을 넘기위해서 Daemon.pm 파일 내의 16x1024라는 모든 표현식을 더 큰 값으로 수정하면 됩니다. 물론, 이런 동작을 하는 경우 당연한 이야기이지만 Denial of Service (DoS) 공격에 취약해질 수 밖에 없겠지요.

결론

이 글에서는 단순히 fact에 대해서만 살펴보았습니다. 기본적으로 URL이 필요 이상으로 길다고 하는 것 (그 기준이 정확하지는 않지만 상식적인 범위를 벗어나는, 가령 100글자 이상)은 정상적인 상황이 아닐 것입니다. 이 정도로 긴 URL을 보내야 한다면, 대개는 Query String이 그 원인일 것이므로, GET 방식 대신 POST 방식의 전송을 고려해보실 수 있습니다. 하지만 긴 URL을 유지해야 할 필요가 있다면 제가 원본으로 참조한 글의 끝자락에 있는 "The Bookmark Problem" 섹션을 참고하시기 바랍니다.

저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

등록 사이트로 바로 가기: https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032473907&Culture=ko-KR



쉽고 빠르게 완성하는 Easy My Web Project
세미나 일시 : 2011. 01. 21(금) / 14:00~18:00
세미나 장소 : 섬유센터 이벤트홀(삼성동)
세미나 참석 대상 : Web 개발자 & 디자이너, 그리고 Web 개발에 관심있는 모든 분들

“오늘 다시 웹 개발에 대해 이야기 하자!”

웹개발이 당연한 것이 되었다고 이야기들 하지만,
소셜과 모바일이 찾아 온 지금,
우리에게 웹을 하나씩 갖는 일은 어느 때보다 중요해졌습니다.
더 유연하게, 더 쉽게, 더 빨리, 더 싸게, 웹사이트를, 소셜 사이트를,
앱서버와 앱사이트를, 모바일 사이트를 모두 만들 수는 없을까요?

지금 전혀 새로운 지평이 펼쳐지려 하고 있습니다.
지금까지 우리가 알고 또 다루어 왔던 웹이 전혀 새로운 차원에서 유연하고 쉬워지려 하고 있습니다. ?

1월 21일 이 새로운 매트릭스로 여러분을 초대합니다.


웹개발의 신조류에 대해 이야기하자!
PHP에서 新ASP.NET, 소셜에서 모바일, 오픈소스활용에서 자체개발까지 이보다 쉬울 수 없는 웹개발 신조류
ASP.NET이 PHP보다 쉬워졌다?
ASP.NET 최신 동향과 최신 사례 소개
오픈소스 패키지를 3분만에 요리하고 서빙하기.
웹매트릭스 지원 호스터의 쇼케이스
이제 정말 내일의 웹개발에 대해 이야기하자!
패널 디스커션

 
등록 사이트로 바로 가기: https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032473907&Culture=ko-KR

저작자 표시 비영리 동일 조건 변경 허락
이 장소를 Daum지도에서 확인해보세요.
서울특별시 강남구 대치2동 | 섬유센터
도움말 Daum 지도
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

참가 신청 바로 가기: http://onoffmix.com/event/1787


  • 주최 : 한국 Visual Studio 공식 팀
  • 일시 : 2010년 9월 28일 오후 7시 ~ 10시
  • 장소 : 한국 마이크로소프트 - 포스코 센터 5층
  • 참가비 : 무료
  • 최근 쏟아지는 기술의 홍수 속에서 '아차~' 하고 눈 깜빡할 순간 신기술에 낙오되기 쉽습니다. 한 번은 괜찮지만, 두 번은 기술 트랜드를 따라잡기가 더 힘들어 집니다. 저희 팀에서 기술을 먼저 접해보고, 먼저 고민해본 살아있는 경험을 여러분들에게 전수해 드립니다.
  • 세미나 아젠다

    시간

    세션 내용

    19:00 ~ 19:30

    등록

    19:30 ~ 20:10

    현실적인 클라우드 컴퓨팅 이야기

    남정현 C# MVP

    20:20 ~ 21:00

    Expression Blend 와 함께하는 윈도우 폰 7 개발 입문

    조진현

    21:10 ~ 21:50

    Razor 로 열어가는 새로운 ASP.NET

    김시원 ASP.NET MVP

      

       

    발표 내용 소개

    현실적인 클라우드 컴퓨팅 이야기 / 남정현 C# MVP

    클라우드 컴퓨팅, 말로만 들어봤지 실제로 어디에 어떻게 사용이 될 수 있는지 알려주는 사람이 없어 답답할 때가 많습니다. 이번 세션에서는 클라우드 컴퓨팅에 관한 실질적인 이야기, 그 중에서도 특별히 마이크로소프트의 윈도 애저 플랫폼에 대한 이야기를 나누면서, 클라우드 컴퓨팅의 현실적인 사례를 간단히 들어보기로 하겠습니다.

      

    Expression Blend 와 함께하는 윈도우 폰 7 개발 입문 / 조진현

    윈도우 폰7 개발에 대한 간단한 소개와 방법에 대해서 살펴본다. 그리고 더 쉽고 편한 개발을 위한 고민을 해보며, 이를 위해서 Expression Blend 의 활용에 대해서 고민해 본다.

      

    Razor 로 열어가는 새로운 ASP.NET - 김시원 ASP.NET MVP

    Razor 는 차세대 ASP.NET 의 새로운 View Engine 으로써 , 이것 때문에 요즈음 ASP.NET 이 한창 주목 받고 있습니다. 이번 시간에는 Razor 의 등장배경과 함께 Razor 로 인해 개발 환경이 어떻게 변화하였는지 살펴보고 , 기본적인 Razor 의 사용법을 익혀보도록 하겠습니다.

    발표자 소개

    남정현 C# MVP

    (주)코아뱅크에 재직 중이며, Microsoft Visual C# MVP로 활동 중입니다. DEVPIA C# Forum SYSOP, Windows Azure Cafe SYSOP을 맡고 있습니다. 여러 커뮤니티와 개인 블로그, 트위터 (@rkttu)를 통하여 윈도 애저 플랫폼에 대한 다양한 이야기를 전파하고 있습니다.

    조진현

    현재 게임 개발자로 재직 중이며  Visual Studio 2010 공식 팀 블로그 (http://vsts2010.net) 에서 DirectX 관련 분야에서 활동 중이다. 최근에는 '김탁구'와 '나는 전설이다' 라는 드라마에 빠져서 살고 있다.

      

     

    김시원 ASP.NET MVP
    ASP/ASP.NET MVP를 2009년 부터 계속 유지해오고 있으며 다양한 형태의 웹 어플리케이션 개발 경험과 세미나 경험을 가지고 있다. 현재 Hugeflow 웹 솔루션 개발팀에서 개발의욕을 불사르고 있다. 세상을 풍요롭게 하고 사람들에게 강한 종속성을 부여하는 프로그램을 개발하는 것이 목표이다.

    오시는 길

    한국 마이크로소프트 - 포스코 센터 5층

     

    참가 신청 바로 가기: http://onoffmix.com/event/1787


    저작자 표시 비영리 동일 조건 변경 허락
    이 장소를 Daum지도에서 확인해보세요.
    서울특별시 강남구 대치4동 | 포스코센터
    도움말 Daum 지도
    크리에이티브 커먼즈 라이선스
    Creative Commons License
    Posted by Windows Azure MVP 남정현 (rkttu.com)

    Microsoft PDC (Professional Developer Conference)는 매년 Microsoft의 주최로 열리는 세계적인 규모의 개발자 컨퍼런스 행사로, Microsoft의 최신 기술들을 가장 완벽한 형태의 내용으로 접할 수 있는 최고의 리소스입니다. 올해도 어김없이 열립니다. :-D

    Microsoft 본사가 있는 미국 레드먼드에서 2010년 10월 28일부터 10월 29일 이틀간 열리는 이번 PDC10 행사에서는 크게 세 가지 주제를 바탕으로 세션들이 배치되고 트랙이 나뉘어지게 됩니다. Windows Azure Platform에 대한 새로운 업데이트와 고급 응용프로그램 개발 전략을 소개할 Cloud Track, 곧 베타 버전 발표를 앞두고 있는 Windows Internet Explorer 9과 여기에 맞추어 지원될 HTML 5, 그리고 조만간 정식 출시를 눈앞에 두고 있는 Windows Phone 7 Series에 대한 다양한 내용을 소개할 Client Track, 그리고 작년 PDC09 행사에 이어서 ASP.NET MVC 3, Razor, Web Matrix, Visual Studio LightSwitch와 같이 새롭게 소개되는 Framework에 연관되어있는 다양한 기술들을 소개할 Framework Track으로 구성될 예정입니다. 아래는 미국 현지 시간 기준 전체적인 행사 Agenda입니다.

    Wednesday, October 27, 2010 
    7:00pm – 9:00pm: Welcome Reception - Microsoft Visitor's Center, Bldg 92 

    Thursday, October 28, 2010 
    7:00am – 5:00pm: Registration 
    9:00am – 11:00am: Keynote 
    11:00am - 12:00pm: Sessions 
    12:00pm – 1:30pm: Lunch 
    1:30pm – 5:00pm: Sessions 
    6:00pm – 10:00pm: Attendee Party - Lucky Strike, Bellevue, WA 

    Friday, October 29, 2010 
    7:30am – 5:00pm: Registration 
    9:00am – 12:00pm: Sessions 
    12:00pm – 1:30pm: Lunch 
    1:30pm – 5:00pm: Sessions 
    5:00pm: Conference Ends 

    아쉽게도, 이미 행사 좌석이 모두 가득찬 상태라서 오프라인 행사를 직접 즐기실 수는 없겠지만, 온라인 생중계 서비스와 향후 PDC10이 종료된 이후에라도 주문형으로 비디오를 시청할 수 있도록 스트리밍 서비스를 계속 이어 나갈 예정이라고합니다. 생중계 서비스는 키노트 세션이 열리는 2010년 10월 28일 오전 9시부터 시작될 예정이며, 한국 시간으로는 2010년 10월 29일 오전 1시부터 PDC10 웹 사이트에서 보실 수 있습니다.

    좀 더 자세한 정보는 PDC10 행사 홈페이지 (http://www.microsoftpdc.com) 을 방문하시면 되겠습니다. :-)

    저작자 표시 비영리 동일 조건 변경 허락
    크리에이티브 커먼즈 라이선스
    Creative Commons License
    Posted by Windows Azure MVP 남정현 (rkttu.com)

    ASP.NET AJAX와 더불어서 ASP.NET MVC를 비롯하여 거의 모든 웹 사이트와 웹 개발 프레임워크들이 채택하는 jQuery에 대한 세미나가 오는 2010년 7월 10일에 열립니다. 이번 세미나에서는 jQuery에 대한 고급 기법을 다루고, jQuery를 어떤 방법으로 확장할 수 있는지에 대한 다양한 테크닉을 "실전! jQuery CookBook"의 역자 분들께서 꼼꼼히 짚어주실 것입니다. 많은 참여 부탁드립니다. :-)

    주의 사항: 세미나 참석 등록을 아래의 주소에서 제공하는 댓글 달기 기능을 이용하여 등록해 주십시오. 아래는 세미나 소개 글을 발췌해 온 것입니다.

    세미나 등록하러 가기: http://taeyo.net/Forum/Content.aspx?TBL=NOTICE&SEQ=383&PGN=1

    7월 10일 기다리던 jQuery 세미나가 시작됩니다.
    실전! jQuery CookBook의 역자들이 모두 모여서 jQuery 고급기법에 관한 세미나를 진행합니다.
    경품으로 신간 "실전! jQuery CookBook"도 드리니 많이 참석하셔서 즐겨주세요.

    이번 세미나는 닷넷 개발자이던, 자바 개발자이던 무관하게 누구나 참석이 가능합니다.
    현장등록도 가능하지만, 사전 준비를 위해서 반드시 리플로 참석 등록을 해주시기 바랍니다.
    미리 참석등록을 한 분에 한해서 경품 추첨에 참여하실 수 있습니다.
    (난 좀 샤이한 사람이다 하시는 분은 등록없이 그냥 오셔도 됩니다만, 그 경우 경품추첨에서 배제됩니다)

    장소 : 한국 마이크로소프트 세미나실(선릉 포스코빌딩 서관 5층)
    일시 : 2010년 7월 10일 토요일 오후 1시 (접수는 1시, 시작은 2시)


    등록방법 : http://taeyo.net/Forum/Content.aspx?TBL=NOTICE&SEQ=383&PGN=1 에 리플로 참석여부와 이름, 개발분야를 남겨주시면 됩니다.

    세션1 : jQuery의 Event 다루기

    • 시간 : 2:00 - 3:00
    • 발표자 : 김경균
    • 내용 :
      jQuery가 지원하는 이벤트에 대한 효과적인 사용방법과 고급 이벤트 기법에 대해서 다룹니다.
      이미 jQuery가 제공하고 있는 이벤트를 사용하는 방법 뿐만 아니라,
      자체적인 이벤트를 작성 및 사용하는 방법 및 이벤트 통지를 받는 방법에 대해서까지 심도 있게 이야기합니다.

    세션2 : jQuery와 QUnit을 이용한 단위 테스트

    • 시간 : 3:15 - 4:15
    • 발표자 : 최지훈
    • 내용 :
      jQuery로 작성한 코드에 대해 단위 테스트하는 방법을 소개합니다.
      Qunit 프레임워크를 사용하여 결과를 어설션하고, 동기/비동기 콜백을 테스트하는 방법을 설명합니다.
      또한, 다양한 테스트를 그룹으로 묶어서 처리하는 방법에 대해서도 다룹니다.

    세션3 : jQuery 확장 플러그인 만들기

    • 시간 : 4:30 - 5:30
    • 발표자 : 김태영
    • 내용 : jQuery를 확장하기 위한 방법들을 설명하고 그를 기반으로 플러그인을 제작해 봅니다.
      기본적인 플러그인 개발 규칙에 대해 다룬 후, 좀 더 완성된 형태의 플러그인 제작을 위해 필요한
      Option Hash 기법 및 $.extend()을 이용한 매개변수 초기화 방법 그리고 클로저 기법을 설명합니다.
      그리고, 그들을 모두 혼합하여 보편적인 형태의 플러그인을 직접 제작하고 활용하는 방법에 대해 이야기합니다.

    경품 : BJ퍼블릭 협찬 - 실전! jQuery CookBook 5권
    - 원하시면 역자들이 사인을 해드립니다.

    * 세션 주제는 좀 더 나은 세미나를 위해 통지없이 변경될 수 있습니다.

    tweet : @taeyo

    세미나 등록하러 가기: http://taeyo.net/Forum/Content.aspx?TBL=NOTICE&SEQ=383&PGN=1

    저작자 표시 비영리 동일 조건 변경 허락
    이 장소를 Daum지도에서 확인해보세요.
    서울특별시 강남구 대치4동 | 포스코센터
    도움말 Daum 지도
    크리에이티브 커먼즈 라이선스
    Creative Commons License
    Posted by Windows Azure MVP 남정현 (rkttu.com)