본문 바로가기

blog/scrap

[Node.js]GULP응용하기(babel, webpack, nodemon, brower-sync)

반응형

출처 : [Node.js]GULP응용하기(babel, webpack, nodemon, brower-sync) : 네이버 블로그 (naver.com)

오늘 배워 볼 내용은 백엔드와 프론트엔드에서 ES6를 사용하는 방법, 클라이언트 코드가 수정되었을 때, 브라우저를 자동으로 새로고침하고, 서버코드가 수정되었을 때, 서버를 자동으로 재시작하는 방법을 알아보도록 하겠습니다~

기본개념설명

GULP는 JavaScript 빌드 자동화 툴 입니다. GULP에는 무수하게 많은 플러그인들이 있습니다. 오늘은 클라이언트와 서버쪽에서 ES6를 사용하는 방법과 서버코드가 변경될때마다 서버를 재시작하게 해주는 것에 대하여 알아볼 것 입니다.

참! 오해할 수도 있을까봐 미리 알려드리겠습니다. GULP는 "빌드 자동화 툴"입니다. 그말인 즉슨, 위의 작업들은 gulp가 없어도 할 수 있는 것들입니다. (예를들어, gulp-uglify, gulp-clean-css, gulp-htmlmin, gulp-imagemin은, npm에 따로 의존 모듈인 uglify-js, clean-css, htmlmin, imagemin이 있습니다.) 단, 여러가지 작업을 일일히 하기엔 번거롭고, 빌드 코드를 따로 작성해도 되지만, 이를 더 편하게 작성하기 위하여 gulp가 사용되는 것입니다.

따라서, 오늘 배울 것들 또한, gulp없이도 할 수 있답니다. 'gulp에 대해서 알아보자'라는 생각보다, 'Javascript 프로젝트 빌드 도구들에 대해 알아보자' 라는 생각으로 강좌를 읽어주시길 바랍니다.

Gulp로 하고싶은 작업?

gulp를 통해 무엇을 자동으로 하고 싶은지 적어봅시다.

* 서버 사이드에서 ES6 사용하기

* 서버 사이드 코드가 변경 됐을 때 서버 다시 시작하기

* 클라이언트 사이드에서 ES6사용하기

* 클라이언트 사이드 코드 변경 시 브라우저 자동으로 새로고침하기

이에 필요한 플러그인들은?

* gulp-babel

* gulp-nodemon

* gulp-webpack

* browser-sync

* gulp-file-cache(기능 향상을 위한 플러그인)

* babel-loader (webpack에서 babel을 사용하기 위한 플러그인)

설치하기

npm install --save-dev gulp-babel gulp-nodemon gulp-webpack browser-sync gulp-file-cache babel-loader

추가적으로, 서버사이드에서 웹서버를 열 때 필요할 express도 설치해주세요

npm install --save express

준비끝 >< !!!!!!!!!

혹시 도중에 이런오류가 발생하셨나요??

npm WARN optional Skipping failed optional dependency /chokidar/fsevents: npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.12

node_modules 폴더를 삭제하고 다시 npm install 명령어를 통해 설치를 하면 오류가 해결됩니다.

적용하기

먼저, 이 프로젝트에서 사용 할 예제 서버를 작성해보겠습니다.

서버의 디렉토리 구조는 다음과 같습니다.

server ├── main.js
└── routes
└── articles.js

server/routes/articles.js - 라우터 작성

import express from 'express';
const router = express.Router();
router.use((req,res,next) => {
console.log('Time: ', Date.now().toString());
next();
});
router.get('/', (req,res) => {
res.send('articles');
})
router.get('/read/:id', (req,res) => {
res.send('You are reading article ' + req.params.id);
});
export default router;

server/main.js - 서버 작성

import express from 'express';
const app = express();
app.use('/', express.static(__dirname + '/../dist'));
app.get('/hello', (req,res) => {
return res.send('Can you hear me?');
});
import articles from './routes/articles';
app.use('/articles', articles);
const server = app.listen(3000, () => {
console.log('Express listening on port 3000');
});

3000 포트로 열리는 Express 서버를 작성하였습니다.

gulpfile - ES6 코드 변환

ES6코드를 일반 Node 환경에서도 호환되도록 ES5형태로 변환하는 과정을 알아보겠습니다.

여기서 사용할 플러그인은 gulp-babel입니다. 먼저 gulpfile의 상단에 해당 플러그인을 import해주세요.

import babel from 'gulp-babel';

다음, 서버 파일의 디렉토리와 컴파일된 코드를 저장 할 디렉토리를 상수로 정의하겠습니다.

const SRC = {
JS : DIR.SRC + '/js/*.js',
CSS : DIR.SRC + '/css/*.css',
HTML : DIR.SRC + '/*.html',
IMAGES : DIR.SRC + '/images/*',
SERVER: 'server/**/*.js'
};
const DEST = {
JS : DIR.DEST + '/js',
CSS: DIR.DEST + '/css',
HTML : DIR.DEST + '/',
IMAGES : DIR.DEST + '/images',
SERVER : 'app'
};

