시스템 컨텍스트

본 장에서는 ProObject의 애플리케이션에서 사용되는 시스템 컨텍스트를 설정하는 방법에 대하여 설명한다.

1. 개요

시스템 컨텍스트(System Context)는 애플리케이션에서 전역적으로 사용하는 각종 변수들의 집합이다.

읽기 전용(Read-Only)성으로 애플리케이션 내에서 공용으로 사용할 값들이 있는 경우에는 시스템 컨텍스트를 통해 데이터를 별도로 읽어오지 않고 편리하게 상수를 사용할 수 있다. 따라서 시스템 컨텍스트는 항상 읽기 전용으로 지정되며, 값을 변경할 경우에는 오류가 발생하므로 유의하도록 한다.

이러한 읽기 전용의 값들은 처리할 업무의 종류에 따라 묶을 수 있고(Categorization), ProObject에서는 하나의 애플리케이션에서 다수의 시스템 컨텍스트를 운용할 수 있다. 따라서 애플리케이션에 다수의 시스템 컨텍스트를 정의한 후 필요에 따라 원하는 시스템 컨텍스트를 얻어 편리하게 값을 사용할 수 있다.

기본적으로 ProObject에서의 데이터 오브젝트는 미리 정의된 필드(Field)가 아닌 경우에는 기본적으로 그 어떠한 필드도 지정할 수 없으며 시스템 컨텍스트는 예외 케이스로 정의되지 않은 필드(Field)에 대해서도 값에 대한 설정이 가능하다. 그러므로 시스템 컨텍스트는 필요에 따라 데이터베이스에 새로운 필드를 추가하고, 언제든지 런타임 엔진에 갱신(Reload) 명령을 내림으로써 클래스에 대한 재배포 없이 편리하게 시스템 컨텍스트의 값을 변경할 수 있다.

일반적으로 시스템 컨텍스트는 데이터베이스의 값을 읽어 사용한다. 다만, 필요한 경우 파일이나 다른 곳에서부터 데이터를 읽어 시스템 컨텍스트를 정의하는 것 또한 가능하다.

2. 기본 설정

시스템 컨텍스트를 이용하기 위해서는 애플리케이션 메타를 지정해주어야 한다.

애플리케이션 메타는 아래 경로에 XML 형식으로 작성한다.

${APP_HOME}/config/application.xml

다음은 application.xml의 설정 예이다.

<ns18:system-context>
    <ns18:name>SystemOne</ns18:name>
    <ns18:context-object>com.test.SystemContextDataObjectOne</ns18:context-object>
    <ns18:context-table>
        <ns18:schema>mySchema</ns18:schema>
        <ns18:table>myTable</ns18:table>
    </ns18:context-table>
</ns18:system-context>
<ns18:system-context>
    <ns18:name>SystemTwo</ns18:name>
    <ns18:context-object>com.test.SystemContextDataObjectTwo</ns18:context-object>
    <ns18:context-initializer>com.test.MyInitializer</ns18:class>
</ns18:system-context>
태그 설명

<name>

시스템 컨텍스트의 이름을 지정한다.

<context-object>

시스템 컨텍스트로 사용할 데이터 오브젝트(DataObject)를 지정한다.

데이터 오브젝트는 애플리케이션의 리소스로 정의되어 공용 데이터 오브젝트로서 배포되어야 함을 유의해야 한다.

시스템 컨텍스트는 반드시 com.tmax.proobject.dataobject.context.ContextDataObject의 자식 클래스로 정의되어야 한다. ContextDataObject는 일종의 맵(Map)과 같은 데이터 오브젝트로써 정의되지 않는 필드(Field)를 지정하여 사용하는 것이 가능하기 때문이다.

<context-table>

데이터베이스를 통해 시스템 컨텍스트를 불러오는 경우 테이블 정보를 지정하여 테이블의 정보를 얻어오는 것이 가능하다. 이때 사용하는 테이블의 기본 구조는 기본 테이블 구조를 참고한다.

다만 context-initializer 옵션이 지정되어 있는 경우 여기에 지정한 schema와 table 요소들이 각각 context-initializer 클래스의 첫 번째와 두 번째 인자로 전달된다.

<context-initializer>

시스템 컨텍스트를 초기화하기 위한 사용자 정의 클래스를 지정한다.

com.tmax.proobject.model.context.ContextInitializer 인터페이스를 상속받아 정의한다. 이 옵션이 정의되면 <context-table>의 옵션은 무시된다.

2.1. 데이터베이스를 이용한 시스템 컨텍스트 초기화

