구관이 명관 – 어느 위치에서 실행하든 경로를 유지하는 배치 파일 만들기

오랫만에 구관이 명관 시리즈를 업데이트해봅니다. 이번 아티클은 작지만 확실히 유용한 팁 하나를 소개해볼까 합니다. 배치 파일을 작성하고 배포할 때 가장 큰 문제가 되는 것이, 배치 파일이 의도하지 않은 디렉터리 경로 상에서 실행된다는 점일 것입니다.


 


 


예를 들면 배치 파일을 명령어나 다른 프로그램을 이용하여 실행하면 배치 파일이 있는 경로가 아닌 호출한 프로그램의 현재 디렉터리 경로 위에서 실행되어서 문제가 될 때가 있습니다. 물론 배치 파일의 이런 특성을 활용해야 하는 경우도 있겠습니다만, 보통은 배치 파일을 실행할 때 정확히 해당 경로 상에서 어떤 작업을 하도록 의도한 것이 많으므로 이런 특성은 불편할 수 있습니다.


이 문제를 수정하려면 배치 파일의 경로를 항상 정확하게 알 수 있어야 하는데, 이럴 때 %~dp0 환경 변수를 사용하면 쉽게 문제를 해결할 수 있습니다. 하지만 무작정 cd 명령을 사용하면 배치파일이 끝나고 난 다음에 디렉터리 위치가 원래대로 돌아오지 않는 문제가 남습니다.


이런 문제를 해결하기 위하여, 새로 작성하는 배치 파일의 시작과 끝을 아래의 코드처럼 작성하도록 하면 편리할 것입니다.
@echo off
pushd “%~dp0”


rem 여기에 배치 파일 본문을 작성합니다.


:exit
popd
@echo on



 


내용은 단순합니다. 실행하는 명령줄이 보이지 않게 @echo off로 감추고, pushd 명령을 사용하여 스택에 현재 디렉터리 경로를 push하고 새 위치로 이동한 다음 원하는 일을 하는 것입니다. 그리고 나중에 종료할 때에는 popd 명령을 사용하여 직전에 저장한 디렉터리 경로를 꺼내와 그 위치로 다시 이동하고 @echo on으로 (심미성을 위하여 @echo on이라고 썼습니다.) echo 상태를 복원합니다. 여기서 :exit 라벨은 프로그램 내에서 탈출 조건을 만났을 때 편리하게 활용할 수 있도록 하기 위한 것입니다.


위의 예제를 활용하면 다음과 같이 응용할 수 있습니다.


@echo off
pushd “%~dp0”



if not exist %windir%system32runas.exe. (
    echo RUNAS.EXE 프로그램을 찾을 수 없습니다.
    pause
    goto exit
)


for /r “%~dp0” %%v in (test.cmd) do (
    if exist “%%v” (
        echo %%v 진행 중…
        call “%%v”
        rem 다른 배치 파일을 호출하고나면 echo on 상태가 되므로 다시 @echo off로 꺼줍니다.
        @echo off
    )
)


:exit
popd
@echo on



 


위와 같이 활용한다면 배치 파일을 어디서 실행하든 원하는 경로로 들어갔다가 다시 쉽게 원래 위치로 되돌아올 수 있으므로 일반 프로그램처럼 배치 파일을 작성하는 것이 좀 더 쉬워집니다.

ubuntu 14.04에서 asp.net vnext 설치하고 사용하기, mono 3.8 업데이트

NOTE: 지난 번에 올렸던 글 이후로 mono 3.8이 빠르게 추석 연휴를 사이로 업데이트가 되었는데, mono의 최신 버전을 설치하는 과정이 무척 복잡하고 까다로웠던 점이었던게 상당히 아쉬웠습니다. 그런데 이 부분이 잘 해결된 듯 하여 업데이트된 내용을 더해 글을 더 보강하여 다시 게시합니다.


 


 


다시 말씀드리면, 이 블로그 포스트는 MS Azure Virtual Machine과 Ubuntu Server 14.04 버전을 최초 설치했을 때의 상태를 기준으로 작성된 것이며, 이 블로그 글을 작성하는 2014년 9월 현재 ASP.NET vNext가 정식 출시 전임을 말씀드립니다.


주의: 실제 배포 환경에서 이 블로그 포스트의 내용을 활용하시는 것은 매우 위험합니다.


사전 준비 작업


중요: 이 아티클에서 소개하는 내용은 Ubuntu 14.04에서 작동하며, Ubuntu 12 버전에서는 패키지 버전 불일치 등으로 인하여 mono 3.8이 정상적으로 설치가 되지 않아 실행할 수 없습니다.


최근들어 변경된 사항으로, Mono의 최신 버전 릴리즈는 Xamarin이 독자적으로 운영하는 패키지 리포지터리를 통하여 좀 더 빠르게 받아보실 수 있습니다. 하지만 2014년 9월 현재 모든 배포판에 대해 완전하게 설치를 보장하는 것이 아닌 것으로 보입니다.


Mono 3.8 및 그 이후 버전을 설치하기 위하여 우선 해야 할 일은 Xamarin 리포지터리를 시스템에 추가하는 일입니다.


단순한 설명을 위하여, 현재 로그인한 사용자의 홈 디렉터리로 일단 디렉터리 변경을 하겠습니다.



cd ~


Xamarin 리포지터리의 GPG Key를 내려받도록 합니다.



wget http://download.mono-project.com/repo/xamarin.gpg


그리고 내려받은 GPG 키를 저장합니다.



sudo apt-key add xamarin.gpg


/etc/apt/sources.list 파일을 편리한 텍스트 편집기로 열고, 가장 마지막에 다음의 줄을 추가한 후 저장하고 닫습니다.



deb http://origin-download.mono-project.com/repo/debian/ wheezy main


패키지 캐시를 업데이트하기 위하여 아래 명령어를 실행합니다.



sudo apt-get update


이제 Mono 3.8을 설치할 준비가 다 되었습니다. 아래 명령어만 실행하면 됩니다.



sudo apt-get -y install mono-complete


설치가 다 끝나면 mono의 버전을 확인해봅니다.



mono –version


K Runtime과 ASP.NET vNext 설치하기


Mono 3.8이 9월에 릴리즈하고 나서 K Runtime과 ASP.NET vNext를 테스트하는 방법에도 조금 변화가 생겨서 그 내용을 같이 말씀드립니다.


HTTPS/SSL 인증서들을 추가하고 Mono에서 사용할 수 있도록 동기화하는 작업을 반드시 실행합니다.



sudo certmgr -ssl -m https://go.microsoft.com
 sudo certmgr -ssl -m https://nugetgallery.blob.core.windows.net
 sudo certmgr -ssl -m https://nuget.org
 sudo certmgr -ssl -m https://myget.org
 mozroots –import –sync


ASP.NET vNext를 실행하기 위해서는 unzip 패키지가 필요합니다.



sudo apt-get install unzip


그리고 ASP.NET vNext 설치 스크립트를 내려 받습니다.



curl https://raw.githubusercontent.com/aspnet/Home/master/kvminstall.sh | sh && source ~/.kre/kvm/kvm.sh


source 명령을 사용하여 K runtime을 쉽게 실행할 수 있도록 설정합니다.



source ~/.kre/kvm/kvm.sh


2014년 9월 23일 현재 최신 버전은 1.0.0-alpha4-10353입니다. 이 버전을 내려 받기 위하여 KRE_FEED 환경 변수에 Feed URL을 설정하고 해당 버전을 설치합니다.



export KRE_FEED=https://www.myget.org/F/aspnetvnext/api/v2
 kvm install 1.0.0-alpha4-10353


예제 소스 받아서 테스트해보기


이전 아티클에서 이야기했던 내용을 좀 더 보강하면, 현재 ASP.NET vNext의 k web 명령은 아직 Windows 환경에서만 실행이 가능한 상태입니다. Mono를 통하여 웹 서버를 시작하고 ASP.NET vNext를 호스팅할 수 있게 하려면 project.json에 별도의 명령어를 추가해주어야 합니다. 물론 이는 추후에 정식 버전이 릴리즈가 될 때 당연히 해결될 문제이므로 걱정하지 않으셔도 됩니다.


git 패키지를 설치하도록 합니다.



sudo apt-get install git


ASP.NET vNext Home 리포지터리에서 예제 소스를 체크아웃합니다.



git clone https://github.com/aspnet/Home.git


늘 그렇듯이, 콘솔 프로젝트를 시작점으로 잡아봅니다. 🙂



cd ~/Home/samples/ConsoleApp/
 kpm restore
 k run


그리고 현재 알파 버전의 ASP.NET vNext 기준으로 리눅스에서 웹 서비스를 실행해보기 위해서는 NOWIN 팩토리 패키지를 구성해야 할 필요가 있습니다.



cd ~/Home/samples/
 mkdir Nowin.vNext
 cd Nowin.vNext
 wget https://github.com/davidfowl/HelloWorldVNext/raw/master/src/Nowin.vNext/NowinServerFactory.cs
 wget https://github.com/davidfowl/HelloWorldVNext/raw/master/src/Nowin.vNext/project.json


위와 같이 준비되면, HelloWeb 프로젝트의 project.json에 들어있는 dependencies 섹션과 commands 섹션을 편집기로 조금 수정하여 앞서 만든 NOWIN 팩토리로 서버를 띄울 수 있게 해야 합니다. project.json에 대한 자세한 내용은 Project.json 파일 을 참고하십시오.



cd ~/Home/samples/HelloWeb/


project.json 파일을 편집기로 열고 각각 다음의 사항을 반영하도록 합니다.
•dependencies에 다음을 추가합니다.
“Nowin.vNext”: “”,
•commands에 다음을 추가합니다.
“nowin”: “Microsoft.AspNet.Hosting –server Nowin.vNext”,


