JNDI
1. 개요
JNDI(Java Naming and Directory Interface)는 자바 RMI 및 Jakarta EE API에서 네트워크 상의 객체를 참조하기 위해 사용되는 API이다. 이름과 객체의 연결, 다양한 조회 방식 지원, 이벤트 인터페이스, LDAP 확장 등을 포함하며, LDAP, DNS, NIS, RMI, CORBA 네임 서비스, 파일 시스템 등 다양한 네이밍 및 디렉터리 서비스를 지원한다. 1997년 3월 10일 썬 마이크로시스템즈에 의해 처음 공개되었으며, J2SE 1.3 이후의 Java SE에 통합되었다. JNDI API는 객체를 이름에 바인딩하고, 디렉터리 조회 인터페이스를 제공하며, 디렉터리 항목 변경 시 클라이언트에게 알리는 기능 등을 제공한다.
-
자바 플랫폼, 엔터프라이즈 에디션 -
IBM 웹스피어
IBM 웹스피어는 IBM에서 출시한 기업용 소프트웨어 제품군 브랜드로, 다양한 애플리케이션 인프라, 비즈니스 프로세스 통합, 정보 통합 및 개발 도구를 포함한다. -
자바 플랫폼, 엔터프라이즈 에디션 -
자카르타 서버 페이지
자카르타 서버 페이지(JSP)는 웹 애플리케이션 개발에 사용되는 서버 측 스크립팅 기술로, 서블릿으로 변환되어 실행되고 HTML 형태로 결과를 반환하며, 지시어, 스크립틀릿, 표현식, 액션 등의 문법 요소, 표현 언어(EL), JSTL을 통해 동적인 웹 페이지를 구현하고 개발 편의성을 높였다.
2. 배경
Java RMI 및 Jakarta EE (구 Java EE) API는 네트워크 상의 객체를 조회하기 위해 JNDI API를 사용한다. JNDI는 객체에 이름을 부여하고 관리하는 네이밍 서비스와, 이름을 통해 객체를 검색하는 디렉터리 서비스 기능을 자바 애플리케이션에 제공하는 API이다. 이를 통해 개발자는 LDAP, DNS 등 다양한 종류의 네이밍 및 디렉터리 서비스에 일관된 방식으로 접근할 수 있다.
썬 마이크로시스템즈는 1997년 3월 10일에 JNDI 사양을 처음 발표했으며, JNDI 1.2 버전부터 J2SE 1.3 이후 버전에 포함되었다. 반면, Jini 기술은 자체적인 검색 서비스(lookup service)를 사용하며 JNDI를 이용하지 않는다.
2.1. JNDI API의 주요 기능
자바 RMI 및 Jakarta EE API는 네트워크에서 객체를 조회하기 위해 JNDI API를 사용한다.
JNDI API는 다음과 같은 주요 기능을 제공한다.
* 객체(오브젝트)를 이름에 바인딩(연결)하기 위한 메커니즘
* 일반적인 쿼리(다양한 조회 방법)를 허용하는 디렉터리(계층 구조) 조회 인터페이스
* 디렉터리 항목(요소)이 수정(갱신)되었을 때 클라이언트가 이를 알 수 있게 하는 이벤트 인터페이스
* LDAP 서비스의 추가 기능(요구 사항)을 지원하는 LDAP 확장
2.2. 지원하는 서비스 (SPI)
SPI는 다음과 같은 다양한 종류의 네이밍 및 디렉터리 서비스를 지원한다.
* LDAP
* DNS
* NIS
* RMI
* CORBA 이름 서비스
* 파일 시스템
3. 버전 역사
썬 마이크로시스템즈는 1997년 3월 10일에 JNDI 1.0 사양을 처음 발표했다. 이후 JNDI 1.2 버전이 발표되었으며, 이는 Java EE 5 플랫폼과 관련이 있다. 2006년 기준으로 최신 버전은 JNDI 1.2이며, Java SE 1.3 버전부터 통합되어 제공된다.
4. 기본 조회 (Lookup)
JNDI는 이름을 계층 구조로 관리한다. 이름은 "com.mydomain.ejb.MyBean"과 같은 문자열일 수도 있고, Name 인터페이스를 구현한 객체일 수도 있지만, 일반적으로 문자열 형식을 사용한다. 이름은 디렉토리 서비스에 해당 이름으로 식별되는 객체 또는 객체에 대한 참조를 저장(bind)함으로써 객체와 연결된다.
JNDI API는 객체를 찾을 위치를 지정하는 컨텍스트를 정의하며, 일반적으로 초기 컨텍스트(Initial Context영어)를 시작점으로 사용한다. 초기 컨텍스트를 얻은 후에는 `lookup` 메서드를 사용하여 특정 이름에 해당하는 객체를 조회할 수 있다. 객체 조회에 대한 구체적인 방법과 예시는 하위 섹션에서 자세히 설명한다.
4.1. 초기 컨텍스트 (Initial Context)
JNDI API는 객체를 찾을 위치를 지정하는 컨텍스트를 정의한다. 이 중 초기 컨텍스트(Initial Context영어)는 일반적으로 객체 검색의 시작점으로 사용된다.
초기 컨텍스트는 특정 구현 방식과 필요한 설정값(매개변수)을 지정하여 생성해야 한다. 이는 마치 파일 시스템의 최상위 디렉토리(루트)와 같은 역할을 하여, 여기서부터 원하는 객체의 이름을 찾아 내려가게 된다. 초기 컨텍스트를 얻은 후에는 이를 사용하여 특정 이름에 연결된 객체를 찾을(lookup) 수 있다.
4.1.1. 초기 컨텍스트 생성 예제 (Java)
가장 간단한 경우, 초기 컨텍스트는 특정 구현과 해당 구현에 필요한 매개변수를 사용하여 생성해야 한다. 초기 컨텍스트는 이름을 찾는 시작점으로 사용되며, 파일 시스템의 루트 디렉토리와 유사한 역할을 한다.
다음은 초기 컨텍스트를 생성하는 예시이다.
: Hashtable contextArgs = new Hashtable
: // 먼저 컨텍스트 팩토리를 지정해야 한다.
: // 예를 들어 JBoss 구현이나 Sun 구현 등 특정 벤더의 구현을 선택한다.
: contextArgs.put( Context.INITIAL_CONTEXT_FACTORY, "com.jndiprovider.TheirContextFactory" );
:
: // 다음으로 데이터 저장소의 위치를 나타내는 URL을 지정한다.
: contextArgs.put( Context.PROVIDER_URL, "jndiprovider-database" );
:
: // (필요한 경우 보안 자격 증명을 제공해야 할 수도 있다.)
:
: // 마지막으로 초기 컨텍스트를 생성한다.
: Context myCurrentContext = new InitialContext(contextArgs);
이렇게 생성된 컨텍스트는 이전에 해당 컨텍스트에 바인딩된 이름을 찾는 데 사용된다. 예를 들면 다음과 같다.
: MyBean myBean = (MyBean) myCurrentContext.lookup("com.mydomain.MyBean");
위 코드 대신 다른 방법을 사용할 수도 있다. 초기 컨텍스트 팩토리 클래스 이름과 공급자 URL을 포함하는 `jndi.properties` 파일을 클래스패스에 추가하여 Context 객체를 설정할 수 있다. 이 경우 코드는 다음과 같이 간결해진다.
: // 초기 컨텍스트 객체를 생성하기만 하면 클래스패스에서 jndi.properties 파일을 읽어 설정을 로드한다.
: Context myCurrentContext = new InitialContext();
이후 컨텍스트를 사용하여 이름을 찾는 방식은 동일하다.
: MyBean myBean = (MyBean) myCurrentContext.lookup("com.mydomain.MyBean");
4.2. 객체 조회 (Lookup)
JNDI API는 객체를 찾을 위치를 지정하는 컨텍스트를 정의한다. 일반적으로 초기 컨텍스트(Initial Context)를 시작점으로 사용한다.
가장 간단한 방법은 특정 구현 클래스와 필요한 매개변수를 직접 지정하여 초기 컨텍스트를 생성하는 것이다. 초기 컨텍스트는 파일 시스템의 루트 디렉터리와 유사하게 이름 검색의 시작점이 된다. 다음은 초기 컨텍스트를 생성하는 예시 코드이다.
Hashtable
// 1. 사용할 컨텍스트 팩토리 클래스를 지정한다.
// (예: JBoss, Sun Microsystems 등 특정 벤더의 구현 선택)
contextArgs.put( Context.INITIAL_CONTEXT_FACTORY, "com.jndiprovider.TheirContextFactory" );
// 2. JNDI 데이터가 저장된 위치(URL)를 지정한다.
contextArgs.put( Context.PROVIDER_URL, "jndiprovider-database" );
// (필요한 경우, 보안 인증 정보를 추가할 수 있다.)
// 3. 설정 정보를 바탕으로 초기 컨텍스트 객체를 생성한다.
Context myCurrentContext = new InitialContext(contextArgs);
초기 컨텍스트를 얻었다면, `lookup()` 메서드를 사용하여 해당 컨텍스트에 미리 바인딩된 이름을 통해 원하는 객체를 찾을 수 있다.
// "com.mydomain.MyBean"이라는 이름으로 바인딩된 객체를 찾는다.
MyBean myBean = (MyBean) myCurrentContext.lookup("com.mydomain.MyBean");
다른 방법으로는, 초기 컨텍스트 팩토리 클래스 이름과 프로바이더 URL 같은 설정 정보를 `jndi.properties` 파일에 작성하여 클래스패스에 포함시키는 것이다. 이 파일을 사용하면 코드를 더 간결하게 작성할 수 있다.
// 클래스패스에서 jndi.properties 파일을 자동으로 읽어 초기 컨텍스트를 생성한다.
Context myCurrentContext = new InitialContext();
// 이후 과정은 동일하다. lookup 메서드를 사용하여 객체를 찾는다.
MyBean myBean = (MyBean) myCurrentContext.lookup("com.mydomain.MyBean");