본문 바로가기

프로그래밍(TA, AA)/자바스크립트

[자바스크립트] 압축(Minify) / 난독화(Uglify)

자바스크립트 관련 구글링을 하다 발견한 git 페이지(https://github.com/nhnent/fe.javascript/)입니다. javascript 개발하실때, 참조하시면 많은 도움이 될것 같습니다.  오늘 포스팅은 위 페이지에서 압축과 난독화 세션을 공부 겸 정리해 두려고 합니다. 모든 상세한 내용은 위의 링크를 따라가셔서 확인 바랍니다.


그외 참고 사이트

https://velopert.com/3421

https://joshua1988.github.io/web-development/webpack/caching-strategy/



압축과 난독화


 - 서비스에서 공통으로 사용되는 주요 소스 코드들은 별도의 파일로 분리하여 사용

 - 코드의 재사용, 캐시 적용, CDN 사용 등의 장점

 - 코드 압축은 최소의 노력으로 큰 효과를 볼 수 있는 최적화 방법중 하나.

 - 파일의 용량이 감소하며, 민감한 코드를 알아보기 어렵게 만들 수 있다

 - 경우에 따라서는 스크립트의 수행 속도에도 영향을 미침

 - 설정에 따라 압축한 소스로도 디버깅을 위한 Source Maps 기능을 사용 가능.



압축(Minify)


압축은 전체 소스코드 중 아래와 같은 경우를 제거하는 작업을 말합니다.

 - 불필요한 줄바꿈, 공백 밑 들여쓰기

 - 짧게 쓸 수 있는 긴 구문(줄일 수 있는 if 구문, 형 변환 축약 등)

 - 스코프 내 사용하지 않는 변수

 - 주석

 - 경우에 따라, console.log, debugger 등의 디버깅용 구문 또는 메서드 호출

 - 경우에 따라, 무의미한 메서드 호출 및 루프(Google Closure Compiler 사용하여 적용)



난독화(Uglify)


 - 자바스크립트 코드 자체를 분석하기 어렵게 만드는 과정

 - 난독화를 했다고 보안처리 없이 중요 정보나 루틴을 자바스크립트에 넣는 것은 매우 위험

 - 변수명, 함수명 치환에서부터 자바스크립트의 일부 루틴을 문자열로 바꿔 변수에 담고 뒤섞는 단계 등 여러 단계 존재

 - 난독화의 단계를 높일 수록 루틴을 알아보기 어렵게 만들 수 있음

 - 변수, 함수명 등이 줄어 용량이 감소하지만 난독화 단계를 높일수록 코드를 해석하고 실행하는 속도가 느려질 수 있으므로, 프로젝트에 맞게 선택하여 적용하는 것이 좋음



압축 도구


- CLI 형태의 바이너리가 제공되며, 다른 인자없이 스크립트를 인자로 넘길 경우 압축과 난독화 동시 진행

 - 프로젝트 상황에 따라 압축/난독화의 정도를 조절하는 등 세부사항을 조절할 필요가 있음



Google Closure Compiler

 - Google Closure Compiler는 별도의 API를 이용하여 소스를 압축하고, jar 파일을 다운받아 사용 가능

 - Google JavaScript Style Guide에 맞춰 개발했을 때 코드 최적화 가능

 - 추가로 Style Guide에 맞는 코드 변환 및 Style Fixer도 제공


java -jar compiler.jar --js hello.js --js_output_file hello-compiled.js


UglifyJS

 - 현재 주요 자바스크립트 라이브러리에서 가장 많이 쓰이는 소스 압축 도구

 - Node.js 기반으로 개발되어 다른 Node.js 모듈들과의 연계 좋음

 - Google Closure Compiler보다 방대한 양의 상세 옵션 제공


npm install -g uglify-js


uglifyjs hello.js -o hello.min.js




압축 시 유의점


코드 압축시, 모든 들여쓰기와 공백이 제거되고, 전체 코드가 한줄로 병합됩니다. 원본 코드에서 들여쓰기, 공백, 세미콜론, 콤마, 대괄호 등이 바르게 사용되지 않았을 경우 압축된 코드가 정상적으로 동작하지 않을 수 있습니다.


자바스크립트는 명시적으로 수행되는 컴파일 과정이 없어 이런 오류를 사전에 알아내는 것은 쉽지가 않습니다.


JSHint와 같은 정적 분석 도구를 사용하면 사전에 문제될만한 코드를 검출해낼 수 있습니다. 또한 하드 코딩된 메서드명 또는 변수명은 난독화 과정에서 아래와 같은 문제를 일으킬 수 있습니다.

// before uglify
var myObj = {
	test: function() {}
	}
};
myObj['test']();

// After Uglify
// myObj.test가 b로 변경되었지만, 하드 코딩된 'test'는 변경되지 않음
var a={b:function(){}};a['test']();


난독화 도구는 하드코딩된 코드를 처리할 수 없으므로, 피하는 것이 좋습니다. 혹은 mangle 옵션을 이용하여 특정 이름의 치환을 막을 수 있습니다. UglifyJS에서는 -m 옵션으로 제공되고 있습니다.



SourceMaps


 - SourceMaps은 압축된 코드와 압축 전의 코드를 Base64 기반으로 매핑한 데이터를 의미

 - 브라우저가 지원할 경우, 압축된 Base64 내용을 원본과 매핑시켜 압축된 코드를 원본처럼 풀어서 보여주거나, 디버깅이 가능하게 하는 등의 기능을 제공


대부분의 압축도구는 SourceMaps를 지원하지만 아직까지 완벽하게 동작하지는 않습니다. BreakPoint가 제대로 걸리지 않는다던가, SourceMaps 파일이 일정크기 이상 커질 경우 인코딩 문제가 발생하는 등 해결되어야할 문제들이 남아있습니다.


SourceMaps 생성

SourceMaps의 생성은 간단하며, 아래는 Google Closure Compiler 사용시 명령어 입니다.


java -jar compiler.jar --js example.js --create_source_map ./example-map --js_output_file example-compiled.js


UglifyJS도 아래와 같이 SourceMaps을 생성할 수 있으며, Google Closure Compiler 보다는 많은 생성옵션을 제공합니다.


uglifyjs hello.js -o hello.min.js --source-map hello.min.js.map --source-map-root http://foo.com/src