project.json 파일을 저장하고, 다음의 명령어를 실행합니다.



kpm restore
 k nowin


앞에서 다운로드 한 Nowin Factory 프로젝트의 코드를 보면 TCP/5000 포트를 웹 리스너 포트로 사용하고 있습니다. 밖에서 호스트 이름과 함께 5000번 포트로 접속하면 웹 페이지가 나타나는 것을 볼 수 있습니다. 그리고 서버를 종료하려면 콘솔에서 아무 키나 누르면 종료가 됩니다.


만약에 원격에서 좀 더 지속적으로 서버의 성능을 측정해보고 싶으시다면 screen 유틸리티를 사용하여 세션을 분리하신 상태에서 위의 명령어를 입력하고, 서버가 떠 있을 때 Ctrl 키를 누른 상태에서 빠르게 a, a, d 키를 누르면 세션이 분리되어 계속 살아있는 서버가 만들어집니다. 이 상태에서 Apache Bench (AB)등의 유틸리티를 사용하여 부하 테스트 등을 해보시는 것도 의미가 있을 것입니다.


참고로, NAT 환경이나 퍼블릭 클라우드 환경에서는 대표 IP 주소에 대한 외부 방화벽 설정을 열어주셔야 밖에서도 접속이 가능합니다.


마무리


ASP.NET vNext는 계속 업데이트가 이루어지고 있는 상태이며, Mono 런타임의 개선에 따라 리눅스와 맥 OS X에서 ASP.NET vNext를 사용하는 것이 좀 더 쉬워지고 간편해질 전망입니다. 더 많은 기대를 해도 좋지 않을까 생각합니다. 🙂


 

Project.json 파일

번역: 남정현



날짜: 2014-08-24



이 문서에 대하여


이 문서는 2014년 8월 19일에 작성된 https://github.com/aspnet/Home/wiki/Project.json-file 의 내용을 한국어로 번역한 것으로, 원본 문서 작성자는 ASP.NET vNext 팀입니다. 오역, 어색한 부분, 매끄럽지 않은 부분이 있을 경우 알려주시면 적극적으로 반영하도록 하겠습니다.


스키마


http://json.schemastore.org/project


의존성


 


 


의존성 섹션은 여러분의 애플리케이션이 사용하는 모든 의존성들을 열거합니다. 이름과 버전으로 정의할 수 있으며, 런타임 로더가 어떤 것을 반드시 로드해야 할지 결정합니다. NuGet 패키지, 소스 코드 등이 될 수 있습니다.


<br /> {</P>
<P>“dependencies”: {</P>
<P>“Microsoft.AspNet.ConfigurationModel”: “0.1-alpha-<em>”,</P>
<P>“SomeProject”: “”</P>
<P>}</P>
<P>}<br /> 


여기서 사용할 수 있는 또 다른 기능으로 아래와 같이 더 구체적으로 의존성 설정을 지정하는 것이 가능합니다.


<br /> {</P>
<P>“dependencies”: {</P>
<P>“Microsoft.AspNet.ConfigurationModel”: { “version”: “0.1-alpha-</em>”, “options”: “private” },</P>
<P>“FakeToolingPackage” : {“version”: “0.1”, “options”: “dev”},</P>
<P>“SomeProject”: “”</P>
<P>}</P>
<P>}<br /> 


참조에는 여러 가지 다른 종류들이 있을 수 있습니다.


•Private – 의존성을 인텔리센스나 혹은 컴필레이션에 노출하지 않도록 할 수 있습니다.


 


•Bago (Build and go away) – 이 참조를 컴파일한 후에 대상 프로젝트 안으로 같이 컴파일됩니다.


 


어떻게 의존성 버전이 선택되는지에 대한 더 상세한 정보는 https://github.com/aspnet/Home/wiki/Dependency-Resolution 에서 자세히 확인할 수 있습니다.


Configurations 섹션


Configurations는 컴필레이션 설정에 대한 이름이 붙여진 그룹 항목들입니다. 실행 시점에는 기본으로 주어지는 설정 두 가지가 있는데, 바로 Debug와 Release입니다. 이들 설정을 project.json에 필요에 따라 다시 설정하거나 새로운 설정을 더 추가하는 것도 가능합니다.


<br /> {</P>
<P>“configurations”: {</P>
<P>“Debug”: {</P>
<P>“compilationOptions”: {</P>
<P>“define”: ["DEBUG", "TRACE"],</P>
<P>“debugSymbols”: “full”</P>
<P>}</P>
<P>},</P>
<P>“Release”: {</P>
<P>“compilationOptions”: {</P>
<P>“define”: ["RELEASE", "TRACE"],</P>
<P>“optimize”: true,</P>
<P>“debugSymbols”: “pdbOnly”</P>
<P>}</P>
<P>}</P>
<P>}</P>
<P>}<br /> 


Frameworks 섹션


어느 프레임워크를 대상으로 개발된 프로그램인지 정의하고, 해당 구성에서 참조하는 의존성들을 dependencies에서 정의할 수 있습니다. 아래 코드 조각에서는 데스크톱 (net45) 또는 Core CLR (k10) 중 하나를 사용할 것입니다. Core CLR은 BCL을 만들기 위해서 더 많은 참조들에 대한 의존성을 가집니다.


<br /> {</P>
<P>“frameworks”: {</P>
<P>“net45″: {},</P>
<P>“k10″: {</P>
<P>“dependencies”: {</P>
<P>“System.Collections”: “4.0.0.0”,</P>
<P>“System.Collections.Concurrent”: “4.0.0.0”,</P>
<P>“System.ComponentModel”: “4.0.0.0”,</P>
<P>“System.Linq”: “4.0.0.0”,</P>
<P>“System.Reflection”: “4.0.10.0”,</P>
<P>“System.Runtime”: “4.0.20.0”,</P>
<P>“System.Runtime.InteropServices”: “4.0.10.0”,</P>
<P>“System.Threading”: “4.0.0.0”,</P>
<P>“System.Threading.Tasks”: “4.0.0.0”</P>
<P>}</P>
<P>}</P>
<P>}</P>
<P>}<br /> 


Sources 섹션


sources 섹션은 컴파일해야 할 소스 코드들을 지정합니다.


