learn

namespace란 무엇인가 — 이름의 그룹화

핵심

namespace는 "이름 앞에 붙는 경로" 다. 같은 이름이라도 다른 namespace 안에 있으면 충돌 없이 공존할 수 있게 해주는 메커니즘. 디렉토리/폴더와 정확히 같은 원리 — /home/notes.txt/work/notes.txt가 같은 이름이면서 충돌 없이 존재하는 것과 같다.

두 가지 가치:

  1. 이름 충돌 방지 — 같은 이름의 함수/타입을 다른 그룹에 둘 수 있음
  2. 조직화 — 관련된 것끼리 묶어서 코드의 영역을 명확히

학교에서 이미 써왔을 가능성이 높다

Java를 배운 적 있다면 다음을 본 순간 namespace를 써온 셈이다.

package com.mycompany.math;       // namespace 생성

import java.util.ArrayList;       // namespace에서 가져오기

java.util.ArrayList"java.util namespace 안의 ArrayList" 라는 의미. namespace 표기가 그대로 코드에 드러난다. namespace 없이는 세상의 모든 라이브러리가 같은 자리에서 이름 경쟁을 해야 했을 것이다.

각 언어의 namespace 메커니즘

같은 의도 — math.addstring.add를 함께 쓰기 — 를 네 언어로 비교.

언어namespace 생성이름 가져오기표기
C++namespace foo { }using foo::bar;foo::bar
Javapackage foo; (디렉토리 자동 매핑)import foo.Bar;foo.Bar
Python파일/디렉토리 자동 매핑import foo / from foo import barfoo.bar
Rustmod foo { } 또는 mod foo;use foo::bar;foo::bar

본질은 같다 — 이름 앞에 그룹 경로를 붙여서 충돌을 막는다. 표기법(:: vs .)과 명시 방법(키워드 vs 자동 추론)만 다를 뿐.

Rust 예시

mod math {
    pub fn add(a: i32, b: i32) -> i32 { a + b }
}
mod strs {
    pub fn add(a: &str, b: &str) -> String { format!("{}{}", a, b) }
}

math::add(1, 2);
strs::add("hi", "there");

use math::add;
add(1, 2);  // math::add의 단축

C++ 예시

namespace math {
    int add(int a, int b) { return a + b; }
}
math::add(1, 2);

using math::add;
add(1, 2);

언제 namespace가 빛나는가

작은 스크립트 수준에선 필요성이 거의 안 느껴진다. 다음 상황에서 없으면 코드가 무너진다.

외부 라이브러리 사용 — Rust 표준 라이브러리에 std::fmt::Resultstd::io::Result가 공존한다. 같은 이름 다른 타입. namespace 없이는 둘 중 하나가 이름을 바꿔야 했을 것이며, 이는 라이브러리 작성자가 사용자에게 "이 이름 못 쓴다"고 강제하는 꼴이 된다.

같은 개념을 다른 도메인에서 — 이커머스 시스템의 User::Order(사용자 주문)와 Restaurant::Order(식당 주문)는 의미가 비슷하나 데이터 모델이 다르다. namespace 분리로 둘 다 Order로 둘 수 있어 도메인 의미가 더 직관적.

큰 코드베이스의 협업 — 다른 사람과 자기 코드의 이름 충돌 가능성이 커진다. namespace는 영역을 분리해 "내 영역에선 짧은 이름 자유롭게"를 가능하게 한다.

학교 과제 수준에서 namespace를 명시적으로 만들 일이 적은 건 프로젝트 규모가 작아 충돌 위험이 낮기 때문이지 namespace 자체가 마이너해서가 아니다. 모든 표준 라이브러리(java.util.*, import math 등)가 namespace 위에서 굴러가고 있다.

디렉토리 비유의 정확함

파일 시스템                          namespace
/home/user/notes.txt        →       home::user::notes
/work/notes.txt             →       work::notes

같은 파일명도 다른 디렉토리에 → 같은 이름도 다른 namespace에

std::collections::HashMap을 보면:

  • std — 최상위 namespace (표준 라이브러리)
  • collections — 그 안의 namespace (자료구조 모음)
  • HashMap — 진짜 타입

:: 한 칸이 namespace 한 단계. 디렉토리 경로 그대로의 구조다.

결론

namespace는 "이름 앞에 붙는 경로" — 폴더 안의 파일과 같은 원리로 같은 이름을 다른 그룹에 두어 충돌을 막고 코드를 조직한다. Java package/import, Python import, C++ namespace, Rust mod/use는 모두 같은 개념의 다른 표기법. 작은 프로젝트에선 안 보이지만 외부 라이브러리·협업·큰 코드베이스로 가는 순간 없으면 코드가 충돌해서 못 굴러간다.

관련: rust-module-system-overview