라이브러리 활용

라이브러리 활용 (Using Libs)

Clojure는 "lib" 기능을 통해 코드 로딩과 의존성 추적을 제공해요. lib란 클래스패스(classpath) 안에 있는 Java 리소스에 들어 있는 Clojure 소스 코드의 이름 붙은 단위랍니다. 전형적으로 lib 하나가 하나의 Clojure 네임스페이스를 구성하는 완전한 정의 집합을 제공해요.

출처: 라이브러리 활용 (Using Libs)

Lib 규약 (Lib Conventions)

Clojure는 lib의 이름 짓기와 구조화에 대한 규약을 정의해요:

  • lib 이름은 보통 마침표로 구분된 두 개 이상의 부분을 포함하는 심볼이에요.
  • lib의 컨테이너는 클래스패스 상대 경로가 lib 이름에서 파생되는 Java 리소스예요: ** 그 경로는 문자열이에요 ** lib 이름의 마침표는 경로에서 슬래시로 바뀌어요 ** lib 이름의 하이픈은 경로에서 밑줄로 바뀌어요 ** 경로는 ".class", ".clj", ".cljc"로 끝날 수 있어요 (아래 Lib 로드 순서 참고)
  • lib는 "ns" 폼으로 시작하며, ** 같은 이름을 공유하는 Clojure 네임스페이스를 만들고, ** Java 클래스, Clojure의 핵심 기능, 그리고/또는 다른 lib에 대한 의존성을 선언해요

Clojure는 "ns" 호출이 예외를 던지지 않고 완료되면, 선언된 의존성이 충족되었고 그것들이 제공하는 기능을 사용할 수 있음을 보장해요.

예제 Lib (Example Lib)

간단한 lib는 다음과 같아요:

(ns com.my-company.clojure.examples.my-utils
  (:import java.util.Date)
  (:use [clojure.string :only (join)])
  (:require [clojure.java.io :as jio]))
  • ns 폼은 lib의 네임스페이스 이름을 정하고 의존성을 선언해요. 이 이름에 따라 이 lib는 전형적으로 클래스패스 상대 경로 com/my_company/clojure/examples/my_utils.clj의 소스 파일에 정의돼요 (마침표→슬래시, 하이픈→밑줄 변환에 주목하세요).
  • :import 절은 이 lib가 java.util.Date를 사용한다는 것을 선언하고, 이 lib의 코드에서 한정되지 않은(unqualified) 이름으로 그것을 사용할 수 있게 해요.
  • :use 절은 clojure.string lib에 대해 그 join 함수만을 대상으로 의존성을 선언해요. join은 이 lib의 코드에서 한정되지 않은 이름으로 사용될 수 있어요.
  • :require 절은 clojure.java.io lib에 대한 의존성을 선언하고, 짧은 네임스페이스 별칭 jio를 사용해 그 멤버에 접근할 수 있게 해요.

접두사 목록 (Prefix Lists)

lib 하나가 완전한(fully qualified) 이름에서 공통 접두사를 공유하는 여러 다른 lib에 의존하는 것은 흔한 일이에요. requireuse 호출(그리고 ns 폼 안의 :require·:use 절)에서는, 공통 접두사를 추출해 접두사 목록(prefix list)으로 한 번만 제공할 수 있어요. 예를 들어 다음 두 폼은 동등해요:

(require 'clojure.contrib.def 'clojure.contrib.except 'clojure.contrib.sql)
(require '(clojure.contrib def except sql))

Lib 로드 순서 (Lib load order)

lib는 컴파일된 형태(.class)나 소스 형태(.clj·.cljc)로 존재할 수 있어요. 어떤 경우에는 그중 하나, 심지어 전부가 클래스패스에 존재할 수도 있어요. lib는 다음 규칙에 따라 그중 하나에서 로드돼요:

  • 소스 파일의 타임스탬프가 .class 파일보다 최신이 아닌 이상, .class 파일이 항상 소스 파일보다 선호돼요. 소스 파일이 더 최신이면 소스 파일이 선호돼요.
  • .clj(플랫폼 특정 파일)는 항상 .cljc(플랫폼 간 공통)보다 선호돼요.

두 번째 규칙 덕분에 라이브러리 작성자는 lib의 이식 가능한(portable) 공통 정의를 제공하면서, 호스트 플랫폼을 활용하는 어떤 일을 하도록 이식 가능한 버전을 덮어쓰는 플랫폼 특정 lib도 함께 배포할 수 있어요.

더 알아보기