JS 모듈 관리(Javascript Modules Management)
RequireJS 는 자바스크립트 파일/모듈 로더입니다.
브라우저 환경에서 최적화되어 있으나 Node 와 같은 다른 자바스크립트 환경에서도 사용될 수 있습니다.
그렇다면 모듈 로더는 무엇인가?!
JAVA 나 그 밖의 다른 서버사이드 언어는 파일을 include 하여 사용할 수 있으나 자바스크립트 자체로는 file01.js 파일로부터 다른 file02.js 파일을 include 할 수 있는 방법이 없습니다. 하지만 이를 해결할 수 있는 여러가지 방법이 존재하고 있으며 이러한 방법을 통해 자바스크립트 파일들 서로 간에 의존성/종속성 관리를 할 수 있습니다.
여러가지 방법 중의 하나인 RequireJS 와 같은 모듈 방식의 스크립트 로더를 사용한다면 웹 어플리케이션의 품질과 속도, 최적화를 향상 시킬 수 있습니다.
이 포스팅에서는 Javascript 관리와 성능을 향상시키기 위한 모듈 관리방법중에 RequrieJS 에 대해 알아보고자 합니다.
그리고 이 글을 읽기에 앞서 Client/Sever Side Javascript 표준화를 위한 CommonJS, AMD 에 대해 알아볼 것을 추천드립니다.
다음의 코드를 간단히 살펴보도록 하겠습니다.
<!DOCTYPE html>
<html>
<head lang="ko-KR">
<meta charset="UTF-8">
<title>Require.js 시작하기</title>
<script src="require.js"></script>
<script type="text/javascript">
// jQuery 를 load 한 후 실행한다.
require(["http://code.jquery.com/jquery-1.11.1.min.js"], function() {
// CDN 으로부터 jQuery 가 로드된 뒤에 아래의 코드가 실행된다.
alert($().jquery);
});
</script>
</head>
<body>
</body>
</html>
http://requirejs.org/docs/download.html 에서 require.js 를 다운받아 import 를 해주고 require 함수를 사용하여 무엇(여기선 jQuery)인가를 로드하면 로드를 하기 전에 또 거기에 의존성이 있는 파일, 즉 require 로 로드할 의존성 모듈들을 먼저 가져온 후에 콜백함수가 실행되는 방식입니다
물론 RequireJS 를 위와 같이 작성하지는 않습니다.
위와 같은 방식을 사용하게 되면 jQuery 가 실행될 때 전역 네임스페이스가 $ 변수로 오염되기 때문입니다. 이는 다른 라이브러리와의 충돌이나 두 개의 다른 버전의 제이쿼리를 사용할 수 없을 것입니다.
이는 모듈 로더인 RequireJS 를 사용하려는 목적에 벗어나는 일이니까요.
일반적인 자바스크립트 패턴의 사용은 편하기는 하지만 이 편안함에 너무 의존하다보면 돌이킬 수 없는 스파게티 코드나
중복 코드 발생이 빈번해 질 수 있기 때문에 모듈 프로그래밍이 필요합니다.
RequireJS 는 일반적인 스크립트 패턴에서 발생할 수 있는 문제점에 대한 대안이 될 수 있으며, RequrieJS 를 사용함으로써 모듈 생성/호출 등 관리를 통해 좀 더 체계적인 프로그래밍을 가능하게 해 주며 브라우저 지원 또한 IE 6 이상을 지원하고 있습니다.
RequireJS 의 모듈 패턴은 일반적으로 스크립트를 작성하는 패턴과는 달리 전역 네임스페이스의 오염을 피할 수 있는 별도의 컨텍스트인 한정된 범위에서 객체를 선언하여 사용하는 점에서 차이점이 있습니다.
모듈은 해당 모듈의 의존(dependancy) 목록을 명시할 수 있으며 전역객체에 대한 참조없이 의존 모듈 상의 객체를 함수의 인자(args)로 받음으로써 핸들링할 수 있게 해줍니다.
Usage RequireJS (기본적인 사용법)
RequireJS 다운로드 및 설치
RequireJS 홈페이지에서 다운로드를 하거나 아래와 같이 npm 을 이용하여 다운로드 받습니다.
$ npm install requirejs
다음 index.html 파일을 아래와 같이 구성합니다.
index.html 파일
<!DOCTYPE html>
<html>
<head lang="ko-KR">
<meta charset="UTF-8">
<title>Require.js 시작하기</title>
<script>
// Require.js 환경설정(Configuration)
// http://requirejs.org/docs/api.html#config
var require = {
// index.html 기준, 기본 위치 지정
baseUrl: "www/js/"
};
// 이와 같이 head 에 인클루드 하지 않고 main.js 에서 환경설정들을 해주는 것이 적당하다.
</script>
<!--
data-main 속성에 설정된 JS 파일은 비동기 호출됩니다.
(※ 파일 경로는 Require.js가 위치한 baseUrl 기준: http://requirejs.org/docs/api.html#jsfiles)
-->
<script src="js/libs/require.js" data-main="js/main"></script>
<!-- main 속성을 설정하여 RequirJS 가 로드된 후 바로 로드해서 실행해줄 자바스크립트 파일을 지정해줍니다. -->
</head>
<body>
<p>main.js 가 DOMContentedLoaded, Load 된 이후에 호출되고 있다.</p>
</body>
</html>
위와 같이 RequrieJS 의 명세서를 따라서 data-main 속성을 설정해 주어 require.js 가 로드된 후 바로 로드(호출)될 스크립트 파일을 지정해 주는 방식입니다.
위의 코드에서는 requrie.js 파일이 로드된 후에 바로 main.js 파일을 호출해서 실행하게 됩니다.
data-main 의 값은 ".js" 가 생략 가능하며, data-main 의 main 은 require 형식의 문법(약속·규약)입니다.
그리고 main.js 파일은 아래와 같이 작성할 수 있습니다.( main.js 는 custom)
main.js 파일
/**
* --------------------------------
* RequireJS 환경 설정 (기본 설정)
* --------------------------------
*/
requirejs.config({
/**
* [ baseUrl 설정 ]
* JavaScript 파일이 있는 기본 경로를 설정한다.
* 만약 data-main 속성이 사용되었다면, 그 경로가 baseUrl 이 된다.
* 환경설정해 주기 위한 main.js 가 위치한 기준 디렉터리의 루트를 설정해 줍니다.
*/
baseUrl : 'js', // 이 곳 환경설정에서는 'js' 라는 폴더를 기본 폴더로 설정합니다.
/**
* [ paths 설정 ]
* path 는 baseUrl 아래에서 직접적으로 찾을 수 없는 모듈명들을 위해 경로를 매핑해주는 속성입니다.
* "/"로 시작하거나 "http" 등으로 시작하지 않으면, 기본적으로는 baseUrl 에 상대적으로 설정하게 됩니다.
* 그리고 아래 exam, jQ 와 같이 별칭(alias)을 설정하여 사용하고 또한 스크립트 파일(모듈)의 .js 확장자는 붙여주지 않습니다.
* 위와 같은 형태로 설정한 뒤에, define 에서 "exam/module" 로 불러오게 되면,
* 스크립트 태그에서는 실제로는 src="aaaa/bbbb/module.js" 로 설정되게 됩니다.
* path 는 또한 아래와 같이 특정 라이브러리 경로 선언을 위해 사용될 수 있는데,
* path 매핑 코드는 자동적으로 .js 확장자를 붙여서 모듈명으로 매핑됩니다.
* 정리 : 모듈의 별칭(Alias)을 설정하고 모듈의 단축 경로를 지정합니다.
*/
paths : {
"exam": "aaaa/bbbb",
// 뒤에 js 확장자는 생략한다.
'jquery': 'libs/jquery-1.11.3.min',
'angular': 'libs/angular/angular-1.0.4'
},
/**
* AMD 를 지원하지 않는 JS 라이브러리 AMD 호환 설정
* shim 설정 (두 사물사이를 연결해주는 끼움쇠) html5Shim 과 같은 것입니다.
* @type {Object}
* [ shim 설정 ]
* AMD 방식을 지원하지 않는 라이브러리의 경우 아래와 같이 shim 을 사용해서 모듈로 불러올 수 있습니다.
* 참고 : http://gregfranko.com/blog/require-dot-js-2-dot-0-shim-configuration/
*/
shim:{
'angular':{
deps: ['jquery'], // angular 가 로드되기 전에 jquery 가 로드되는 것을 의미합니다
// 만약에 angular 가 jQuery 가 필요한 라이브러리라면 의존모듈을 설정해 주는 것입니다.
exports:'angular' // 로드된 angular 라이브러리는 angular 라는 이름의 객체로 사용할 수 있도록 해줍니다.
},
'modernizr' : {
exports : 'Modernizr' // 모더나이저의 클래스가 Moderizr 이므로 Modernizr 를 등록합니다..
},
'detectizr' : {
exports : 'Detectizr', // 디텍타이저의 클래스는 Detectizr 입니다.
// deps(dependencies 의 약어) 의존 모듈을 등록합니다.
// Detectizr 는 Modernizr 의 플러그인으로써 Modernizr 에 의존하는 모듈인 셈입니다.
// paths에 등록된 별칭을 등록합니다.
deps : ['modernizr']
}
}
});
/**
* ----------------------------------------------
* requireJS 를 활용하여 모듈을 호출,로드하는 방법
* ----------------------------------------------
*/
requirejs( [
/**
* 디펜던시(의존 모듈)를 콜렉션 타입으로 설정하고,
* 이 의존 모듈들이 먼저 로드 된 뒤에 아래 콜백함수가 수행됩니다.
*/
'jquery', // config 에 미리 선언해둔 path 의 별칭(alias),
// jQuery 는 AMD 방식을 지원하기 때문에 이렇게 로드해도 jQuery 또는 $ 로 호출할 수 있습니다.
'angular' // config 에 미리 선언해둔 path,
],
/**
* dependency 로드 뒤 콜백함수를 설정
* 로드 된 디펜던시(의존 모듈)들은 콜백함수의 인자로 넣어줄 수 있습니다.
*/
function ($, angular) {
// 이 콜백 함수는 위에 명시된 모든 의존 모듈들이 모두 로드 된 후에 호출되게 됩니다.
// 주의해야할 점은, 디펜던시 로드 완료 시점이 페이지가 완전히 로드되기 전 일 수도 있다는 점입니다.
// 이 콜백함수는 생략할 수 있습니다.
// 페이지가 완전히 로드 된 뒤에 실행
console.log($ === jQuery); // true 가 출력된다.
$('body')
.addClass('assign-jquery')
.height(window.innerHeight)
.attr('data-body', 'root');
}
);
/**
* 의존 모듈을 불러오지 않을 경우의 사용 방법
* DOMScript Code
*/
require([], function() { // 의존 모듈이 없으므로 콜렉션(배열)을 empty 로 설정
var body = document.body;
body.classList.add('no-assign-jquery');
body.style.height = window.innerHeight + 'px';
body.setAttribute('data-body', 'root');
});
main.js 에서 require.config 를 통해 requireJS 의 환경 설정을 셋팅할 수 있습니다.
위와 같은 설정 이 외에도 다양한 옵션들이 존재하는데, 아래의 requireJS 사이트를 참고하면 해당 옵션들에 대한 자세한 내용을 살펴볼 수 있습니다.
http://requirejs.org/docs/api.html
모듈 호출방법에 대해서 다음 포스팅에서 좀 더 살펴보도록 하겠습니다.
'Web Tech > RequireJS' 카테고리의 다른 글
MVC requireJS - 자바스크립트 모듈 로더 (0) | 2016.01.27 |
---|---|
RequireJS 의 모듈 (431) | 2016.01.25 |
RequireJS - AMD의 이해와 개발 (0) | 2015.06.11 |
javaScript 모듈의 양대 산맥,CommonJS vs AMD (0) | 2015.06.11 |