scripts 업무 프로세스와 동일한 CSS 업무 정의

scripts 업무 프로세스와 동일한 CSS 업무 정의
자바스크립트 파일을 처리한 업무 프로세스와 유사하게 CSS 파일을 처리하는 업무도 정의합니다.
CSS 파일에 처리 적용할 업무는 문법 검사, 코드 병합, 압축 과정으로, 필요한 모듈은
gulp-csslint, gulp-concat-css, gulp-uglifycss 입니다.
다음 처럼 위 모듈을 한번에 설치할 수 있습니다.
설치가 끝나면 gulpfile.js 상단에 각 모듈을 호출하는 코드를 작성합니다. 다음을 참고하여 CSS 파일을 처리할 styles 업무를 정의합니다.
[src/css] 디렉터리를 생성하여 모든 파일을 소스로 설정했고, 파이프로 문법 검사(csslint), 병합(concatcss), 압축(uglifycss) 과정을 수행한 후
[dist/css] 디렉터리에 결과물을 배포하도록 했습니다.
                    
                        const gulp = require('gulp');
                        const csslint = require('gulp-csslint');
                        const concatcss = require('gulp-concat-css');
                        const uglifycss = require('gulp-uglifycss');
                        const stylish = require('jshint-stylish');
                        const jshint = require('gulp-jshint');
                        const uglify = require('gulp-uglify');
                        const concat = require('gulp-concat');
                        const rename = require('gulp-rename');
                        const del = require('del');

                        const path = {
                            js: {
                                src: 'src/js/libs/**/*.js',
                                dest: 'dist/',
                                filename: 'DOMlibrary.js'
                            }
                        };

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

                        // NPM 설치 모듈 : gulp-csslint, gulp-concat-css, gulp-uglifycss
                        // CSS 문법 검사 > 병합 > 압축
                        gulp.task('styles', function () {
                            gulp.src('src/css/**/*.css')
                                .pipe(csslint())
                                .pipe(csslint.formatter())
                                .pipe(concatcss('style.css'))
                                .pipe(uglifycss())
                                .pipe(gulp.dest('dist/css/'))
                        });

                        // JS 문법 검사
                        gulp.task('js:hint', function () {
                            return gulp.src(path.js.src)
                                .pipe(jshint())
                                .pipe(jshint.reporter(stylish));
                        });

                        // JS 병합
                        gulp.task('js:concat', function () {
                            return gulp.src(path.js.src)
                                .pipe(concat(path.js.filename))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 압축
                        gulp.task('js:uglify', function () {
                            return gulp.src(path.js.dest + path.js.filename)
                                .pipe(uglify())
                                .pipe(rename({suffix: '.min'}))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 문법검사 > 병합 > 압축
                        gulp.task('scripts',
                            gulp.series('js:hint', 'js:concat', 'js:uglify')
                        );

                        // Gulp.task()를 사용해 기본(Default) 테스크 정의
                        gulp.task('default',
                            gulp.series('clean', 'scripts')
                        );
                    
                
csslint.reporter() 메소드가 작동하지 않아 검색을 해보았습니다.
https://github.com/xtratio/amocrm-widget-starter-kit/issues/8
위 사이트는 참고 사이트입니다.

이제 [src/css] 디렉터리에 여러 개의 실습용 CSS 파일을 생성한 후 Git Bash에서 gulp styles 명령어를 실행하여 결과를 확인합니다.

깨알 Tip
자바스크립트 업무 프로세스를 나눠 별도의 업무를 정의했던 것처럼 CSS 업무도 동일하게 처리할 수 있습니다.

파일 경로 환경 설정 객체에 CSS 설정 옵션 추가하기
다음을 참고하여 styles 업무를 처리할 설정 값을 파일 경로 환경 설정 객체로 추가하면 쉽게 유지보수를 할 수 있습니다.
                    
                        const gulp = require('gulp');
                        const csslint = require('gulp-csslint');
                        const concatcss = require('gulp-concat-css');
                        const uglifycss = require('gulp-uglifycss');
                        const stylish = require('jshint-stylish');
                        const jshint = require('gulp-jshint');
                        const uglify = require('gulp-uglify');
                        const concat = require('gulp-concat');
                        const rename = require('gulp-rename');
                        const del = require('del');

                        const path = {
                            css: {
                                src: 'src/css/**/*.css',
                                dest: 'dist/css/',
                                filename: 'style.css'
                            },
                            js: {
                                src: 'src/js/libs/**/*.js',
                                dest: 'dist/',
                                filename: 'DOMlibrary.js'
                            }
                        };

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

                        // NPM 설치 모듈 : gulp-csslint, gulp-concat-css, gulp-uglifycss
                        // CSS 문법 검사 > 병합 > 압축
                        gulp.task('styles', function () {
                            return gulp.src(path.css.src)
                                .pipe(csslint())
                                .pipe(csslint.formatter())
                                .pipe(concatcss(path.css.filename))
                                .pipe(uglifycss())
                                .pipe(gulp.dest(path.css.dest))
                        });

                        // JS 문법 검사
                        gulp.task('js:hint', function () {
                            return gulp.src(path.js.src)
                                .pipe(jshint())
                                .pipe(jshint.reporter(stylish));
                        });

                        // JS 병합
                        gulp.task('js:concat', function () {
                            return gulp.src(path.js.src)
                                .pipe(concat(path.js.filename))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 압축
                        gulp.task('js:uglify', function () {
                            return gulp.src(path.js.dest + path.js.filename)
                                .pipe(uglify())
                                .pipe(rename({suffix: '.min'}))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 문법검사 > 병합 > 압축
                        gulp.task('scripts',
                            gulp.series('js:hint', 'js:concat', 'js:uglify')
                        );

                        // Gulp.task()를 사용해 기본(Default) 테스크 정의
                        gulp.task('default',
                            gulp.series('clean', 'scripts')
                        );
                    
                
CSS @import 규칙으로 파일 병합 처리하기
CSS는 @import 규칙을 사용하여 분리된 CSS 파일 코드를 먼저 읽어 들일 수 있습니다.
따라서 스타일을 역할에 따라 모듈별로 관리할 수 있습니다.
하지만 실무에서는 @import 규칙을 거의 사용하지 않습니다.
@import 규칙으로 불러들인 CSS 파일 개수만큼 서버에서 요청(Request)이 늘어나 로딩 속도에 악영향을 미칩니다.
또 병렬 방식이 아닌 직렬 방식으로 다운로드하므로 전체 로딩 시간도 길어집니다.
심지어 인터넷 익스플로러(IE)에서는 다운로드 순서가 다르게 작동하는 문제가 발생합니다.


다시 말해, 다음처럼 각 역할에 따라 분리한 CSS 파일을 웹 문서에 적용할 때는 @import 규칙으로 호출하면 안되고,
HTML 문서에서 <link> 요소를 사용하여 호출해야 합니다. 이처럼 @import 규칙으로 스타일을 관리하는 데는 문제가 있습니다.
하지만 gulp-concat-css 모듈을 사용한 styles 업무를 활용하면 @import 규칙을 사용하는 데 전혀 문제가 없습니다.
@import 규칙으로 호출한 파일을 병합하여 하나의 CSS 파일로 만들기 때문에 문제가 말끔히 해결됩니다.
즉, styles 업무를 사용하면 @import 규칙을 사용한 스타일 문서 모듈에 따른 관리가 실무에서도 가능합니다.
자세한 방법을 알아보겠습니다.

[src/css] 디렉터리에 [modules] 디렉터리를 생성하고, 호출하여 사용할 CSS 파일을 준비합니다.
다음과 같이 [css] 디렉터리에 CSS 파일을 호출한 style.css 파일을 생성합니다. 디렉터리와 파일 준비가 끝났으면 gulpfile.js의 CSS 파일 경로 환경 설정 객체에서 src 속성 값을 다음처럼 style.css 파일로 변경하여 저장합니다.
                    
                        const gulp = require('gulp');
                        const csslint = require('gulp-csslint');
                        const concatcss = require('gulp-concat-css');
                        const uglifycss = require('gulp-uglifycss');
                        const stylish = require('jshint-stylish');
                        const jshint = require('gulp-jshint');
                        const uglify = require('gulp-uglify');
                        const concat = require('gulp-concat');
                        const rename = require('gulp-rename');
                        const del = require('del');

                        const path = {
                            css: {
                                src: 'src/css/style.css',
                                dest: 'dist/css/',
                                filename: 'style.css'
                            },
                            js: {
                                src: 'src/js/libs/**/*.js',
                                dest: 'dist/',
                                filename: 'DOMlibrary.js'
                            }
                        };

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

                        // NPM 설치 모듈 : gulp-csslint, gulp-concat-css, gulp-uglifycss
                        // CSS 문법 검사 > 병합 > 압축
                        gulp.task('styles', function () {
                            return gulp.src(path.css.src)
                                .pipe(csslint())
                                .pipe(csslint.formatter())
                                .pipe(concatcss(path.css.filename))
                                .pipe(uglifycss())
                                .pipe(gulp.dest(path.css.dest))
                        });

                        // JS 문법 검사
                        gulp.task('js:hint', function () {
                            return gulp.src(path.js.src)
                                .pipe(jshint())
                                .pipe(jshint.reporter(stylish));
                        });

                        // JS 병합
                        gulp.task('js:concat', function () {
                            return gulp.src(path.js.src)
                                .pipe(concat(path.js.filename))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 압축
                        gulp.task('js:uglify', function () {
                            return gulp.src(path.js.dest + path.js.filename)
                                .pipe(uglify())
                                .pipe(rename({suffix: '.min'}))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 문법검사 > 병합 > 압축
                        gulp.task('scripts',
                            gulp.series('js:hint', 'js:concat', 'js:uglify')
                        );

                        // Gulp.task()를 사용해 기본(Default) 테스크 정의
                        gulp.task('default',
                            gulp.series('clean', 'scripts')
                        );
                    
                
Git Bash에서 gulp styles 명령어를 실행하면 @import로 호출된 CSS 파일들의 병합이 진행되며,
[dist/css] 디렉터리에 style.css 파일이 생성됩니다.
업무 처리 결과 오류(Error) 메시지가 출력되는데, 문제가 있는 건가요?
화면에 출력된 @import prevents parallel downloads, use <link> instead. 오류 메시지는
@import 규칙을 사용했을 때 발생하는 문제를 gulp-csslint 모듈이 처리 과정에서 발견하여 지적한 것입니다.
이것으로 CSS 파일 검사가 정상적으로 수행되고 있음을 확인할 수 있습니다.

그런데 사실 이 오류 메시지는 styles 업무 처리 과정에서 크게 신경쓰지 않아도 됩니다.
@import로 호출한 파일들을 병합하기 전에 검사한 내용이기 때문입니다.
검사 과정 이후에는 파일들이 병합되기 때문에 @import 규칙을 사용하는 문제는 실제 서비스에서는 아무런 장애가 되지 않습니다.
화면에 출력되는 해당 오류 메시지는 무시합니다.
하지만 업무를 수행할 때마다 표시되는 오류 메시지가 신경 쓰인다면 csslint() 함수에 import 옵션 값을 무시(false)하도록 설정합니다.
더 이상 @import 규칙 문제를 오류로 처리하지 않습니다.
설정 가능한 옵션은 https://github.com/CSSLint/csslint/wiki/Rules-by-ID를 참고합니다.
                    
                        const gulp = require('gulp');
                        const csslint = require('gulp-csslint');
                        const concatcss = require('gulp-concat-css');
                        const uglifycss = require('gulp-uglifycss');
                        const stylish = require('jshint-stylish');
                        const jshint = require('gulp-jshint');
                        const uglify = require('gulp-uglify');
                        const concat = require('gulp-concat');
                        const rename = require('gulp-rename');
                        const del = require('del');

                        const path = {
                            css: {
                                src: 'src/css/style.css',
                                dest: 'dist/css/',
                                filename: 'style.css'
                            },
                            js: {
                                src: 'src/js/libs/**/*.js',
                                dest: 'dist/',
                                filename: 'DOMlibrary.js'
                            }
                        };

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

                        // NPM 설치 모듈 : gulp-csslint, gulp-concat-css, gulp-uglifycss
                        // CSS 문법 검사 > 병합 > 압축
                        gulp.task('styles', function () {
                            return gulp.src(path.css.src)
                                .pipe(csslint({
                                    'import': false
                                }))
                                .pipe(csslint.formatter())
                                .pipe(concatcss(path.css.filename))
                                .pipe(uglifycss())
                                .pipe(gulp.dest(path.css.dest))
                        });

                        // JS 문법 검사
                        gulp.task('js:hint', function () {
                            return gulp.src(path.js.src)
                                .pipe(jshint())
                                .pipe(jshint.reporter(stylish));
                        });

                        // JS 병합
                        gulp.task('js:concat', function () {
                            return gulp.src(path.js.src)
                                .pipe(concat(path.js.filename))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 압축
                        gulp.task('js:uglify', function () {
                            return gulp.src(path.js.dest + path.js.filename)
                                .pipe(uglify())
                                .pipe(rename({suffix: '.min'}))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 문법검사 > 병합 > 압축
                        gulp.task('scripts',
                            gulp.series('js:hint', 'js:concat', 'js:uglify')
                        );

                        // Gulp.task()를 사용해 기본(Default) 테스크 정의
                        gulp.task('default',
                            gulp.series('clean', 'scripts')
                        );
                    
                
CSS 압축하지 않은 파일과 압축한 파일로 출력 설정하기
scripts 업무에서 처리한 것과 유사한 방법으로 styles 업무에서도 압축한 파일과 압축하지 않은 파일을 동시에 출력할 수 있습니다.
다음을 참고하여 압축하지 않은 파일과 이름을 바꿔 압축한 파일이 동시에 출력되도록 설정합니다.
Git Bash에서 gulp styles 명령어를 실행하면, 압축하지 않은 파일과 압축한 파일(style.min.css)로 결과가 처리됩니다.
                    
                        const gulp = require('gulp');
                        const csslint = require('gulp-csslint');
                        const concatcss = require('gulp-concat-css');
                        const uglifycss = require('gulp-uglifycss');
                        const stylish = require('jshint-stylish');
                        const jshint = require('gulp-jshint');
                        const uglify = require('gulp-uglify');
                        const concat = require('gulp-concat');
                        const rename = require('gulp-rename');
                        const del = require('del');

                        const path = {
                            css: {
                                src: 'src/css/style.css',
                                dest: 'dist/css/',
                                filename: 'style.css'
                            },
                            js: {
                                src: 'src/js/libs/**/*.js',
                                dest: 'dist/',
                                filename: 'DOMlibrary.js'
                            }
                        };

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

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

                        // JS 문법 검사
                        gulp.task('js:hint', function () {
                            return gulp.src(path.js.src)
                                .pipe(jshint())
                                .pipe(jshint.reporter(stylish));
                        });

                        // JS 병합
                        gulp.task('js:concat', function () {
                            return gulp.src(path.js.src)
                                .pipe(concat(path.js.filename))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 압축
                        gulp.task('js:uglify', function () {
                            return gulp.src(path.js.dest + path.js.filename)
                                .pipe(uglify())
                                .pipe(rename({suffix: '.min'}))
                                .pipe(gulp.dest(path.js.dest));
                        });

                        // JS 문법검사 > 병합 > 압축
                        gulp.task('scripts',
                            gulp.series('js:hint', 'js:concat', 'js:uglify')
                        );

                        // Gulp.task()를 사용해 기본(Default) 테스크 정의
                        gulp.task('default',
                            gulp.series('clean', 'scripts')
                        );