Grunt와 Bower를 이용한 Visual Studio 2015의 클라이언트 측 웹 개발 관리

등록일시: 2015-01-12 08:00,  수정일시: 2015-01-13 12:05
조회수: 7,699
이 문서는 ASP.NET vNext 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.

ASP.NET 5.0에서는 ASP.NET 응용 프로그램의 프로젝트 시스템과 빌드 과정에 몇 가지 큰 변화가 생겼습니다.

근래의 웹 응용 프로그램 개발에는 서버 측 코드(ASP.NET 같은)나 클라이언트 측 라이브러리들, 도구들의 복잡한 연계 같이 유동적인 부분들이 많습니다. 전형적인 웹 응용 프로그램에 LESS나 CoffeeScript, 또는 TypeScript 등이 사용되기도 합니다. JavaScript 파일들을 번들시키거나 축소하기도 하고, JSLint 같은 도구나 단위 테스트를 수행하기도 합니다.

Visual Studio 2015 Preview는 클라이언트 측 패키지들을 쉽게 관리하고, 빌드 태스크들을 자동으로 실행할 수 있도록 몇 가지 인기있는 서드-파티 도구들에 대한 지원 기능을 내장하고 있습니다.

Visual Studio 2015를 사용하면:

  • jQuery나 Bootstrap, 또는 Angular 같은 클라이언트 측 패키지들을 쉽게 관리할 수 있습니다.
  • LESS 컴파일, JavaScript 축소, JSLint, 또는 JavaScript 단위 테스트 같은 빌드 태스크들을 자동으로 실행할 수 있습니다.
  • 웹 개발 커뮤니티에 의해서 만들어진 생태계의 풍부한 도구들의 이점을 누릴 수 있습니다.

이런 시나리오를 지원하기 위해서, Visual Studio 2015 Preview는 다음과 같은 몇 가지 인기있는 서드-파티 도구들에 대한 지원 기능을 내장하고 있습니다:

  • Bower. "웹을 위한 패키지 관리자"라고 설명할 수 있는 Bower를 이용하면 JavaScript 및 CSS 라이브러리들을 비롯한 클라이언트 측 패키지들을 설치하거나 복원할 수 있습니다. 물론, MVC 6 프레임워크 같은 서버 측 라이브러리들은 여전히 NuGet 패키지 관리자를 이용해서 관리하면 됩니다.
  • GruntGulp. Grunt와 Gulp는 JavaScript 기반의 태스크 런너들입니다. 만약, 태스크 런너라는 개념이 낯설다면, 반복적인 개발 작업을 자동화시켜주는 응용 프로그램 정도로만 이해해도 무방합니다. 현재 ASP.NET 5.0의 프로젝트 템플릿은 Grunt를 사용하고 있습니다.
  • npm (Node 패키지 관리자). npm은 본래 Node.js를 위해서 만들어진 패키지 관리자입니다. Bower, Grunt, 그리고 Gulp는 모두 npm을 이용합니다.

본문은 여러분이 Bower, Grunt, 또는 Gulp에 관해서 이미 알고 있다고 가정하고 있지 않습니다. 만약 이 도구들을 사용해본 경험이 있더라도, Visual Studio 2015가 이 도구들을 ASP.NET 5의 프로젝트 구조에 통합시키는 방법을 직접 살펴볼 수 있을 것입니다. 이제 본론으로 들어가도록 하겠습니다.

본문에서는 다음과 같은 내용들을 살펴봅니다.

그럼 우선, Visual Studio 2015를 실행해서 새로운 ASP.NET 5.0 프로젝트를 생성합니다. 파일(File) 메뉴에서 새로 만들기(New) > 프로젝트(Project)를 선택해서 새 프로젝트(New Project) 대화 상자를 열고, Visual C# > 웹(Web) > ASP.NET 웹 응용 프로그램(ASP.NET Web Application)을 선택합니다. 그리고 프로젝트 이름을 지정한 다음, 확인(OK) 버튼을 클릭합니다.

그런 다음, New Project 대화 상자에서 "ASP.NET 5.0 Starter Web"을 선택하고 OK 버튼을 클릭합니다.

그러면 기본적인 ASP.NET MVC 6 응용 프로그램이 생성되는데, 그 프로젝트의 구조는 다음과 같습니다.

생성된 프로젝트에는 몇 가지 중요한 구성 파일들이 포함되어 있습니다.

  • Project.json. 가장 중요한 프로젝트 파일입니다. 특히 NuGet 패키지 의존성들의 목록이 이 파일에 저장됩니다.
  • package.json. npm 패키지들의 목록이 이 파일에 저장됩니다.
  • bower.json. Bower 패키지들의 목록이 이 파일에 저장됩니다.
  • gruntfile.js. 이 파일에 Grunt 태스크들을 구성합니다.

정적 파일들과 wwwroot

이 wwwroot 폴더는 ASP.NET 5.0에서 새롭게 도입된 폴더로, 프로젝트 내부에 존재하는 모든 정적 파일들이 이 폴더에 위치하게 됩니다. 여기에서 말하는 정적 파일들이란, HTML 파일, CSS 파일, 이미지 파일, 그리고 JavaScript 파일을 비롯한 클라이언트로 응용 프로그램이 직접 제공해주는 자산(Asset)들을 말합니다. 또한 wwwroot 폴더는 웹 사이트의 루트이기도 합니다. 다시 말해서, http://hostname/ 같은 URL들은 wwwroot 폴더를 가리키며, 정적 콘텐트에 대한 모든 URL들도 wwwroot 폴더를 기준으로 합니다.

그 반면 코드 파일들은 wwwroot 이외의 폴더에 위치해야 합니다. 가령, 모든 C# 파일과 Razor 파일들이 여기에 해당됩니다. 이런 방식으로 wwwroot 폴더를 활용함으로서 코드 파일들과 정적 파일들을 명확하게 분리시킬 수 있습니다.

그런데 일부 정적 파일들은 컴파일 과정이나 전처리 단계에서 동적으로 생성되기도 합니다. 가령, 다음과 같은 경우들입니다:

  • CoffeeScript 파일이나 TypeScript 파일을 JavaScript로 컴파일 할 때.
  • LESS 파일이나 Sass 파일을 CSS로 컴파일 할 때.
  • JavaScript 파일을 축소시키거나 병합시킬 때.
  • 이미지 파일들을 최적화 할 때.

이런 경우, 빌드 과정에 필요한 입력 파일들은 wwwroot 폴더의 외부에 위치해야 하고, 빌드 단계에서 출력된 파일들은 wwwroot 폴더로 복사되어야 합니다. 그리고 바로 이 시점이 태스크 런너가 등장하는 부분이기도 합니다. 본문의 뒷부분에서는 이런 유형의 빌드 작업의 한 예로, Grunt를 이용해서 LESS 파일을 컴파일하는 방법을 살펴보도록 하겠습니다.

이 wwwroot 폴더를 웹 루트라고 부르며, 선호하는 이름으로 폴더명을 변경할 수도 있습니다. 웹 루트 폴더의 이름은 project.json 파일의 "webroot" 옵션에 지정됩니다.

{
    "webroot": "wwwroot",
    "version": "1.0.0-*",
    // ...
}

Bower를 이용한 클라이언트 측 패키지 관리

먼저 Visual Studio 2015 Preview가 Bower를 이용해서 클라이언트 측 패키지를 관리하는 방법을 살펴보도록 하겠습니다. 이번 절에서는 응용 프로그램에 RequireJS 라이브러리를 추가해봅니다.

bower.json 파일을 열고, dependencies 섹션에 requirejs 항목을 추가합니다.

"dependencies": {
    "bootstrap": "~3.0.0",
    "jquery": "~1.10.2",
    "jquery-validation": "~1.11.1",
    "jquery-validation-unobtrusive": "~3.2.2",
    "requirejs": "^2.1"
},

패키지 버전에는 "주.부.수(Major.Minor.Patch)" 형식의 버전 번호로 구성되는 의미론적 버전 지정방식(Semantic Versioning)이 사용됩니다. 또한 ^2.1에 사용된 캐럿(Caret) '^' 기호는 지정한 버전과 주 버전이 일치하면서 부 버전은 같거나 더 높은 버전을 사용한다는 뜻입니다. 틸드(Tilde) '~' 기호를 사용해서 주 버전과 부 버전 모두를 지정할 수도 있습니다. 가령, '~1.10.2'는 적어도 1.10.2 버전, 또는 더 높은 1.10 대의 수 버전을 사용하겠다는 뜻입니다. 더 자세한 정보는 https://github.com/npm/node-semver 문서를 참고하시기 바랍니다.