<br /> {</P>
<P>“code”: “<em>.cs”,</P>
<P>“exclude”: “buggy/<strong>/*.cs”,</P>
<P>“resources”: “embed/</strong>/</em>.<em>”</P>
<P>}<br /> 


공유 파일 섹션


여러 프로젝트에서 의존하는 코드를 공유할 수 있습니다. 공유 어셈블리 정보 같은 내용을 담고 있는 코드를 공유하기 위해서, 공통 프로젝트를 만들고, 이 프로젝트에서 공유 파일 섹션을 포함하도록 공유할 코드를 참조하게 하면 됩니다. 그 후에는 새로 만든 공통 프로젝트를 참조하는 프로젝트라면 항상 프로젝트에 해당 파일들이 같이 포함되어 컴파일이 이루어지게 됩니다.


<br /> {</P>
<P>“shared”: “</em>.cs”</P>
<P>}<br /> 


컴파일 옵션


컴파일 옵션에서는 Roslyn으로 전달할 설정을 지정할 수 있습니다. 여기서 언어의 버전을 선택할 수 있습니다.


<br /> {</P>
<P>“compilationOptions”: {</P>
<P>“define”: ["SOMETHING"],</P>
<P>“allowUnsafe”: true,</P>
<P>“warningsAsErrors” : true,</P>
<P>“languageVersion”: “experimental”</P>
<P>}</P>
<P>}<br /> 


명령


K.cmd를 실행할 때에는 실행하려는 명령의 이름을 지정할 수 있습니다. 아래 코드 조각은 K web이라는 명령어를 실행할 때 셀프 호스트를 시작하도록 하고 있고, K test라는 명령어를 실행할 때에는 모든 단위 테스트를 실행하도록 하고 있습니다.


<br /> {</P>
<P>“commands”: {</P>
<P>“web”: “Microsoft.AspNet.Hosting server.name=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001″,</P>
<P>“test”: “Xunit.KRunner”</P>
<P>}</P>
<P>}<br /> 


스크립트


KPM에서 어떤 일을 수행하기 전과 후에 발생하는 이벤트에 간섭하여 추가 작업을 지시할 수 있습니다.


<br /> {</P>
<P>“scripts”: {</P>
<P>“prebuild”: “echo before building”,</P>
<P>“postbuild”: “echo after building”,</P>
<P>“prepack”: “echo before packing”,</P>
<P>“postpack”: “echo after packing”,</P>
<P>“prerestore”: “echo before restoring packages”,</P>
<P>“postrestore”: “echo after restoring packages”</P>
<P>}</P>
<P>}<br /> 


그리고 사용 가능한 변수들은 다음과 같습니다.
</p><p>%project:Directory% – 프로젝트 디렉터리 경로
</p><p>%project:Name% – 프로젝트 이름
</p><p>%project:Version% – 프로젝트 버전<br />


메타데이터


프로젝트에 대한 메타데이터를 기록할 수 있습니다.


<br /> {</P>
<P>“version”: “0.1-alpha”,</P>
<P>“authors”: ["John Doe"],</P>
<P>“description”: “A wonderful library that does nice stuff”</P>
<P>}<br /> 


Entity Framework 프로젝트에서 가져온 project.json 파일의 한 예시


<br /> {</P>
<P>“version”: “0.1-alpha-<em>”,</P>
<P>“compilationOptions”: {</P>
<P>“warningsAsErrors”: true</P>
<P>},</P>
<P>“dependencies”: {</P>
<P>“Microsoft.Bcl.Immutable”: “1.1.18-beta-</em>”,</P>
<P>“Microsoft.AspNet.ConfigurationModel”: “0.1-alpha-<em>”,</P>
<P>“Microsoft.AspNet.DependencyInjection”: “0.1-alpha-</em>”,</P>
<P>“Microsoft.AspNet.Logging”: “0.1-alpha-<em>”,</P>
<P>“System.Data.Common”: “0.1-alpha-</em>”</P>
<P>},</P>
<P>“code”: “**<em>.cs;..Shared</em>.cs”,</P>
<P>“frameworks”: {</P>
<P>“net45″: {</P>
<P>“dependencies”: {</P>
<P>“System.Runtime”: “”,</P>
<P>“System.Collections”: “”</P>
<P>}</P>
<P>},</P>
<P>“k10″: {</P>
<P>“dependencies”: {</P>
<P>“System.Collections”: “4.0.0.0”,</P>
<P>“System.Collections.Concurrent”: “4.0.0.0”,</P>
<P>“System.ComponentModel”: “4.0.0.0”,</P>
<P>“System.Console”: “4.0.0.0”,</P>
<P>“System.Diagnostics.Contracts”: “4.0.0.0”,</P>
<P>“System.Diagnostics.Debug”: “4.0.10.0”,</P>
<P>“System.Globalization”: “4.0.10.0”,</P>
<P>“System.Linq”: “4.0.0.0”,</P>
<P>“System.Linq.Expressions”: “4.0.0.0”,</P>
<P>“System.Linq.Queryable”: “4.0.0.0”,</P>
<P>“System.Reflection”: “4.0.10.0”,</P>
<P>“System.Reflection.Extensions”: “4.0.0.0”,</P>
<P>“System.Resources.ResourceManager”: “4.0.0.0”,</P>
<P>“System.Runtime”: “4.0.20.0”,</P>
<P>“System.Runtime.Extensions”: “4.0.10.0”,</P>
<P>“System.Threading”: “4.0.0.0”,</P>
<P>“System.Threading.Tasks”: “4.0.10.0”</P>
<P>}</P>
<P>}</P>
<P>}</P>
<P>}<br /> 


 

.NET에서의 String과 Null Character에 대한 이야기

.NET은 문자열을 다루는 데 있어서 C, C++, 혹은 파스칼과 비슷한 듯 다른 면이 있습니다. 그리고 이번 아티클에서는 사소하지만 큰 오류를 내포하게 될 가능성이 있는 부분을 잠시 소개하려고 합니다.


http://msdn.microsoft.com/ko-kr/library/ms228362.aspx 에서는 .NET의 String에 대해 이렇게 소개하고 있습니다.


 


 



문자열은 값이 텍스트인 String 형식의 개체입니다. 내부적으로 텍스트는 Char 개체의 순차적 읽기 전용 컬렉션으로 저장됩니다. C# 문자열 끝에는 null 종결 문자가 없습니다. 따라서 C# 문자열은 포함된 null 문자(‘′)를 제한 없이 포함할 수 있습니다. 문자열의 Length 속성은 유니코드 문자의 수가 아니라 포함된 Char 개체의 수를 나타냅니다. 문자열에서 개별 유니코드 코드 포인트에 액세스하려면 StringInfo 개체를 사용합니다.


굵게 강조 표시한 부분의 내용에 오늘 아티클의 핵심 내용이 모두 들어있습니다. 하지만 꼼꼼하게 기억해두지 않으면 허술하게 다루어질 가능성도 있는 부분이라고 생각합니다.


위의 내용을 상기하면서, 아래의 코드들이 각각 어떻게 실행될지 예상해보면 흥미롭습니다.
string a = “‘abc'”.Replace(”’, default(char));
Console.WriteLine(“a: {0} (Length: {1})”, a, a.Length);
string b = “‘abc'”.Replace(”’, Char.MinValue);
Console.WriteLine(“b: {0} (Length: {1})”, b, b.Length);
string c = “‘abc'”.Replace(”’, (char)0);
Console.WriteLine(“c: {0} (Length: {1})”, c, c.Length);
string d = “‘abc'”.Replace(”’, ”);
Console.WriteLine(“d: {0} (Length: {1})”, d, d.Length);



 


 


Replace로 한 글자만 제거하고 싶어서 위와 같은 코드를 작성하기 쉬운데, 위의 결과에서 원래 의도는 ‘abc’ 라는 다섯 글자를 abc라는 세 글자로 만드는 것이지만, 실제로는 여전히 다섯 글자가 됩니다. 그런데 여기서 한 가지 더 중요한 것은, Trim() 메서드가 앞 뒤로 붙는 null character를 제거해 주지는 않는다는 점입니다.
string a = “‘abc'”.Replace(”’, default(char)).Trim();
Console.WriteLine(“a: {0} (Length: {1})”, a, a.Length);
string b = “‘abc'”.Replace(”’, Char.MinValue).Trim();
Console.WriteLine(“b: {0} (Length: {1})”, b, b.Length);
string c = “‘abc'”.Replace(”’, (char)0).Trim();
Console.WriteLine(“c: {0} (Length: {1})”, c, c.Length);
string d = “‘abc'”.Replace(”’, ”).Trim();
Console.WriteLine(“d: {0} (Length: {1})”, d, d.Length);



 


앞/뒤로 붙은 null character를 제거하려면 null character를 명시하는 작업이 필요합니다. 그리고 이것은 Replace 메서드에 대해서도 동일하게 적용됩니다.
</pre>
<pre>string a = “‘abc'”.Replace(”’, default(char)).Trim(”);
Console.WriteLine(“a: {0} (Length: {1})”, a, a.Length);
string b = “‘abc'”.Replace(”’, Char.MinValue).Trim(”);
Console.WriteLine(“b: {0} (Length: {1})”, b, b.Length);
string c = “‘abc'”.Replace(”’, (char)0).Trim(”);
Console.WriteLine(“c: {0} (Length: {1})”, c, c.Length);
string d = “‘abc'”.Replace(”’, ”).Trim(”);
Console.WriteLine(“d: {0} (Length: {1})”, d, d.Length);



이런 맥락에서 보았을 때, 외부로부터 들어오는 입력 문자열에 대해 엄격하게 이야기하자면, null character에 대한 것을 String.Empty로 치환하는 작업도 필요할 수 있다고 볼 수 있겠습니다.


 

ubuntu 14.04에서 asp.net vnext 설치하고 사용하기

업데이트: mono 3.8이 9월 초에 새로 릴리즈되었으며 이 내용을 기초로 새로 업데이트한 아티클을 올렸습니다.


이 블로그 포스트의 내용은 아래 두 블로그 포스트의 내용을 기초로 작성한 것임을 말씀드립니다.
•http://graemechristie.github.io/graemechristie/blog/2014/05/26/asp-dot-net-vnext-on-osx-and-linux/
•http://www.rocko.me/install-mono-3-4-ubuntu/


또한 이 블로그 포스트는 MS Azure Virtual Machine과 Ubuntu Server 14.04 버전을 최초 설치했을 때의 상태를 기준으로 작성된 것이며, 이 블로그 글을 작성하는 2014년 8월 현재 ASP.NET vNext가 정식 출시 전임을 말씀드립니다.


주의: 실제 배포 환경에서 이 블로그 포스트의 내용을 활용하시는 것은 매우 위험합니다.


 


 


ASP.NET vNext는 기존의 System.Web 기반의 레거시 웹 개발 프레임워크에서 탈피하고자 하는 MS의 강력한 의지의 결과물인듯 합니다. 이전에는 상상하기 어려웠고, MS의 손이 아닌 오픈 소스 그룹 (Mono의 System.Web 구현)이나 써드 파티 회사 (Grasshoper 같은)에 의한 제한적인 수준의 작업 결과물일 뿐이었던 ASP.NET의 이식성이 이제서야 완벽함을 기할 수 있게 되었습니다.


이 블로그 포스트에서는 ASP.NET vNext를 우분투 서버 14.04에서 설치해본 과정을 기록하여 그것을 토대로 작성하였습니다. ASP.NET vNext의 발전 가능성을 살펴보시고, 여러 이야기를 나눌 수 있지 않을까 하여 기록해봅니다.


사전 준비 작업


ASP.NET vNext는 Windows 서버 환경에서는 손수 기존에 설치된 .NET Framework를 대체하는 K Runtime을 사용하여, 어느 버전의 K Runtime을 사용할 것인지 패키지 레벨에서 정의할 수 있는 것이 특징이었는데, 리눅스의 경우 기본 실행 엔진은 현재는 Mono를 기반으로 하고 있는 것이 특징입니다. 그럼에도 불구하고 K Runtime이 가지는 영역이 엄연히 있고, 아마 핵심 실행 엔진만 현재는 Mono를 기반으로 실행되는 것 같습니다.


그런 이유로 Mono의 최신 버전을 시스템에 설치해야 하는데, 안타깝게도 Ubuntu 14.04에 등록된 Mono 패키지의 최신 버전은 ASP.NET vNext를 실행하기 위해 필요한 버전과 격차가 상당히 크고, 또한 지원되지 않습니다. 그래서 제일 먼저 해야 할 일은 github에 올라와있는 Mono 소스 코드를 내려 받아 컴파일하고 새 버전으로 바꾸는 작업입니다.


우선은 기존에 Mono 런타임을 설치했던 이력이 있을 경우를 고려하여 Mono와 관련된 모든 패키지를 제거해야 하는데, 아래 명령어로 간단히 제거할 수 있습니다.



sudo apt-get -y purge mono-*


그 다음, Mono를 설치하기 위하여 필요한 이미징 라이브러리 관련 종속성을 해결해주어야 하는데, 필요한 패키지들중 상당수는 Ubuntu 14.04에서 직접 지원하지 않거나 오래된 버전으로 취급하여 apt-get으로 직접 설치가 어려운 패키지들입니다. 따라서, 이들 패키지들을 수동으로 내려 받아 설치하는 작업이 필요한데, 아래 명령어를 복사하여 하나씩 실행하시면 되겠습니다.



wget http://security.ubuntu.com/ubuntu/pool/main/j/jbigkit/libjbig0_2.0-2ubuntu1.13.10.1_amd64.deb
 wget http://security.ubuntu.com/ubuntu/pool/main/libj/libjpeg-turbo/libjpeg-turbo8_1.3.0-0ubuntu1.1_amd64.deb
 wget http://mirrors.kernel.org/ubuntu/pool/main/libj/libjpeg8-empty/libjpeg8_8c-2ubuntu8_amd64.deb
 wget http://mirrors.kernel.org/ubuntu/pool/universe/t/tiff3/libtiff4_3.9.7-2ubuntu1_amd64.deb
 wget http://mirrors.kernel.org/ubuntu/pool/universe/t/tiff3/libtiffxx0c2_3.9.7-2ubuntu1_amd64.deb
 wget http://mirrors.kernel.org/ubuntu/pool/main/libj/libjpeg8-empty/libjpeg-dev_8c-2ubuntu8_amd64.deb
 wget http://security.ubuntu.com/ubuntu/pool/main/j/jbigkit/libjbig-dev_2.0-2ubuntu1.13.10.1_amd64.deb
 wget http://security.ubuntu.com/ubuntu/pool/main/libj/libjpeg-turbo/libjpeg-turbo8-dev_1.3.0-0ubuntu1.1_amd64.deb
 wget http://mirrors.kernel.org/ubuntu/pool/main/libj/libjpeg8-empty/libjpeg8-dev_8c-2ubuntu8_amd64.deb
 wget http://mirrors.kernel.org/ubuntu/pool/main/libj/libjpeg8-empty/libjpeg-dev_8c-2ubuntu8_amd64.deb
 wget http://mirrors.kernel.org/ubuntu/pool/universe/t/tiff3/libtiff4-dev_3.9.7-2ubuntu1_amd64.deb


sudo dpkg -i libjbig0_2.0-2ubuntu1.13.10.1_amd64.deb
 sudo dpkg -i libjpeg-turbo8_1.3.0-0ubuntu1.1_amd64.deb
 sudo dpkg -i libjpeg8_8c-2ubuntu8_amd64.deb
 sudo dpkg -i libtiff4_3.9.7-2ubuntu1_amd64.deb
 sudo dpkg -i libtiffxx0c2_3.9.7-2ubuntu1_amd64.deb
 sudo dpkg -i libjbig-dev_2.0-2ubuntu1.13.10.1_amd64.deb
 sudo dpkg -i libjpeg-turbo8-dev_1.3.0-0ubuntu1.1_amd64.deb
 sudo dpkg -i libjpeg8-dev_8c-2ubuntu8_amd64.deb
 sudo dpkg -i libjpeg-dev_8c-2ubuntu8_amd64.deb
 sudo dpkg -i libtiff4-dev_3.9.7-2ubuntu1_amd64.deb


Mono 최신 버전 설치하기


이제 기본 준비 작업은 끝났고, 필요한 패키지들을 한꺼번에 설치할 차례입니다. 아래 명령어를 입력하도록 합니다.



sudo apt-get -y install libpng3 libpng3-dev libtool libexif12 libexif-dev libgif4 libgif-dev libpango1.0-dev libatk1.0-dev libgtk-3-0 libgtk-3-dev bison automake autoconf make gcc gtk-sharp2 build-essential xorg-dev libfreetype6 libfontconfig libfontconfig-dev gettext libglib2.0-dev git libjpeg-dev libjpeg8-dev libjpeg-turbo8-dev g++ unzip


쉬운 설명을 위하여, 사용자 프로필 디렉터리에서 설치를 진행한다고 가정하겠습니다.



cd ~


설치가 모두 되고 나면, mono git 리포지터리에서 libgdiplus 소스를 복사합니다.



git clone https://github.com/mono/libgdiplus.git


받은 소스 디렉터리로 이동합니다.



cd ~/libgdiplus


그리고 각종 설정 검사 및 헤더 구성을 진행합니다. 주의할 것은 공식 가이드에서는 –prefix=/usr/local로 소개하고 있으나 우분투의 경우 아래와 같이 /usr을 기준으로 잡아야 합니다.



./autogen.sh –prefix=/usr


구성이 끝나면 컴파일을 하도록 합니다.



make


컴파일 중 특별한 오류 메시지가 없었다면 시스템에 설치하도록 합니다.



sudo make install


이제 다시 홈 디렉터리로 이동합니다.



cd ~


mono 소스를 컴파일하는 과정 중에는 재귀적으로 mcs 컴파일러가 필요합니다. 이를 위하여 mono-gmcs 패키지를 구 버전이지만 우선 설치해야 합니다.



sudo apt-get -y install mono-gmcs


설치가 끝나면, 이제 mono 소스를 복사하도록 합니다.



git clone git://github.com/mono/mono.git
 cd mono


libgdiplus 때와 마찬가지로 prefix 설정에 유의하여 자동 구성을 진행합니다. 자동 구성 중에 다른 git 리포지터리에서 추가로 관련된 소스를 내려받기도 합니다.



./autogen.sh –prefix=/usr


모든 구성이 끝나면 컴파일하고 설치하도록 합니다.



make
 sudo make install


모든 설치가 다 끝났다면, 새 버전 (2014년 8월 현재 3.8)으로 업데이트가 잘 되었는지 확인해보도록 합니다.



mono –version
 mcs –version


위의 명령어에서 새 버전으로 표시가 된다면 ASP.NET vNext를 설치할 준비가 다 끝난 것입니다. 이제 다시 홈 디렉터리로 이동합니다.



cd ~


계속 하기 전에, 라이브러리 경로에 관련된 환경 변수를 하나 설정해주는 것이 좋습니다. 아래 명령어를 실행하여 LD_LIBRARY_PATH 환경 변수를 설정하도록 합니다.



export LD_LIBRARY_PATH=/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH


K Runtime과 ASP.NET vNext 설치하기


이제 중요한 부분이 남았습니다. K Runtime과 ASP.NET vNext를 설치하는 것이 남았는데, 앞의 과정보다 시간도 짧게 걸리고 비교적 쉽습니다.


ASP.NET vNext의 전체 소스 코드를 복사하지 않고 필요한 셸 스크립트 파일인 kvminstall.sh 파일만 가져오도록 합니다. 아래 명령어를 홈 디렉터리에서 실행합니다.



curl https://raw.githubusercontent.com/aspnet/Home/master/kvminstall.sh | sh


경로 설정을 맞추기 위하여, 아래 명령어를 실행합니다.



source ~/.kre/kvm/kvm.sh


이제 KVM을 사용자 프로필 디렉터리 아래의 .kre 폴더에 설치하기 위해, 다음 명령어를 실행합니다.



kvm upgrade


기본적인 실행 환경이 준비되었고, K Package Manager (달리 표현하면 K Package Manager의 실행을 담당하는 Mono)가 통신해야 할 사이트들의 HTTPS 인증서를 추가한 다음, 시스템에 설치된 루트 인증서를 가져올 수 있도록 하기 위하여 아래 명령어들을 실행합니다. 확인 프롬프트가 나타나면 여러번 yes를 입력하여 모든 필요한 인증서 및 인증서 체인을 가져오도록 합니다.



sudo certmgr -ssl -m https://go.microsoft.com
 sudo certmgr -ssl -m https://nugetgallery.blob.core.windows.net
 sudo certmgr -ssl -m https://nuget.org
 sudo certmgr -ssl -m https://myget.org
 mozroots –import –sync


Hello, World! 찍어보기


모든 설치가 끝났습니다. 예제 소스 코드를 가져와서 실행하기 위하여, David Fowler님의 github 리포지터리에 올라와있는 ASP.NET vNext 샘플을 이용하도록 하겠습니다. 공식 웹 사이트에 있는 샘플은 HTTPAPI를 기반으로 하는 것이어서 Nowin Factory로 교체하여 실행할 수 있지만 쉬운 설명을 위해 David Fowler님의 예제를 가져와서 대신 설명함을 말씀드립니다.


홈 디렉터리로 이동합니다.



cd ~


그리고 아래 명령어를 실행하여 콘솔 프로젝트 샘플 소스를 복사합니다.



git clone https://github.com/davidfowl/HelloWorldVNext.git


해당 디렉터리로 이동하여 다음 순서대로 명령어를 입력하여 Hello World! 메시지가 나타나는지 확인합니다.



cd ~/HelloWorldVNext/src/helloworld
 kpm restore
 k run


여기서 kpm restore 명령은 해당 예제를 실행하기 위하여 필요하다고 project.json에서 명시한 NuGet 패키지들을 전부 시스템에 설치하는 과정을 포함하며, 최초 한 번만 실행하면 됩니다. 그리고 k run 명령은 project.json 또는 그 상위에 정의되어있는 run 명령어를 실행한다는 의미이며, 보통 run 명령어는 재정의하지 않는 한 Main 메서드를 찾아 실행하는 것과 의미가 같습니다.


받은 프로젝트 디렉터리 상의 파일을 보면 흥미로운 것이, 이전처럼 mcs (gmcs)를 호출하여 exe 파일을 만들지 않았는데도 소스 상태에서 바로 k run이라는 명령어를 넣으면 프로그램이 시작된다는 점입니다. 이런 방식의 닷넷 응용프로그램은 웹 환경에서 큰 강점을 발휘하게 될 것입니다.


ASP.NET vNext 샘플 웹 프로젝트 띄워보기


이제 핵심입니다. ASP.NET vNext 샘플 웹 프로젝트를 띄워볼 차례인데, 다음과 같이 명령어를 입력하도록 합니다. 물론, 진행의 편의를 위해 홈 디렉터리에서 실행하는 것이 좋겠습니다.



git clone https://github.com/davidfowl/HelloWorldVNext.git
 cd ~/HelloWorldVNext/src/helloworldweb
 kpm restore
 k web


예제에 같이 들어있는 Nowin Factory 프로젝트의 코드를 보면 TCP/5000 포트를 웹 리스너 포트로 사용하고 있습니다. 밖에서 호스트 이름과 함께 5000번 포트로 접속하면 웹 페이지가 나타나는 것을 볼 수 있습니다. 그리고 서버를 종료하려면 콘솔에서 아무 키나 누르면 종료가 됩니다.


만약에 원격에서 좀 더 지속적으로 서버의 성능을 측정해보고 싶으시다면 screen 유틸리티를 사용하여 세션을 분리하신 상태에서 위의 명령어를 입력하고, 서버가 떠 있을 때 Ctrl 키를 누른 상태에서 빠르게 a, a, d 키를 누르면 세션이 분리되어 계속 살아있는 서버가 만들어집니다. 이 상태에서 Apache Bench (AB)등의 유틸리티를 사용하여 부하 테스트 등을 해보시는 것도 의미가 있을 것입니다.


참고로, NAT 환경이나 퍼블릭 클라우드 환경에서는 대표 IP 주소에 대한 외부 방화벽 설정을 열어주셔야 밖에서도 접속이 가능합니다.


마무리


아직 ASP.NET MVC 6나 다른 기술들이 완전히 준비된 것은 아니지만, 이 정도만 하더라도 ASP.NET은 더 이상 윈도 OS 안에서만 사용 가능한 기술이 아니라는 것을 증명하는데에는 손색이 없을 것입니다. 더 많은 가능성과 잠재력을 포함하는 최신 기술이 곧 나타나게 될 것이 무척 기대가 됩니다.


만약 기존에 ASP.NET 웹 사이트를 개발해 놓은 것이 있다면, ASP.NET vNext로 프로젝트를 마이그레이션하면서 플랫폼에 중립적으로 동작하는 코드로 업데이트하는 프로젝트를 한 번 진행함으로서 그리 어렵지 않게 멀티 플랫폼으로 ASP.NET 웹 응용프로그램을 포팅하실 수 있을 것입니다.


앞으로 더 자세한 정보와 상세한 내용들, 그리고 활용 방안들도 블로그 포스트로 전할 수 있도록 하겠습니다.

ASP.NET Custom Loader의 원리

ASP.NET Custom Loader (코드 네임 Helios)는 기존의 System.Web 기반의 전통적인 ASP.NET 프레임워크를 대체하는 기술로, IIS 파이프라인에 직접 관여하여 System.Web에 의존적이지 않은 최신 ASP.NET 개발 프레임워크들 (OWIN, Nancy, FubuMVC 같은)의 실행에 필요하지 않은 System.Web 및 관련 파이프라인을 생략하고 직접 이들 프레임워크를 중개할 수 있도록 도와주는 도우미입니다.


 


 


이 글을 작성 중인 2014년 8월 현재 최신 버전은 1.0 알파 버전으로, 조만간 출시될 ASP.NET vNext와 함께 릴리즈가 될 것으로 예상되는 기술입니다. 현재는 Windows Server 2008 R2 및 Windows 7 이상의 운영 체제를 정식으로 지원하며, IIS 및 IIS Express의 경우 7.5 버전 이상을 지원합니다. 정식 출시에 맞추어, Windows Server 2008과 Windows Vista, 그리고 IIS 7도 지원 대상에 포함될 것으로 예상됩니다.


ASP.NET Custom Loader의 실행 성능 개선 효과에 대해서는 여러 블로그 아티클이 있지만, http://blogs.msdn.com/b/webdev/archive/2014/02/18/introducing-asp-net-project-helios.aspx 의 내용을 살펴보실 것을 권합니다.


이 글에서는 ASP.NET Custom Loader의 동작 원리에 대해서 간단하게 설명을 하려고 합니다.


ASP.NET Custom Loader의 구성 파일 내역


ASP.NET Custom Loader는 다음과 같이 구성됩니다.
•AspNet.Loader.dll
•Microsoft.AspNet.Loader.IIS.dll
•Microsoft.AspNet.Loader.IIS.xml
•x86Microsoft.AspNet.Loader.IIS.Interop.dll
•amd64Microsoft.AspNet.Loader.IIS.Interop.dll


일단 위의 파일들이 bin 폴더에 복사되면, 특별히 web.config에서 수정하는 내용 없이 곧바로 기능이 활성화됩니다. 또한 이름에서도 알 수 있듯이, 지원 가능한 아키텍처는 x86과 amd64 아키텍처만 가능하며, 아이태니엄 및 ARM 아키텍처는 지원되지 않습니다.


실제 웹 프레임워크와의 연결


이제 중요한 것은 위의 Loader가 그 다음으로 주선할 웹 프레임워크를 지정하는 과정인데, 각 웹 프레임워크 별로 HttpApplicationAttribute를 어셈블리 수준에 적용하여 자신들의 웹 프레임워크 기술을 사용하는 개발자들을 위한 부트스트랩을 제공합니다. ASP.NET Web Loader는 이 정보를 찾아 연결을 시도하게 됩니다.


대강 아래와 같은 모양새를 가진 부트스트랩이 있어야 합니다. (물론 필요하다면 직접 만들 수도 있습니다.)


[assembly: HttpApplication(typeof(YourClass))]
 public class YourClass : HttpApplicationBase
 {
 }


이런 목적에 부합하는 기능과 관련된 종속 기능들을 OWIN에서는 아래 어셈블리들에 나누어 제공하고 있습니다.
•Microsoft.Owin.Host.IIS.dll
•Microsoft.Owin.Host.IIS.xml
•Microsoft.Owin.Host.IIS.Security.dll
•Microsoft.Owin.Host.IIS.Security.xml
•Microsoft.Owin.Hosting.dll
•Microsoft.Owin.Hosting.xml


기존에 OWIN 기반으로 배포한 응용프로그램이 있다면 ASP.NET Custom Loader를 배포한 다음 위의 어셈블리 파일들을 추가로 복사해야 ASP.NET Loader가 OWIN 시작 클래스를 연결해줄 수 있습니다.


주의 사항


이 글을 작성하는 현 시점에서 ASP.NET Custom Loader는 알파 버전을 릴리즈한 상태입니다. 그리고 이에 관하여 다음의 제약 사항들이 있습니다.
•Windows Server 2008과 Windows Vista, 즉 IIS 7의 경우 로더 실행 시 보안 알고리즘 관련 알 수 없는 HRESULT가 발생했다는 예외가 나타나면서 초기화가 이루어지지 않습니다. 공식 개발팀의 언급에 따르면, 정식 버전에서 해결할 예정이라고 합니다.
•Web.config에 configSource 애트리뷰트를 사용하여 나누어놓은 구성 파일이 있을 경우, 잘못된 경로 문자열이라면서 역시 Helios 초기화 도중 예외가 발생합니다. 불편하더라도 알파 버전의 테스트를 위해서는 구성 파일을 web.config 하나로 통합하셔야 테스트할 수 있습니다.


위와 같은 문제점에도 불구하고, 상당한 수준의 성능 개선은 개인적으로 만족스러웠습니다. 🙂

OWIN과 함께 춤을 – Hello, World

OWIN과 미들웨어


OWIN은 .NET Framework를 이용하여 코드를 실행할 수 있는 서버 환경이면 어디서든 사용이 가능한 이식이 편리한 코어 웹 프레임워크입니다. 기본적으로 OWIN은 웹 요청을 받아들이면 주어진 순서대로 구성된 미들웨어 체인을 따라 응답을 만들어내게 됩니다.


.NET Framework를 이용한 웹 응용프로그램 개발도 요즈음에는 다양한 프레임워크를 결합하여 개발하는 것이 요구 사항으로 자리잡고 있으며, 초창기의 .NET과는 달리 더 이상 System.Web 기반의 기술만으로 모든 것을 구현하지는 않습니다.


 


 


대표적으로, 최근 소개된 비동기 양방향 웹 소켓 호환 통신을 지원하는 SignalR의 경우 버전 2.0부터는 System.Web과 독립적으로 움직일 수 있도록 OWIN 위에서 실행되는 구조를 취하게 되었습니다. SignalR을 도입하는데 뜬금없이 OWIN Startup이라던지 하는 코드를 보면서 생소하다는 느낌을 받으셨다면 그게 바로 이것입니다.


재미있는 것은 OWIN 스택 전체는 기존에 ASP.NET을 실행하던 환경과 독립적인 관계를 가집니다. 기존 ASP.NET 환경 위에서 호스팅하는 경우 ASP.NET 환경보다 가장 먼저 앞서서 실행되는 형태로 되어있습니다. 이전처럼 Visual Studio 도구에 종속적인 방식으로 프로그래밍하는 것이 아니라, 내가 어떤 웹 기술을 사용할 것인지 Startup 클래스에서 정하여 선택적으로 사용할 수 있게 됩니다.


OWIN 기반의 응용프로그램 처음 만들어보기


앞에서 잠시 이야기한 것처럼 OWIN은 흔히 콘솔이나 클라이언트 응용프로그램처럼 시작점이 존재합니다. ASP.NET 기반의 응용프로그램으로 말할 것 같으면 Global.asax 같은 역할을 담당한다고 할 수 있습니다. 이것을 OWIN Startup 클래스라고 하며, OWIN Startup 클래스에서 내가 어떤 미들웨어를 사용하여 웹 요청을 처리할 것인지 프로그래밍할 수 있습니다.


빠르게 예제를 만들어보기 위하여, Visual Studio에서 비어있는 ASP.NET 프로젝트를 하나 만들어보도록 하겠습니다. (MVC나 Web Form 등은 일절 필요하지 않습니다.)


참고로, 이번 아티클에서 사용하는 Visual Studio 버전은 2013 버전이지만 2012로도 큰 차이 없이 작업할 수 있습니다.


새 웹 프로젝트를 만들면서 아래와 같이 One ASP.NET 프로젝트 대화 상자가 나타나는데, 빈 템플릿으로 하나 만들도록 합니다.


 


그러면 아래와 같이 최소 수준으로 구성된 웹 프로젝트가 만들어지게 됩니다.


 


프로젝트 항목 (위 그림 기준으로 OwinExample)을 마우스 오른쪽 버튼으로 클릭하고 NUGET 패키지 관리 메뉴를 클릭하면 아래와 같이 패키지 설치 대화 상자가 나타납니다. 우측 항목들 중 온라인 항목을 선택하고, 검색어에 “system.web owin”이라고 입력하여 검색합니다.


만약 이 기능을 찾을 수 없는 경우 Visual Studio에 NuGet 패키지 관리자가 설치되어있지 않은 것이므로, http://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c 에서 익스텐션을 내려 받아 설치하시면 됩니다.


 


나타나는 검색 결과 항목들 중 Microsoft.Owin.Host.SystemWeb 항목을 클릭하고 Install 버튼을 클릭하면, 종속성 관계에 따라 추가 설치가 필요한 패키지에 대한 정보나 라이선스 동의 등의 추가 확인 대화 상자가 나타날 수 있고, 여기에 모두 승인하시면 ASP.NET 프로젝트에서 OWIN을 사용할 수 있게 준비가 완료됩니다.


설치가 마무리되면 새 클래스를 만듭니다. 아래와 같이 클래스의 내용을 작성하도록 합니다. 혹은 Visual Studio 2013을 사용하는 경우 새 파일 템플릿 중에 OWIN 시작 클래스라는 항목도 있는데 이 항목을 대신 사용해도 됩니다.
using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;


[assembly: OwinStartup(typeof(OwinExample.Startup1))]


namespace OwinExample
{
    public class Startup1
    {
        public void Configuration(IAppBuilder app)
        {
        }
    }
}



위에 보시는 것이 처음 OWIN 프로그램을 시작할 때 사용되는 시작 클래스입니다. 여기서 Configuration 부분에 OWIN에서 사용할 미들웨어 등에 대한 구성을 추가하면 됩니다.


OWIN 패키지로 설치되는 라이브러리에 대한 이해


엄격하게 말해서 OWIN 어셈블리는 IAppBuilder라고 불리는 인터페이스 하나만을 가지고 있습니다.


 


보시는 것처럼 정말 IAppBuilder라는 인터페이스를 하나만 가지고 있을 뿐입니다. 그런데 이 인터페이스가 OWIN 기반의 응용프로그램을 만들기 위한 여러 가지 기본 사항들을 정의하고 있습니다. 각 멤버들에 대해서 간단히 살펴보면 다음과 같습니다.


•Build(System.Type): 이 인터페이스를 구현하는 클래스의 재량이며, 주어진 Type 형식에 대응되는 객체의 참조를 반환합니다. Microsoft OWIN 구현체의 경우, Map과 MapWhen 관련 기능을 소화하기 위한 목적으로 이 메서드를 활용합니다.


 


•New(): 역시 인터페이스를 구현하는 클래스의 재량이며, 또 다른 IAppBuilder 인터페이스 형식의 객체의 참조를 반환합니다. Microsoft OWIN 구현체의 경우, Map과 MapWhen 관련 기능을 소화하기 위한 목적으로 이 메서드를 활용합니다.


 


•Use(object, params object[]): OWIN 초기 구성에 있어서 가장 중요한 메서드입니다. 요청을 처리하고자 하는 미들웨어를 필요한 만큼 추가할 수 있으며, Use 메서드를 구성 과정에서 부른 순서대로 내부적으로 배열이나 리스트 안에 Use 메서드를 통해 전달받은 미들웨어 진입점들을 보관하고 순서대로 호출이 이루어질 수 있게 합니다.


 


OWIN 기반으로 프로그램을 만드는 과정에서 가장 첫 단추는 바로 이 IAppBuilder의 Use 메서드를 적절하게 활용하는 것입니다.


하지만 이 인터페이스 만으로 프로그래밍을 한다는 것은 정말 최소한의 수준을 만족하는 프로그래밍 기법을 사용하는 것으로, 실제 우리가 관심을 가져야 할 부분과는 거리가 상당히 멀리 떨어져 있습니다. 호스팅 환경이나 웹 프로그래밍에서 응당 필요한 요청과 응답 과정에서의 파이프라인 처리 등 필요한 것이 많습니다. 이런 부분들을 적절히 제공하는 것이 바로 Microsoft가 제안하는 Katana 프로젝트를 통한 프로그래밍입니다. Microsoft.Owin 이라는 이름으로 시작하는 어셈블리들의 시리즈이며, 이것을 사용하여 좀 더 웹 프로그래밍 다운 웹 프로그래밍을 할 수 있게 됩니다.


지금 여러분이 만든 ASP.NET 프로젝트에서 OWIN을 실행할 수 있도록 해준다는 것은 Katana 프로젝트의 일부인 System.Web Loader 프로젝트의 기능입니다. 어떻게 해서 이 클래스가 별다른 설정도 없이 자동으로 모든 요청을 받아들일 수 있는 시작점이 되는가에 대해서는 지금은 자세히 알지 못해도 괜찮습니다.


Hello World 미들웨어 작성


이제 본격적으로 Hello World 메시지를 출력하는 간단한 미들웨어를 하나 작성해보도록 하겠습니다.


Configuration 메서드 안에 다음과 같이 코드를 작성합니다.
app.Run(async (context) =&gt;
{
    await context.Response.WriteAsync(“Hello, World!”);
});


앞에서 살펴본 Use 메서드를 응용하는 도우미 메서드로 Run 메서드를 Katana에서 제공하고 있습니다. 이 메서드를 사용하면 다른 미들웨어를 실행하지 않고 자기 선에서 요청에 대한 응답을 끝낼 수 있는 미들웨어를 간단한 코드로 쉽게 작성할 수 있게 해줍니다. 여기서는 Hello World라는 문자열을 HTTP 응답으로 내보내도록 하는 코드를 작성해보았습니다.


이 코드를 실행하면 다음과 같이 웹 브라우저에 Hello, World! 라는 문구가 나타날 것입니다.


 


HTTP Query String 받아서 처리하기


Response 속성을 통해 응답을 내보내는 것 말고, 조금 더 나가보기로 하겠습니다. 이번에는 Query String을 입력으로 받아들여 이름을 출력하는 코드를 조금 더 작성해보기로 하겠습니다.


문자열을 다루는 코드를 조금 추가할 것이므로 네임스페이스에 대한 참조가 다음과 같이 추가되어야 합니다.



using Microsoft.Owin;
using Owin;
using System;
using System.Globalization;


 



그리고 앞에서 작성한 Hello, World! 메시지를 내보내는 미들웨어의 코드를 다음과 같이 변경하겠습니다.



var query = context.Request.Query;
var name = query.Get(“name”);


if (name == null)
    name = “Stranger”;


var message = String.Format(
    CultureInfo.InvariantCulture,
    “Hello, {0}!”,
    name);


await context.Response.WriteAsync(message);


 



Query 속성의 Get 메서드를 사용하여 Query String 형태로 전달되는 매개 변수의 값을 가져오도록 할 수 있는데, 만약 값을 가져오지 못한다면 NULL 참조를 대신 반환합니다. 이 경우 기본값으로 Stranger로 설정하도록 코드를 작성하였습니다. 그 다음은 익히 잘 아시는 String.Format 메서드를 사용하여 문구를 완성하는 것이고, 응답에 이를 사용하게 됩니다.


그럼 이제 다시 한 번 코드를 실행해보겠습니다. 이름을 지정하지 않은 상태에서는 다음과 같이 실행될 것입니다.


 


그리고 주소 뒤에 ?name=David 라고 입력해봅니다.


 


그런데 여기서 한 가지 궁금한 점이 생깁니다. 보통 웹 프로그래밍을 할 때 흔히 어떤 파일에 대해서 작업을 하고 그 파일을 열어보면 실행된다는 식인데 지금 이 화면을 띄우기까지 어떤 파일 위에서 작업한 것이 아니라 그냥 프로그래밍을 했을 뿐입니다. 다시 말해, 어떤 URL을 경유해서 들어오든 지금 보는 화면과 동작이 적용됨을 뜻합니다. 임의로 아무렇게나 주소를 한 번 넣어보시면 어떤 의미인지 금방 알 수 있습니다. 예를 들어, http://localhost:37339/askbvkkewr?name=David 라고 없는 주소를 임의로 써봅니다.


 


그렇습니다. 어디서 어떻게 들어오든 모든 웹 요청을 전부 방금 만든 미들웨어가 소화를 하도록 되어있는 것입니다. 전통적인 ASP.NET 또는 웹 프로그래밍 환경과는 다르게, OWIN 안에서는 HTTP 서비스 전체를 자유자재로 통제할 수 있습니다.


HTTP POST URL Encoded Form 다루기


마지막으로 한 가지 더 살펴보도록 하겠습니다. Query String도 쉽게 처리할 수 있었는데, 그렇다면 POST로 보내는 요청들도 Katana에서 쉽게 처리할 수 있을까요?


간단하게 요약하면, Katana가 제공하는 Request에 대한 처리는 Request Body를 실시간으로 읽을 수 있는 System.IO.Stream 구현체를 사용하거나, ReadFormAsync() 메서드를 사용하여 URL Encoded Form을 받아들이는 정도를 우선 활용할 수 있습니다. 그러나 흔히 사용하는 Multipart 데이터는 자체적으로 소화할 수 있는 방법은 따로 없고, ASP.NET MVC Web API v2의 도우미 클래스를 사용하여 처리하는 방법을 사용할 수 있습니다. 일단 여기서는 URL Encoded Form의 형태로 받아서 처리할 수 있는 예를 한 번 다루어보도록 하겠습니다.


URL Encoded Form으로 들어오는 요청을 손쉽게 만들기 위하여, 아래와 같이 간단한 웹 페이지를 하나 만들어보도록 하겠습니다. <FORM> 태그의 ACTION 속성 값에 들어갈 URL은 현재 여러분이 만든 OWIN 응용프로그램의 웹 주소로 적절하게 치환하셔야 정상적으로 전송이 됩니다. 이 주소를 확인하는 방법은 방금 만든 프로젝트의 속성을 연 다음, 웹 탭을 클릭하는 것입니다. 참고로 이 주소는 프로젝트 생성 시점에 동적으로 할당되어 프로젝트 설정으로 저장되는 값으로, 개발 과정 중에는 계속 같은 포트 값을 유지할 수 있습니다.


 


위의 주소를 확인하여 아래와 같이 HTML 페이지를 작성하도록 합니다.


<!DOCTYPE html>


<html lang=”en” xmlns=”http://www.w3.org/1999/xhtml“>
<head>
    <meta charset=”utf-8″ />
    <title>Hello, World!</title>
</head>
<body>
    <form action=”http://localhost:37339/” method=”post”
          enctype=”text/plain”>
        <label for=”name”>Your Name: </label>
        <input type=”text” name=”name” id=”name” />
        <input type=”submit” value=”Hello?” />
    </form>
</body>
</html>


 


여기서 중요한 것은 <FORM> 태그의 METHOD 속성의 값이 POST라는 것과 ENCTYPE 속성이 “application/x-www-form-urlencoded”로 지정된 것입니다. 이렇게 지정해야 OWIN에서 데이터를 가져올 수 있습니다.


그리고 Form 데이터를 받아서 처리할 수 있도록 아래와 같이 수정합니다.


//var query = context.Request.Query;
var form = await context.Request.ReadFormAsync();
var name = form.Get(“name”);


 



특별히 바뀐 것은 없습니다. context.Request.Query 속성 대신 context.Request.ReadFormAsync() 비동기 메서드를 호출하여 얻은 결과로 나오는 객체를 활용하도록 하는 것이고 그 이후는 동일한 로직을 사용합니다.


테스트를 위해서 앞에서 만든 HTML 페이지를 브라우저로 열어봅니다. 텍스트 상자 안에 임의의 이름을 넣고 Hello? 버튼을 클릭하면 다음과 같이 입력한 문자열이 반영된 응답이 나오게 됩니다.


 


만약 HTML 폼에서 “application/x-www-form-urlencoded” 대신 “multipart/form-data”를 지정할 경우 ReadFormAsync() 비동기 메서드는 비어있는 컬렉션을 반환합니다.


다음 아티클에서는


다음 아티클에서는 이 특성을 사용하여 좀 더 세밀하고 다양한 미들웨어 프로그래밍을 다루어보도록 하겠습니다.

OWIN과 함께 춤을 – 시작하기

OWIN 개요


요즈음 .NET 기반 웹 개발에서 주목을 받고 있는 것은 ASP.NET MVC나 ASP.NET Web API가 아니라 사실 OWIN이 아닐까 생각합니다. OWIN은 Open Web Interface for .NET을 줄여서 쓴 말로 .NET Framework 기반의 웹 개발 프레임워크들을 더 다양하게 고르고 조합할 수 있도록 도와주는 표준화된 인터페이스를 말합니다. (http://owin.org/ 에서 자세한 정보를 볼 수 있습니다.)


왜 OWIN인가?


OWIN이 주목을 받는 이유는, 이전에 다루던 웹 응용프로그램 개발 환경과는 달리, 목적과 상황에 맞게 더 정밀하고 더 세세한 웹 프로그래밍이 가능하기 때문입니다. 이전의 ASP.NET 만을 사용하던 개발 환경에서 가장 큰 문제가 되었던 것은 의외로 단순한 부분들로부터 나타나는 것들이 많았는데, 예를 들어 파일 업로드에 대한 것이 가장 큰 문제였습니다.


 


 


인터넷 속도가 빠르지 않은 지역에서의 사용을 기준으로 잡혀있는 파일 업로드 제한과 공간 할당 정책이 기본값이었기 때문에, 대용량 파일 업로드가 필요한 때에는 이것을 처리하기 위해 ASP.NET의 파일 업로드 제한을 다시 정의할 수 밖에 없었고, 사실 이것은 면밀하지 못한 설정이 되어서 보안 리스크가 될 수 밖에 없었습니다. 그리고 .NET Framework 2.0 서비스팩 적용 이전까지는 놀랍게도 파일 업로드를 임시 저장소가 아닌 메모리 공간에 저장하는 방식이어서 대용량 파일 업로드를 할 경우 서버 자원이 고갈되는 (!) 문제까지 있었습니다.


지금은 임시 디스크에 저장한 후에 파일 업로드가 다 되었음을 알려주는 식이 되었지만, 여전히 세밀한 파일 업로드 제어는 하기 어려운 상태입니다. 그리고 제일 큰 문제는, 환경 설정에서 지원하는 최대 파일 업로드 크기가 여전히 부호있는 32비트 정수값 (.NET의 표준은 부호있는 정수 사용을 권합니다.)의 범위에 있어서 최대 업로드가 2GB 밖에 가능하지 않습니다. 이를 해소하기 위해서 청크 방식의 업로드 등을 이용해야 하지만 웹 브라우저가 지원하지 않으면 별도 클라이언트를 이용할 수 밖에 없는 상태입니다. 다시 말해, 간단한 파일 업로드를 필요로 한다면 ASP.NET이 여전히 편리하지만, 복잡해진 요구 사항을 맞추기 위해서는 턱없이 커스터마이징 변수가 부족한 것입니다.


비단 이 문제 뿐 아니라 ASP.NET이 편의를 위하여 제공하는 기능이 요즈음에 들어서는 오히려 복잡한 요구 사항 개발에 방해 요소가 되는 일이 많습니다. 그리고 이러한 요구 사항을 만족하기 위해 ASP.NET의 기본 설정을 변경하는 것 자체가 보안 리스크가 됨은 물론, ASP.NET 자체에 대한 강력한 커플링이 발생하여 유지 보수에 큰 문제가 되곤 합니다. 왜냐하면 커플링이 강력해질수록 ASP.NET에 사소한 업데이트나 패치 하나가 전체 프로그램에 큰 영향을 줄 개연성이나 확률이 더 높아지기 때문입니다. 그래서 기존 ASP.NET의 영역을 유지하면서, 안전하고 더 편리하게 복잡한 요구 사항을 쉽게 맞출 수 있는 방법이 필요해지게 되는데, OWIN이 여기에 대한 확실한 답이 됩니다.


OWIN의 기본 개념


OWIN 그 자체는 HTTP 요청을 받아들이고, 응답을 결정하는 행위를 규정하는 스펙을 .NET 4.0을 기반으로 제공하는 것이 전부이며, 모든 처리 과정은 미들웨어를 통해 이루어지는데, 미들웨어 간의 호출에 사용되는 것은 아주 단순한 Dictionary 자료 구조입니다. (http://owin.org/spec/owin-1.0.0.html)


OWIN-5


OWIN이 하는 일 자체는 위의 그림 (클릭하면 크게 볼 수 있습니다.)이 전부입니다. 여러 개의 미들웨어 구성 요소를 OWIN 프로그램을 시작할 때 등록하고, 미들웨어의 입장에서는 자신이 처리할 수 있는 요청인 경우에만 요청을 가로채고, 그 외에는 다음 미들웨어로 호출을 넘겨주는 것이 전부입니다. 만약 모든 미들웨어를 지나 끝까지 도착했음에도 불구하고 처리할 수 있는 미들웨어가 없다면, OWIN을 어떤 환경에서 사용하는지에 따라 다음 동작이 결정됩니다.
•만약 OWIN 그 자체를 바로 호스팅하는 베어본 서버 환경이라면 익히 알려진대로 404 오류 코드를 내보내거나 빈 응답을 반환할 수 있습니다.
•만약 ASP.NET 환경에서 OWIN을 얹어서 사용하는 형태라면, OWIN 환경 자체가 다른 ASP.NET 모듈보다 먼저 실행되는 ASP.NET 모듈이기 때문에, 다음 ASP.NET 모듈로 넘어가게 됩니다. 기존에 개발한 ASP.NET 웹 프로젝트 위에 OWIN을 추가 장착하게 되면 이런 형태가 됩니다.
•만약 ASP.NET Native Loader 위에서 OWIN을 얹어서 사용하는 형태라면, OWIN 환경 자체를 완전히 분리된 환경에서 실행하는 것을 의미합니다.


각각의 경우를 따로 설명하는 데에는 이유가 있습니다. 이어서 말씀드리면 다음과 같습니다.


세 가지 실행 환경과 가능성


첫 번째는 OWIN과 미들웨어들을 묶어서 어디에서든 웹 서비스를 시작할 수 있음을 말씀드리고 싶어서입니다. 즉, 정상적인 .NET Framework 실행 환경을 갖추고 클라이언트와 서버 사이의 연결을 정확하게 처리하도록 만들어주기만 한다면 서버 OS가 윈도우이든 리눅스이든 맥이든 상관이 없으며 (리눅스와 맥은 Mono 덕분이라고 할 수 있겠습니다.), 전혀 다른 형태로 구현된 웹 서버일지라도 OWIN으로 정확하게 연결을 전달할 수 있다면 이론상으로 .NET 기반이 아닌 서버 플랫폼 환경에서도 얼마든지 .NET 서버 응용프로그램을 호스팅할 수 있는 상태가 됩니다.


두 번째는 기존에 가지고 있던 ASP.NET 웹 프로젝트에 얼마든지 OWIN 응용프로그램을 추가 장착할 수 있음을 의미합니다. System.Web이라고 불리는 레거시 ASP.NET 웹 프레임워크의 종속성에서 완전히 벗어나지는 못하지만, 그 규칙 안에서라면 기존 ASP.NET의 기술과 완전히 무관하게 독자적인 미들웨어를 개발하고 수행하는 것이 가능하므로, 전송 프로토콜 수준에서 HTTP 응답을 재정의하는 것도 가능하고, 실시간으로 파일 업로드에 개입할 수도 있습니다. 기존 ASP.NET 웹 프로젝트를 해치지 않고 얼마든지 복잡한 기능을 쉽게 추가할 수 있음을 뜻합니다.


마지막 세 번째 방법은 기존의 ASP.NET 실행 환경을 사용하지 않고, IIS에 최소 버전의 .NET 실행 환경을 직접 주입하여 실행 속도를 획기적으로 개선하고, 기존의 System.Web 관련 설정을 모두 무시하는 방식입니다. 이것은 Project Helios라고 불리던 것을 제품화한 것으로, 실행 속도와 메모리 점유율을 획기적으로 개선하여 응답 성능을 비약적으로 개선시킬 수 있습니다. 기존 ASP.NET 프로젝트와 독립된 형태로 웹 프로젝트를 개발하면서 IIS 위에서 OWIN 프로그램을 실행하려는 경우 이 방식을 이용하여 성능을 극대화할 수 있습니다.


다음 아티클에서는 OWIN의 내부 구조와 미들웨어를 프로그래밍하는 방법을 몇 가지 살펴보도록 하겠습니다.


이미지 출처: http://byterot.blogspot.kr/2013_08_01_archive.html


 

Azure VHD 디스크 생성 시 캐시 지정에 관하여

Microsoft Azure에서 실행되는 VM은 Azure BLOB Storage를 사용하여 VHD 디스크를 동적으로 연결하여 사용합니다. 이것은 광의로 해석하면 Storage Area Network 위에서 실시간으로 호스팅되는 가상 디스크를 마운트하여 사용하는 셈인데, 실제로 Microsoft Azure의 VM이 시험판 단계일 때에는 예기치 않은 문제들이 제법 많았습니다. (물론 지금은 그런 일도 없고, 또 그렇게 되어서는 안되겠죠.)


 


 


Azure BLOB Storage 그 자체도 내부적으로 상당히 많은 추상화가 이루어져있는 복잡한 기술이지만, 이것을 기반으로 하는 VHD를 사용한다는 것은 어떻게 생각하면 추상화의 극을 달린다는 느낌에 가깝습니다. 물론, 이토록 고도화된 시스템을 사용하기 때문에 얻을 수 있는 이점으로는 무중단 상태에서 같은 지역은 물론 여러 지역에 걸쳐 VHD를 실시간으로 미러링하여 백업하거나 VHD 자체를 로드밸런싱하는 등의, 종전의 클라우드 서비스 공급자들도 상상하기 어려운 스케일의 서비스를 제공할 수 있게 된 점은 있습니다. 하지만 흔히 기대하는 베어메탈급의 고성능 서버와는 거리가 멀리 떨어진 듯한 느낌을 지울 수는 없겠지요.


엄밀히 말해서, 정말 빠른 디스크 I/O를 필요로 한다면 오히려 클라우드 환경에 의존하기 보다는 직접 고성능 서버를 구입하여 구축하는 것이 훨씬 더 이치에 맞습니다. 하지만, 단순히 디스크 I/O가 빨라야 하는 요구 사항을 고려하는 것이 아니라면, 대부분의 인프라의 가치는 장애 대비와 적시 복구인 경우가 많습니다. 이런 점을 고려하여, 어느정도 만족할만한 수준의 디스크 성능과 안정성을 동시에 거둘 수 있는 간단한 팁을 하나 올립니다.


Azure에서 VM을 만들고 디스크를 추가로 생성하여 연결할 때, 다음 그림과 같이 질문을 받습니다.


001


여기서 제일 아래쪽의 호스트 캐시 기본 설정이라는 항목이 제가 오늘 말씀드리려는 내용에 대한 것입니다.


호스트 캐시란 앞에서 이야기한 대로 실제 디스크 I/O를 처리하기 위한 과정에서 중간에 관여하는 구성 요소로, 원칙대로라고 한다면 Azure Storage의 VHD에 대해 발생하는 디스크 I/O를 Azure Storage가 완전히 처리해서 응답을 되돌려주기까지의 과정을 운영 체제의 입장에서는 기다려야 하는 셈입니다. (물론 여기서 다 설명하기에는 어려울 정도로 복잡한 메카니즘이 있어서 정말 순진하게 캐시를 사용하지 않는다고해서 무작정 기다리기만 하는 것은 아닙니다.)


그러나 좀 더 적극적으로 개입해서, 실제로 디스크 I/O가 저멀리 있는 Azure Storage에 전달이 되기 이전이라고 하더라도, 확실하게 디스크 I/O에 대한 요청이 접수되었고 처리가 되었음을 기억하여 정확한 응답을 되돌려주면서, 다른 한편으로는 그 내용을 실제 Azure Storage의 VHD에 지속적으로 보내주는 역할을 따로 수행하게 됩니다.


다르게 말하면, 만약 Azure Storage와 연결이 끊어지거나 문제가 발생하는 경우 캐시의 유효성이나 지속성에 문제가 생겨서 서비스 장애로 이어지는 불상사가 벌어질 수 있습니다. 그러나 바꾸어 말하면 캐시를 사용하지 않을 때에는 이것이 직접적으로 VM 위에서 돌아가는 프로그램에 대한 OS의 IO API 호출에 대한 실패로 직격탄이 되어버립니다. 이런 점을 고려해보면, 문제의 전파나 영향 범위를 최소화하는 관점에서 캐시가 미미하지만 어느정도 역할을 수행하는 것도 가능합니다.


이러한 성격의 캐시를 사용할 수 있는 방안은 두 가지가 있는데, 읽기 작업을 위한 캐시만 사용하는 경우와, 읽기/쓰기 작업을 모두 관리하는 캐시를 사용하는 경우입니다. 운영 체제용으로 만들어지는 VHD는 읽기/쓰기 작업을 모두 관리하는 캐시를 기본으로 사용하도록 하고 있습니다. 그리고 추가 연결하는 디스크에 대해서는 디스크 I/O 빈도가 높지 않을 것임을 가정하고 기본적으로는 캐시 없이 직접 Azure BLOB Storage와 연결되도록 하는 것이 기본입니다.


이러한 상황에서, 만약 디스크의 읽기 성능이 중요하다면 읽기 캐시를 사용하도록 해주는 것이 필요합니다. 이렇게 하면 최초로 캐시에서 가지고 있지 않은 데이터 영역에 대한 요청이 들어왔을 때, 이를 캐시에 저장하고 다음 회차 요청 때 좀 더 빠르게 전달할 수 있도록 해주는 식이 됩니다. 물론 쓰기나 다른 동작에 의해 변경이 발생하게 되면 이에 맞추어 당연히 캐시도 다시 형성됩니다.


여기에 쓰기 캐시를 사용하는 것 까지 포함하게 되면, 쓰기 캐시에 들어오는 요청과 읽기 캐시의 내용을 병합하여 중간 버퍼를 형성하고 Azure Storage의 VHD와 동기화하는 작업을 적극적으로 개입하여 수행하게 됩니다.


결론을 이야기하면, 쓰기 작업이 많은 응용프로그램을 위해 디스크를 추가할 때는 읽기/쓰기 캐시 사용을, 웹 사이트나 읽기 작업이 많은 응용프로그램을 위해서는 읽기 캐시 사용을 권할 수 있습니다.


사실 클라우드 서비스를 사용한다는 것이 어떤 의미인지 본질적으로 잘 이해하고 계시다면, 그리고 필연적으로 사람이 하는 일에 있을 수 있는 결함성을 인정하신다면, 이러한 아키텍처 속에서 갑작스럽게 나타날 수 있는 예외 상황은 항상 관리해야 할 리스크가 될 수 있습니다.


적절한 설정을 확인하고 검증하는 단계를 통해 더 성공적으로 클라우드 서비스를 현업에 투입할 수 있게 될 것입니다.


 

Visual Studio 테스트, 어렵지 않아요

Visual Studio에서 제공하는 테스트 도구에 NUNIT을 결합해서 사용할 수 있다면 정말 유용할 것입니다. 이번 웹 캐스트는 Visual Studio에서 제공하는 테스트 도구와 NUNIT 간의 연동을 도와주는 NUNIT Test Adapter의 사용 방법과 함께, Windows Forms 기반 응용프로그램에서 Visual Studio와 NUNIT Test Adapter를 결합하여 테스트를 진행할 수 있는 방법을 소개합니다.


(비디오 콘텐츠로 올렸던 게시물이었으나 아티클로 조만간 복원할 예정입니다.)