본문 바로가기

C++/C, C++, STL

네임스페이스(Namespace)란?

이 문서의 내용

    네임스페이스란?

    네임스페이스(Namespace)는 직역하면 이름에 대한 공간입니다.

    • 이름은 C++에서 사용되는 변수 함수 구조체 클래스 등에 대한 선언입니다.
    • 공간은 이들에 대한 선언을 관리하는 영역입니다.

    어떤 함수나 변수 등에 대한 이름을 네임스페이스로 정의하는 이유는 이들 이름에 대한 충돌을 방지하기 위함입니다.

    네임스페이스 사용 예시

    다음 예시에서 두 개의 네임스페이스 foobar이 있습니다.

    그리고 동일한 함수 이름 hello()를 선언하고 있습니다.

    이때 외부에서 hello()를 호출할 때 프로그램은 어떤 함수를 호출해야할까? 모호한 상황이 발생합니다.

    #include "foo.h"
    #include "bar.h"
    
    int main()
    {
        // what funcion will be called?
        hello();
        return 0;
    }

    테스트를 위해 두 개의 네임스페이스를 작성합니다.

    foo.h는 함수에서 hello 문자열을 출력합니다.

    #include <iostream>
    
    namespace foo
    {
        void hello()
        {
            printf("hello ");
        }
    }

    bar.h는 함수에서 world! 문자열을 출력합니다.

    #include <iostream>
    
    namespace bar
    {
        void hello()
        {
            printf("world!");
        }
    }

    그리고 이들을 호출하는 main.cpp는 다음과 같이 작성합니다.

    #include "foo.h"
    #include "bar.h"
    
    int main()
    {
        foo::hello();
        bar::hello();
        return 0;
    }
    코드 비고
    Line 1:2 #include "foo.h" foo.h bar.h 헤더 파일을 포함시킵니다.
    #include "bar.h"
    Line 6:7 foo::hello() foo 네임스페이스에서 정의하고 있는 hello() 함수를 호출합니다.
    bar::hello() bar 네임스페이스에서 정의하고 있는 hello() 함수를 호출합니다.
    더보기

    네임스페이스에서 정의하는 함수 등에 접근할 때 사용되는 키워드 ::스코프 분석 연산자(Scope resolution operator)라고 부릅니다.

    프로그램에서 컴파일러가 특정 네임스페이스에 접근하도록 명시적으로 알리는 역할을 합니다.

    프로그램을 실행하고 결과를 확인합니다.

    hello world!

    네임스페이스 접근 간소화

    소스 파일에서 자주 사용되는 네임스페이스는 using 키워드를 사용해 접근을 간소화합니다.

    #include "foo.h"
    #include "bar.h"
    
    using namespace bar;
    
    int main()
    {
        foo::hello();
        hello();
        return 0;
    }
    코드 비고
    Line 4 using namespace bar bar 네임스페이스에 대한 접근을 간소화합니다.
    Line 8:9 foo::hello() foo 네임스페이스에 접근하여 hello() 함수를 호출합니다.
    hello() bar 네임스페이스에서 선언하고 있는 hello() 함수를 호출합니다.
    이때 네임스페이스를 지칭하는 한정자를 사용하지 않습니다.

    네임스페이스의 중첩

    네임스페이스 안에는 또 다른 네임스페이스가 선언 될 수 있습니다.

    마치 클래스 내부에 또 다른 클래스가 선언 될 수 있는 것처럼, 네임스페이스 안에서도 여러 네임스페이스를 구분하여 역할과 성격을 분리하기 위한 목적입니다.

    앞서 예시의 foo.h를 다음과 같이 수정합니다.

    #include <iostream>
    
    namespace foo
    {
        void hello()
        {
            printf("hello ");
        }
    
        namespace man
        {
            void hello()
            {
                printf("hi man ");
            }
        }
    }
    코드 비고
    Line 10:16 namespace man { } foo 네임스페이스 안에 중첩되는 man 네임스페이스를 선언합니다.
    더보기

    C++ 17부터는 중첩된 네임스페이스를 다음과 같이 선언 할 수 있습니다.

    #include <iostream>
    
    namespace foo::man
    {
        void hello()
        {
            printf("hi man ");
        }
    }

    부모 네임스페이스에서 소스 파일을 분리하여 중첩된 네임스페이스를 별도 관리 할 수 있습니다.

    마찬가지로 중첩 네임스페이스를 호출하려면 스코프 분석 연산자(::)를 중첩해 사용합니다.

    foo::man::hello();

    또는 using 키워드를 사용해 중첩된 네임스페이스를 사용합니다.

    #include "foo.h"
    #include "bar.h"
    
    using namespace foo::man;
    
    int main()
    {
        hello();
        return 0;
    }
    더보기

    using 키워드를 사용면 어떤 네임스페이스에서 선언된 것인지 가독성이 떨어집니다. 반면 :: 키워드를 사용하더라도 여러 번 중첩된 네임스페이스에 접근할 때 코드 길이가 길어져 마찬가지로 가독성이 떨어집니다.

    이때 사용하기 위한 것이 네임스페이스 별칭입니다.

    #include "foo.h"
    #include "bar.h"
    
    namespace hi = foo::man;
    
    int main()
    {
        hi::hello();
        return 0;
    }

    별칭을 선언하면 네임스페이스를 명시적으로 사용하면서 중첩된 길이를 간소화 할 수 있다는 장점이 있습니다.

    정리 및 복습

    • 네임스페이스(Namespace)변수 함수 구조체 클래스 등에 대한 선언을 별도 공간으로 구분합니다.
    • 네임스페이스를 사용하면 분업과 라이브러리 사용 등에 있어서 이름의 충돌을 회피 할 수 있습니다.
    • 네임스페이스는 namespace 키워드로 선언합니다.
    • 네임스페이스에 명시적으로 접근하려면 스코프 분석 연산자(::)를 사용합니다.
    • 네임스페이스를 소스 파일에서 전역 접근하려면 using namespace <네임스페이스 이름>을 사용합니다.
    • 네임스페이스는 중첩 될 수 있습니다.