패키지 명을 한 글자씩 입력해보면서, 사용 가능한 패키지들의 목록이 인텔리센스로 제공되는 것을 확인해보시기 바랍니다:

더불어, 패키지 버전에 대해서도 인텔리센스가 제공되는 것을 확인하실 수 있습니다:

이제 실제로 새로운 패키지를 설치해보겠습니다. 솔루션 탐색기에서 Dependencies 노드를 확장합니다. 그리고 Bower 노드를 마우스 오른쪽 버튼으로 클릭한 다음, Restore Packages를 클릭합니다.

그러면 Output 창을 통해서 설치 과정이 진행되는 것을 확인할 수 있습니다. 이 패키지들은 bower_components 폴더에 설치됩니다.

Visual Studio는 솔루션을 열 때 자동으로 모든 패키지들을 복구시켜줍니다. 따라서, 프로젝트를 소스 제어 시스템에 체크인 할 때 bower_components 폴더는 제외시켜도 됩니다.

Grunt를 이용한 태스크 실행

gruntfile.js 파일에는 Grunt 태스크들이 정의됩니다. 가령, 본문의 예제에서 선택한 "ASP.NET 5.0 Starter Web" 프로젝트 템플릿에는 기본적으로 Bower 패키지 관리자를 실행하기 위한 태스크가 단 하나 정의되어 있습니다.

이번 절에서는 Grunt를 이용해서 빌드 과정에 LESS 전처리를 추가해보도록 하겠습니다. 먼저 프로젝트에 LESS 파일을 추가해야 합니다. 따라서 프로젝트 하위에 "assets"라는 이름의 새로운 폴더를 추가합니다.

마우스 오른쪽 버튼으로 이 "assets" 폴더를 클릭한 다음, 추가(Add) > 새 항목(New Item)을 선택합니다. 새 항목 추가(Add New Item) 대화 상자가 나타나면 "LESS 스타일시트(LESS Style Sheet)" 항목을 선택하고 파일 이름을 "site.less"로 지정합니다.

그리고 site.less 파일에 다음의 코드를 붙여 넣습니다.

@base: teal;
body {
    background-color: @base;
}

이 코드는 배경색을 청록색으로 설정하게 되는데, 색상 값을 설정하기 위해서 @base라는 변수를 정의하고 있는 부분에 주목하시기 바랍니다. LESS의 주된 기능들 중 하나가 이런 변수들을 사용할 수 있게 해주는 것입니다.

기본적으로 Visual Studio는 이 파일을 대상으로 아무런 처리도 수행하지 않습니다. Grunt가 필요한 시점이 바로 여기입니다. Grunt 태스크를 추가하기 위한 기본적인 단계는 다음과 같습니다:

  1. 태스크를 설치합니다. 물론 사용자 지정 Grunt 태스크를 작성할 수도 있지만, 이미 패키지로 만들어져 있는 태스크를 설치하는 경우가 더 많을 것입니다.
  2. Grunt 파일에 태스크를 구성합니다.
  3. Visual Studio의 빌드 이벤트와 태스크를 바인드시킵니다.

그러면 이 과정을 LESS 태스크를 대상으로 직접 적용해보겠습니다.

Grunt LESS 태스크를 설치합니다. grunt-contrib 리파지토리에서는 유용한 Grunt 태스크들의 모음을 상당수 제공해주는데, LESS 파일을 컴파일해주는 태스크도 그 중 하나입니다. 이 태스크를 설치하려면, package.json 파일의 "devDependencies" 영역에 태스크를 추가하면 됩니다.

{
    "version": "0.0.0",
    "name": "MyApp",
    "devDependencies": {
        "grunt": "^0.4.5",
        "grunt-bower-task": "^0.4.0",
        // Add this:
        "grunt-contrib-less": "^0.12.0"
    }
}

이번에도 역시 패키지 명을 한 글자씩 입력해보면, 패키지들의 목록이 인텔리센스로 제공되는 것을 확인할 수 있습니다:

버전 문자열을 입력할 때도 최신 패키지 버전들에 대한 인텔리센스가 제공됩니다.

