자바스크립트 네임스페이스(javascript namespace)
자바스크립트는 변수의 선언 및 자용이 자유롭고 느슨합니다. 빠른 프로토타이핑을 가능하게 하고 반대로 디버깅을 할 때 미치게 만드는 요소이기도 합니다. 개인적으로는 작업할 때 간단한 로직 구성은 필요할 때마다 선언하고 사용하지만, 다른곳에서 사용할 가능성이 있는 경우에는 가능하면 하나의 네임스페이스를 구성해서 사용합니다.
네임스페이스의 필요성
다음과 같은 코드가 있습니다.
var x = 100; function x(){ console.log("inner"); }; x(); // TypeError: number is not a function
자바스크립트는 느슨한 언어이기 때문에 타입 체킹(type checking)은 동적으로 합니다. 그러면 x라는 변수에 정수형 값을 넣었다가 함수로 덮어 쓰고 실행이 될까요?
실제로 코드를 실행시켜보면 오류가 납니다. 숫자는 함수가 아니라는 문구와 함께요. 물론 이런 코드를 실제로 일부러 짜지는 않겠지만 어쩌다보니 변수명과 함수명이 겹치기라도 하면 난감하게 됩니다. 따라서 이런 경우를 방지하려면 다음처럼 작성해야 합니다.
var x = 100; x = function(){ console.log("inner"); }; x(); // inner
위와 같은 코드도 해결책이 될 수 있지만 x는 언제든지 누군가가 사용 가능한 변수입니다. 따라서 더 좋은 방법은 네임스페이스를 만드는것이죠. 다음처럼요.
var x = 100; var myLib = {}; myLib.x = function(){ console.log("inner"); }; myLib.x(); // inner
더 깔끔하게 myLib를 변경해 봅시다.
var myLib = { x:function(){ console.log("inner"); } }; myLib.x(); // inner
좋습니다. 이제 myLib 변수 안에 x 함수도 넣었습니다. 그런데 여기에 함수 y를 추가하고 싶은데 이건 외부에서 직접 사용하지 않게 하고 싶어요. 그러면 어떻게 해야 할까요?
익명 함수 & 즉시 실행 함수
var myLib = (function(){ var y = function(){ /* this is private func. */ }; var x = function(){ console.log("inner"); y(); // can to execute y func in namespace }; return{ x:x } })(); myLib.x(); // inner myLib.y(); // undefined is not a function
갑자기 코드가 많이 바뀌었지만 차근차근 이해해 보면 됩니다. 위의 코드를 실행해 보면 x 함수는 외부에서 실행 가능하지만 y 함수는 외부에서 실행이 안됩니다. 하지만 같은 네임스페이스 내부에서는 호출이 가능합니다.
이런 코드를 만들기 위해선 익명 함수(anonymous function)을 알아야 합니다.
익명 함수(anonymous function)
익명 함수는 이미 자바스크립트를 공부 해봤다면 자주 볼 수 있습니다. 예를 들면 다음과 같은겁니다.
var x = function(){};
우측에 function 키워드가 붙었지만 변수명은 없습니다. 이런 것을 익명함수라고 합니다. 하지만 이 코드만 따로 실행 시키면 오류가 납니다.
function(){}; // SyntaxError: Unexpected token (
이렇게 말이죠. 따라서 적절한 변수에 할당을 해야 합니다. 하지만 변수에 할당하지 않고 익명 함수를 실행 시키고 싶을 때가 있겠죠. 그럴때는 즉시 실행 함수 표현식(Immediately-invoked function expression)을 사용합니다.
즉시 실행 함수 표현식(Immediately-invoked function expression)
주로 다음처럼 사용합니다.
(function(){/* code */})();
code로 주석 처리 된 부분에 한 번 실행할 코드를 넣어두면 해당 코드를 실행합니다. 하지만 변수에 할당 하지는 않았기 때문에 접근은 요원합니다.
다시 뜯어보기 & 접근 제어
그러면 다시 최종 코드를 가져와서 살펴보면 이젠 이해가 될겁니다.
var myLib = (function(){ var y = function(){ /* this is private func. */ }; var x = function(){ console.log("inner"); y(); // can to execute y func in namespace }; return{ x:x } })(); myLib.x(); // inner myLib.y(); // undefined is not a function
익명 함수 및 즉시 실행 함수 표현식을 이용해서 myLib 이라는 변수에 할당을 한거죠. 이제 내부/외부에 공개를 제어하는 것은 어떻게 할까요?
소스 코드 하단의 return 키워드를 보시면 됩니다. 이곳이 외부에서 직접 접근할 함수를 제어합니다. 심지어 별칭(alias) 설정도 가능합니다. 예를 들면 다음처럼요. 외부에서 z라는 이름으로 함수를 실행시키면 내부에서 x함수로 실행 시켜 결과를 줄 수 있습니다.
var myLib = (function(){ var y = function(){ /* this is private func. */ }; var x = function(){ console.log("inner"); y(); // can to execute y func in namespace }; return{ x:x, z:x } })(); myLib.x(); // inner myLib.z(); // inner myLib.y(); // undefined is not a function
return 시킬 객체(object)에다가 key:value 형식으로 묶어주면 되는데 key는 외부에서 접근할 함수명이 되고 value값은 네임스페이스 내부의 함수명이 됩니다. 물론 인자값이 있어도 관계 없습니다. 인자값이 여러개더라도 이름만 명시하면 됩니다.
Closing Remarks
어쩌다보니 포스팅이 길게 써졌습니다. 그말인즉슨 두서가 없다는 말입니다. -_-; 나중에 보완해야겠지만 혹시라도 지적하실 점 있으면 즉시 수정토록 하겠습니다.