기술자료

DBMS, DB 구축 절차, 빅데이터 기술 칼럼, 사례연구 및 세미나 자료를 소개합니다.

ASP.NET 리부트 - ASP.NET 5 솔루션 구성

기술자료
DBMS별 분류
Etc
작성자
dataonair
작성일
2015-09-25 00:00
조회
4256



ASP.NET 리부트

ASP.NET 5 솔루션 구성



ASP.NET 5에서 프로젝트 구성을 위해 새롭게 등장하는 개념과 web.config를 대체하는 새로운 설정(configuration) 모델에 대해 소개한다. 또한, 클라이언트 라이브러리를 관리하는 방식에 많은 변화가 있는데 Node.js 커뮤니티의 패키지들을 적극적으로 수용한 것이 흥미롭다.



첫 번째 ‘ASP.NET 5’ 글에 이어 ASP.NET의 중요한 변화를 열 가지로 나눠 소개한다. 지난 달엔 닷넷 코어, 병렬 수행과 크로스플랫폼, 미들웨어 측면을 다뤘다. 이번 호에서는 솔루션 구조, web.config의 변화와 project.json, task runner를 소개한다.



1. 솔루션 구조

Visual Studio 2015 RC 에서는 ASP.NET 5 웹 애플리케이션을 생성할 때, <그림 1>과 같이 세 가지 종류의 템플릿을 제공한다.



tech_img4039.jpg

<그림 1> ASP.NET 5 웹 애플리케이션을 만들기 위한 템플릿

tech_img4040.jpg

<그림 2> ASP.NET 5 Preview 템플릿에 따른 솔루션 구조

Empty와 Web API 템플릿에 의해 생성된 프로젝트는 Controllers 폴더를 제외하면 동일하다. 반면 Web Site 프로젝트는 기존의 ASP.NET MVC 프로젝트와 유사한 폴더 구조와, 클라이언트 라이브러리 구성에 사용하는 여러 가지 json 파일들을 포함하고 있다. json 형태의 설정 파일들은 이 글의 후반부에서 알아볼 것이다.

솔루션의 전반적인 구조를 보면 첫 번째로 global.json 파일과 src 폴더가 눈에 띈다. 소스를 의미하는 src 폴더에 여러 프로젝트가 모이고, 그 외부에 global.json 파일을 두어 프로젝트간 공통적인 내용을 설정하고 있다. global.json 파일의 내용을 보면 프로젝트가 위치한 폴더와 프로젝트에서 사용할 CLR의 버전을 지정하고 있다.


<리스트 1> 프로젝트 속성
{
"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-beta4"
}
}



projects 속성은 그 값으로 배열 형태의 폴더 목록을 갖는데, test라는 폴더는 템플릿에 의해 생성되는 폴더가 아니다. 개발자가 test 폴더를 생성하여 테스트 프로젝트만을 관리하도록 권장하는 설정으로 보인다. 참고로 Visual Studio 2015 RC에서 ASP.ET 5 Preview 템플릿은 Unit Tests 프로젝트를 추가하는 옵션이 비활성화되어 있어 테스트 프로젝트를 동시에 생성할 수 없다.

두 번째 눈에 띄는 변화는, IIS 설치 후에나 볼 수 있었던 wwwroot 폴더가 프로젝트의 일부로 등장한 것이다. 프로젝트 루트가 곧 웹 사이트의 루트였던 기존의 파일 기반 접근법은 web.config, global.asax 파일처럼 민감한 프로젝트 파일을 감추기 위해 프레임워크 수준에서 대책이 필요하다는 문제가 있었다. 특정 파일에 대한 접근을 막기 위해 blacklist를 관리해야 했다.

wwwroot 폴더는 그 이름에서 알 수 있듯이 웹 애플리케이션의 루트다. 그렇다고 이 폴더 안의 파일들이 자동으로 서비스되는 것은 아닌데 whitelist 접근법을 사용하기 때문이다. 지난 호 연재에서 다루었던 미들웨어와 관련이 있다. 개발자가 미들웨어를 통해 직접 HTTP 요청을 처리하는 파이프라인을 구성하기 때문에 간단한 html 페이지라도 요청에 응답하게 하려면 애플리케이션 구동시 app.UseStaticFiles() 메서드를 사용해서 정적 파일이 서비스되도록 구성해야 한다고 했다. 이런 whitelist 접근법은 보안 측면에서 blacklist 접근법보다 우수하다.