이제 솔루션 탐색기에서 Dependencies > NPM 폴더를 확장해보면, 의존성 목록에 grunt-contrib-less가 등록됐지만, 아직 설치되지는 않은 상태라는 것을 알 수 있습니다.

패키지를 설치하려면, 마우스 오른쪽 버튼으로 NPM 폴더를 클릭하고 Restore Packages를 선택합니다.

그러면 패키지가 설치됩니다. (다음에 솔루션을 다시 열 때, Visual Studio가 자동적으로 패키지들을 복구시켜주므로, 이 패키지들을 소스 제어 시스템에 체크인 할 필요는 없습니다.) 계속해서 이번에는 설치된 태스크를 구성해야 합니다. gruntfile.js 파일을 열고 다음과 같이 수정합니다:

module.exports = function (grunt) {
    grunt.initConfig({
        bower: {
            install: {
                options: {
                    targetDir: "wwwroot/lib",
                    layout: "byComponent",
                    cleanTargetDir: true
                }
            }
        },
        // Add this JSON object:
        less: {
            development: {
                options: {
                    paths: ["Assets"],
                },
                files: { "wwwroot/css/site.css": "assets/site.less" }
            },
        }
    });

    grunt.registerTask("default", ["bower:install"]);

    grunt.loadNpmTasks("grunt-bower-task");
    // Add this line:
    grunt.loadNpmTasks("grunt-contrib-less");
};

이 코드에 사용된 initConfig 메서드에서는 실행하고자 하는 Grunt 태스크들을 구성합니다. 모든 Grunt 플러그인은 자체적인 일련의 구성 옵션들을 갖고 있습니다. 이 예제에서는 grunt-contrib-less가 assets/site.less 파일을 컴파일한 다음, 출력 파일을 wwwroot/css/site.css로 복사하도록 구성하고 있습니다. (파일 Globbing을 이용해서 복수의 파일을 지정할 수도 있습니다.)

그리고 loadNpmTasks 메서드는 Grunt 플러그인으로부터 태스크들을 로드합니다. 본문의 예제에서 선택한 "ASP.NET 5.0 Starter Web" 프로젝트 템플릿은 기본적으로 grunt-bower-task를 로드합니다. 그리고 방금 grunt-contrib-less를 로드하기 위해서 이 메서드를 한 번 더 호출한 셈입니다.

이제 테스크를 실행할 수 있는 상태가 됐습니다. 솔루션 탐색기에서 gruntfile.js 파일을 마우스 오른쪽 버튼으로 클릭하고 Task Runner Explorer를 선택합니다.

이 Task Runner Explorer는 보기(View) 메뉴를 이용해서 (보기(View) > 다른 창(Other Windows) > Task Runner Explorer) 열 수도 있습니다. 이 창에서 방금 정의한 "less" 태스크가 Tasks 하위에 등록되어 있는 것을 확인할 수 있습니다.

태스크의 이름("less")을 마우스 오른쪽 버튼으로 클릭하고 Run을 선택하면 태스크가 실행됩니다.

그러면 출력 창을 통해서 태스크가 처리되는 상태를 확인할 수 있을 것입니다.

이제 /wwwroot/css/site.css 파일을 열어봅니다. 이 파일에는 컴파일된 CSS가 작성되어 있을 것입니다.

body {
    background-color: #008080;
}

응용 프로그램을 실행시켜보면, 배경색이 청록색으로 적용되어 렌더됩니다.

그러나 대부분의 경우, 이번 예제처럼 태스크를 일일이 수작업으로 실행하는 대신 Visual Studio가 빌드 과정이나 처음 솔루션을 열 때 자동으로 태스크를 실행시켜주는 방식을 선호할 것입니다. 이 방식을 적용하려면 Task Runner Explorer에서 "less" 태스크를 마우스 오른쪽 버튼으로 클릭한 다음, Bindings > After Build를 선택합니다.

그런 다음 태스크가 자동으로 실행되는 것을 확인해보기 위해서, 방금 생성된 wwwroot/css/site.css 파일을 삭제하고 프로젝트를 빌드해봅니다. 그러면 site.css 파일이 다시 생성되는 것을 확인할 수 있을 것입니다.

이 기사는 2014년 11월 12일에 최초 작성되었습니다.