사용자 삽입 이미지
JBoss 시작한지 석달이 지났는데 HelloWorld, 즉 Echo EJB를 이제서야 작성해 보았습니다. 아~ 이 게으름!

여기서의 Test는 EJB Coding Style은 2.1로 그리고 deploy descriptor는 3.0으로 구성하여 EJB3 Container에 deploy했기 때문에 클라이언트에서는 context lookup시 remote interface가 바로 날아오는 특징을 가지고 있습니다.

1. 먼저 Home Interface를 작성합니다.

package com.jboss.ejb.example.echo;

import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface EchoHome extends EJBHome {
 public Echo create() throws RemoteException, CreateException;
}


2. Remote Interface를 작성합니다.

package com.jboss.ejb.example.echo;

import java.rmi.RemoteException;

import javax.ejb.EJBObject;

public interface Echo extends EJBObject {
 public String sayEcho(String name) throws RemoteException;
}


3. Enterprise Bean 클래스를 작성합니다.

package com.jboss.ejb.example.echo;

import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

public class EchoEJB implements SessionBean {
 public EchoEJB() {
  System.out.println("EchoEJB() method");
 }
 
 //Buseness Method
 public String sayEcho(String name) {
    // System.out.println(name + " enter this server");
    System.out.println("Call EJB!!");
  return "Hi... "+name+"!!!";
 }
 
 //callback method
 public void ejbCreate() {
  System.out.println("ejbCreate() method");
 }

 public void ejbRemove() {
  System.out.println("ejbRemove() method");
 }

 public void ejbActivate() {
  System.out.println("ejbActivate() method");
 }

 public void ejbPassivate() {
  System.out.println("ejbPassivate() method");
 }

 public void setSessionContext(SessionContext sc) {
  System.out.println("setSessionContext() method");
 }
};

4. Deployment Descript를 작성합니다.
4.1 ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.0" xmlns="
http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
 <description>Simple Echo EJB</description>
 <display-name>echo-stateless</display-name>
 <enterprise-beans>
  <session>
   <display-name>EchoEJB</display-name>
   <ejb-name>EchoEJB</ejb-name>
   <home>com.jboss.ejb.example.echo.EchoHome</home>
   <remote>com.jboss.ejb.example.echo.Echo</remote>
   <ejb-class>com.jboss.ejb.example.echo.EchoEJB</ejb-class>
   <session-type>Stateless</session-type>
   <transaction-type>Container</transaction-type>
  </session>
 </enterprise-beans>
 <assembly-descriptor>
   <container-transaction>
        <method>
          <ejb-name>EchoEJB</ejb-name>
          <method-name>*</method-name>
        </method>
        <trans-attribute>NotSupported</trans-attribute>
     </container-transaction>
 </assembly-descriptor>
</ejb-jar>

4.2 jboss.xml

<?xml version="1.0"?>

<jboss xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
                            http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
 version="3.0">
 <enterprise-beans>
  <session>
   <ejb-name>EchoEJB</ejb-name>
   <jndi-name>com.jboss.ejb.example.Hello</jndi-name>
  </session>
 </enterprise-beans>
</jboss>

5. 클라이언트 애플리케이션을 작성합니다.

package com.jboss.ejb.example.echo.client;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;

import com.jboss.ejb.example.echo.Echo;