데이터베이스를 이용하여 시스템 컨텍스트를 이용하기 위해서는 먼저 테이블을 생성한 이후 해당 테이블에 접근할 수 있도록 애플리케이션 런타임 설정을 통해 사용할 데이터소스를 지정해주어야 한다.

2.1.1. 기본 테이블 구조

시스템 컨텍스트는 Key, Value를 이용해 변수에 접근해 값을 얻어오는 구조로 작성되어 있다. 기본적으로는 다음과 같은 테이블 구조를 생성해서 시스템 컨텍스트가 정보를 읽어오도록 설정한다.

create table {TABLE_NAME}
(
    KEY VARCHAR(256) primary key,
    VALUE VARCHAR(4096)
);

2.1.2. 애플리케이션 런타임 설정

애플리케이션 메타에서 <context-initializer>를 지정하지 않은 경우 시스템 컨텍스트 정보를 아래 경로에 설정한다.

${APP_HOME}/config/application.properties

다음은 application.properties 항목에 대한 설명이다.

APPLICATION_SYSTEM_CONTEXT_{0}_DATASOURCE = datasource_value
항목 설명

SYSTEM_CONTEXT_{0}_DATASOURCE

애플리케이션의 시스템 컨텍스트를 초기화하기 위해 사용할 데이터소스를 지정한다.

{0}에는 시스템 컨텍스트 이름을 반드시 대문자로 설정해야 한다.

설정한 데이터소스는 반드시 dbio_config.xml에 지정되어 있어야 한다. 애플리케이션 메타에서 <context-initializer>를 지정한 경우 이 옵션은 Constructor의 세 번째 인자로써 전달된다.

2.2. 사용자 정의 시스템 컨텍스트 초기화

애플리케이션 메타에서 <context-initializer>를 지정한 경우에는 다음과 같이 ContextInitializer 인터페이스를 상속받아 코드를 작성해야 한다. 상속받는 인터페이스의 이름은 com.tmax.proobject.model.context.ContextInitializer이다.

public interface ContextInitializer {
    public ContetextInitializer(String schemaName, String tableName, String datasource);
    public void init(String contextName, ContextObject object) throws Exception;
}

해당 인터페이스에서는 init 메소드를 상속받아 코드를 작성한다.

public class CustomSystemContextInitializer implements ContextInitializer {
    private String      schema;
    private String      table;
    private String      datasource;


    public DefaultSystemContextInitializer(String schema, String table, String datasource) {
        /* 애플리케이션 메타의 context-table > schema로 설정한 부분 */
        this.schema     = schema;
        /* 애플리케이션 메타의 context-table > table로 설정한 부분 */
        this.table      = table;
        /* 애플리케이션 런타임 설정의 dataasource로 설정한 부분 */
        this.datasource = datasource;
    }

    @Override
    public void init(String contextName, ContextObject object) throws Exception {
        CustomContextDOF dof = new CustomContextDOF(datasource);
        dof.setFullQuery(FULLQUERY.SELECT_ALL_ENTRY);
        dof.setTableInformation(schema, table);

        List<SystemContextEntry> entries = well.getForwardList();
        for(SystemContextEntry entry : entries) {
            object.set(entry.getKey(), entry.getValue());
        }
    }
}

3. 시스템 컨텍스트 사용

시스템 컨텍스트는 RequestContext에서 값을 얻어 사용하는 것이 가능하다. RequestContext 객체를 얻은 후에는 시스템 컨텍스트를 얻어 온다. 이후 해당 시스템 컨텍스트에서 저장된 값을 가져와 사용할 수 있다. RequestContext를 얻는 방법에 대해서는 서비스 개발, 채널 이벤트 계층 개발, 이벤트 계층 개발을 참고한다.

3.1. 일반적인 시스템 컨텍스트 접근

다음의 API를 사용해서 애플리케이션에 설정한 시스템 컨텍스트들이 담긴 SystemContext 객체를 얻을 수 있다.

SystemContext systemContext = requestContext.getSystemContext();

SystemContext 객체를 얻은 후에는 getContext API를 사용해서 원하는 시스템 컨텍스트를 얻고, 해당 객채에서 원하는 값을 꺼내어 사용할 수 있다. 이때 getContext의 인자로는 애플리케이션 메타에서 작성한 <name>과 동일한 값을 넣어준다.

SystemContext systemContext = requestContext.getSystemContext();
ContextObject systemContextOne = systemContext.getContext("systemContextOne");
String value = systemContextOne.get(KEY);

3.2. 시스템 컨텍스트 이름 얻기

애플리케이션에서 사용 중인 시스템 컨텍스트들의 이름들을 얻는 경우 다음의 API를 사용한다.

SystemContext systemContext = requestContext.getSystemContext();
Set<String> contextNames = systemContext.getContextNames();