이제 babel task를 작성하겠습니다. 코드의 위치는 watch task의 상단에 작성해주세요.

gulp.task('babel', () => {
return gulp.src(SRC.SERVER)
.pipe(babel({
presets : ['es2015']
}))
.pipe(gulp.dest(DEST.SERVER));
});

이 코드에는 조금 문제가 있습니다. 이렇게 하면, 나중에 watch를 할 때, 서버에서 사용하는 js파일 중 하나만 수정되도 모든 파일들을 다시 컴파일하게 됩니다. 조금 비효율적이죠? 이를 고치려면, gulp-file-cache 플러그인을 통해 변동이 있는 파일만 컴파일 하도록 만들어봅시다.

gulpfile - gulp-file-cache 불러오기

import Cache from 'gulp-file-cache';
let cache = new Cache();

위 코드를 gulpfile의 상단에 작성한 다음, babel task를 수정하세요.

gulp.task('babel', () => {
return gulp.src(SRC.SERVER)
.pipe(cache.filter())
.pipe(babel({
presets : ['es2015']
}))
.pipe(cache.cache())
.pipe(gulp.dest(DEST.SERVER));
});

이 플러그인의 원리는 파일 경로와 수정 시각을 캐시에 등록하여 .gulp-cache 파일에 저장한 후, 수정된 파일, 혹은 캐시에 등록되지 않은 파일만 작업한 후 그 파일의 정보를 다시 기록하는 방식입니다. 다 작성하였다면, 다음 명령어를 통해 코드를 컴파일하고 서버를 열어보세요.

명령어를 두 번 입력하니까, 파일들이 이미 캐시에 등록되어 있어서 작업시간이 많이 단축됐죠?

gulpfile - babel watch 작성하기

let watcher = {
js : gulp.watch(SRC.JS, ['js']),
css: gulp.watch(SRC.CSS, ['css']),
html : gulp.watch(SRC.HTML, ['html']),
images: gulp.watch(SRC.IMAGES, ['images']),
babel : gulp.watch(SRC.SERVER, ['babel'])
};

watch task의 watcher 객체만 변경해주면 됩니다. 정말 쉽죠?

서버사이드 코드가 변경 되었을 때 자동으로 재시작하기

이 부분은 gulp-nodemon플러그인이 해결 해준답니다!

gulpfile gulp-nodemon 불러오기 및 start task 작성하기

import nodemon from 'gulp-nodemon'
gulp.task('start', ['babel'], () => {
return nodemon({
script: DEST.SERVR + '/main.js',
watch: DEST.SERVER
});
});

nodemon이 DEST.SERVER 디렉토리를 감시하고 있다가 변화가 감지되면, main.js를 재시작합니다. gulp-nodemon의 사용예제에서는, babel과 함께 사용할 때, babel watch를 따로 등록하지 않고, nodemon 자체에서 SRC.SERVER 디렉토리를 감시하고 있다가 변화가 감지되면 babel task를 실행한 다음에 서버를 재시작합니다. 그러나 서버가 재시작할 때 기존 서버가 제대로 종료가 되지 않는 버그가 있습니다. 허나 이 버그가 제 환경에서만 그런지는 불확실합니다. watch의 갯수를 한개 줄이고 싶은 분들은 한번 시도해보시길 바랍니다.

default task 수정하기

gulp.task('default', ['clean','js','css','html','images','watch','start'], () => {
gutil.log('Gulp is running');
});

이제 screen에서 gulp를 실행하고, server 파일을 수정해보세요.

# 저번 강좌에서 스크린을 안만들었다면 screen -S gulp 를 입력하세요.
$ screen -x gulp
$ gulp
[00:30:03] Requiring external module babel-register
# 생략..
[00:30:05] [nodemon] starting `node app/main.js`
Express listening on port 3000
# CTRL + A + D
# main.js 수정..
# screen -x gulp
[17:04:06] File /home/vlpt/node_tutorial/gulp-es6-webpack/server/main.js was changed [17:04:06] Starting 'babel'...
[17:04:06] [nodemon] restarting due to changes...
[17:04:06] [nodemon] restarting due to changes...
[17:04:06] [nodemon] starting `node app/main.js`
[17:04:07] Finished 'babel' after 824 ms Express listening on port 3000

클라이언트 사이드에서 ES6 및 import 기능 사용하기

클라이언트 사이드에서 단순히 ES6문법을 사용하려면 위에서 했던 것처럼 babel을 사용하면 됩니다.

단, 이걸 한다고 해서 import기능까지 호환되지는 않죠.

클라이언트 사이드에서도 import기능을 사용하려면 필요한 것은 바로 Module Bundler 입니다.

Module Bundler는 브라우저단에서도 CommonJS 스타일을 사용할 수 있게 해주는 도구입니다.