public class EchoClient {
 public static void main(String[] args) {
  try {

   Hashtable<Object, String> env = new Hashtable<Object, String>();

   env.put(Context.INITIAL_CONTEXT_FACTORY,
     "org.jnp.interfaces.NamingContextFactory");
   env.put(Context.PROVIDER_URL, "localhost:1099");

   Context ctx = new InitialContext(env);
   System.out.println("<<< Before Lookup >>>");

   Echo echo = (Echo)ctx.lookup("com.jboss.ejb.example.Hello");
   System.out.println("<<< After Lookup >>>");


   System.out.println(echo.sayEcho("Ji-Woong Choi"));

   echo.remove();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}


 



6. Test를 진행합니다.

Project에 사용한 ant build파일은 다음과 같습니다.

<project name="ejb-basic-statelessSession" default="all" basedir=".">

 <!-- set global properties for this build -->
 <property environment="env" />
 <property name="src.dir" value="ejbModule" />
 <property name="build.dir" value="build" />
 <property name="jboss.home" value="/home/jboss/jboss-4.2.3.GA" />
 <property name="server.name" value="default" />
 <property name="app.name" value="hello-ejb" />

 <property name="jboss.server.dir"
  value="${jboss.home}/server/${server.name}" />

 <!-- Classpath Declaration -->
 <path id="compile.classpath">
  <!--
   <fileset dir="${lib.dir}">
   <include name="**/*.jar"/>
   </fileset>
  -->
  <fileset dir="${jboss.server.dir}/lib">
   <include name="**/*.jar" />
  </fileset>
  <pathelement location="${client.jar}" />
 </path>


 <target name="all" depends="clean, init, compile.ejb, jar.ejb, deploy" />

 <target name="init">
  <!-- Create the time stamp -->
  <tstamp />
  <!-- Create the build directory structure used by compile
   and copy the deployment descriptors into it-->
  <mkdir dir="${build.dir}" />
  <mkdir dir="${build.dir}/META-INF" />
  <copy todir="${build.dir}/META-INF">
   <fileset dir="xml">
    <include name="*.xml" />
    <exclude name="build.xml" />
   </fileset>
  </copy>
 </target>


 <!-- Compile ejb classes into the build directory (jar preparation) -->
 <target name="compile.ejb">
  <echo>compile.classpath</echo>
  <javac srcdir="${src.dir}" destdir="${build.dir}"
   classpathref="compile.classpath" />
 </target>

 <!-- Make a standard ejb jar file, including XML deployment descriptors -->
 <target name="jar.ejb" depends="compile.ejb">
  <jar jarfile="${app.name}.jar" basedir="${build.dir}"></jar>
 </target>

 <target name="clean">
  <delete file="./${app.name}.jar" />
  <delete dir="${build.dir}" />
 </target>
 
 <target name="deploy" depends="jar.ejb">
  <copy todir="${jboss.server.dir}/deploy">
   <fileset dir=".">
    <include name="${app.name}.jar" />
   </fileset>
  </copy>
 </target>

 <taskdef name="jmx" classname="org.jboss.ant.JMX">
  <classpath>
   <pathelement path="${jboss.home}/client/jbossjmx-ant.jar" />
   <pathelement
    path="${jboss.home}/client/jbossall-client.jar" />
  </classpath>
 </taskdef>
 
 <target name="redeploy-war">
  <echo message="Redeploy : file:/${war.path}" />
  <jmx>
   <invoke target="jboss.system:service=MainDeployer" operation="redeploy">
    <parameter type="java.lang.String" arg="file:/${war.path}" />
   </invoke>
  </jmx>
 </target>

</project>



Deploy는 jboss home 디렉토리 밑의 server/default로 테스트 서버를 잡고 복사하면 자동으로 디플로이되어지며 다음과 같은 메시지가 나오면 정상입니다.

17:45:59,781 INFO  [JmxKernelAbstraction] creating wrapper delegate for: org.jboss.ejb3.stateless.StatelessContainer
17:45:59,781 INFO  [JmxKernelAbstraction] installing MBean: jboss.j2ee:jar=hello-ejb.jar,name=EchoEJB,service=EJB3 with dependencies:
17:45:59,789 INFO  [EJBContainer] STARTED EJB: com.jboss.ejb.example.echo.EchoEJB ejbName: EchoEJB
17:45:59,803 INFO  [EJB3Deployer] Deployed: file:/home/jboss/jboss-4.2.3.GA/server/default/deploy/hello-ejb.jar
17:51:25,201 INFO  [STDOUT] EchoEJB() method
17:51:25,213 INFO  [STDOUT] setSessionContext() method
17:51:25,217 INFO  [STDOUT] ejbCreate() method
17:51:25,225 INFO  [STDOUT] Call EJB!!


[첨부자료]
Echo Stateless Session Bean Project sample :
크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/29 10:24 2008/08/29 10:24

오늘 메일링 리스트에 이런게 올라왔네요.
접영 부분은 상당히 미심쩍은 부분이 많습니다. 2MB가 하던 방식을 5MB(오메가)가 썼던 게 아닐까 하는 생각이 듭니다.

사용자 삽입 이미지

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/28 09:31 2008/08/28 09:31

사용자 삽입 이미지
This content is to describe how to change JBoss Application Server's port.
한꺼번에 JBoss AS의 적용 포트를 변경하는 방법을 설명합니다.
JBoss가 사용하는 포트는 이미 이전 글에서 설명되어 있습니다.

JBoss의 서비스 포트를 일률적으로 변경하고 싶은 경우 다음의 절차를 진행하십시오.
1. $SERVER_HOME/conf/jboss-service.xml 파일을 엽니다.
해당 파일의 service binding 영역을 찾아 주석을 풀도록 합니다.

<!-- ==================================================================== -->
   <!-- Service Binding                                                      -->
   <!-- ==================================================================== -->

   <!-- Automatically activated when generatting the clustering environment -->
   <!-- @TESTSUITE_CLUSTER_CONFIG@ -->

   <!--
      | Binding service manager for port/host mapping. This is a sample
      | config that demonstrates a JBoss instances with a server name 'ports-01'
      | loading its bindings from an XML file using the ServicesStoreFactory
      | implementation returned by the XMLServicesStoreFactory.
      |
      | ServerName: The unique name assigned to a JBoss server instance for
      | lookup purposes. This allows a single ServicesStore to handle mulitiple
      | JBoss servers.
      |
      | StoreURL: The URL string passed to org.jboss.services.binding.ServicesStore
      | during initialization that specifies how to connect to the bindings store.
      | StoreFactory: The org.jboss.services.binding.ServicesStoreFactory interface
      | implementation to create to obtain the ServicesStore instance.

   <mbean code="org.jboss.services.binding.ServiceBindingManager"
     name="jboss.system:service=ServiceBindingManager">
     <attribute name="ServerName">ports-01</attribute>
     <attribute name="StoreURL">${jboss.home.url}/docs/examples/binding-manager/sample-bindings.xml</attribute>
     <attribute name="StoreFactoryClassName">
       org.jboss.services.binding.XMLServicesStoreFactory
     </attribute>
   </mbean>
   -->

위의 설정파일에서는 port를 변경할 수 있는 파일이 sample-bindings.xml 에 정의되어 있다는 내용이 있습니다. 위의 파일 위치에 있는 설정 파일을 여십시오..

2. bindings.xml 파일을 열어 ServerName의 ports-01에 해당하는 태그를 찾습니다. 500라인 부근에 ports-01 속성값들이 해당 서버의 port정보를 모두 담고 있습니다. 필요한 port로 바꾸도록 합니다.

<!-- ********************************************************** -->
   <!-- *                          ports-01                      * -->
   <!-- ********************************************************** -->
   <server name="ports-01">

      <!-- EJB3 Remoting Connector ejb3.deployer/META-INF/jboss-service.xml -->

      <service-config name="jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3" delegateClass="org.jboss.services.binding.AttributeMappingDelegate">
        <delegate-config>
           <attribute name="InvokerLocator">socket://${jboss.bind.address}:3973</attribute>
        </delegate-config>
         <binding port="3973"/>
      </service-config>

      <!-- ********************* jboss-service.xml ****************** -->

      <service-config name="jboss:service=Naming" delegateClass="org.jboss.services.binding.AttributeMappingDelegate">
         <delegate-config portName="Port" hostName="BindAddress">
            <attribute name="RmiPort">1198</attribute>
         </delegate-config>
         <binding port="1199" host="${jboss.bind.address}"/>
      </service-config>


      <service-config name="jboss:service=WebService" delegateClass="org.jboss.services.binding.AttributeMappingDelegate">
         <delegate-config portName="Port"/>
         <binding port="8183"/>
      </service-config>

      <service-config name="jboss:service=invoker,type=jrmp" delegateClass="org.jboss.services.binding.AttributeMappingDelegate">
         <delegate-config portName="RMIObjectPort"/>
         <binding port="4544"/>
      </service-config>


      <service-config name="jboss:service=invoker,type=pooled" delegateClass="org.jboss.services.binding.AttributeMappingDelegate">
         <delegate-config portName="ServerBindPort"/>
         <binding port="4545"/>
      </service-config>

이하 생략
. . . . .

위의 xml tag 중 ServerName에 해당하는 값은 각 파일간에 서로 매핑되어 있어야 함은 당연합니다.


 

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/27 13:23 2008/08/27 13:23

Tuning Process

CONSULTING 2008/08/27 11:15

사용자 삽입 이미지
전에는 WebLogic을 tuning하고 다녔는데 이제는 JBoss를 튜닝하고 다녀야 할 시점이 왔습니다. BEA Services팀에서 발군의 실력을 발휘하시던 분이 제 옆자리에 떡하니 자리를 잡으셨습니다. JBoss 사이트를 오픈하고 나면 보다 탄력받아 많은 개발자 분들에게 JBoss를 지원할 수 있지 않을까 하는 생각이 듭니다.

각설하고 WAS 튜닝 방정식을 간략히 적어봅니다. 모든 Java WAS(Web Application Server)는 JVM상에서 구동되므로 해당 JVM이 구동되는 운영체제의 커널 파라미터 및 VM 기동 옵션을 통하여 대부분의 성능을 증가시키고 문제점을 찾아낼 수 있습니다.

초기의 튜닝은 어려운 분야지만 문제가 발생하는 부분을 찾아내고 패턴을 인식하면 90%이상의 작업은 해당하는 패턴 내에서 이루어지게 되므로 차근차근 문제를 일으키는 것들을 해결해 나갈 수 있습니다.
사용자 삽입 이미지


Tuning의 Rule은 다음과 같습니다.

Performance는 많은 이슈들과 연관됨
Tuning은 Trade-off가 필요하다
현재 시스템에 대한 파악이 필요하다
   - H/W, S/W System
   - Application
   - 업무 특성
현 시스템의 측정을 위한 여러 툴이 필요하다

Performance 저하의 원인은 대략 다음과 같습니다.

System Configuration
   - Kernel Parameter
   - OS Patch, JVM Version, S/W Version
과도한 Garbage Collection
CPU, Memory등 Resource 제약
Memory Leak
Short-lived Object의 빈번한 호출
Thread의 과도한 사용
Application 관련 이슈

위의 저하 원인에 대한 분석 및 대응 방법은 여러 아티클에 나와 있습니다. 추후 각 사항에 대한 글을 작성하도록 하겠습니다.





 

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/27 11:15 2008/08/27 11:15

사용자 삽입 이미지
만득이라는 마인드 맵 프로그램이 있습니다. 전에 BEA에 있었을 때 같이 일하던 분들이 만든 건데요 워낙에 오픈 소스를 좋아하는 분들이라 오픈 마인드를 가지고 무료 솔루션으로 제공하고 있습니다.

지금 사용해보고 있는데 참신한 아이디어를 솔루션에 포함시켜 놓았네요. 재밌습니다. Freemind에서 전환이 가능할 것 같습니다.

마인드 맵 처음 들어보신 분들은 관련책도 서점에 있고하니 한번 둘러보고 사용해 보세요. 모든 일상 생활사가 논리 정연해짐을 느끼실 수 있을 겁니다.

사이트는 다음과 같습니다.
만득이네 : http://www.mandki.com/index.php

  • 주요 기능
    • 만득이 공작실은 PC 에 설치하는 전문 마인드맵 소프트웨어입니다.
    • 문서 편집기 (웹에디터)
      • 마인드맵의 텍스트를 문서 편집기에서 바로 편집할 수 있습니다.
    • 다양한 클립아트 제공
      • 만 여가지의 온라인 클립아트
      • 구글 이미지 검색
      • 심볼
      • PC 에 이미지 가져오기
    • 다양한 매쉬업 기능
      • 네이버 영어 사전
      • 블로그나 게시판에 퍼가기
        • 작성하신 마인드맵과 문서을 블로그나 게시판으로 퍼갈 수 있도록 태그를 복사하는 기능을 제공합니다.
    • 온라인/오프라인 마인드맵 저장
      • 마인드맵 파일을 PC 에 오프라인으로 저장
      • 온라인으로 마인드맵 저장
        • 자기만의 마인드맵 웹 폴더에 저장하여 언제/어디서나 마인드맵과 문서를 확인 할 수 있습니다.
      • 공개 마인드맵 저장
        • 온라인 저장시 공개를 선택하시면 작성하신 마인드맵을 블로그/게시판/파워포인트 등에 붙여 넣으실 수 있습니다.
    • 프리마인드 포맷 지원
      • 기존에 작성하셨던 프리마인드맵 파일을 불러오실 수 있습니다.
    • 온라인 문서 폴더
      • PC의 디렉토리 처럼 마인드맵과 문서를 동시에 온라인에서 관리 할 수 있습니다.
      • 마인드맵 뿐만이 아니라 관련된 첨부파일들 함께 온라인 문서 폴더 저장 하실 수 있습니다.
      • Drag&Drop 으로 문서 폴더를 손쉽게 관리 하실 수 있습니다.
      • 온라인으로 저장된 마인드맵과 문서들은 인터넷 환경에서는 언제 어디서나 이용하실 수 있습니다.
    • 첨부파일
      • 마인드맵과 관련된 첨부파일을 온라인에 저장 하실 수 있습니다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/26 16:34 2008/08/26 16:34

사용자 삽입 이미지
최현덕님의 Rule Engine 2탄입니다.

사람들은 다음과 같은 질문들을 자주 한다.
언제 룰 엔진을 사용해야 하는가.
룰 엔진을 사용하면 "if...then"을 사용하여 하드코딩한것에 비해서 어떠한 이점들이 있는가?
BeanShell같은 스크림팅 프레임워크 대신에 룰 엔진을 사용해야 하는 이유는 무엇인가?

다음은 이러한 질문들에 대한 답변이다.

2.2.1. Rule Engine 사용의 장점

Declarative Programming선언적 프로그래밍 방식

Rule engines은 ‘어떻게 해야 하는가’(How to do it) 아닌 무엇을 해야 하는가’What to do’에 집중할 수 있게 해 준다.

이것의 핵심적인 장점은, 룰을 사용하는 것이 복잡한 문제점들의 해법을 좀더 쉽게 표현할 수 있게 만들어 준다는 것이다. 결론적으로 이 솔루션들이 검증될 수 있도록 해준다. (룰은 코드보다 읽기가 훨씬 쉽다)
룰 시스템은 엄청나게 복잡한 문제들을 푸는것이 가능하다, 그 해법이 어떤 과정을 거쳐서 결론지어졌는지, 각각의, 해당 결론이 내려지는 각각의 단계에서 어떻게 ‘결정(decision)’이 이루어졌는지에 대한 설명을 제공함으로써.(이것은 Neural Network이나 Human Brain 같은, 다른 Ai시스템에서는 쉽지 않은 일이다. 

  • Logic and Data Separation 로직과 데이터의 분리
    여러분의 데이터는 여러 분의 도메인 객체 내에 있고, 로직은 룰들 내에 존재합니다. 이것은 기본적으로 객체 지향 시스템의 데이터와 로직의 결합이라는 원칙을 깨뜨립니다. 이것은 보는 관점에 따라서 장점이 될수도 있고, 단점이 될 수도 있습니다. 장점은 로직이 보다 관리하기 쉬워지고, 나중에 보다 쉽게 변경할 수 있다는 것 입니다. 로직이 룰 안에 내재되어 있기 때문입니다. 이것은 로직이 크로스 도메인이거나 멀티 도메인인 경우 보다 부각됩니다. 로직을 매우 많은 숫자의 도메인 객체와 컨트롤러들에 분산시키기 보다는, 그것을 하나, 혹은 그 이상의 독자적인 룰 파일들에 조직화할 수 있습니다.

  • 속도와 확장성
    Rete 알고리즘, Leaps 알고리즘과, Drools의 ReteOO(그리고 leaps)같은 그것의 파생 알고리즘들은 룰 패턴을 도메인 객체 데이터에 매칭시키는 매우 효과적인 방법을 제공합니다. 이것은 여러분이 전체적으로 변경되지 않는 데이터집합을 가지고 있을때 특히 유용합니다.(이러면 룰 엔진이 과거의 매칭 결과들을 기억할 수 있도록 해 줍니다.) 이러한 알고리즘들은 경쟁을 통해서 증명되었습니다.

  • 지식의 중앙 집중화
    룰을 사용함으로써, 여러분은 지식의 저장소를 생성할 수 있습니다 (지식베이스스) 이것은 실행 가능합니다. 이것은 여러분이 비즈니스 정책을 구축하기 위한 사실 관계들만 모아놓은 단일 저장소를 의미합니다. (예를 들자면) 이상적으로, 룰은 매우 읽기 쉽기때문에 바로 문서로써 제공될수도 있습니다.
    도구 통합
    Eclise 같은 도구들은,(차후에는 웹 기반의 Ui를 제공 예정) 룰을 수정하고 관리할 수 있는 방법을 제공하며, 즉각적인 피드백, 유효성 검증, 그리고 컨텐츠 지원들을 제공합니다. 감사 및 디버깅 도구들도 역시 사용가능합니다.

  • 설명 Explanation Facility
    룰 시스템은 효과직으로 설명 기구를 제공한다. 이것은 결론이 추론되기까지 왜 이런 결정들이 이루어졌고 최종 결론들이 만들어졌는지를 로깅할 수 있는 기능을 제공함으로써 이해하기 쉬운 룰을 여러분의 문제 도메인을 표현하기 위한 객체 모델들과 부가적인 도메인 특화 언어들을 생성함으로써, 여러분은 마치 자연어처럼 보이도록 룰들을 기술할 수 있습니다. 이것들은 실제 로직을 표현하지만, 보다 이해하기 쉽고, 가능한한 기술적인 내용들을 배제하여, 도메인 전문가가 그들 자신의 언어로써 룰을 표현할 수 있도록 합니다. 모든 프로그램 기법들이 사용 가능하지만, 실제 코드에서 그것들이 어떻게 이루어지는지는 사용자로부터 숨겨집니다.

2.2.2. 언제 룰 엔진을 사용해야 합니까
이 질문에대한 가장 짧은 대답은, “전통적인 프로그래밍 접근방식으로는 문제를 해결하기 위한 만족스러운 방법을 찾을수 없을때”입니다. 이 짧은 대답을 하면, 보다 자세한 설명이 요구됩니다. 이것은 “전통적인”접근방식이라는것은 아마도 다음중 하나일 것이기 때문입니다.

  • 문제가 전통적인 코드 방식으로 풀기에는 지나치게 간단한 경우
    문제점은 복잡하지 않을수도 있습니다. 그렇지만 여러분은 해법을 구축하기 위한 견고하고 확실한 방법을 찾을수 없을수 없습니다.
    문제를 풀기 위한 명확한 알고리즘에 기반한 솔루션이 없는 경우.
    복잡한 문제이지만, 명확하고 전적인 솔루션이 없거나, 기본적으로 문제가 전체적으로 이해할수 없는 경우.
  • 로직이 자주 변경되는 경우.
    로직 그 자체는 매우 단순할수도 있지만 (꼭 단순할 필요는 없다) 그러나 룰들이 매우 자주 변경될 경우. 많은 조직들에서 소프트웨어 릴리즈를은 자주 변경되지 않지만, 룰들을 변경하므로써 요구되는 기민성을 제공하고, 합리적이면서 안정적인 방법을 기대할 수 있다.
  • 도메인 전문가(혹은 비즈니서 전문가)가 준비되어 있지만, 기술적인 내용에 대해 잘 모르는 경우.

도메인 전문가는 종종 비즈니스 룰과 프로세스들에 관한 풍부한 지식을 가지고 있지만, 전형적으로 기술적인 부분에 취약하다. 그렇지만 그들은 매우 논리적이다. Rules는 그들이 로직을 그들 자신이 이해할 수 있는 용어들을 사용하여 표현할 수 있도록 해 준다. 물론, 그들은 여전히 핵심적인 사항들에 대해 고민해야 하고, 논리적으로 생각할 수 있어야 한다. 약간 기술적인 야치에 있는 많은 사람들이 정규 논리에 대한 교육을 받지 않았기때문에, 그들과 함께 일할때는 매우 주의해야 한다. 룰 내의 코드화된 비즈니스 규칙으로 인해, 여러분은 종종 현재 이해되어지고 있는 비즈니스 로직과 프로세스들 내에 취약점을 노출시킨다. 버그..)

만약 룰이 여러분의 프로젝트 팀에 새로운 기술이라면, 이론적인 내용을 배우는데 많은 시간을 할애야야 할 것이다. 이것은 쉬운 기술은 아니지만, 이 문서에서는 그것을 보다 쉽게 표현하려고 노력하였다.
현대의 객체 지향 어플리케이션 내에서 전형적으로 여러분은 비즈니스 로직의 핵심 부분을 저장하기 위해서 룰 엔진을 사용하려고 할 것이다 (비즈니스 로직이 무엇을 의미하는지는 물론 어플리케이션에 따라 달라질것이다) ? 이것이 특히 정말로 너저분한 부분이다. 이것은 모든 로직을 여러분의 객체에 캡슐화한다는 객체 지향 개념을 뒤집는 것이다. 이것은 여러분이 객체 지향 실 예들을 던져 치워버리라는것을 의미하는것이 아니고, 반대로, 실 세계의 어플리케이션내에서 비즈니스 로직은 단지 어플리케이션의 한 부분이는라 것이다.

만약 여러분이 엄청나게 많은 if, else, switch 문이나, 엄청나게 많은 strategy 패턴, 그리고 다른 적절해 보이지 않는 너저분한 로직을 여러분의 코드 내에서 발견했다면(여러분은 그것을 계속해서 반복해서 고쳤을 것이다. 여러분이 잘못했기때문이거나, 로직이나, 여러분의 로직에 대한 이해도가 변경되었기 때문에) 이런 경우 룰을 사용하는 것을 고려해보라. 만약 여러분이 기존의 알고리즘이나 패턴을 사용하여 풀기 어려운 난해한 문제에 부딛혔을때 룰을 사용하는것을 고려하라.

Rules는 어려분의 어플리케이션에 내장된 형태로 사용되거나 또는 서비스로써 사용될 수 있다. 종종 룰즈는 ‘유상태’ 컴포넌트로써 가장 잘 동작한다 ? 그래서 그들은 종종 어플리케이션의 통합 파트가 된다. 그러나 ‘무상태’ 컴포넌트를 사용하여 재사용 가능한 룰 서비스를 생성한 성공적인 케이스들이 있었다.

여러분의 조직 내에서 여러분이 시스템 내의 룰을 프로덕션중인 시스템 내의 룰을 업데이트하는 프로세스에 관해 생각하는것이 중요하다면, (옵션들은 많지만, 서로 다른 조직들은 서로 다른 요구사항들이 있다. 종종 그것들은 어플리케이션 벤더나 프로젝트 팀들의 제어권에서 벗어나 있다.)


2.2.3. 언제 룰 엔진을 사용해서는 안되는가
Drools 메일링 리스트의 정규원 Dave Hamu의 말을 인용하면.

“내가 보기에는 룰 엔진을 가지고 작업하는게 단지 흥미거리같다. 사람들은 룰 엔진이 단지 복한잡 어플리케이션이사 솔루션의 한 부분이라는것을 잊어버린것처럼 보인다. 룰 엔진은 워크플로우나 프로세스 실행을 위해 바로 사용하도록 의도된것이 아니마, 워크플로우 엔진이나 프로세스 관리 도구들도 룰을 수행하기 위해서 디자인된것들이 아니다. 목적을 위해서 정확한 도구를 사용하라. 물론 몇가지 piler의 도합이 난해한 상황에서 사용될 수 도 있지만, 그것은 디자인 의도와는 다르다.”



 룰 엔진들이 동적이므로 (룰이 데이터처럼 저장되고, 관리되고, 업데이트될 수 있다는 의미다), 그것들은 종종 소프트웨어를 배포하는 문제를 해결하기 위한 솔루션처럼 보인다.(대부분의 IT 부선는 소프트웨어가 rolled out되는것을 금지하기 위한 의도로 존재하는것처럼 보인다) 만약 이것이 여러분이 룰 엔진을 사용하고 싶어하는 이유라면, 룰 엔진이 여러분이 선언적 룰을 사용할 수 있을 경우에만 최선으로 동작한다는 것에 유의하라. 대체품으로써, 여러분은 데이터 드리븐 디자인을 고려할 수 있다(룩업 테이블 같은), 혹은 스크립트 프로세스 엔진을 고려할 수도 있다. 스크립트들이 데이터 베이스 안에 저장되고 관리되기 때문에, 동적으로 업데이트 할 수 있는 것들 말이다.

2.2.4. 스크립팅, 또는 프로세스 엔진.

기쁘게도, 이전 섹션은 여러분에 언제 룰 엔진을 사용하기를 원할 수 있을까에 대해 설명하였다.

대체 방안은, 스크립트 기반의 엔진이다, 이것은 운영중 변경을 위한 역동성을 제공한다. (여기에는 매우 많은 솔루션들이 있다)

대체 Process Engines (또한 워크플로우 엔진)같은 것들, 예를들어 jBPM은 여러분이 시각적으로 (또는 프로그램적으로)프로세스 내의 단계를 기술할 수 있도록 만들어준다.
- 이러한 단계들은 또한 결정 시점(decision point)를 포함할 수 있으며, 결정시점은  그 내부에 간단한 룰을 가지고 있다. 프로세스 엔진들과 룰은들 종종 매우 함께 잘 동작한다. 그래서 둘중 하나만 취할 수 있는것이 아니다.

룰 엔진을 기술하기 위한 한가지 핵심 포인트는, 몇몇 룰 엔진들이 실제로는 스크립팅 엔진이라는 것이다. 스크림팅 엔진들의 downside는 여러분이 당신의 어플리케이션을 스크림팅 엔진과 강하게 결합시켜야 한다는 것이다. (만약 그것들이 룰들이라면, 여러분은 룰들을 직접적인 방식으로 효과점으로 호출해야 한다) 그리고 이것은 차후의 유지보수를 더욱 어렵게 만들수도 있다. 그것들이 시간이 지남에 따라 복잡도가 증가하는 경향이 있기 때문에다. 스크립팅 엔진의 장점은 그것들이 초기에 구현하기가 훨씬 쉽다는 것이다. 그리고 여러분이 빠른 결과를 받아볼수 있다는 것이다. (그리고 imperative 프로그래머들에게 개념적으로 훨씬 쉽다)

많은 사람들이 데이터 드리븐 시스템을 성공적으로 구현해왔다. (여러분의 어플리케이션의 행동양식을 변경하는 메타데이터를 저장하고 있는 컨트롤 테이블들이 있는)
이것들은 컨트롤이 매우 제한적인 상태로 남아있을때 매우 잘 동작할 수 있다. 그러나 컨트롤이 지나치게 많아지는 경우, 빠르게 제어권을 상실할 수 있다. (이런 경후 최초 개발자만이 어플리케이션의 행동양식을 변경할 수 있다.) 혹은 그것이 어플리케이션이  지나치게 유연하지 못하게되어 정체되도록 만들수도 있다.

2.2.5. Strong and Loose Coupling
여러분은 아마도 ‘tight coupling’이라는 용어와 ‘loose coupling’ 이라는 용어를 시스템 디자인 관련해서 들어보았을 것이다. 일반적으로 사람들은 디자인적인 측면에서 loose나 weak coupling 이라고 주장하기를 더 좋아한다, 왜냐하면 이것이 유연성을 제공하기 때문이다. 유사하게, 여러분은 ‘strongly coupled’, ‘weakly coupled’ 룰이라는 용어를 사용할 수 있다.

강하게 결합되었다는 것은, 하나의 룰이 실행되면, 반드시 관련된 또다른 룰이 실행된다는것을 의미한다. 달리 말하면, 룰간에 연결고리가 있다는 것이다. 만약 여러분의 룰들이 강하게 결합되어 있다면, 나중에 룰을 변경하는데 있어 유연함이 떨어질것이고, 더움 중요하게, 이것은 아마도 룰 엔진이 overkill이고 (로직이 룰들의 명확한 집합으로써, 하드코딩될 수 있다 [결정 트리가 특정 순서를 가질 수 있다.] 이것은 강한 결합, 또는 약한 결합이 태생적으로 나쁘다는 것을 말하는 것이 아니며, 룰 엔진을 고려하고 어떻게 룰들을 capture할 것인지를 명심하는 것이 포인트라는 것이다. 약하게 결합된 룰들은 시스템내에서, 관계 없는 다른 룰들을 변경할 필요 없이 룰들을 쉽게 제거하고 추가하고 변경될 수 있도록 만들어준다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/22 10:37 2008/08/22 10:37

사용자 삽입 이미지
놀새~의 블로그 제목이 "변화를 두려워하면 1등은 없다"입니다. 왜 변화를 두려워하는가 라는 주제로 메인 타이틀을 적고 있습니다. 하지만 제조업 등의 경우에는 변화가 더 무서운 결과를 초래할 수도 있습니다.

몇 조의 돈을 들여 생산 라인을 만들고 그 설비를 제어하는 시스템을 만들었을 경우겠죠. 이 경우에는 일반적인 생각이라면 반드시 검증된 솔루션 또는 기존의 설비에서 사용되던 솔루션들을 가지고 하는 게 일반적입니다.

장애가 1시간이라도 발생해서 라인이 멈추게 되면 수백억씩 날아가는 상황이라면 여러분은 어떻게 하시겠습니까? 항상 얼리 어댑터의 마음으로 새로운 솔루션을 도입하시겠습니까?

어려운 문제입니다. 그러한 고객을 설득하는 게 제 임무인데 쉽지 않겠죠. IT분야의 변화를 하지 않아도 1등을 유지하는 데 문제가 되지 않는 경우는 허다합니다.
크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/21 14:51 2008/08/21 14:51

Rule Engine이란..

CONSULTING 2008/08/21 09:53

JBoss GLS(Global Learning Service) 최현덕 과장님의 글입니다.

인공지능(Artificial Intelligence, A.I.)은 컴퓨터가 사람처럼 생각하도록 만드는것에 초점을 맞추는 매우 넓은 범위의 학문이며, 신경망(Neural Network), 유전자 알고리즘(Generic Algorithm), 결정 트리(Decision Tree), 프레임 시스템(Frame System), 전문가 시스템(Expert System) 등의 다양한 원리들을 포함하고 있다. 지식 표현(Knowledge representation)은 인공 지능에서 연구하는 분야중 하나이며, 우리가 알고 있는 지식을 어떻게 표현하고 기계적으로 다룰 수 있는지를 연구하는 학문이다. 전문가 시스템(Expert System)은 이러한 지식 표현 기법을 사용하여 지식들을 어떠한 결론을 추론하는데 사용할 수 있도록 특정 저장소에 지식을 코드화해서 집어넣는다. 이 지식 저장소(Knowlege Base)를 사용하여 우리는 특정 데이터를 프로세싱하여 결론을 추론해낼 수 있다. 전문가 시스템(Expert System)은 보통 ‘Knowledge Base System’, ‘Knowledge Base Expert System’이라는 이름으로 더 많이 알려져 있으며, 인공 지능이 적용된 시스템으로 간주된다. 이한러 전문가 시스템을 이용하여 시스템을 개발하는 과정을 Knowledge Engineering 이고라 한다.

EMYCIN은 전문가 시스템을 위한 최초의 ‘shell’들 중 하나였다. 이것은 건강 진단 전문가 시스템인 MYCIN으로부터 생성되었다. 이것들은 초기 버전의 전문가 시스템이었기 때문에, 많은 로직들이 하드코딩되어 있었고, 사용자가 손쉽게 입력할 수 있도록 ‘shell’은 시스템의 로직과 분리되었다.  Drools는 전문가 시스템을 구축하기 위해 룰 기반의 접근 방식을 사용하는 룰 엔진이고, 보다 정확하게 분류하면 Production Rule System에 해당한다.

Production Rule 이라는 용어는 정형 기법 문법(formal grammar)으로부터 유래하였다. 정형 기법에서 그것은 “정형 기법 언어를 정확하게 기술하기 위한 추상적인 구조” 예를 들어 ‘수학적으로 알파벳을 사용하여 만들어 낼 수 있는, 유한 길이의 문자열’을 정의하는 규칙들의 집합이 이러한 Production Rule에 해당한다. (wikipedia 참조)

비즈니스 룰 관리 시스템은 일반적인 용도의 룰 엔진에 비즈니스 사용자에 초점을 맞축, 룰 생성, 관리, 배치, 분석 기능을 제공하는 사용자 도구들을 추가하여, 룰 엔진의 가치를 배가시킨다. 이와같은 도구들에 힘입어 ‘비즈니스 룰 접근방식’은 빠르게 진화하고, 인기있는 방법론이 되어가고 있다. 이 방법론은 기업 내에서 룰 엔지니어들이 어떤 작업을 수행해야 하는지를 정형화하는것을 도와준다.

Rule Engine 이라는 용어는 매우 모호하다. 룰을 사용하는 모든 시스템들이 이러한 엔진에 해당하기 때문이다. 예를들어 특정 규칙에 의거하여 결과 데이터를 생성해내는, 폼 유효성 체크 엔진이나, 동적 표현식 엔진같은 단순한 시스템들도 이러한 룰 엔진에  포함될 수 있다. 
 Malcolm Chisholm의 저서 “How to Build a Business Rules Engine (2004)" 는 이러한 모호성을 잘 나태내준다. 이 책은 실제로, 유효한 규칙들을 저장하기 위한 데이터베이스 스키마를 구축하고 변경하는 방법에 관한 책이다. 이 책은 그 다음, 이 데이터 입력값을 체크하는 규칙들을 가지고 VB코드를 작성하는 방법에 관해 보여준다. 물론 이은것 누군가에게는 매우 유용한 주제일 수 있다. 하지만 필자처럼 룰 엔진을 전문적으로 다루는 사람들은, 많은 이들이 룰 엔진의 미묘한 차이에 대해 모르고 있다는 것에 대해서 놀라움을 금치 못했다. 또한 Drool 엔진을 좀더 효과적으로 개선하기 위해서, 룰 엔진에 대한 좀더 세부적인 내용들을 이 책에서 찾으려고 했던 사람들은 크게 실망했을 것이다.
Jboss jBPM은 그것의 Decision node내에서 표현식들과 위임방식을 사용한다. 이것은 워크플로우 내에서 작업이 진행되는것을 제어한다. 평가되는 각각의 노드들은 언제 상태 전이가 일어나야하는지에 관한 규칙 집합들을 가지고 있고. 이것도 또한 Rule Engine이다. 반면에 Production Rule 시스템은 룰 엔진의 한 종류일뿐만 아니라 전문가 시스템이다. 이전에 언급된 유효성 체크와 표현식 평가하는 룰 엔진들은 전문가 시스템이 아니다.

Production Rule System은 지식 표현에 초점을 맞추고, propositional과 일차 술어 논리(first order logic)을 명확하고, 모호하지 않은 선언적인 방식으로 표현하기 위한 지식 표현에 초점을 맞춘 튜링 머신(Turing Machine)이다.
Production Rules System의 핵심은 추론 엔진이다. 이것은 보다 많은 수의 룰과 팩트들로 확장이 가능하다. 추론 엔진은 팩트와 데이터를 비교하고, 생성 규칙에 기반하여, 결론을 추론해낸다. 이것이 최종 결과물이 된다. 이 생성 규칙은 Production이라고 불리기도 하고, 단지 Rule 이라고 불리기도 한다. 생성 규칙은 두개의 구조 부분을 갖는다. 지식 표현을 위한 First Order Logic을 사용하는 경우. 다음과 같이 두 부분으로 구성된다.

1차 논리(first-order logic), 1차 술어 논리는 수학, 철학, 언어학, 컴퓨터 과학 등에서 쓰이는 형식 언어로, 일반적으로 술어논리로 부르기도 한다. 명제논리를 보다 강력하게 확장한 것이다.
http://ko.wikipedia.org/wiki/1%EC%B0%A8_%EB%85%BC%EB%A6%AC

when
    <conditions>
then
    <actions>
프로덕션 룰에 대하여 신규 팩트나 기존 팩트들을 대한 매칭하는 프로세스는 패턴 매칭이라고 불리며.  Pattern Matching, 이 작업은 추론 엔진에 의해 수행된다. 추론 엔진이 사용하는 패턴 매칭 알고리즘은 여러 가지가 있는데,  다음과 같은 것들이 포함된다.

  • Linear
  • Rete
  • Treat
  • Leaps

Drools는 Rete 알고리즘을 구현하고 확장하였으며, Leaps는 이전 버전에서는 지원되었지만, 잘 유지보수가 되지 않아 현재는 지원되지 않는다. Drools Rete 구현은 ReteOO라고 불리며, Drools가 객체 지형 시스템을 위한 Rete 알고리즘의 구현을 개선하고 최적화한것을 의미한다. 다른 Rete 기반 엔진들 또한 마케팅적인 측면에서 자신들의 독점적인 강화된 Rete 알고리즘 구현을 나타내는 마케팅 용어를 가지고 있다. RetePlus나 ReteIII 같은 것들이다. ReteIII 같은 이름들이 단지 마케팅적인 용어이기 때문에, 그것들이 실제 오리지널 Rete 알고리즘과 다르다는 것 이외에, 실제 어떻게 구현되어져 있는지는 전혀 공개되어 있지 않다는것을 아는 것은 중요하다. 이런 이유때문에. “Drools가 ReteIII 알고리즘을 구현하고 있나요?”와 같은 질문들은 전혀 말이 되지 않는것이다. 현재 가장 일반적인 개선사항들은 다음 책에서 다루어지고 있다. "Production Matching for Large Learning Systems (Rete/UL)" (1995) by Robert B. Doorenbos.

Rules 는 Production Memory 내에 저장되며 추론 엔진이 매치시키는 팩트들은 Working memory에 대응한다. 팩트들은 working memory 내에서 assert되며, 그 다음 수정된 후 다시 검증될 수 있다. 매우 많은 룰과 팩트들을 가진 시스템든 동일한 팩트에 대한 검증에 대해 여러 많은 룰들이 true값을 결과로 반환할 수도 있다. 이러한 룰들을 confilict충돌 이라고 부른다. Agenda는 Conflict Resolution 전략을 사용하여 이러한 충돌하는 룰들의 실행 순서를 다룬다.

사용자 삽입 이미지



Production Rule System의 추론 엔진은 상태를 지니고 있으며, 이러한 상태를 기반으로 추론하는 것을 Truth Maintenace라고 한다. 논리적인 관계는 액션들에 의해 선언될 수 있는데. 이것은 액션의 상태가 추론이 true인 상태로 남아있는가에 의존하는 것을 의미한다.
그것이 더이상 true가 아닌경우 논리적인 의존 관계에 있는 action들은 수행되지 않는다. Drools의 예제중 하나인 “Honest Politician”은 Truth Maintenance의 한가지 예이다. 이것은 우리가 정직한 정치가들을 가지고 있다면. 민주주의에 항상 희망이 존재한다는 것을 확신시켜준다.
when
    an honest Politician exists
then
    logically assert Hope

when
   Hope exists
then
   print "Hurrah!!! Democracy Lives"

when
   Hope does not exist
then
   print "Democracy is Doomed"
Production Rule을 수행하기 위한 두가지 방법이 있는데, 하나는 Forward Chaining 이고, 다른 하나는 Backward Chaining 이다. 이 두가지 방식을 모두 구현하고 있는 시스템들은 Hybrid Production Rule 시스템이라고 불린다. 이 두가지 실행 방식을 이해하는 것은, 왜 Production Rule System이 서로 다르고, 우리가 그것들로부터 최선의 결과를 얻어낼수 있는가를 아는데 핵심적이다. Forward Chaining은 ‘data-driven’이고 그래서 reactionary이다.- 이것은 팩트들이 작업 메모리 내에서 assert되고, 이것이 하나, 그 이상의 rule들을 동시에 true로 만들고, Agenda에 의해서 스케줄링 되는것이다 -
우리는 팩트에서부터 시작하고, 그것이 전파되고 우리는 최종적으로 결론을 얻는다. Drools는 포워드 체이닝 엔진이다.

사용자 삽입 이미지
<Forward Chaining>

 Backward Chaining은 ‘goal-driven’이다. 이것은 우리가 결론으로부터 시작해서, 엔진이, 결론을 만족시키는 조건을 시도하는것을 의미한다. 만약 그것이 결론을 만족시킬 수도 있는 sub-goal’이라고 알려진 것들을 찾지 못할 경우, 초기 결론이 증명되거나, 혹는 더이상 어떠한 sub-goal들도 존재하지 않는다는것이 확인될때까지  계속해서 이 프로세스를 반복한다.
 Prolog는 이러한 Backword Chaining Engine의 한 예이다. Drools는 다음 버전 릴리즈에서 Backward Chaining에 대한 지원을 추가할 예정이다.

사용자 삽입 이미지

<Backward Chaning>

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/21 09:53 2008/08/21 09:53

현재 상태
-------------------------------------------------------------------
평균 비거리 : 270~290야드
좌우 오차 : 4~6 Left
출발 탄도 : Good
출발시 좌우 오차 : 4~6
볼 최고 높이 : 120 FT
Back Spin : 4000 rpm
Side Spin : 2000~2500 rpm <-- Slice의 주원인
최적의 구성을 Side Spin/Back Spin의 경우 1:10의 비율이 최적임.
클럽 헤드스피드 : 104 mph(Korean Tour Professional Level)

클럽선택
-------------------------------------------------------------------
Loft : 9.0~9.5도
샤프트 : 토크 2.5도~3.5도 사이의 Stiff or SX(Stiff, Extreme)
클럽길이 : 45 inch
체적 : 425cc급.
그립 0.60 TV(Tour Velvet) or 0.60 Regular(All Vendor)
크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/19 23:52 2008/08/19 23:52