세 번째로 global.asax 파일이 사라지고 StartUp 클래스가 애플리케이션의 실행 지점을 제공한다. 생성자를 통해 종속성 주입이 가능하고 Configure 메서드에서 미들웨어를 조합하는 것으로 HTTP 요청을 처리할 파이프라인을 구성한다.

네 번째로 프로젝트 파일의 확장자가 .csproj 에서 .xproj 로 바뀌며 프로젝트 파일이 간소화되었고, 프로젝트 구성에 대한 대부분의 내용이 새롭게 등장한 project.json 파일로 이동했다.

마지막으로 프로젝트 폴더를 윈도우 탐색기에서 열어보면 솔루션 탐색기에서 보는 것과 같은 구조를 확인할 수 있는데, 이제 파일을 프로젝트에 추가하거나 제외시키는 일은 윈도우 탐색기에서도 직접 할 수 있게 되었다. 파일 감시자를 통해 파일 시스템에서의 변경 내용이 프로젝트에 그대로 반영되기 때문이다. 만약 파일 시스템에는 존재하지만 프로젝트에 포함시키고 싶지 않다면 project.json 파일의 exclude 설정을 통해 특정 파일과 폴더를 제외할 수 있다.

이제 ASP.NET 에서도 JSON 포맷의 인기를 실감할 수 있다. 프로젝트 설정을 위해 도입된 project.json 파일에 대해 알아보자.



2. project.json

ASP.NET 5 프로젝트는 DNX(.NET Execution Environment) 프로젝트라고도 말할 수 있다. DNX는 애플리케이션의 실행을 위해 CLR을 호스트하고 종속성을 관리하며 애플리케이션의 실행지점(Startup 클래스)을 찾아서 실행한다. JSON 포맷의 project.json 이라는 가볍고 단순한 파일이 실행환경에 필요한 모든 정보를 제공함으로써 DNX 프로젝트를 쉽게 정의할 수 있다.

ASP.NET 5 애플리케이션을 실행할 때, 비주얼 스튜디오를 사용하지 않고 윈도우 커맨드 창에서 DNX 명령어를 사용할 수도 있는데, 이 때 project.json 파일이 포함된 폴더 경로를 반드시 지정해야 한다. project.json 파일이 프로젝트를 정의한다는 의미를 다시 한번 확인할 수 있는 대목이다.

앞서, 기존의 프로젝트 파일(.csproj)이 새 프로젝트 파일(.xproj)과 project.json 파일로 대치되었다고 했다. 단순하게 프로젝트 파일의 크기만 비교해 보면 15KB에서 1KB로 줄었으니 그 차이만큼의 내용이 project.json 파일로 옮겨 갔다고 생각할 수 있겠다.

tech_img4041.jpg

<그림 3> ASP.NET 5 프로젝트(상단)와 ASP.NET 4.5 프로젝트(하단)의 속성 비교

<그림 3>은 ASP.NET 5 프로젝트와 이전 프로젝트의 속성을 비교하고 있다. 전체적인 카테고리의 수도 1/4로 줄었지만 빌드라는 속성, 한 가지만 보더라도 큰 변화를 느낄 수 있다.

이와 같이 프로젝트 속성 창에서 사라진 모든 속성을 포함하여 project.json 파일에는 수 많은 설정이 있지만 그 중 대표적인 몇 가지만 살펴보기로 한다.

1) DEPENDENCIES
NuGet 패키지를 관리하는 섹션이다. 패키지 명과 버전에 대한 인텔리센스를 지원하며 특정 버전을 선택할 수 있어 편리하다. 기존처럼 “Manage NuGet Packages…” 메뉴를 선택해 GUI 툴을 사용할 수도 있지만 툴을 사용하여 변경한 내용도 결국 여기에 업데이트 된다. 모든 변경은 실시간으로 반영되는데 변경 내용 저장시 솔루션 탐색기의 References 폴더를 보고 있으면 일시적으로 restoring 하는 순간을 포착할 수 있다.

2) FRAMEWORKS
애플리케이션이 실행되는 대상 프레임워크를 명시하는 섹션이다. 아래 코드에서는 Full CLR인 .NET Framework 4.5.1과 ASP.NET 5에서 등장한 CoreCLR을 함께 사용하도록 설정하고 있다.


<리스트 2> 다중 프레임워크 설정
"frameworks": {
"dnx451": { },
"dnxcore50": { }
}



