Namespaces

Namespaces (네임스페이스)

Clojure 코드를 파일이나 REPL에서 다루다 보면, def로 정의한 변수라든가 import로 가져온 클래스가 "어디에 들어 있는지"를 늘 의식하게 돼요. 그 기준점이 바로 네임스페이스(namespace)예요. 이름이 같은 심볼도 서로 다른 네임스페이스에 있으면 충돌하지 않죠. 이 글에서는 네임스페이스가 정확히 무엇인지, 파일과 REPL에서 어떻게 만들고 전환하는지 살펴볼게요.

출처: Clojure 공식문서

본문

네임스페이스는 단순(qualify되지 않은) 심볼을 Var나 Class에 연결하는 매핑이에요. def나 그 변형을 쓰면 Var가 네임스페이스에 intern(등록)되는데, 이때 Var는 이름이 될 단순 심볼과 자신이 속한 네임스페이스에 대한 참조를 갖게 되고, 네임스페이스는 그 심볼을 같은 Var에 연결해요.

네임스페이스에는 다른 네임스페이스에 intern된 Var를 가리키는 연결도 들어갈 수 있어요. referuse로 Var를 가져오거나, import로 Class 객체를 가져오는 식이죠. 네임스페이스는 first-class여서 열거(enumerate)할 수 있고요, 또 동적이라 REPL 등에서 런타임에 만들고, 지우고, 수정할 수도 있어요.

파일 위에서 네임스페이스 만들기

Clojure 소스 파일 맨 위에 네임스페이스를 새로 구성하는 가장 좋은 방법은 ns 매크로를 쓰는 거예요. 기본적으로 nsjava.lang의 클래스명과 clojure.lang.Compiler, 그리고 clojure.core의 함수들에 대한 연결을 담은 새 네임스페이스를 만들어 줘요. 그래서 파일 안에서는 별다른 설정 없이도 clojure.core의 함수를 바로 쓸 수 있어요.

REPL에서 네임스페이스 만들기

REPL에서는 in-ns를 쓰는 게 좋아요. 이 경우 새 네임스페이스에는 java.lang의 클래스명에 대한 연결만 들어가요. clojure.core의 이름을 쓰려면 (clojure.core/refer 'clojure.core)를 직접 실행해야 해요. REPL 시작 시점의 user 네임스페이스는 이미 이 작업이 되어 있는 상태예요.

현재 네임스페이스 *ns*

현재 네임스페이스를 가리키는 *ns*in-nsns 매크로로만 설정해야 해요. 두 함수 모두 네임스페이스가 없으면 새로 만들어 주기 때문에, 직접 다른 방식으로 바꾸는 일은 피하는 게 좋아요.

더 알아보기

관련 함수들을 역할별로 정리하면 이래요.

  • 네임스페이스 만들고 전환하기: in-ns, ns, create-ns
  • 네임스페이스에 추가하기: alias, def, import, intern, refer
  • 존재하는 네임스페이스 찾기: all-ns, find-ns
  • 네임스페이스 살펴보기: ns-name, ns-aliases, ns-imports, ns-interns, ns-map, ns-publics, ns-refers
  • 심볼에서 네임스페이스 얻기: resolve, ns-resolve, namespace
  • 제거하기: ns-unalias, ns-unmap, remove-ns

같이 보면 좋은 자료: