C++ namespace 이름공간 | C++ 자습서 4

C++ namespace

이 포스팅에서는 C++ namespace(이름공간)에 대해서 알아보겠습니다.

이름공간에 대하여 너무 구애받을 필요는 없습니다. C++에서 이름공간이란 개념은 지역변수, 전역변수, extern 변수, 객체 등과 섞여서 흐릿한 구석이 있습니다.

컴파일러가 식별자(identifier – 변수, 함수 등)를 더 잘 구분하여 오류를 최소화하기 위한 기능입니다. 대형 프로젝트로 갈수록 많은 사람들이 변수를 만들기 때문에 충돌을 방지하기 위한 측면도 있습니다.

이름공간이란 아이디어는 C#, Python 등에도 이어지기 때문에 좀 일반적인 센스로 받아들일 필요가 있습니다.

C++ namespace
C++ namespace

이름공간이란 생소한 단어입니다. 이름공간에 대하여 인사이트를 갖기 위해서는 { } 괄호안에서만 사용되는 지역변수와 이 바깥에서 전역변수에 대하여 알아야 합니다.

지역변수와 전역변수

변수의 범위에서 다룰 내용이지만 잠깐만 보고 가겠습니다.

지역변수는 아래와 같은 변수를 말합니다. int var1은 main 함수안에 있는 지역변수 있니다.

int main() {
	
	int var1;
	
	return 0;
}

규칙을 명확하게 알고 싶으면 아래와 같이 코드를 작성해봅니다. 정수형 var1 이라고 식별자가 다 같은데 이들은 각 지역에 포함된 다른 변수들입니다.

프로그래밍을 하면서 주의할 점은 ‘보이는 그대로 믿지 말라’는 것입니다. var1 과 var1 은 위치에 따라 다른 변수입니다.

int var1;

int main() {
	
	int var1;
	{
		int var1;
		{
			int var1;
		}
	}
	
	return 0;
}

확인을 해보겠습니다. main() 바깥에 있는 것은 전역변수고 나머지는 지역변수입니다.

지역변수의 초기값을 다르게 만들어서 각 지역에서 출력해봤습니다. 어떻게 될까요?

using std::cout;
using std::endl;

int var1 = 0;

int main() {

	cout << var1 << endl;

	int var1 = 1;
	cout << var1 << endl;
	{
		int var1 = 2;
		cout << var1 << endl;
		{
			int var1 = 3;
			cout << var1 << endl;
		}
	}
	cout << var1 << endl;
	cout << ::var1 << endl;
	
	return 0;
}
0
1
2
3
1
0

이 코드를 따라가보면 컴파일러가 어떻게 지역을 나눴는지 볼 수 있습니다. 또 컴파일러의 허점도 알게 됩니다. 마지막 줄에 ::var1 이 의미하는 것은 전역변수의 var1을 의미합니다. :: 이것은 이름공간을 지정하기 위한 연산자입니다. 이것이 없을 때는 현재의 지역에서 식별자(identifier)를 찾습니다.

namespace 이름공간 생성

이름공간은 외부라이브러리에서 주로 가져다가 쓰지만 사용자가 정의하는 것도 가능합니다.

namespace 키워드를 사용해서 지정할 수 있습니다. 이 안에 뭘 넣어도 이름공간:: 의 형식으로 꺼내올 수 있습니다.

아래의 예제 코드는 이름공간을 사용하여 컴파일러에게 어떤 영역에 접근할 것인지 알려주고 있습니다. 결과값을 볼 때 출력 내용과 순서를 보면 알 수 있습니다.

#include <iostream>


using std::cout;
using std::endl;

namespace mySpace1 {
	int var1 = 111;
	void sayHello() {
		cout << "Hello mySpace1" << endl;
	}
}

int var1 = 999;
void sayHello(){
	cout << "Hello Global space" << endl;
}

int main() {

	int var1 = 777;

	sayHello();
	mySpace1::sayHello();
	
	cout << var1 << endl;
	cout << ::var1 << endl;
	cout << mySpace1::var1 << endl;

	return 0;
}
Hello Global space
Hello mySpace1
777
999
111

using namespace

using namespace 의 사용법을 알아봅니다.

#include <iostream>

using std::cout;
using std::endl;

namespace mySpace1 {
	int var1 = 111;
	void sayHello() {
		cout << "Hello mySpace1" << endl;
	}
}

using namespace mySpace1;
int main() {

	sayHello();
	mySpace1::sayHello();	
	cout << var1 << endl;

	return 0;
}
[결과값]
Hello mySpace1
Hello mySpace1
111

using namespace mySpace1을 하게 되면 mySpace1:: 을 붙이지 않고도 이름공간을 사용할 수 있습니다.

만약 지역 변수나 함수의 이름과 같다면 컴파일러는 모호하기 때문에 오류를 냅니다. 이름 공간의 각 변수와 함수의 이름이 겹치지 않도록 관리하는 것은 프로그래머의 몫입니다.

그리고 저위의 using std::cout 을 보면 이제 구조를 알 수 있습니다. using namespace std 는 일괄적으로 그 안에 들어있는 모든 이름을 사용한다는 것이고 cout 처럼 하나의 객체만 뽑아온다면 다른 것들은 건드리지 않고 이것만 사용하겠다고 골라온 것 입니다.

필요한 이름만 가져오는 것이 당연히 현명합니다. 여기서 퉁을 쳐서 using namespace std 를 해버리면 무슨 이름인지도 모르지만 지금 이름을 잡고 있는 겁니다. 물론 컴파일 시 겹치는 것은 확인이 가능하지만 사용하지 않을 라이브러리를 컴파일 단계에 끌어들이는 것은 별로 좋은 방법이 아닙니다.

실제 std 를 확인해보면 iostream, cmath 등 수십개 파일에서 수백개의 이름들을 포함하고 있습니다. 물론 이건 std(Standard) 표준파일이기 때문에 여기서 그닥 문제될 일은 없겠지만 namespace의 동작을 알게되면 찜찜하죠. 그냥 필요할 때 std::cout 처럼 사용하는게 좋습니다.

요약

약간 초반부에 커버하기는 뭐하지만 알고보면 별 내용이 아니기에 namespace 에 대하여 알아봤습니다.

중요한 것은 내가 소소코드를 쓰고 있는 라인이 어떤 영역이고 현재 영역에서 사용가능한 이름공간은 어떤 것이 있나 정도만 체크하면 됩니다.

외부참조

C++ namespace 사용하는 이유

네임스페이스 (C++) | Microsoft Docs

Namespaces – C++ Tutorials (cplusplus.com)

Namespaces in C++ – Tutorialspoint

Namespace in C++ | Set 1 (Introduction) – GeeksforGeeks

Leave a Comment