비주얼 스튜디오의 코드 편집창은 <그림 4>와 같이 대상 프레임워크를 모두 고려하여 친절하게 인텔리센스를 지원한다.

tech_img4042.jpg

<그림 4> 비주얼 스튜디오의 다중 프레임워크 인텔리센스 지원

한쪽 프레임워크에서만 제공되는 메서드를 어쩔 수 없이 사용해야 하는 상황에서는 <리스트 3>과 같은 구문을 사용해 조건부 컴파일 할 수 있다.


<리스트 3> 조건부 컴파일 구문
#if DNX451
Debug.Print("This method is not avaliable in .NET Core.");
#endif



3) COMMANDS
명령어 창에서 dnx를 사용하여 애플리케이션을 실행할 때 사용할 수 있는 명령어를 지정하는 섹션이며 dnx를 사용하는 문법은 아래와 같다.

dnx < project.json 폴더 경로> < command>

project.json 파일에서 명령어를 <리스트 4>와 같이 구성한 후, 명령어 창을 띄워 프로젝트가 위치한 폴더로 이동했다고 가정하자.


<리스트 4> project.json 파일의 명령어 설정
"commands": {
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000",
"kestrel" : "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:5004"
}



윈도우 환경이라면 “dnx . web”을 실행해 웹 애플리케이션을 셀프 호스팅할 수 있고, 맥 또는 리눅스 환경이라면 “dnx . kestrel”을 실행하여 kestrel이라는 HTTP 서버를 사용한 셀프 호스팅이 가능하다.

애플리케이션의 대상 프레임워크 설정은 이전 프로젝트라면 web.config 파일에 선언되어 있었다. 새로운 프로젝트 설정 파일의 등장으로 web.config 파일에 생긴 변화를 알아보자.



3. 사라진 web.config

ASP.NET 프레임워크의 변화에 따라 web.config의 설정 내용도 조금씩 변해 왔지만 개발자들에게 web.config 파일의 첫 번째 용도는 appSettings 섹션에서 애플리케이션에 필요한 정보를 관리하는 것이었다. 또한, web.config 파일은 프로젝트 수준에서의 대상 프레임워크 버전, 종속 어셈블리 목록 등을 관리하고 있어 여러 내용을 모두 포함하는 단일 설정 파일로 사용되어 왔다.

ASP.NET 5와 함께 web.config 파일에 있던 프로젝트 관련 설정은 project.json 파일로 이동하였고, 개발자를 위해서는 Key-Value의 쌍을 관리하는 깔끔한 설정(configuration) 모델이 새롭게 도입되었다. 이렇게 web.config 파일은 그 역할을 나눠주고 이제 역사의 뒤안길로 사라졌다.

새 설정 모델은 외부 소스로서 XML, JSON, INI, 세 가지의 파일 양식을 기본적으로 지원하고 인메모리(in-memory) 방식과 사용자 정의 설정 제공자(configuration provider)도 작성할 수 있는 유연한 모델이다. 보다 중요한 변화로, 운영환경 자체에 정의된 환경 변수(environment variables)를 사용할 수 있게 되어 프로젝트 외부에서도 설정이 가능해 졌다. 외부 소스에 의존하지 않는 인메모리 방식의 설정은 <리스트 5>와 같다.


<리스트 5> 인메모리 방식의 설정
var config = new Configuration();
config.Add(new MemoryConfigurationSource());
config.Set("somekey", "somevalue");string setting = config.Get("somekey); // returns "somevalue"
string setting2 = config["somekey"]; // also returns "somevalue"



파일을 사용하는 방식은 웹사이트(Web Site) 템플릿에 의해 생성되는 config.json 파일이 좋은 예다.


<리스트 6> config.json 파일. JSON 포맷의 다층 구조가 읽기 편하다.
// config.json 파일
{
"AppSettings": {
"SiteTitle": "ConfigDemo"
},
"Data": {
"DefaultConnection": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-ConfigDemo;"
}
}
}



이렇게 설정한 값들은 애플리케이션이 시작되는 시점에 로드되는데 여러 소스로 구성할 수 있기 때문에 추가하는 순서에 따라 우선순위가 정해지고, 나중에 추가되는 소스가 높은 우선순위를 갖는다.


<리스트 7> 외부 파일(config.json)과 환경 변수로 구성한 예
var configFluent = new Configuration()
.AddJsonFile("config.json")
.AddEnvironmentVariables();



