티스토리 뷰
[ GRUNT ]
Grunt 란 : task 단위의 command line 을 통해 동작하는 자바스크립트용 빌드 툴 ( 더 자세히 알기 클릭 )
이 글에서 사용할 Grunt 기능 : js, css 파편화를 모두 합치고(concat), 간결화하며(uglify), 압축한다(minifying)
Grunt 로 얻을수 있는 잇점 : compile build된 결과물처럼 파일을 얻을수 있기때문에
웹 패키지 배포를 자동화 툴을 사용하여 손쉽게 구축할 수 있다.
Grunt 를 설치하기 전에 준비해야할 폴더및 파일
Grunt를 실제 실행해 보기위한 샘플 코드가 필요한데
본인의 경우 D 드라이브 바로 아래에 GRUNT 라는 폴더를 만들고 아래와 같이 폴더를 구성하였다
D:\>GRUNT
참고로 아래에있는 예제 소스작성 혹은 붙여넣기가 번거로운 경우 아래 GRUNT.zip 파일을 다운받아 폴더를 구성하도록 하고
실제 Grunt 툴을 사용함에 있어서 주의깊에 살펴볼 폴더는 build 에 생성되는 결과물이다.
# D > GRUNT 폴더구성
아래와같이 build, css, js, log, after.html, before.html 을 만든다.
# D > GRUNT 폴더 > before.html
( 아래 나열된 소스코드를 전부 입력, 혹은 붙여넣기 하거나 GRUNT.zip파일을 다운받아 압축풀었다면 )
먼저 before.html을 실행하면 Grunt 툴을 이용하기 이전의 결과물을 확인할 수 있다.
각각 test_1.css, test_2.css, test_1.js, test_2.js 를 이용하여 화면을 출력하고 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel='stylesheet' href='css/test_1.css' /> <link rel='stylesheet' href='css/test_2.css' /> <title>Document</title> </head> <body> <script src='js/test_1.js'></script> <script src='js/test_2.js'></script> </body> </html> | cs |
# D > GRUNT 폴더 > after.html
( 실제로 Grunt 를 모두 설치하고 나서 최종적으로 다시 실행할 html 이다 )
아직 실제 파일은 없지만 css는 style.css 이름으로 js는 built.min.js 이름으로 바꾸어서
미리 after.html 을 만들어 둔다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel='stylesheet' href='build/styles.css' /> <title>Document</title> </head> <body> <span class='sass'>sass color is orange!</span> <script src='build/built.min.js'></script> </body> </html> | cs |
# D > GRUNT > css 폴더 > test_1.css
1 2 3 4 | body{ background-color: #eee; } | cs |
# D > GRUNT > css 폴더 > test_2.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | h2{ color:blue; font-weight: 800; } h3{ color:blue; font-weight: 400; } h4{ color:blue; font-weight: 200; } | cs |
# D > GRUNT > js 폴더 > test_1.js
1 2 3 4 | var newH1 = document.createElement("H1"); newH1.innerHTML = "test_1.js 에서 추가된 H1 입니다."; document.body.appendChild(newH1); | cs |
# D > GRUNT > js 폴더 > test_2.js
1 2 3 4 5 6 7 8 9 10 11 | var newH2 = document.createElement("H2"); newH2.innerHTML = "test_2.js 에서 추가된 H2 입니다."; document.body.appendChild(newH2); var div; for(var i=0; i<10; i++){ div = document.createElement("div"); div.innerHTML = i.toString(); document.body.appendChild(div); } | cs |
# D > GRUNT > js 폴더 > errorToDo.js
JSHint 플러그인 실습을 위해서 아래에 있는 에러코드가 포함된 js 를 넣어놓는다.
D:\>GRUNT>js>errorToDo.js
1 2 | "일부러 발생시킨 에러" + string; | cs |
# D > GRUNT > js 폴더 > etc폴더 > errorToDo.js
JSHint 플러그인 실습을 위해서 아래에 있는 에러코드가 포함된 js 를 넣어놓는다.
D:\>GRUNT>js>etc>errorToDo.js
1 2 | "일부러 발생시킨 에러" + string; | cs |
# D > GRUNT > log 폴더 > grunt_compiled 폴더
js가 제대로 compile 되었는지 로그로 남기기위한 폴더를 만들어 둔다.
D:\>GRUNT>log>grunt_compiled
(폴더만 생성하도록 한다)
자, 여기까지 준비가 되었다면 실제로 grunt 테스트할 준비가 모두 완료되었다.
Grunt 설치
1. 먼저 NodeJS 설치유무와 버전을 확인한다.
반드시 관리자권한으로 실행한 명령 프롬프트에서 다음 명령어를 실행한다.
> node -v
nodejs 가 설치되어 있는지 확인함과 동시에 버전을 알려주는데 현재 이 글에서는 6.10.3 이상을 기준으로 설명하도록 하겠다.
2. Grunt CLI 설치
커맨드라인으로 실행할 수 있는 인터페이스를 다음의 명령어로 설치한다. ( 참조 : https://github.com/gruntjs/grunt-cli )
> npm install -g grunt-cli
여기서 -g 옵션은 어떤 폴더상에 위치해 있던지 전역적으로 명령 호출이 가능한 globally 옵션이다.
(Install this globally and you'll have access to the grunt command anywhere on your system.)
3. Grunt 를 사용할 폴더로 이동하여 Grunt 설치
앞서서 만들었던 D:\>GRUNT 폴더로 이동한다. 본인의 경우 D 드라이브 바로 밑에 GRUNT 폴더를 생성하였으므로
C:\> 드라이브에서 명령어 D: 를 입력하여 D 드라이브로 이동하였다.
( 참고로 드라이브 이동은 cd 명령이 아닌 C: D: E: 처럼 드라이브명 + 콜론으로 입력한다. )
드라이브가 이동된 이후에 GRUNT가 만들어진 폴더를 cd 명령어를 사용하여 이동하도록 한다.
이후 앞으로의 모든 플러그인 설치와 실행은 D\GRUNT> 경로상에서 이루어지며
아래 명령어를 실행하여 Grunt를 설치한다.
> npm install grunt --save-dev
--save-dev 옵션은 package.json 파일과 연동되어 파일 내부의 의존성(devDependencies)항목에 자동으로 추가해준다.
설치가 완료되면 GRUNT > node_modules 라는 패키지가 자동으로 설치되어있을것이다.
package.json 파일생성하기
package.json 은 node.js로 프로젝트를 진핼할때 npm install 모듈명 으로 패키지를 설치하고 사용하게되는데
이때 이런 정보를 담고있는 json 파일이다.
package.json 을 처음 작성할때 다음의 명령을 입력한다.
> npm init
을 실행하면 name 부터 입력을 받는 질문이 표시된다.
name, description 정도만 입력하고 특별한 코멘트가 없는경우 엔터키로 skip 한다.
Gruntfile.js 생성하기
GRUNT 폴더에 Gruntfile.js 를 아래와 같은 형식으로 만들어 둔다.
7번 라인 : 앞으로 사용할 패키지들을 설치하여 사용할것이고
13, 16 번 라인 : 설치된 패키지들을 호출할 것이다.
GRUNT > Gruntfile.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), package:{ //여기에 패키지들이 적용된다. } }); //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용 grunt.loadNpmTasks('full-package-name'); //grunt 명령어로 실행할 작업 grunt.registerTask('default', ['package-name']); }; | cs |
concat 플러그인 설치
grunt-contrib-concat : File 통합 플러그인
ㄱ. concat 을 설치한다.
> npm install grunt-contrib-concat --save-dev
--save-dev 옵션으로 설치하였기 때문에 package.json 에 다음과같이
"devDependencies": {
"grunt-contrib-concat": "^1.0.1",
.... 으로 자동으로 플러그인명과 버전이 등록될 것이다.
Tip! > npm uninstall grunt-contrib-concat --save-dev 하면 package.json 에서 자동으로 플러그인명이 삭제될 것이다.
ㄴ. Gruntfile.js 작성.
GRUNT > Gruntfile.js 에서 다음과 같이 입력한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat:{ options: { stripBanners: true, separator: ';', banner: '/* <%= pkg.name %> - v<%= pkg.version %> - '+'<%= grunt.template.today("yyyy-mm-dd") %> */', //동작 시점의 날짜가 출력 footer : "", }, dist:{ src:['js/test_1.js','js/test_2.js'], dest:'build/built.js' }, // Invalid or Missing Files Warning 잘못 또는 누락된 파일 경고 : 해당파일이 없거나 유효하지 않으면 경고 missing:{ src:['log/grunt_compiled'], dest: 'log/grunt_compiled/compiled.log', nonull: true } /* //Multiple targets 별도의 설정을 두개지정하고 다중작업 //basic 구성 basic: { src: ['js/test_1.js', 'js/test_2.js'], dest: 'build/basic.js', }, // extras extras: { src: ['js/test_1.js', 'js/test_2.js'], dest: 'build/extras.js', }, */ } }); //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용 grunt.loadNpmTasks('grunt-contrib-concat'); //grunt 명령어로 실행할 작업 grunt.registerTask('default', ['concat']); }; | cs |
concat 플러그인을 사용하기 위해 concat 객체를 정의하고 그 안에 세부적인 옵션들을 정의하여 파일을 통합할수 있다.
options :
dist :
missing :
ㄷ. grunt 실행
> grunt 를 실행해 보면
아래와 같이 test_1.js 와 test_2.js 가 build/build.js 로 합쳐져있다.
missing 옵션으로 사용한 src와 dest 파일지정으로 log 옵션으로 사용하였는데 제대로 생성됨을 확인.
uglifyJS
grunt-contrib-uglify : 공백및 줄바꿈에대한 압축실행
ㄱ. 설치
> grunt-contrib-uglify --save-dev
ㄴ. Gruntfile.js 작성 (기존의 내용은 지우고 이 내용으로 작성하여 테스트 하도록한다.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify:{ options: { mangle: false, //변수와 함수 이름을 변경되는 것을 방지할경우 false 사용 compress: { drop_console: true //콘솔경고해제 }, //beautify: true // 디버깅이나 문제해결을 위해 사용 }, build: { src: 'build/built.js', dest: 'build/built.min.js' } } }); //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용 grunt.loadNpmTasks('grunt-contrib-uglify'); //grunt 명령어로 실행할 작업 grunt.registerTask('default', ['uglify']); }; | cs |
ㄷ. 실행
> grunt
결과 ) 위에서 합쳐졌던 build.js 가 build.min.js 로 변환되었다
JSHint
jsHint : 자바스크립트 코드 검사
ㄱ. 설치
> grunt-contrib-jshint --save-dev
ㄴ. Gruntfile.js 작성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), jshint:{ //all: ['Gruntfile.js', 'js/test_01.js', 'js/test_02.js'] // 기본적으로 자기자신을 포함하고, 직접 지정해서 사용 //all: ['js/*'] // 혹은 js 폴더의 모든 파일을 검사 //all: ['js/etc/*.js'] //측정폴더의 모든 js 검사 all:['js/*'], options:{ force: true, // true로 설정시 error 가 있다하더라도 fail 시키지않고 계속 진단 //reporter: require('jshint-stylish') } } }); //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용 grunt.loadNpmTasks('grunt-contrib-jshint'); //grunt 명령어로 실행할 작업 grunt.registerTask('default', ['jshint']); }; | cs |
ㄷ. 실행
플러그인 유틸인 jshint-stylish 설치 : output을 modifying 할 수 있는 옵션 유틸
> npm install jshint-stylish --save-dev
Gruntfile.js 재작성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), jshint:{ //all: ['Gruntfile.js', 'js/test_01.js', 'js/test_02.js'] // 기본적으로 자기자신을 포함하고, 직접 지정해서 사용 //all: ['js/*'] // 혹은 js 폴더의 모든 파일을 검사 //all: ['js/etc/*.js'] //측정폴더의 모든 js 검사 all:['js/*'], options:{ force: true, // true로 설정시 error 가 있다하더라도 fail 시키지않고 계속 진단 reporter: require('jshint-stylish') } } }); //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용 grunt.loadNpmTasks('grunt-contrib-jshint'); //grunt 명령어로 실행할 작업 grunt.registerTask('default', ['jshint']); }; | cs |
실행하여 위의 이미지와 같이 에러결과가 파란색으로 표시된다.
cssmin
cssmin : css 공백및 줄바꿈에대한 압축실행
ㄱ. 설치
> npm install grunt-contrib-cssmin --save-dev
ㄴ. Gruntfile.js 작성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), cssmin:{ minify:{ expand: true, cwd: "css/", // css 폴더 위치 src:['*.css', '!*.min.css'], // 파일지정, 이때 .min.css 는 제외한다. dest:'build', // 출력폴더 지정 ext:".min.css" // 확장자 지정 }, options:{ keppSpecialComments: 0 // default : '!' 가 붙은 주석 보존, 1 : '!' 가 붙은 주석 중 첫번째 주석만 보존, 0 : 모든 주석 제거 } } }); //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용 grunt.loadNpmTasks('grunt-contrib-cssmin'); //grunt 명령어로 실행할 작업 grunt.registerTask('default', ['cssmin']); }; | cs |
ㄷ. 실행결과 : styles.min.css 로 압축되어있다.
ATOM 에 Grunt 패키지 설치하고 플러그인 모두 한번에 실행해보기
ATOM 에서 grunt-runner package 를 설치한다.
Gruntfile.js 에 여태까지의 플러그인의 내용을 한번에 작성한다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), /******************************************************************************************************************************* * * 1. jshint 로 유효성검사 * *******************************************************************************************************************************/ jshint:{ //all: ['Gruntfile.js', 'js/test_01.js', 'js/test_02.js'] // 기본적으로 자기자신을 포함하고, 직접 지정해서 사용 //all: ['js/*'] // 혹은 js 폴더의 모든 파일을 검사 //all: ['js/etc/*.js'] //측정폴더의 모든 js 검사 all: ['js/test_1.js', 'js/test_2.js'], options:{ force: true, // true로 설정시 error 가 있다하더라도 fail 시키지않고 계속 진단 reporter: require('jshint-stylish') } }, /******************************************************************************************************************************* * * 2. concat 으로 파일 통합 * *******************************************************************************************************************************/ concat:{ options: { stripBanners: true, //separator: ';', separator: '', banner: '/* <%= pkg.name %> - v<%= pkg.version %> - '+'<%= grunt.template.today("yyyy-mm-dd") %> */', //동작 시점의 날짜가 출력 footer : "", }, basic:{ src:['js/test_1.js','js/test_2.js'], dest:'build/built.js' }, extras:{ src:['css/test_1.css','css/test_2.css'], dest:'build/styles.css' }, // Invalid or Missing Files Warning 잘못 또는 누락된 파일 경고 : 해당파일이 없거나 유효하지 않으면 경고 missing:{ src:['log/grunt_compiled'], dest: 'log/grunt_compiled/compiled_js.log', nonull: true } }, /******************************************************************************************************************************* * * 3. ugilfy 로 js 압축 * *******************************************************************************************************************************/ uglify:{ options: { mangle: false, //변수와 함수 이름을 변경되는 것을 방지할경우 false 사용 compress: { drop_console: true //콘솔경고해제 }, //beautify: true // 디버깅이나 문제해결을 위해 사용 }, build: { src: 'build/built.js', dest: 'build/built.min.js' } }, /******************************************************************************************************************************* * * 4. cssmin 으로 css 압축 * *******************************************************************************************************************************/ cssmin:{ minify:{ expand: true, cwd: "build/", // css 폴더 위치 src:['*.css', '!*.min.css'], // 파일지정, 이때 .min.css 는 제외한다. dest:'build', // 출력폴더 지정 ext:".min.css" // 확장자 지정 }, options:{ keppSpecialComments: 0 // default : '!' 가 붙은 주석 보존, 1 : '!' 가 붙은 주석 중 첫번째 주석만 보존, 0 : 모든 주석 제거 } } }); //Gruntfile 내에서 자바스크립트의 코드로 아래의 명령을 사용 grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-cssmin'); //grunt 명령어로 실행할 작업 grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'cssmin']); }; | cs |
package > Grunt Runner > Toggle Panel 실행하여 활성화시킨다.
Start 클릭하고 default 입력후 엔터
아래와 같이 Grunt 가 실행되고 build 에 여태까지 작업했던 내용들이 한번에 생성된다.
최종 화면비교
좌측이 Grunt 전에 우리가 실행했던 before.html, 우측이 Grunt 를 모두 실행하고 나서 결과물인 after.html