핵심
namespace는 "이름 앞에 붙는 경로" 다. 같은 이름이라도 다른 namespace 안에 있으면 충돌 없이 공존할 수 있게 해주는 메커니즘. 디렉토리/폴더와 정확히 같은 원리 — /home/notes.txt와 /work/notes.txt가 같은 이름이면서 충돌 없이 존재하는 것과 같다.
두 가지 가치:
- 이름 충돌 방지 — 같은 이름의 함수/타입을 다른 그룹에 둘 수 있음
- 조직화 — 관련된 것끼리 묶어서 코드의 영역을 명확히
학교에서 이미 써왔을 가능성이 높다
Java를 배운 적 있다면 다음을 본 순간 namespace를 써온 셈이다.
package com.mycompany.math; // namespace 생성
import java.util.ArrayList; // namespace에서 가져오기
java.util.ArrayList는 "java.util namespace 안의 ArrayList" 라는 의미. namespace 표기가 그대로 코드에 드러난다. namespace 없이는 세상의 모든 라이브러리가 같은 자리에서 이름 경쟁을 해야 했을 것이다.
각 언어의 namespace 메커니즘
같은 의도 — math.add와 string.add를 함께 쓰기 — 를 네 언어로 비교.
| 언어 | namespace 생성 | 이름 가져오기 | 표기 |
|---|---|---|---|
| C++ | namespace foo { } | using foo::bar; | foo::bar |
| Java | package foo; (디렉토리 자동 매핑) | import foo.Bar; | foo.Bar |
| Python | 파일/디렉토리 자동 매핑 | import foo / from foo import bar | foo.bar |
| Rust | mod 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::Result와 std::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는 모두 같은 개념의 다른 표기법. 작은 프로젝트에선 안 보이지만 외부 라이브러리·협업·큰 코드베이스로 가는 순간 없으면 코드가 충돌해서 못 굴러간다.