Jade 학습을 위한 기본 준비

Jade 학습을 위한 기본 준비
Jade(http://jade-lang.com)는 Node.js 기반 환경에서 사용하는 고성능 HTML 템플릿 엔진으로,
HTML을 빠르게 작성할 수 있게 도와주는 Emmet과는 작동 방식이 다릅니다.

하지만 Emmet을 작성하는 방법은 Jade에서도 활용할 수 있으므로 병행이 가능합니다.
국내에서는 생소한 기술이라 사용자 수가 적지만, Gulp와 Jade를 실무에서 활용하면 업무 생산성을 극대화할 수 있습니다.
유사한 도구로 Haml, Slim, Markdown 등이 있지만, 필자는 Jade를 더 선호합니다.
Gulp 기반 프로젝트 다운로드 및 모듈 설치하기
이번에 사용한 모듈은 다음과 같습니다.
del, gulp, gulp-connect, gulp-if, gulp-open, gulp-rename
                    
                        npm i -D del
                        npm i -D gulp
                        npm i -D gulp-connect
                        npm i -D gulp-if
                        npm i -D gulp-open
                        npm i -D gulp-rename
                    
                
gulpfile.js
                    
                        const {src, dest, watch, series, parallel} = require('gulp'),
                            csslint = require('gulp-csslint'),
                            concatcss = require('gulp-concat-css'),
                            uglifycss = require('gulp-uglifycss'),
                            stylish = require('jshint-stylish'),
                            jshint = require('gulp-jshint'),
                            uglify = require('gulp-uglify'),
                            concat = require('gulp-concat'),
                            rename = require('gulp-rename'),
                            gulpif = require('gulp-if'),
                            del = require('del'),
                            connect = require('gulp-connect'),
                            open = require('gulp-open'),
                            config = require('./config.json');

                        // 파일 삭제
                        function clean() {
                            return del([config.path.js.dest + '*']);
                        }

                        // NPM 설치 모듈 : gulp-csslint, gulp-concat-css, gulp-uglifycss
                        // CSS 문법 검사 > 병합 > 압축
                        function styles() {
                            return src(config.path.css.src)
                                .pipe(gulpif(config.lint, csslint({
                                    'import': false
                                })))
                                .pipe(gulpif(config.lint, csslint.formatter()))
                                .pipe(gulpif(config.concat, concatcss(config.path.css.filename)))
                                .pipe(gulpif(config.rename, dest(config.path.css.dest)))
                                .pipe(gulpif(config.uglify, uglifycss()))
                                .pipe(gulpif(config.rename, rename({
                                    suffix: '.min'
                                })))
                                .pipe(dest(config.path.css.dest))
                                .pipe(connect.reload())
                        }

                        // JS 문법 검사
                        function jsHint() {
                            return src(config.path.js.src)
                                .pipe(jshint())
                                .pipe(jshint.reporter(stylish));
                        }

                        // JS 병합
                        function jsConcat() {
                            return src(config.path.js.src)
                                .pipe(concat(config.path.js.filename))
                                .pipe(dest(config.path.js.dest));
                        }

                        // JS 압축
                        function jsUglify() {
                            return src(config.path.js.dest + config.path.js.filename)
                                .pipe(uglify())
                                .pipe(rename({suffix: '.min'}))
                                .pipe(dest(config.path.js.dest))
                                .pipe(connect.reload())
                        }

                        // html
                        function html() {
                            return src(config.path.html.src)
                                .pipe(dest(config.path.html.dest))
                                .pipe(connect.reload())
                        }

                        // 웹 서버 업무 (LiveReload 사용)
                        function server() {
                            return connect.server({
                                root: config.path.html.dest,
                                port: config.port,
                                livereload: config.livereload
                            })
                        }

                        // 브라우저 오픈 업무
                        function browserOpen() {
                            const options = {
                                uri: 'http://localhost:' + config.port,
                                app: config.browser //chrome, firefox, iexplore, opera, safari
                            };
                            return src(config.path.html.dest + '/index.html')
                                .pipe(open(options)); // local 서버가 아닌 파일 경로로 열려면 '<%file.path%>' 를 넣어주면된다.
                        }

                        // 지속적 관찰(Watch) 업무 정의
                        function fileWatch() {
                            watch(config.path.html.src, series(clean, html));
                            watch(config.path.css.src, series(clean, styles));
                            watch(config.path.js.src, series(clean, series(jsHint, jsConcat, jsUglify)));
                        }

                        // Gulp.task()를 사용해 기본(Default) 테스크 정의
                        exports.default = series(clean, parallel(styles, html, series(jsHint, jsConcat, jsUglify, parallel(server, browserOpen, fileWatch))));
                    
                
config.json
                    
                        {
                          "port": 90,
                          "livereload": true,
                          "browser": "chrome",
                          "lint": true,
                          "concat": true,
                          "uglify": true,
                          "rename": true,
                          "path": {
                            "html": {
                              "src": "src/html/*.html",
                              "dest": "dist/"
                            },
                            "css": {
                              "src": [
                                "src/css/**/*.css",
                                "src/css/style.css"
                              ],
                              "dest": "dist/css/",
                              "filename": "style.css"
                            },
                            "js": {
                              "src": "src/js/libs/**/*.js",
                              "dest": "dist/js/",
                              "filename": "DOMlibrary.js"
                            }
                          }
                        }
                    
                
실행
Git Bash에서 gulp 명령어를 실행하면 세부 업무가 연속해서 실행됩니다.
해당 프로젝트는 웹 서버 모듈(gulp-connect)과 오픈(gulp-open)모듈을 활용하므로, 명령어가 실행되면 다음과 같이 Chrome 웹 브라우저를 엽니다.
이 설정은 바꿀 수 있습니다. config.json 파일에서 "browser" 부분을 수정하면됩니다. (chrome, firefox, iexplore, opera)
localhost 서버가 아닌 file 경로로 열려면 gulpfile.js에서 .open() 메소드 소괄호 안에 '<%file.path%>' 를 입력합니다.
서버 설정과 자동으로 열리는 웹브라우저 종류를 변경할 수 있나요?
gulpfile.js 파일을 보면 웹서버, 웹브라우저 오픈 업무 코드가 아래 사진처럼 설정되어 있습니다.
각 업무 코드는 환경 설정 JSON 파일(config.json)에서 설정 값을 받아옵니다.
자동으로 열리는 웹브라우저 기본 설정 값은 config.browser이며, 설정 가능한 웹 브라우저 이름은
chrome, firefox, iexplore, opera입니다. 웹 서버 루트(Root) 디렉터리 설정 변경과, 웹서버 포트 넘버는 아래에서 변경하면 됩니다.

깨알 tip
Git Bash에서 작동 중인 웹서버를 중단하려면 ctrl+c를 누릅니다.

HTML, CSS, JS 파일을 수정할 때마다 웹브라우저를 새로고침(F5)해야 하나요?
프로젝트에서 아용 중인 웹서버 모듈(gulp-connect)은 실시간으로 수정한 내용을 웹브라우저에 반영하는 LiveReload 기능을 포함하고 있습니다.
위 프로젝트에선 기본적으로 Live Reload가 활성화(true) 되어있습니다. 따라서 HTML, CSS, JS 파일을 수정한 후 저장하면 웹브라우저를 새로고침(F5)하지 않아도 수정한 내용이 바로 반영됩니다.

깨알 Tip
Live Reload 기능을 끄려면 config.json 파일에서 livereload 값을 false로 변경합니다.