네임스페이스는 이름이 존재하는 공간과 같다. 우리는 이름이 C로 같은 두 사람을 구분할 때, A 지역에 거주하는 C와 B 지역에 거주하는 C로 구분하기도 한다. 이러한 구분에서 이름이 C로 같은 두 사람이 A와 B라는 서로 다른 지역 (공간)에 존재했기 때문에 우리는 두 사람을 식별할 수 있었다.
복잡한 프로그램을 개발하거나, 협업을 하다보면 전역 범위에 위의 예시와 같이 이름이 같은 변수, 함수, 객체 등을 정의하는 경우가 발생한다. 네임스페이스는 이러한 경우에 발생할 수 있는 충돌을 방지하기 위해 이름이 존재하는 공간을 정의하는 기능을 제공한다.
네임스페이스 기능을 제공하는 대표적인 언어로는 C++와 자바가 있다. C++에서는 아예 namespace라는 키워드를 이용하여 변수, 함수, 객체의 네임스페이스를 지정할 수 있다 [코드 1].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <iostream> namespace A { void add() { std::cout << "call add() from A" << std::endl; } } namespace B { void add() { std::cout << "call add() from B" << std::endl; } } int main() { A::add(); B::add(); return 0; } | cs |
[코드 1] C++의 네임스페이스
자바에서는 패키지 (package)라는 개념을 이용하여 네임스페이스 기능을 제공한다. 다음의 [코드 2, 3]과 같이 이름이 각각 module1, module2라는 패키지에 MyClass라는 동일한 이름의 클래스가 정의되어 있다.
1 2 3 4 5 6 7 | package module1; public class MyClass { public MyClass() { System.out.println("I'm from module1"); } } | cs |
[코드 2] module1 패키지의 MyClass
1 2 3 4 5 6 7 | package module2; public class MyClass { public MyClass() { System.out.println("I'm from module2"); } } | cs |
[코드 3] module2 패키지의 MyClass
[코드 2, 3]과 같이 정의된 MyClass가 있을 때, main 함수에서 MyClass를 이용하기 위해 [코드 4]를 작성하였다.
1 2 3 4 5 6 7 8 9 10 | package exec; import module1.*; import module2.*; public class Main { public static void main(String[] args) { MyClass mc = new MyClass(); } } | cs |
[코드 4] MyClass를 이용하기 위한 main 함수의 내용
자바에서는 [코드 4]와 같이 코드를 작성하면, MyClass를 선언하는 부분에서 어떠한 패키지의 MyClass를 의미하는지가 모호하기 때문에 컴파일 에러가 발생한다. 이러한 모호성을 제거하기 위해서는 import module1.MyClass처럼 명시적으로 어떠한 패키지의 MyClass를 포함할 것인지를 선언해야 한다.
자바스크립트는 C++나 자바처럼 네임스페이스 기능을 위한 별도의 키워드나 개념을 제공하지 않는다. 그러나 자바스크립트의 몇 가지 디자인 패턴을 이용하면, 네임스페이스와 동일한 기능을 수행하는 코드를 만들 수 있다. 아래의 [코드 5]는 자바스크립트의 객체 개념을 이용하여 네임스페이스의 개념을 구현한 것이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var MyModule = {}; var value = 1; function callSender() { console.log('call sender'); } MyModule.value = 5; MyModule.callSender = function () { console.log('I am a sender.'); } window.onload = function () { console.log(value); console.log(MyModule.value); callSender(); MyModule.callSender(); } | cs |
[코드 5] 네임스페이스 MyModule 정의 1
[코드 5]의 실행 결과는 아래의 [그림 1]과 같다. [코드 5]의 2번째 줄에서는 전역적으로 참조가 가능한 value라는 변수를 선언하고, 1이라는 값을 할당하였다. 그 다음, 8번째 줄에서는 MyModule이라는 네임스페이스를 갖는 value라는 변수를 선언하고, 5라는 값을 할당하였다. 4번째 줄과 9번째 줄의 callSender()라는 함수 또한 하나는 전역 참조가 가능하도록, 나머지 하나는 MyModule이라는 네임스페이스를 갖도록 선언하였다.
[그림 1] MyModule 네임스페이스 코드에 대한 실행 결과
자바스크립트에서는 네임스페이스를 구현하기 위해 여러 디자인 패턴을 사용할 수 있다. 아래의 [코드 6]은 [코드 5]에서 네임스페이스 MyModule을 정의하는 코드와 동일하다.
1 2 3 4 5 6 | var MyModule = { value1: 5, callSender: function () { console.log('I am a sender'); } } | cs |
[코드 6] 네임스페이스 MyModule 정의 2
그러나 [코드 5, 6]과 같이 객체의 개념을 이용하여 구현하는 네임스페이스는 객체의 이름이 충돌하는 것과 같이 네임스페이스의 이름 또한 충돌할 수 있다. 이러한 네임스페이스 간의 충돌을 방지하기 위해 [코드 7]과 같이 네임스페이스를 정의할 수 있다. [코드 7]에서는 네임스페이스를 정의하기 전에 기존에 동일한 이름을 갖는 네임스페이스가 존재하는지를 검사하고, 동일한 이름을 갖는 네임스페이스가 없을 경우에만 네임스페이스를 정의한다.
1 2 3 | if (typeof MyModule === 'undefined') { var MyModule = {}; } | cs |
[코드 7] 네임스페이스 간의 충돌 검사 1
위의 [코드 7]을 간소화하면, 아래의 [코드 8]과 같이 작성할 수 있다.
1 | var MyModule = MyModule || {}; | cs |
[코드 8] 네임스페이스 간의 충돌 검사 2
'웹 프로그래밍' 카테고리의 다른 글
[JavaScript] - Web Notification API와 알림 기능 (2) | 2016.09.13 |
---|---|
Java 환경에서 트위터 API를 이용한 SNS 분석 (0) | 2016.09.09 |
[JavaScript] - 자바스크립트와 객체지향 프로그래밍 (0) | 2016.09.04 |
[JavaScript] - 전역 변수의 문제점과 해결 방법 (1) | 2016.09.04 |
[JavaScript] - 코드 블로킹 (Code Blocking) 방지 (0) | 2016.09.04 |