이는 대표적으로 Browerify와 Webpack이 있는데요. 이 포스트에서는 여러 로더를 지원하고 자체적으로 최적화가 이미 되어있는 webpack을 사용하도록 하겠습니다.

Webpack config파일 작성하기

webpack은 자체로 할수있는게 정말 많아서, config파일을 따로 작성해야 합니다.

var webpack = require('webpack');
module.exports = {
entry: './src/js/main.js',
output: {
path: __dirname + '/dist/js/',
filename: 'bundle.js'
},
 
module: {
loaders : {
test : /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
cacheDirectory: true,
presets : ['es2015']
}
}
},
plugins : {
new webpack.optimize.UglifyJsPlugin({
compress : {
warnings : false
}
})
}
}

간단히 위 파일을 설명하자면,,

* entry : ./src/js/main.js 파일을 가장 처음으로 읽습니다.

그리고 그 파일에서부터 import된 파일들을 계속해서 읽어가면서 연결시켜줍니다.

* output: 읽은 파일을 모두 합쳐서 /dist/js/bundle.js에 저장합니다.

* module: 읽은 파일들을 babel-loader를 통하여 ES6 스크립트를 컴파일해줍니다.

* plugins : UglifyJsPlugin 을 사용하여 컴파일한 스크립트를 minify합니다.

네. 보시다시피 webpack에서 uglifyjs를 사용하므로,, 더이상 gulp-uglify가 필요없어졌습니다.

npm uninstall gulp-uglify --save-dev를 통하여 모듈을 삭제하시고,

gulpfile에서도 관련 부분을 지워주세요.

gulpfile - gulp-webpack 불러오기 및 webpack task 작성하기

import webpack from 'gulp-webpack'
import webpackConfig from './webpack.config.js';
gulp.task('webpack', () => {
return gulp.src('src/js/main.js')
.pipe(webpack(webpackConfig))
.pipe(gulp.dest('dist/js'));
});

gulpfile - watch 수정하기

let watcher = {
webpack : gulp.watch(SRC.JS, ['webpack']),
css: gulp.watch(SRC.CSS, ['css']),
html : gulp.watch(SRC.HTML, ['html']),
images: gulp.watch(SRC.IMAGES, ['images']),
babel : gulp.watch(SRC.SERVER, ['babel'])
};

gulpfile - default 수정하기

gulp.task('default', ['clean','webpack','css','html','images','watch','start'], () => {
gutil.log('Gulp is running');
});

여기까지 잘 따라오셨나요? gulp-webpack이 잘 되는지 확인하려면 우선,, 저희 js코드에서도 ES6 및 import를 사용하는 예제를 만들어봐야겠죠? 예제 파일은 자유롭게 작성해보세요.

src/js/Sample.js - 예제 모듈

class Sample {
constructor(name) {
this.name = name;
}
say() {
console.log("Hi, I AM", this.name);
}
}
export default Sample;

src/js/main.js - 예제 스크립트

import Sample from './Sample';
let sample = new Sample("velopert");
sample.say();

src/index.html - 스크립트 불러오기

<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<title>Hi</title>
</head>
<body> Hello Hello World!
<script src = './js/bundle.js'></script>
</body>
</html>

#테스팅

gulp명령어를 입력하여 빌드 후 서버를 가동 후 페이지에 들어가보세요.

브라우저 단에서도 잘 작동하는군요 ㅎㅎ

클라이언트 사이드 코드 변경 시 브라우저 자동으로 새로고침하기

자, 드디어 마지막 단계입니다.

gulpfile - browser-sync 불러오기 및 browser-sync task 작성하기

import browserSync from 'browser-sync';
gulp.task('browser-sync', () => {
browserSync.init(null, {
proxy: "http://localhost:3000",
files: ["dist/**/*.*"],
port: 7000
})
});

proxy 부분은 express 서버에서 사용하는 포트를 넣어주세요.

이 설정을 넣어주면 static 파일들 외에도 내부 API에 접근할 수 있게 됩니다.

port부분은 browser-sync서버의 포트입니다.

gulpfile - default 수정하기

gulp.task('default', ['clean','webpack','css','html','images','watch','start', 'browser-sync'], () => {
gutil.log('Gulp is running');
});

이렇게 하면 새로고침을 따로 하지 않아도 파일이 저장될 때 자동으로 새로고침이 됩니다.

CSS파일을 변경할 땐, 전체 페이지를 새로고침하지 않고 CSS만 갈아끼워주는 멋진 모듈이랍니다.

오늘은 nodejs를 한다면 무조건 알아야하는 gulp라는 모듈에 대해 알아보았습니다~ 이 안에는 다양한 플러그인들이 존재하는데, 하나하나의 역할을 찾아 써보는것도 좋지않을까 생각합니다 ㅎㅎ

오늘 눈이왔는데 모두 퇴근하는데 조심하세요~~>< 오늘두 즐건하루되세욤 ㅎㅎㅎ

반응형