Configuration 클래스는 여러 소스에 대한 컬렉션이다. <리스트 7>의 예는, config.json에 정의된 키 값이 환경 변수에도 정의되어 있을 경우, 환경 변수의 키 값이 최종적으로 사용된다. <리스트 8>에서는 환경 변수를 활용하여 web.config의 transform과 유사한 기능을 구현하고 있다.


<리스트 8> 환경 변수를 활용해 web.config의 transform과 유사한 기능 구현
var configuration = new Configuration()
.AddJsonFile("config.json")
.AddJsonFile($"config.{env.EnvironmentName}.json", optional: true);



<리스트 8>의 마지막 줄을 보면 C# 6의 새로운 문자열 포매팅 기능을 사용해 파일명을 표현하고 있는데 env.EnvironmentName 값이 production 이라면 config.production.json 파일을 로드 할 것이다. 애플리케이션을 배포할 서버의 환경 변수를 고려한 설정 파일을 만들 수 있어 서버 특화된 설정이 가능한 것이다.



4. Task Runner

자바스크립트의 비약적인 발전으로 현대의 웹 개발은 클라이언트 단에서 다양한 일을 효과적으로 수행하고 있다. 모던 웹을 작성한다고 할 때 어떤 일들이 필요한가.

-LESS 또는 SASS 파일을 CSS로 컴파일하기
-CoffeeScript 또는 TypeScript를 자바스크립트 파일로 컴파일 하기
-자바스크립트 파일들을 묶고(bundle) 축소(minify)하기
-자바스크립트가 코딩 규칙을 따르는지 JSHint 툴로 검사하기



아마 박스 속 작업들이 웹 개발의 일부가 되어 애플리케이션마다 반복적으로 수행될 것이다. 이런 일련의 작업들을 자동화 하기 위해 태스크 런너(이하 task runner)라는 하나의 앱을 사용하는데 비주얼 스튜디오 2015(Visual Studio 2015)는 task runner로서 가장 인기 있는 자바스크립트 기반의 Gulp와 Grunt를 지원한다.
Gulp가 비교적 최근에 개발되었고 현대적인 문법과 디스크 I/O가 아닌 스트림을 사용한 빠른 성능 때문인지 ASP.NET 5 Web Site 템플릿에 의해 기본적으로 사용된다. Gulp는 노드 패키지로서 NPM(Node.js Package Manger) 설정 파일인 package.json 에 의해 설치된다. 그리고, 자동화 작업(task)은 gulpfile.js 파일에 작성한다. <리스트 9>는 Assets 폴더 하위의 모든 자바스크립트 파일을 wwwroot/js 폴더로 복사하는 예제다.


<리스트 9> Assets 폴더 하위의 모든 자바스크립트 파일을 wwwroot/js 폴더로 복사
var gulp = require('gulp');
var paths = {
src: "./Assets/**/*.js",
dest: "./wwwroot/js/"
}
gulp.task('default', function () { // default 는 작업명
return gulp.src(paths.src) // Returns a stream
.pipe(gulp.dest(paths.dest)) // Pipes the stream somewhere
});



이렇게 default라고 정의한 작업을 Task Runner 탐색기를 통해 실행할 수도 있지만 <그림 5>에서처럼 일반적으로 빌드 이벤트에 바인딩하여 자동으로 수행하게 한다.

tech_img4043.jpg

<그림 5> default 작업을 프로젝트 빌드 후에 수행하도록 설정

Task runner의 지원이 꼭 필요한 Bower라는 또 다른 노드 패키지가 있다. Bower는 Git 위에서 동작하며 jquery, bootstrap, angular를 포함한 35,000 이상의 패키지를 관리하는 웹 패키지 매니저로 알려져 있는데, 생태계의 규모와 task runner와의 좋은 궁합 때문에 클라이언트 단에서 NuGet 패키지보다 Bower가 추천된다. Bower.json 파일에 등록된 클라이언트 라이브러리들은 bower_components 폴더에 다운로드 되고 task runner를 이용해 wwwroot 폴더로 복사하는 것이 ASP.NET 5 애플리케이션의 전형적인 관리 방식이다.

다음 연재에서는 MVC와 Web API의 통합을 포함한 개발의 변화에 대해 알아보도록 한다.



출처 : 마이크로소프트웨어 8월호

제공 : 데이터 전문가 지식포털 DBguide.net