이름 공간이란 다소 생소한 개념이다. C 언어에는 존재하지 않는 개념이기 때

문이다. 그러나 어려운 개념은 아니다. 이름공간이란 이름을 지니는 공간이라

는 뜻이다. 말 그대로 특정영역(공간)에 이름을 붙여주기 위한 문법적 요소이

다.

1] 등장 배경

 프로그램이 대형화되어 가면서 등장하기 시작한 문제는 이름의 충돌이다 .예

를 들어서 은행 관리 시스템을 개발하는데 있어서 세 개의 회사가 참여를 한다.
각 회사의 이름은 A, B, C 이다. 이들은 규모가 큰 관계로 일을 독립적으로 진

행하기로 하였다. 그러기 위해서는 구현해야 할 부분도 적절히 나눴다. 이제 6

개월 뒤 다시 모여서 하나의 프로젝트를 완성하기로 약속을 한다.

 6개월이라는 시간이 흘렀다. 이제 각각의 회사가 구현한 모듈을 하나로 묶고

부족한 부분을 완성 할 때가 되었다. 그런데 문제가 생기고 말았다. A라는 회사

에서 정의한 함수의 이름과 B라는 회사에서 정의한 함수의 이름이 같은 것이

아닌가! 이름 충돌이 나지 않도록 미리 약속이라도 할 것을 그랬다는 후회가 든

다. 이제는 전쟁이다! 이름하나 바꾸는 것이 어디 쉬운 일인가? A  회사의 팀장

과 B 회사의 팀장이 서로 싸우기 시작한다. 물론 싸움의 요는 이거다. " 저희가

무지 바쁘거든요? 당신네 회사에서 양보를 조금 해 주셔야 하게습니다." 그런데
문제는 산 넘어 산이다. C 라는 회사에서는 자신들이 맡은 부분을 구현하는 과

정에서 다른 회사에서 구현해 놓은 함수들을 사용했는데, 이 함수들의 이름이

회사A, B에서 구현해 놓은 함수의 이름과 또 충돌이 나는 것이 아닌가? 결국 이
프로젝트는 실패로 돌아가고 말았다.

이러한 문제를 해결하기 위해서 이름공간(namespace) 이라는 문법이 C++ 표

준에 새롭게 포함되었다.

2] 기본 원리

 한 집에 철수 라는 이름을 지니는 사람이 두 명 살고 있다면 이는 문제가 된다.
" 철수야!" 라고 부르면, 어떤 철수를 말하는지 구분 지을 수 없기 때문이다. 그

러나 서로 살고 있는 집이 다르다면 문제될 것이 없다. 201호에 사는 철수와

202호에 사는 철수는 구분 지을 수 있기 때문이다.  이것이 이름 공간의 기본 원

리이다.  다음 예제는 앞에서 이야기한 문제점을 간략화해서 코드로 옮겨 놓은

것이다. A와B라는 이름의 회사가 구현한 프로그램 모듈을 하나의 완성된 프로

그램으로 옮기는 과정에서 이름 충돌이라는 문제가 발생하였다.

 #include <iostream>

 void function(void)
{
      std::cout << "A.com에서 정의한 함수 " << std::endl;
}

void function(void)
{
      std::cout << "B.com에서 정의한 함수 " << std::endl;
}

 int main(void)
{
       function();
       return  0;
}

 위의 예제에는 A.com 이라는 회사에서 정의한 함수와 , B.com 이라는 회사에

서 정의한 함수의 이름이 같다. 따라서 컴파일 시 문제를 일으킬 것이다. 둘다

필요한 기능의 함수라서 어느것 하나를 뺄 수도 없는 상황이다. (물론 그렇다고
가정만 하자) 

다음 예제에서는 이름 공간을 정의해서 문제를 해결하고 있다. 일단 위의 예제

와 어느 부분이 달라졌는지 비교해 보자.

#include <iostream>

namespace A_COM
{
       void function(void)
       {
               std::cout << "A.com에서 정의한 함수 " << std::endl;
       }
}

namespace B_COM
{
        void function(void)
       {
                std::cout << "B.com에서 정의한 함수 " << std::endl;
        }
}

int main(void)
{

      A_COM:: function();

      B_COM:: function();

       return  0;
}

 위의 예제를 보면 namespace 라는 키워드가 등장한다. 이는 이름 공간을 구

성하겠다는 의미다. 즉 "namespace A_COM " 이라는 선언은 A_COM이라는

이름의 공간을 구성하겠다는 의미가 되며, 이름공간의 범위는 이어서 등장하는
중괄호를 통해서 지정된다. 조금 더 쉽게 이야기를 하면, " 특정 영역(공간)의

범위를 지정하고 이름을 붙여준 것" 이다. 이름 공간이 다르면 같은 이름의 변

수나 함수의 선언이 허용 된다. 하지만 한가지 주의할 것은 이름 공간 내에 선

언되어 있는 변수나 함수에 접근하는 방법이다. 다음과 같은 선언이 필요하다.

A_COM::function(); 

위 코드에서 :: 연산자를 가리켜 " 범위 지정 연산자(scope resolution

operator) " 라 한다. 즉 이름공간의 범위를 지정할 때 사용하는 것이다. 따라서

위 그림과 같은 선언은 다음과 같은 의미를 지니게 된다. 

" A_COM 이라는 이름 공간안에 선언되어 있는 function 함수를 호출하라"

 이렇듯 이름 공간 안에 선언되어 있는 변수나 함수에 접근하기 위해서는 범위

지정 연산자를 사용해서 선언되어 있는 이름공간을 지정해 줘야한다.

참고) 위의 예제들에서는 하나의 이름공간 안에 하나의 선언 및 정의만을 담고

있지만 실제로는 둘 이상의 선언 및 정의를 담을 수 있고 또 그것이 더 일반적

이다.

3] std::cout, std::cin, std::endl

 지금까지 입력 및 출력을 하고자 하는 경우에는 std::cout 과 std::cin을 사용해
왔다. 이것의 정체는 아직 모르지만 사용법만은 알고 있다. 그런데 이제는 조금
이해가 될 것이다. :: 연산자가 어떠한 의미를 지니는지 이해 했기 때문이다.

std::cout은 무슨 의미인가? std라는 이름공간 안에 존재하는 cout을 참조하겠

다는 의미이다. 물론 우리는 아직 cout의 정체를 모르고 있다. 마찬가지로

std::cin은 std라는 이름 공간 안에 존재하는 cin을 참조하겠다는 의미로 사용

된다. 아마도 다음과 같은 가정을 할 수 있을 것이다. 헤더파일 iostream에 선

언되어 있는 cout, cin, 그리고 endl은 std 라는 이름공간 안에 선언되어 있다는
결론을 내릴 수있다. 이름 충돌을 막기 위해서 c++표준에서 제공하는 다양한 함

수나 변수들을 이름공간 std 안에 선언 및 정의 했기 떄문이다.

4]using

이제 cout, cin 그리고 endl을 참조할 때 마다  " std:: " 을 앞에다 붙여줘야 하

는 이유에 대해서 알게 되었다. 그리고 이 일이 여간 귀찮은 것이 아니라는 생

각도 들기 시작한다. 오히려 접근하고자 하는 이름공간에 대한 선언이 불 필요

한 과거의 표준이 더 맘에 끌리기도 한다. 하지만 걱정하지 말자. 추가적인 선

언 하나만으로도 여러분의 이러한 불만사항을 해소할 수 있으니 말이다.

Posted by 바람처럼..
|