네임스페이스는 C#에만 있는 것은 아니고
C++, 파이썬 등 다른 OOP 언어들에도
탑재되어 있는 개념입니다.
뭐 자바의 package 등 이름은 다르더라도
비슷한 개념도 있는데 중요한 질문은
이 네임스페이스(namespace)가
왜 이렇게 많이 나오냐는 말이지요.
특히 C#은 namespace를 중요시 하는 것을
알 수 있는데 기본적으로 namespace로
클래스 그룹을 분류하기 때문입니다.
최근에는 C#에 최상위문 개념이 도입되서
그냥 파일에서 코드를 작성하기도 하지만
dotnet의 기본 템플릿에는 namespace가
설정되어 있습니다. 이것의 비판은 간단한
코드를 쓰는데도 너무 길다는 것이었지요.
코드의 길이를 비교할 때는 hello world를
화면에 출력하는데 얼마나 코드가 필요하냐?
로 봐도 어느정도 감이 옵니다.
파이썬은 print("Hello World") 지만
C는 int main () 함수 안에 써야 되고
C#은 한개의 namespace와
한개의 class 한개의 Main 메소드가
나와야지 비로소 Hello World 를
콘솔에 출력할 수 있습니다.
최상위문 개념이 나와 대충 스크립트
파일처럼 쓸 수도 있지만 MSDN 조차도
초보자들 학습용이나 테스트 용으로
쓰기를 권장하고 있습니다.
결국 제대로된 앱을 만들기 위해서는
namespace가 풀로 필요하다는 것 입니다.
자 그러면 C#의 namespace를 본격 알아보겠습니다.
namespace는 같은 그룹의 클래스를 묶는
도구입니다. 직역하면 '이름공간'인데
약간 어색하지만 뜻을 생각해보면 맞긴합니다.
namespace 는 이름이 모인 공간입니다.
그냥 모인게 아니라 의미가 있게 모여있다.
처음부터 사용했던 Console.WriteLine 메소드는
System 이름 공간에 소속된 Console 클래스의
메소드입니다. System.Console을 보면
namespace가 System 입니다.
그렇다면 Console만 System 인가?
당연히 그렇지 않습니다.
System은 .NET의 중요한 BCL이고
관련된 클래스는 많습니다.
예들 들어서 Random 클래스도
System에 속해있습니다.
이렇게 많은 클래스들이 System 이란
이름공간에 모여있어서 이들을 사용하려고
그동안 using System 으로 소스코드가
시작했던 것 입니다.
참고로 System은 .NET 플랫폼의 BCL(Base Class Library)로
C#컴파일러에서 CIL로 변환되고 CLR(공용언어 런타임)에서
사용되기 때문에 Visual Basic.NET 등 다른 언어로도
.NET 런타임에서 사용할 수 있습니다.
(런타임 버전과 맞아야함)
쉽게말하면 System 클래스를 사용하는
프로그래머는 헤더에 넣는 값을 알고 있으면 됩니다.
권장되는 방식은 아니지만 System 이름공간에
커스텀 클래스를 정의할 수도 있습니다.
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var nk = new System.NeoKay();
nk.Var = 23;
Console.WriteLine("namespace ex: " + nk.Var);
}
}
}
namespace System
{
class NeoKay
{
public int Var { get; set; }
}
}
이상한 방식이지만 예제를 위해 만든 코드입니다.
System 이란 이름공간이 특별하지만
따지고 보면 특별한게 아니라
다른 이름공간과 같다는 것 입니다.
그런데 또 보니까 ConsoleApp1 이란
이름공간이 있는데 Visual Studio에서
콘솔 .NET 앱을 만들 때 넣었던 이름입니다.
템플릿도 처음부터 이름 공간을 사용하라고
알려 주는 것 입니다. System 은 SDK가
제공해주는 제품이고 이제부터 새로운
네임스페이스로 자신의 앱을 만들고
그 이름 공간으로 관리하는 것 입니다.
그런데 namespace에서 주의해야할 것이
있는데 폴더 이름과 파일 이름입니다.
비주얼 스튜디오에서 폴더와
namespace가 일치되도록 생성하고
또 그렇게 추정을 합니다.
(클래스이름과 파일도 같음)
물론 자동으로 생성한 namespace를
원하는 이름으로 바꿀 수도 있습니다.
폴더이름과 클래스 namespace가 다르다고
실행이 안되는 것은 아니지만 경우에 따라
IDE가 인식을 못할 수 있으니까
솔루션 탐색기에 모든 파일이
잘 들어와 있는지 확인하도록 합니다.
비주얼 스튜디오의 메뉴를 사용하는게
제일 편리한 방법이긴 합니다.
자바도 그렇고 폴더 구조를 짜는게
네임스페이스 계층구조와 관련되 있습니다.
C#은 자바의 package 구조에 비해 느슨한 편입니다.
비주얼 스튜디오라면 간단합니다.
프로젝트에 클래스를 추가하면 자동으로
Main 메소드가 있는 namespace와 같은
네임스페이스에 넣습니다.
Nested라는 폴더안에 넣는다면
ConsoleApp1.Nested 처럼 폴더 이름이
계층으로 포함됩니다. 상위 계층에서
Nested 로 하위 계층에 접근할 수 있습니다.
아니면 직접 namespace를 넣어서
클래스를 작성하면됩니다.
아래는 Nested 란 폴더에 비주얼 스튜디오가
생성한 클래스입니다. 자동으로
ConsoleApp1.Nested로 이름을 정합니다.
물론 Nested를 빼고 그냥 ConsoleApp1을
해도 됩니다만 폴더의 계층 구조를
명확하게 표기하는 것은 가독성이 좋습니다.
using System;
namespace ConsoleApp1.Nested
{
class SubClass
{
public SubClass()
{
Console.WriteLine("Created SubClass");
}
}
}
사용법은 풀네임을 사용하는 것과
using 키워드로 네임스페이스를
가져오는 방법입니다.
다음은 풀네임을 사용하는 예제입니다.
풀네임을 사용하면 정확하게 구분이됩니다.
예를 들어 namespace가 두개 있는데
ConsoleApp1과 ConsoleApp2에
Module1이 각각 있습니다.
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Module1 m1 = new Module1();
}
}
class Module1
{
public Module1()
{
Console.WriteLine("ConsoleApp-1");
}
}
}
namespace ConsoleApp2
{
class Module1
{
public Module1()
{
Console.WriteLine("ConsoleApp-2");
}
}
}
[실행결과]
ConsoleApp-1
이런 경우 Main 와 같이 ConsoleApp1
내부에 있는 Module1에게 우선권이 갑니다.
그럼 바깥에 있는 이름과 구별하기 위해서는?
static void Main(string[] args)
{
ConsoleApp1.Module1 myModule1 = new ConsoleApp1.Module1();
ConsoleApp2.Module1 myModule2 = new ConsoleApp2.Module1();
}
[실행결과]
ConsoleApp-1
ConsoleApp-2
처럼 명확한 구분이 됩니다.
좀 길긴한데 두개의 클래스를 혼동할 일은 없습니다.
우리가 생각하는게 비슷하기 때문에
중복된 이름들이 많이 있습니다.
하지만 네임스페이스로 한정을 하면
겹칠일은 거의 없어집니다.
*이것이 namespace를 사용하는 진짜 이유입니다.
-> 클래스의 이름은 namespace 안에서 유일해야 한다.
이름이 같으면 컴파일이 안됩니다.
다른 namespace를 불러왔는데
그 안에 어떤 클래스가 있는지
모를 수 있습니다. 외부 라이브러리나
프레임워크를 가져오면 그렇게 되는데요.
물론 라이브러리에 어떤 클래스 이름이
있는지 들여다 보는게 상식이긴 합니다만,
클래스 이름이 너무 많아서 다 못보겠다.
(Ctrl+F로 검색하면 이럴 일은 없을 것 같지만)
그럴 때는 현재 namespace에서 풀네임을
사용하면 문제가 해결됩니다.
namespace안에서 유일하면 됩니다.
이것은 복잡하고 거대한 프로젝트에서
충분히 고려할 수 있는 방법입니다.
C#을 시작하고 using System 이거는
많이 봤을 것 입니다. 이 namespace에
많은 Base Class Library가 있다고 했습니다.
using의 사용법은 이게 다는 아니지만
소스파일의 맨 위에 using 이것들은
namespace를 가져오는 것 입니다.
System 에 속한 Console, Math, Random,
Exception 등 클래스를 사용할 수 있습니다.
Console도 원래는 System.Console 로
사용해야하지만 using System 이후
Console.WriteLine 처럼 사용할 수 있습니다.
System 네임스페이스 | Microsoft Docs
네임스페이스는 중첩하여
계층구조를 만들 수 있습니다.
namespace 안에 중괄호{ } 를
활용할 수도 있고 또 도트연산자 (.)를
활용하는 방법도 있습니다.
관리적으로 좋은 것은 비주얼 스튜디오의
솔루션 탐색기에서 하위 폴더를 추가하고
그 폴더의 이름을 네임스페이스로
만드는 방법입니다. 하위 폴더에 클래스를
추가하면 비주얼 스튜디오가 자동으로
<폴더이름>.<네임스페이스> 형식을 만듭니다.
자바는 이 규칙이 까다로운데 C#은
느슨하기 때문에 아무래도 폴더이름을
네임스페이스와 일치시킨다면
나중에 클래스가 어디에 있는지
찾기가 쉬울 겁니다. 자신을 위해서도
필요하지만 같이 일하는 동료를 위해서라면
처음부터 계층도를 잘 잡아놔야 할 것 입니다.
확장까지 미리 감안한다면
훌륭하지 않을까... (욕은 안먹을 정도로)
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
TopLevel.Module1 m1 = new TopLevel.Module1();
TopLevel.SubLevel.Module1 m2 = new TopLevel.SubLevel.Module1();
TopLevel.SubLevel.Module2 m3 = new TopLevel.SubLevel.Module2();
}
}
}
namespace TopLevel
{
class Module1
{
public Module1()
{
Console.WriteLine("TopLevel");
}
}
namespace SubLevel
{
class Module1
{
public Module1()
{
Console.WriteLine("SubLevel-1");
}
}
}
}
namespace TopLevel.SubLevel
{
class Module2
{
public Module2()
{
Console.WriteLine("SubLevel-2");
}
}
}
[실행결과]
TopLevel
SubLevel-1
SubLevel-2
네임스페이스(namespace) 기초를 알아봤습니다.
사람의 입장에서는 메모리를 정리하는 것 보다
네임스페이스를 정리하는게 더 빠릅니다.
추상적이긴 하지만 개념은 있기 때문입니다.
사람이나 CPU나 공통점은 이 데이터들을
메모리 위에서 정리해야 한다는 것 입니다.
정리 방법이 다를 뿐 입니다.
체계도를 잘 작성할 수 있으면 남이
만들어 놓은 네임스페이스도 이해하기
어렵지 않을 것 입니다.