괄호 -> 단항연산자 -> 곱하기/나누기 -> 덧셈/뺄셈 ->시프트 -> 관계연산자 -> 비트 연산자 -> 논리 연산자 -> 대입 연산자
Posted by '김용환'
,

vc++ 팁

c++ 2005. 11. 8. 19:43

Visual C++ 팁

1. dll 파일을 만들기 위해서 다음과 같은 Project를 써야 한다.
- New Project - MFC AppWizard(dll) (mfc를 쓰고 있는 상황이라면)
- New Project - Dynamic-Link Library
- New Project - Static Libarary

2. MFC AppWizard(dll)을 선택, static? shared libary 선택
- Project-Setting-General
  Microsoft Foundation Classes : Use MFC in a Static Library 또는 Use MFC in a Shared Library 선택
  (static버젼을 선택하면, dll에 모든 모듈을 static하게 모은다. shared를 선택하면, 윈도우의 시스템 lib을 이용한다.)

3. Output Dir 선택
- Project-Setting-General-Output directories

4. 다른 프로세스를 이용하여 실행시키기
- Project-Setting-Debug
  Category를 General로 선택,
    Executable fo debug session에  C:\Program Files\Java\jre1.5.0_05\bin\java.exe
    Working directory에 debug
    Program argument에 -classpath dew.jar com.alticast.dmb.dew.factum.FactumRequestor

5. Unicode language 설치
- CD에서 setup.exe 선택
  Visual C++ 6.0 선택 - VC++ MFC and Template Libraries - MS Foundation Class Libraries - Static Libraries for Unicode, Shared Libraries for Unicode 선택

6. c++ 코드와 c 소스 컴파일할때 문제 해결.
- Project-Setting-C/C++
  Category를 Precompiled Headers에서 Not using precompiled headers

7. 이 프로젝트에서 어떤 모듈이 필요한지 알고 싶을때
- Project-Setting-C/C++
  Category를 General 선택, Preprocesser definitions 을 WIN32,_DEBUG,_WINDOWS,_MBCS,_USRDLL,_UNICODE,_WINDLL확인
  => unicode lib이 필요하구나..

8. link시 output 파일을 지정하고 싶을 때.
- Project-Setting-Link
  Category를 General로, Output file Name을 Debug/dls.dll로 선택

9. Include, library, executable 파일을 들어 있는 디렉토리 선택
  Tool - option - Directories 에서 추가

Posted by '김용환'
,

http://www.grasp.upenn.edu/~mcken/grasplab/hints/msvc.html

 

Microsoft Visual Studio and C++

Documentation

To build programs from a command shell

You can use the Visual C++ compiler cl.exe directly from a command shell, much as you would use a Unix compiler. First, set the shell's environment variables INCLUDE, LIB, and PATH to record the following directories:

Variable Path(s)
INCLUDE d:/pkg/VisualStudio/VC98/include
LIB d:/pkg/VisualStudio/VC98/lib
PATH d:/pkg/VisualStudio/VC98/bin
d:/pkg/VisualStudio/Common/MSDev98/bin

For a t-shell, add these to your Windows startup file .tcshrc-windows. For a bash shell, it seems you must set INCLUDE and LIB before starting bash. You can simply assign them via the Control Panel.

Use your favorite text editor, such as Emacs, to edit your source files. You'll probably want to add the GNU/Cygwin utilities to your path, too.

To see a list of options for cl.exe, open the Microsoft Visual C++ 6.0 IDE, select Help -> Index from the menubar, and type "CL options" for the keyword to find.

To build programs using a C/C++ API

The Lab provides several C/C++ APIs, including MIL, ImageMagick, Intel libraries, OpenGL/GLUT, and VTk. To build and run programs using an API, you usually need to specify the location of header and library files for the compiler and the system run-time linker. Here's the general procedure for a fictitious API, called "api." For clarity, let's suppose it is installed under p:/api and that our application requires its header file p:/api/api.h, LIB file p:/api/api.lib, and DLL file p:/api/api.dll. The big picture:

  1. Put the following line in each source file that uses the API: #include <api.h>
  2. Tell the compiler to look for the header file api.h in directory p:/api.
  3. Tell the linker to search p:/api/api.lib when resolving symbols.
  4. Add p:/api to your shell's PATH variable so the run-time system can find api.dll.

Here's an example for building program main.exe from main.c via the command line. The C source file calls functions from the API, which it declares by including api.h. To compile main.c into main.obj without linking:

   -> cl -c main.c -Ip:/api
The include directive in the source file tells the compiler to look for and use the header file aph.h of the API. The switch "-Ip:/api," in turn, tells the compiler to look in directory p:/api when searching for header files. Thus the compiler finds and includes p:/api/api.h.

Next, to build main.exe from main.obj:

   -> cl -Femain.exe main.obj p:/api/api.lib
This tells the linker to look in library file p:/api/api.lib when resolving symbols, like functions, not defined in main.obj. Thus the linker finds the functions provided by the API. (For static libraries, the linker finds and incorporates the object code into the executable. For dynamic libraries, the linker incorporates stub object code that loads the actual library object code at run time.) You can also specify the search path and the library separately, like so:
   -> cl -Femain.exe main.obj -LIBPATH:p:/api api.lib
The switch "-LIBPATH:p:/api" tells the compiler to look in directory p:/api when searching for libraries specified on the command line. Thus it finds and searches p:/api/api.lib. This approach is convenient when linking against multiple libraries from the same API.

Of course, you can combine these two steps into one:

   -> cl -Femain.exe main.c -Ip:/api p:/api/api.lib

If you prefer, you can add p:/api to your shell's INCLUDE variable and omit "-Ip:/api" above. Similarly, you can add p:/api to your shell's LIB variable and omit the path "p:/api" from "p:/api/api.lib" or omit "-LIBPATH:p:/api." Under a t-shell, for example:

   -> setenv INCLUDE "${INCLUDE};p:/api"
   -> setenv LIB "${LIB};p:/api"
   -> cl -Femain.exe main.c api.lib

When builing programs from within Visual Studio, you specify the header and library information under "Project -> Settings." For compiling, click the C/C++ tab, select Preprocessor from the Category box, and enter p:/api in the "Additional include directories" box. For linking, click the Link tab and enter p:/api/api.lib in the "Object/library modules" box. Alternatively, you can enter only api.lib in the this box, choose Input from the Category box, and list p:/api in the "Additional library path" box.

Finally, you need to adjust your shell's PATH variable if the API uses a DLL. If you run from a t-shell, for example, adjust your path like this.

   -> setenv PATH "${PATH};p:/api"
Or, add this path in the startup files. If you run your program from Visual Studio, use the System applet in the Control Panel as you would to set your HOME variable. Adjust your path before opening Visual Studio.

Generally, an API puts its header and library files in separate subdirectories include and lib of its main directory. The aggregate build command would look something like this:

   -> cl -Femain.exe main.c -Ip:/api/include -LIBPATH:/p:/api/lib api.lib
See the API's hints for details on what paths to list.

Trouble saving files

If Visual Studio reports that it cannot save files to the h: drive, make sure that you have sufficient quota. If it cannot save to a network drive mapped to a project directory, make sure that directory's disk has sufficient free space. If it cannot save to a local disk drive, make sure that disk has sufficient free space. In all cases, you must have suitable write access to the file or its directory, of course.

Use the i: drive in Visual Studio IDE (obsolete)

[The Lab's h: drive is no longer sensitive to case, so the \\grasp\homeci share and the i: drive are no longer necessray or supported. These notes are retained for the record.

When using the Visual Studio IDE (integrated development environment), specify the i: drive instead of the h: drive to access your Grasp home directory. To do so, you must map i: to \\grasp\homeci (just once).

The map to your home directory on Grasp through the h: drive is case-sensitive, in consistency with Grasp's unix file system. For some reason, Visual Studio does not preserve case in file names; it appears to change file names to upper case. Consequently, Visual Studio usually cannot find files you specify with the h: drive. To get around this foolishness, file requests through i: match different cases in file names if the original request is not found.

By the way, the i: drive is a convention for the map to \\grasp\homeci. (Mnemonics: "i" for "insensitive"; "i" follows "h"; "ci" for "case-insensitive") You can choose another letter if you prefer.]

Error spawning cl.exe (obsolete)

[The Lab PCs have been re-configured to prevent this error. These notes are retained for the record.

If you get this error, your roaming profile records an incorrect directory for the Microsoft Visual C++ installation on the PC. Consequently, Microsoft Visual C++ cannot locate the compiler executable. The problem occurs because Microsoft Visual C++ is not yet installed in a uniform directory across PCs. This inconsistency is being resolved actively, but slowly. In the mean time, here's a fix:

  1. Exit Microsoft Visual C++.
  2. Select Start -> Run... and enter regedit. This starts the registry editor.
  3. Carefully navigate down this path:
       H_KEY_CURRENT_USER
          Software
             Microsoft
                DevStudio
                   6.0
                      BuildSystem
                         Componenets
                            Platforms
                               Win32 (x86)
                                  Directories
    
  4. Carefully right-click on the Directories key and choose Delete.
  5. Exit from the registry editor.]

Posted by '김용환'
,
Java Native Interface에 관련된 서적을 찾으려고 아마존을 뒤적일 때, 다음과 같은 서평을 보게 되었다. “한 가지 분명한 사실은 JNI를 쓰지 않는 것이 훨씬 좋다는 것이다. JNI는 다루기 힘들고, 불안정하며, 에러가 발생할 소지가 많으며, 무엇보다도 JNI가 쏟아내는 Runtime 에러는 자바 가상 머신을 날려 버릴 수 있는 사악한 기술이다.” 이 서평을 쓴 사람은 그 책을 사서 봤을 것이며, 단지 관심에서가 아니라 심각하게 Java Native Interface를 사용했을 것이며, 아마도 사용하고 있을 것이다. JNI는 자주 사용되지는 않지만, 그렇다고 불필요한 기술도 아니다. 아니 절대적으로 필요한 기술임이 틀림없다.

Java Native Interface는 자바에서 다른 언어로 개발된 기능을 내부적으로 사용할 수 있게 해 준다. 이미 C 언어나 C++로 개발된 기능이 있다면 그것을 자바 프로그램 안에서 사용할 수 있게 해 준다. 이 글은 JNI을 사용하는 두가지 간단한 예제를 통해 JNI가 무엇이며, JNI를 어떻게 사용하는지에 대해 간단히 살펴볼 것이다. 첫 번째 예제는 항상 등장하는 HelloWorld식 예제이고, 두 번째는 C 언어로 개발된 정렬 프로그램을 자바 프로그램에서 사용하는 예제이다.

썬 자바 사이트에는 JNI를 구현하는 여섯가지 단계를 설명하고 있다.
1. Native 메소드를 호출하는 자바 코드 작성.
2. 첫 단계에서 쓴 자바 코드의 컴파일.
3. javah 명령어를 사용하여 헤더 파일의 생성.
4. 지정된 언어로 호출되는 Native 메소드를 구현.
5. Native 메소드를 구현한 코드를 동적 라이브러리로 컴파일.
6. 실행.

Native 메소드를 호출하는 자바 코드에는 세 가지 요소가 포함된다. Native 메소드의 선언, 실제 Native 메소드의 사용, 동적 라이브러리를 시스템 상에 상주하도록 불러오는 것이다. 이 세 가지는 아래 코드에서 강조되어 있다.


[HelloWorld.java]
/*
 * Created on 2004. 12. 31.
 * File name : HelloWorld.java
 * @author DaeGon Kim
 *
 */
public class HelloWorld {

              String greeting = "Hello Java World";

              public native void display();

              public static void main(String[] args) {

                            HelloWorld hw = new HelloWorld()
              System.out.println(hw.greeting);
                            hw.display();
                            System.out.println(hw.greeting);

              }

              static {
                            System.load("D:\\Project\\Java\\hello.dll");
              }

}


두 번째와 세 번째 단계에서는 javac 명령어로 HelloWorld.java를 컴파일한 후, javah 명령어로 헤더 파일을 생성한다.
> javac HelloWorld.java
> javah HelloWorld
javah 명령을 실행하면, 아래에 보이는 HelloWorld.h가 생성되며, 이 파일을 수정하지 않는다.


[HelloWorld.h]
/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    display
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_display
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


헤더 파일에서 강조된 부분은 실제 C 언어로 구현되어야 하는 함수이다. JNIEXPORT와 JNICALL과 같은 자바와 관련된 용어의 등장에서 알 수 있듯이, 헤더 파일에 정의된 함수를 구현하는 C 파일을 컴파일하기 위해서는 자바 시스템에서 포함되어 있는 파일이 필요하다. 환경설정에 관한 설명은 C 파일의 컴파일 단계에서 설명하기로 하고, C 언어로 위 함수를 구현해 보자.


[HelloWorld.c]
#include 
#include "HelloWorld.h"
#include 


JNIEXPORT void JNICALL Java_HelloWorld_display(JNIEnv *env, jobject this) {

    jfieldID       fldid;
    jstring        greeting;
    const   char   *temp;

    // 넘겨지는 객체 this의 클래스를 가져온다.   
    jclass instance = (*env)->GetObjectClass(env,this);

    printf("   Start of C implementation.\n");
    
    if ( this == NULL ) {
        fprintf(stderr, "Input pointer is null!");
        return;
    }
    
    // 클래스 안에서 greeting이라는 속성이 가진 위치를 가져온다.
    fldid = (*env)->GetFieldID(env, instance, "greeting", "Ljava/lang/String;");
    
    if ( fldid == NULL ) {
        fprintf(stderr, "Failed to get the field id\n");
        return;
    } 
    
    // 실제 객체에서 fldid에 있는 값을 읽어온다.
    greeting  = (*env)->GetObjectField(env, this, fldid);
    // 일어온 값을 C 데이터로 변환한다.
    temp      = (*env)->GetStringUTFChars(env, greeting, NULL);
   
    printf("      %s \n", temp);

    // 자바의 String 필드에 저장할 값을 만든다.
    greeting = (*env)->NewStringUTF(env, "Hello C World");
   
    if ( greeting == NULL ) {
        printf("Out of memory\n");
        return;
    }
    
    // greeting에 저정돤 값을 자바 객체로 전달한다.
    (*env)->SetObjectField(env, this, fldid, greeting);

    printf("   End of C implementation \n");
   
    return;

}


이제 필요한 모든 파일을 갖추어졌다. 이제 컴파일하고 실행하는 일만 남아 있다. 컴파일 하기 위해서는 몇 가지 설정이 필요하다. 앞으로 기술되는 설정은 윈도우를 기준으로 하고 있고, 마이크로 소프트 C 컴파일러를 쓴다는 가정하에서 기술되었다. 먼저, jni.h가 필요하다. 이 파일은 자바 홈디렉토리(이하 JAVAHOME) 아래 include 디렉토리에 있으며, 그 아래에 있는 win32 디렉토리도 include에 포함되어 있어야 한다.

set INCLUDE=%JAVAHOME%\include;%JAVAHOME%\include\win32;%INCLUDE%

LIB 속성을 위해서는 JAVAHOME 아래에 있는 lib 디렉토리가 포함되어야 한다.

set LIB=%JAVAHOME%\lib;%LIB%

위에서 설명한 설정은 JNI를 사용하게 됨에 따라 추가적으로 해야 하는 설정이며, Command Prompt에서 VC7 컴파일러를 실행하고자 할 때는 다음의 설정이 추가적으로 필요하다.

INCLUDE : VC 홈 디렉토리 아래에 있는 include 디렉토리
LIB : VC 홈 디렉토리 아래에 있는 lib 디렉토리
PATH : Studio 홈 - Common7 아래에 있는 IDE, VC 홈 디렉토리 아래에 있는 bin 디렉토리.

이제 남은 일은 HelloWorld.c를 컴파일하고 HelloWorld를 실행하는 일만 남았다.

cl HelloWorld.c -Fehello.dll -MD -LD

위의 명령어를 실행하면 hello.dll 파일이 생성된다. 그리고 나서 HelloWorld 클래스를 실행하면 다음과 같은 결과를 얻게 될 것이다.


Hello Java World
   Start of C implementation.
      Hello Java World
   End of C implementation
Hello C World


이것으로 첫 번째 예제가 성공한 것이다. 이 예제는 일반적으로 JNI가 사용되는 방식과 거리가 있어 보인다. JNI는 개발 중인 자바 어플리케이션이 있으며, 이미 개발된 Native 라이브러리가 존재한다. 두 번째 예제에서는 기존에 C 언어로 개발된 정수 정렬 함수를 자바에서 사용하는 예제이다.

먼저 Sort.c를 살펴보자. 흔히 볼 수 있는 C로 구현된 Insertion 정렬 함수이다.


[Sort.c]
#include 
#include 

int *sortIntegers(int *A, int n) {
    
    int i   = 0;
    int j   = 0;
    int key = 0;
    
    for ( j=1; j < n ; j++ ) {
        key = A[j];
        i = j - 1;
        while ( i >=0 && A[i] > key ) {
            A[i+1] = A[i];
            i--;
        }
        A[i+1] = key;
    }
    
    return A;
    
}


Sort.h 에는 Sort.c 안에 구현된 함수의 리스트가 나열되어 있다.


[Sort.h]
int *sortIntegers(int *A, int n);


이제 이 함수의 기능을 사용하는 Sorting.java 를 작성하자.


[Sorting.java]
public class Sorting {

    public static native int[] sort(int[] A, int n);
    
    public static void main(String args[]) {
        
        int Input[] = {3,4,7,2,5,6,9,11,1,8,10};
        
        int sorted[] = sort(Input, Input.length);
        
        for (int i=0; i < sorted.length ; i++ ) {
            System.out.println("A[" + i + "] = " + sorted[i]  );
        }
    }
    
    static {
        System.load("D:\\Project\\Java\\sorting.dll");
    }
    
}


Sorting.java를 컴파일 하고, Sorting 클래스를 사용하여 Sorting.h 를 생성한다. 이제 남은 일은 HelloWorld.c 와 같은 입력값과 반환값을 전달해주는 C 프로그램이다.


[Sorting.c]
#include 
#include "Sorting.h"
#include "Sort.h"
#include 

JNIEXPORT jintArray JNICALL Java_Sorting_sort(JNIEnv *env, jclass cl, jintArray arr, jint n) {

    jint       *A   = NULL;
    jintArray  temp = NULL;
    
    A = (*env)->GetIntArrayElements(env, arr, NULL);
    
    if ( A == NULL ) {
        fprintf(stderr, "Failed to get int array\n");
        return arr;
    }
    
    A = sortIntegers(A, n);
    
    temp = (*env)->NewIntArray(env, n);
    
    (*env)->ReleaseIntArrayElements(env, temp, A, 0);
    
    return temp;

}


Sorting.c 를 컴파일하자. 이 때 다음과 같은 에러가 발생한다면,

“LINK : warning LNK4098: defaultlib 'LIBC' conflicts with use of other libs; use /NODEFAULTLIB:library”

Sorting.c 와 Sort.c가 다른 방식으로 컴파일 되었기 생긴 에러이다. Sort.c를 MD 옵션으로 다시 컴파일하면, 정상적으로 컴파일될 것이다. 이제 Sorting 클래스를 사용할 수 있다. Sorting 클래스를 실행하면 다음과 같은 출력을 보게 될 것이다.

A[0] = 1
A[1] = 2
A[2] = 3
A[3] = 4
A[4] = 5
A[5] = 6
A[6] = 7
A[7] = 8
A[8] = 9
A[9] = 10
A[10] = 11


필자는 여기에서 어떻게 Wrapper 프로그램을 작성하는지에 대해서 설명하지 않았다. 하지만 앞에서 다룬 두 예제에는 Primitive 타입인 int, 배열, 객체를 다루었기 때문에 각 경우에 해당되는 함수 리스트만 있으면, 프로그램에 별 어려움이 없으리라 생각된다. 다음 기사에는 JNI가 자바 가상 머신을 날려버려 전체 자바 어플리케이션이 다운되는 것을 피해가는 방법에 대해서 살펴보도록 하자. <@NHN@LINEBREAKER@NHN@>

한빛 네트워크 > 프로그래밍

저자: 김대곤

원문: http://network.hanbitbook.co.kr/view.php?bi_id=1033

Posted by '김용환'
,

비쥬얼 스튜디오 닷넷이 나온지 한참 되어가지만 여전히

익숙한건 버릴수 없는 처지네요..

아직도 무슨 개발을 하던 스튜디오 6.0을 사용하는 추세인건

부정할 수 없듯이..ㅋㅋ


http://www.microsoft.com/msdownload/platformsdk/sdkupdate/default.htm
에 접속하여 core SDK 및 Internet Development SDK 를 설치하면 됩니다~~~.
설치가 끝나면 기본적으로 C:\Program Files\Microsoft SDK 에 설치 되게 됩니다.
그럼 이넘을 비쥬얼 스튜디오 내부에서 인지 할 수 있도록 세팅 해 줍니다.

Tools -> Options... -> Directory 탭 을 선택하고
include 와 Lib 에 위 디렉토리를 추가하고 가상 상위로 올려 줍니다.
(최신 인클루드 파일과 라이브러리를 사용하겠다란 의미죠)

일단 지금 Mdi 프로그래밍을 공부하는데 있어서 이런 기초적인 유틸정보는

가지고 있어야 겠다는 생각을 합니다~~

Posted by '김용환'
,
HTML 특수 문자

HTML 문서에서 <HTML>태그와 같이 표현 하기 위해서는 특문을 사용 해야 합니다.
그렇지 않고 꺽쇠 문자기호를 이용해서 사용 하면 브라우저에서 그대로 태그로 인식됩니다. 실제로 태그를 표현 하기 위해서는
&lt;HTML&gt; - 브라우저에서 <HTML>로 표현 됩니다.

[&] 특수 문자를 표현하기 위한 시작을 알립니다.
[;] 특수 문자를 표현하고 끝마침을 알립니다.
[#] ASCII 또는 Unicode 값으로 표현할때 사용 됩니다. (10진수 변환 코드)

특수 문자를 표현하기 위해 꼭 사용 되지 않아도 되며 경우에 따라 꼭 사용해야 합니다.

아래 표는 HTML문서에서 많이 사용 되는 특수 문자 입니다. 문자를 쓴 경우와 숫자를 쓴 경우는 동일 효과를 보여 줍니다.
[특수 문자] 단, (■) 실제 공간을 보이기 위해 사용 했습니다.

&lt; &#60; [<] less-than: ~ 보다 작다, 꺽쇠 열기 문자 기호
&gt; &#62; [>] greater-than: ~ 보다 크다, 꺾쇠 닫기 문자 기호
&amp; &#38; [&] ampersand: and 문자 기호, 사용예(&lt;를 표현 하려면 &amp;lt;로 코딩)
&nbsp; &#160; [■ ■] no-break space: 공간을 표현 하기 위한 문자 기호(■공간■)
&ensp; &#8194; [■ ■] en space: 공간을 표현 하기 위한 문자 기호(■공간■)
&emsp; &#8195; [■ ■] em space: 공간을 표현 하기 위한 문자 기호(■공간■)
&thinsp; &#8201; [■ ■] thin space: 공간을 표현 하기 위한 문자 기호(■공간■)
&copy &#169; [©] copyright: 저작권 문자 기호
&quot; &#34; ["] quotation: 따옴표 문자 기호

수학 기호

&lt; &#60; < &cap; &#8745;
&gt; &#62; > &cup; &#8746;
&forall; &#8704; &int; &#8747;
&part; &#8706; &there4; &#8756;
&exist; &#8707; &sim; &#8764;
&nabla; &#8711; &asymp; &#8776;
&isin; &#8712; &ne; &#8800;
&ni; &#8715; &equiv; &#8801;
&prod; &#8719; &le; &#8804;
&sum; &#8721; &ge; &#8805;
&radic; &#8730; &sub; &#8834;
&prop; &#8733; &sup; &#8835;
&infin; &#8734; &sube; &#8838;
&ang; &#8736; &supe; &#8839;
&and; &#8743; &perp; &#8869;
&or; &#8744;      

글자 기호

글자 기호(라틴/그리스)
라틴 대문자 그리스 대문자
&Agrave; &#192; À &Alpha; &#913; Α
&Aacute; &#193; Á &Beta; &#914; Β
&Acirc; &#194; Â &Gamma; &#915; Γ
&Atilde; &#195; Ã &Delta; &#916; Δ
&Auml; &#196; Ä &Epsilon; &#917; Ε
&Aring; &#197; Å &Zeta; &#918; Ζ
&AElig; &#198; Æ &Eta; &#919; Η
&Ccedil; &#199; Ç &Theta; &#920; Θ
&Egrave; &#200; È &Iota; &#921; Ι
&Eacute; &#201; É &Kappa; &#922; Κ
&Ecirc; &#202; Ê &Lambda; &#923; Λ
&Euml; &#203; Ë &Mu; &#924; Μ
&Igrave; &#204; Ì &Nu; &#925; Ν
&Iacute; &#205; Í &Xi; &#926; Ξ
&Icirc; &#206; Î &Omicron; &#927; Ο
&Iuml; &#207; Ï &Pi; &#928; Π
&ETH; &#208; Ð &Rho; &#929; Ρ
&Ntilde; &#209; Ñ &Sigma; &#931; Σ
&Ograve; &#210; Ò &Tau; &#932; Τ
&Oacute; &#211; Ó &Upsilon; &#933; Υ
&Ocirc; &#212; Ô &Phi; &#934; Φ
&Otilde; &#213; Õ &Chi; &#935; Χ
&Ouml; &#214; Ö &Psi; &#936; Ψ
&Oslash; &#216; Ø &Omega; &#937; Ω
&Ugrave; &#217; Ù      
&Uacute; &#218; Ú      
&Ucirc; &#219; Û      
&Uuml; &#220; Ü      
&Yacute; &#221; Ý      
&THORN; &#222; Þ      
라틴 소문자 그리스 소문자
&szlig; &#223; ß &alpha; &#945; α
&agrave; &#224; à &beta; &#946; β
&aacute; &#225; á &gamma; &#947; γ
&acirc; &#226; â &delta; &#948; δ
&atilde; &#227; ã &epsilon; &#949; ε
&auml; &#228; ä &zeta; &#950; ζ
&aring; &#229; å &eta; &#951; η
&aelig; &#230; æ &theta; &#952; θ
&ccedil; &#231; ç &iota; &#953; ι
&egrave; &#232; è &kappa; &#954; κ
&eacute; &#233; é &lambda; &#955; λ
&ecirc; &#234; ê &mu; &#956; μ
&euml; &#235; ë &nu; &#957; ν
&igrave; &#236; ì &xi; &#958; ξ
&iacute; &#237; í &omicron; &#959; ο
&icirc; &#238; î &pi; &#960; π
&iuml; &#239; ï &rho; &#961; ρ
&eth; &#240; ð &sigmaf; &#962; ς
&ntilde; &#241; ñ &sigma; &#963; σ
&ograve; &#242; ò &tau; &#964; τ
&oacute; &#243; ó &upsilon; &#965; υ
&ocirc; &#244; ô &phi; &#966; φ
&otilde; &#245; õ &chi; &#967; χ
&ouml; &#246; ö &psi; &#968; ψ
&oslash; &#248; ø &omeag; &#969; ω
&ugrave; &#249; ù      
&uacute; &#250; ú      
&ucirc; &#251; û      
&uuml; &#252; ü      
&yacute; &#253; ý      
&thorn; &#254; þ      
&yuml; &#255; ÿ      

JAVASCRIPT 특수 문자

자바스크립트에서는 문자열 안에 몇 가지 특수 문자들을 사용할 수 있습니다.
자바스크립트 코드를 작성중에 문자열에 대해 줄 바꿈을 하거나 (")와 같은 기호를 넣고 싶을때 사용 합니다.

특수 문자에 (\)은 Backslash이며 키보드 키중 (\)으로 사용 합니다.
\(Backslash)는 앞에 사용 하면 특수 문자를 사용을 말하며 뒤에 각 특수 문자의 특성에 맞는 문자로 실행 됩니다.
"내용 \특수문자 내용"

<script language="JavaScript">
<!--예제
function JSschar() {
message1 = "이곳은 첫번째 줄입니다.\n";
message2 = "이곳은 두번째 줄입니다.";
alert(message1 + message2);
}
//스크립트 끝-->
</script>

특수 문자 특수 문자 의미
\b [\b : Backspace] 뒤로 한칸 지움
\f [\f : Form feed] 새로운 페이지로
\n [\n : Line feed (newline)] 개행(새로운 라인으로)
\r [\r : Carriage return] 리턴(예를 들어 TEXTAREA에서 Enter를 사용한 결과)
\t [\t : Horizontal tab] 탭 문자 삽입
\' [\' : Single quotation mark] 작은 따옴표 표현
\" [\" : Double quotation mark] 큰 따옴표 표현
\\ [\\ : Backslash] 역 슬래쉬 표현

Posted by '김용환'
,

svn 명령시 한글같은 것이 깨져 보이는 현상이 보일 때가 있다.

그 때는 .bash_profile을 다음과 같이 수정한다.

 

export LANG="C"

 

로케일을 수정하면, 꺠진 글자대신 영문이 보일 것이다.

Posted by '김용환'
,

왜 EJB 없는 J2EE 개발에 대해 이야기하는가?

  1. 작성자 : 이일민(토비)
  2. 작성일 : 2004년 12월 17일

Spring Framework의 개발자 Rod Johnson의 최신저서 "J2EE Development without EJB"라는 책을 읽고 있다. Gavin King의 Hibernate In Action을 읽을 때와 마찬가지로 정말 한문장도 빼놓을 것이 없는 주옥 같은 내용으로 가득차 있다. 자바의 서버기술 - J2EE을 이용한 시스템 개발에 대한 가장 현실적이고 맹쾌한 분석과 비판 그리고 그에 대한 대안까지 빠짐없이 제시되고 있다. 처음엔 책을 다 읽고 나서 서평정도나 써볼까 했는데 다 읽고 나면 너무 할 얘기가 많아서 아예 손도 못대지 않을까 싶다. 그때 그때 각 챕터마다 또는 부분마다 제시하는 핵심 메시지와 그에 대한 나의 생각을 정리해보고 싶다.

왜 EJB가 없는 J2EE를 말하는가? 그에 대한 답으로 저자가 먼저 제시하는 것은 J2EE = EJB가 아니라는 사실이다. 오히려 J2EE는 EJB 를 포함하여 훨씬 넓은 영역을 가지고 있다. J2EE에는 그 자체로 훌륭한 - 버릴 수 없는 - 좋은 서비스들을 많이 가지고 있다. EJB는 그 중 하나에 불과하다. 그럼 왜 EJB는 왜 사용하려 하지 않는가? EJB는 너무 많은 문제를 가지고 있기 때문이다. EJB는 over-engineering된 spec.을 가지고 있다. 너무 이상적이랄까? 그래서 실전에서 난이도, 생산성, 성능, 유지보수성, 테스트 모든 면에서 많은 문제를 노출하고 있다. EJB책을 처음 읽기 시작하면서 참 이상적이고 완벽한 스펙을 지향한다는 느낌을 받았다. 그러나 그 이상적인 스펙이 현실에서는 매우 드물게 요구된다. 그 외의 대부분의 개발요구사항이나 환경에서는 사실 그 이상적인 스펙을 충족하는 EJB를 개발하기 위해서 너무 많은 것을 희생한다.

EJB는 그 난이도와 요구하는 시스템의 규모와 중요성 크기 때문에 초기엔 엔지니어들의 몸값이 엄청났던 기억이 난다. 그 후에 많은 엔지니어들이 EJB시장에 뛰어들었고 EJB는 매우 보편적인 기술로 자리를 잡은 듯 하다. 하지만 아직 대부분의 EJB개발자나 아키텍트들은 EJB를 대부분 완벽하게 이해하고 있지조차 못하다. 게다가 생산성이 너무 떨어지므로 고가의 IDE를 사용하거나 각종 관련툴에 익숙해야 하고 성능의 손해부분을 감당하기 위해 역시 고가의 시스템을 도입해야 했다. 물론 엔지니어의 기술부족으로 인해서 실패한 프로젝트로 끝나는 경우가 가장 많기도 하다. 저자는 EJB가 3년 내에 Legacy Technology가 될 것 이라고 말한다. EJB3.0이 나온다고 할지라도. 분산객체기술의 대표격이었던 OMG의 CORBA의 몰락과 어쩌면 유사한지도 모르겠다.

오버하지 말아야 한다는 진리는 어디에나 적용되는 것 같다. 그럼 대안은 무엇인가? EJB가 없다면? EJB이전 시절로 돌아가야 하는가? 기존 EJB의 비판자들은 비판만 했을 뿐이지 별다른 대안을 내놓지 못했다. 기것해야 SLSBs에 JDBC등을 쓰는 정도로 타협했을 뿐이다. 그러나 이 책의 저자는 EJB의 훌륭한 대안으로 - EJB의 많은 장점들을 내포하고 또 더 나은 - 많은 기술과 또 다른 Framework들이 있음을 제시하고 그것을 어떻게 적용할지 설명하기 위해서 이 책을 쓰고 있는 것이다.

또다른 EJB와 갈은 실패를 만들지 않기 위해서 가장 먼저 생각할 것은 기본 핵심가치(core values)인데 그 것은 6가지로 구성된다.


1. Simplicity

자바기술의 요즘 경향은 simple한 것을 추구하는 것이다. 복잡한 기술나 아키텍처가 요구될 때가 있다. 하지만 그것이 실제적인 필요에 의해서가 아니라 기술 그 자체가 그렇게 구성되어 있기 때문이라면 바람직 할 수 없다. 설령 복잡한 요구사항들이 (분산DB, 멀티타입 클라이언트와 갈은) 후에 요구된다 하더라도 처음부터 그런 모든 것을 위한 복잡한 아키텍처를 사용할 필요가 없다. Scale down이 되지 않는 EJB같은 복잡한 아키텍처가 아니라 필요에 따라서 아키텍처 리팩토링에 의해서 scale up할 수 있는 심플한 아키텍처를 추구하는 것이 바람직 하다.

리팩토링이 가능한 좋은 아키텍처는 어떤 것인가? 저자는 두가지를 제시한다.

  1. 첫째는 좋은 OO디자인을 따르는 것이다. 예를 들면 class보다는 interface를 이용한 프로그램 같이. 수많은 OOP서적과 디자인패턴 책에서 너무도 잘 가르쳐 주고 있는 부분이다.
  2. 둘째는 EJB와 같은 복잡한 기술을 POJO인터페이스 뒤로 숨기는 것이다.

그런면에서 Spring Framework은 이 두가지 원칙을 철저하게 따라서 만들어진 프레임웍이다. 그로 인해 얼마나 유연하게 수많은 기술들이 그 기본 아키텍처안에 쉽게 연결이 되고 scaling될 수 있는지 볼 수 있다. 최근 TopLink개발팀에서 먼저 나서서 Spring과 연동되는 기술을 만들어 제공한 것도 일단 Spring이 그만큼 유연하고 심플한 그러나 스케일링이 쉽게 가능한 프레임웍이기 때문일 것이다.

2. Productivity

실무에서 가장 중요한 것은 결국 생산성이고 그로 인한 비용절감&시간단축이 아니겠는가. 왜 J2EE개발자들을 고급 노가다맨들로 전락시키는 것인가.

3. OO

Java는 그 자체로 훌륭한 OO언어이다. 왜 특정기술(EJB)등이 OO에 선행하여 좋은 OO디자인을 방해하는가? OO기술이 주는 장점을 살릴 수 없는 기술을 선택하는 것은 피해야 할 것이다. 깔끔한 디자인과 높은 코드재활용을 가능케 할 수 있는 좋은 OO디자인을 포기해야 할 이유가 없다. 웹이나 서버환경이라는게 단일 클라이언트 환경보다 OO디자인면에서 조금 더 불편하다고 해도 J2EE기술은 충분히 Object Oriented 할 수 있다.

4. Primacy of Requirement

중요하지 않은 부분-요구사항에 많은 정력을 낭비하지 말자. 분산-멀티DB를 지원할 수 있게 하는 것이 지금 하는 프로젝트에서 정말 꼭 필요한 중요한 것인가? 아니라면 왜 그것을 위해서 시간과 기술을 낭비하는가. 정말 고객-프로젝트의 목표-이 원하는 핵심요구사항에 집중하기.

5. Empirical Process

실증(실험?)적인 방법으로 기술을 도입하고 사용하자. 스스로 확인하고 테스트하고 검증된 기술과 구조를 사용해야 한다. IT계는 희한하게도 감정적인 유행도 많고 검증되지 않은 추측과 유언비어가 난무한다. 무뇌아 수준의 초보개발자들이 기술적인 경험이나 확인도 없이 업체가 제시한 마케팅 캐치프레이즈나 읊어대면서 서로 자기 기술이 잘났다고 싸우는 모습을 보면 정말 가관이다. 어느 누구의 말도 믿지 말고 스스로 가장 심플한 구조를 만들어 검증해보면 된다. 여기서 그 유명한 말 "Ask the computer"가 나오는데 어떤 요구사항을 만족시킬 수 있는 가장 좋은 아키텍처는 컴퓨터 스스로가 가장 잘 안다. 만들어서 스스로 돌려보면 될 것 아닌가. 이를 지원하기 위한 각종 방법론들 - RUP, XP Verical Slice - 등이 있으니 알아서 좋을 대로 해보면서 하기를.

사전 테스트에서 꼭 고려해야 할 세가지로 성능, 난이도, 유지보수성을 들고 있다. 가슴 절절히 와 닿는다.

최근 초대형 프로젝트가 검증안된 어떤 특정기술에 종속적으로 개발했다가 막판에 시스템이 정상가동이 안되서 개발자들과 업체가 애를 먹고 있다는 얘기를 들었다. 프로젝트를 베타테스트화 하지 말자. 마루타 사이트도 아니고 말이다. 베타테스트는 프로젝트 앞에 하면 될 것을.

6. Testability

TDD니 TFD(Test First Development)등이 유행하고 있다. 좀 지나치게 유행하는게 아닌가 싶기도 한데 그래도 그 중요성을 무시할 수 없다.

저자의 이 지향점들을 추구하기 위해서 그 결과물로 등장한 것이 결국 Spring Framework이다. 물론 Spring Framework외에도 이런 요구조건을 충족시킬만한 제품들이 몇가지 더 있다. 앞으로 더 많이 등장할 것이고 더 발전하리라 본다. 여러 기술과 제품들이 경쟁하고 발전해 나가는 과정이 그간 EJB를 쓰면서 힘들었던 시간을 보상해주리라 믿는다.

다음 번에는 좀더 본격적으로 얘기를 해보자.

 

 

EJB 없는 J2EE 개발이 추구하는 목적

  1. 작성자 : 이일민(토비)
  2. 작성일 : 2004년 12월 19일

Rod Johnson의 J2EE Development without EJB를 읽으면서 끄적이기 계속...

저자는 두번째 챕터에서 앞 장에서 제시한 6가지 core values에 대해서 좀 더 상세하게 설명하면서 J2EE w/o EJB에서 추구하는 목적을 분명하게 제시하고 있다. 전통적인 J2EE개발방식(with EJB)의 문제점들은 이 책의 전반에 걸쳐서 지속적으로 지적되고 있다. 어떤 이는 EJB를 너무 까는 것 아니냐며 불평하는 것도 들었지만 그래도 냉정하게 볼 때 사실이니까. 깔 건 까야지.

1. 생산성

전통적인 J2EE 개발에서 생산성 문제를 해결하기 위한 방법으로 등장한 대표적인 것은 code generation이다. 많은 IDE나 xdoclet같은 툴들이 code generation을 통해서 EJB개발의 부하를 줄여주고 있기는 하다. 하지만 code generation기술은 그 자체로 필요악(EJB개발이라면)일 수 밖에 없다. 차라리 그런 땜방기술을 쓰는 것보다는 근본적인 아키텍처를 다시 고려하는 것이 마땅하다. 내 경험으로 볼 때 EJB개발시 IDE등의 code generation기능을 이용하는 것은 사실 매우 편하다. 다만 개발초기에만 편할 뿐이다. 그 후에 시스템이 복잡해지고 일정 부분이 지나고 나면서 생성된 코드들을 다루거나 건드리기 시작하면 많은 문제와 불편함이 발생된다. JBuilder에서 JBoss용 EJB애플리케이션을 개발할 때 jboss plugin을 써서 J2EE-EJB DD를 생성하곤 했는데 그 jboss plugin은 round-trip에는 대책이 없는지라 각종 내가 추가 변경했던 DD의 내용들이 bean하나만 수정해도 한번에 날라가곤 했다. 이것을 막아보려고 별짓을 다해봤지만 뭐 뚜렸한 대책이 없었다.

Code generation으로 복잡한 아키텍처의 단점을 땜빵하려고 하지말고 그것을 쓰지 않을 수 있을 만큼 심플하고 유연한 아키텍처를 사용하도록 하자. 특히 중복되는 코드(code duplication)들 만큼은 절대 피할 수 있는 길을 찾도록 한다. DB로부터 Entity bean과 관련 artifacts를 생성하는 것 또는 entity bean으로부터 DB schema용 DDL을 만드는 것. DAO자동생성, EJB DDs생성, XML interchange code생성. Service Locator & Business Delegate pattern을 따르는 각종 EJB 연동 코드 생성 또는 전체 J2EE stack을 한번에 생성하는 것(헉!). 그리고 각종 template 코드를 만들어 복제해서 쓰는 것 등은 모두 피할 수 있고 피해야만 하는 code generation기술이다. 가만히 생각해 보면 저런 방법등을 사용했던 것이 그저 당장 일을 쉽게 하려고 다른 대안이나 구조적인 부분에서 고민을 하지 않은 결과라는 생각이 든다.

MDA기반의 code generation기술(higher levels of abstraction)이 성숙해져서 언젠가 이상적으로 사용될 수 있겠지만 저자는 그런 날이 빨라도 10-15년 후에나 올 것 같다고 한다. 헉! Code generation과 같은 방법이 아니라면 J2EE개발생산성을 높이기 위한 어떤 방법들을 취해야 하는가.

저자는 3가지 면에서 생산성 향상을 위한 방법을 제시하는데. 첫째는 아키텍처이고 둘째는 문제에 대한 집중과 방법론 세째는 적절한 툴의 사용이다.

  1. 아키텍처

아키텍처면에서 보자면 결국 좋은 프레임웍-아키텍처를 선택하는 것이 제일 중요하다고 본다. 간혹 자체적으로 개발한 in-house 환경을 사용하려는 시도가 있는데 이는 경험적으로 볼 때 매우 위험한 선택이다. 상당한 시간과 돈과 시행착오에 대한 투자를 할 수 있을 여력이 없다면 이미 나와서 검증된 좋은 프레임웍과 기술을 선택하는 것이 바람직하다. 또 상용 애플리케이션서버에 번들로 제공되는 기술을 쓸 수도 있는데 이 것은 특정서버에 매우 오랜 동안 종속될 것이 분명한 경우일 때만 선택가능하다. 특히 표준에 나오지 않은 특정벤더의 추가 기술들은 향후 새버전에서 새로운 표준기술로 바뀌면서 더 이상 구버전의 기능들과 호환이 되지 않을 수 있음을 기억할 필요가 있다.

제일 좋은 아키텍처 선택은 open source기반의 검증된 프레임웍이나 또는 상용이라고 하더라도 표준을 잘 따르고 이 책에서 제시하는 그런 핵심가치들을 잘 지키는 제품을 선택해야 할 것이다.

제일 안좋은 방법으로는 아키텍처적인 문제를 무시하고 그냥 몸으로 땜빵하려는 것인데... 내 주위만 봐도 이런 경우가 적지 않은 것 같으니... 왜 사서고생일까!

  1. 문제에 집중하기와 적절한 방법론선택

어떤 개발프로젝트든지 그 것이 요구하는 핵심요구사항 - 풀어야할 문제는 선명하게 구별되어 질 수 있다. 그 외에 주변적인 것에 몰두하는 것은 프로젝트를 산으로 몰고가는 지름길일 것에다. 사용자가 뻔히 수백명이 전부인 - 그러나 비즈니스 로직은 복잡한 - 내부 인트라넷을 개발하는데 모든 것을 퍼포먼스 - 수백만이 사용하는 시스템에서 요구하는 - 에만 촛점을 맞춰서 매달린다면 그야 말로 삽질하는 것일 수밖에.

적절한 후보 기술-프레임웍 등이 결정됐으면 그 모든 기술이 사용되어지는 간단한 뼈대프로그램(skeleton application)으로부터 출발하는 것이 좋다. 대부분의 유명 프레임웍등은 자체적으로 제공하는 좋은 skeleton applications(codes)들이 여러 케이스에 맞춰서 제공된다. 다만 너무 완벽하게 만들어진 샘플프로그램 - petstore같은 - 은 가져다 사용하기가 오히려 더 부담이 될 수도 있으니 피하는 것이 좋을 듯 하다.

나는 내가 사용할 가능성이 있는 각 프레임웍-기술의 조합별로 간단한 skeleton application을 만들어서 저장해 두고 사용하는데 주로 처음 그 기술을 공부할 때 많이 만들어 사용한다. 후에 프레임웍이 버전업 되거나 또 새로운 기능이나 구조를 알게 됐을 때마다 이를 업데이트 해둔다.

방법론은 agile methogology들을 사용하는 것이 개발속도를 위해서 가장 이상적이겠지만 뭐.. 프로젝트 규모나 특성에 따라서 역시 가장 적절한 방법론을 선택하면 될 것이다.

  1. 적절한 툴

종종 자바개발자 중에는 툴을 사용하는 것을 무슨 죄를 짓는 것처럼 두려워하는 사람들이 있다. EJB개발을 어떠한 툴의 도움도 받지 않고 vi 하나가지고 다 하려 하는 개발자들도 보았는데 집에 가면 부싯돌을 가지고 장작을 때서 밥을 해먹을 사람들이다. 툴을 사용하지 않는 이유가 툴을 쓰면 그 아래 돌아가는 기술에 대해서 무지해지기 때문이라고 하는데 - 그러면서 꼭 VB개발자를 걸고 넘어진다. VB개발자는 프로그래머도 아닌가? - 그럼 그 기술에 익숙해 지고 나서도 계속 툴을 쓰지않고그렇게 개발하는 이유는 뭔가? 자신들의 비효율적인 개발방법으로 수많은 피할 수 있는 잠재적인 오류들을 생산해 내면서 고객의 돈과 시간을 낭비하고 있다는 것을 왜 인식하지 못할까.

물론 툴에만 의지해서 기술을 등안시 하려하는 사람들도 문제이다. 또는 적절치 못한 툴을 선택해서 - 또는 특정툴에 대한 집착이 너무 강해서 - 문제가 될 수도 있다. 바른 툴을 선택해서 전체 개발프로세스에 걸쳐서 익숙해지도록 훈련하는 것이 필요할 것이다.

IDE뿐만 아니라, unit testing을 위한 툴, build tool, xml editor, source control system등의 선택도 중요할 것이다. 나도 notepad + dos command로부터 시작해서 다양한 자바툴들을 사용해왔는데 지금 가장 익숙하고 편한 툴을 eclipse + 각종 plug-in이다. 메모리를 좀 많이 먹는 것이 좀 불만이지만 그 외엔 대부분 만족스럽다. 좀더 많은 종류의 plug-in들이 개발되어지고 편리하게 이용되기를 바랄 뿐이다. 사실 MS의 Visual Studio만큼 생산성이 높고 편리한 IDE는 아직 경험해 보지 못했다. 그 면에선 .NET개발자들이 부러울 따름이다.

2.. OO

OO는 J2EE보다 중요하다. OO의 탈을 썼으나 OO가 아닌 것들을 배제해야 한다. 그것을 저자는 fake object라고 부르는데 대표적으로 DTO, RDB테이블에서 생성되어진 Entity bean이나 persistent object, 또는 getter/setter만 있고 behavior가 없는 persistent object를 꼽는다. 대안이 없는 것이 아니라면 이런 fake object들은 피하라.

인퍼페이스 프로그래밍. 아무리 강조해도 지나치지 않다.

3. 비즈니스 요구사항의 중요성

고객이 요구하지도 않은 가상의 요구사항(phantom requirement)에 매달리지 말자. J2EE계에서 유행한다고 꼭 필요없는 기능을 구현하려는 것은 피해야 한다. 유행이라고 필요없는 것을 만드는 데 낭비를 할 것은 없다. 실력자랑이나 개발단가를 올리기 위해 오버스펙을 끌어들이는 짓은 이제 그만 하도록.

4. 기술과 아키텍처의 검증과정(empirical process)의 중요성

가능하면 프로젝트 시작 이전에 그게 아니라면 프로젝트 초반에 하도록 하자. 거의 10년전의 이야기다. 모대기업 SI업체에서 긴급 요청이 왔다 (그때 나는 주로 망친 프로젝트 막판 해결사로 유명한 한 팀에서 일을 했다) 일년여간 개발한 시스템이 막판에 테스트를 들어갔는데 오버스펙으로 인해 시스템이 부하를 감당 못하고 쓰기만 하면 뻗는 것이다. C/S시스템이라 서버만 늘린다고 되는 것도 아니고 2만여개의 클라이언트를 다 업그레이드 할 수도 없고 프로젝트 마감 두달을 남겨놓고 난리가 났다. 결국 그 업체가 처음에 검증도 없이 너무 무리한 기술환경을 도입한 것이 문제였다. 최적화를 하기에도 만든 시스템이 너무 엉망이었고 결국 남은 두달동안 우리팀에서 기존 개발한 것을 완전히 새로운 기술로 포팅하는 작업을 해서 겨우 시스템을 안정화 시켰던 기억이 난다.

많은 프로젝트들이 프로젝트가 끝나가는 시점 - 또는 오픈하고 나서야 - 선택한 아키텍처의 성능이나 기타 문제점을 발견하고 한다. 그 개발자나 아키텍트는 그래도 이게 외국에서는 알아주는 좋은 시스템인데.. 또는 세미나에 갔더니 강사가 이걸 쓰면 좋다고 하던데.. 따위의 핑계를 댄다. 다시 말하지만 누구도 믿지 말라. 책도 믿지 말고 벤더가 직접 또는 투자해서 개최된 세미나나 컨퍼런스 강사들의 말은 절~~~대로 더 믿지 마라. 영업사원의 말은 더더욱 그렇고 인터넷 - 블로그에 올라온 개인경험담이나 추측성 기사나 글은 더더욱 그렇다. 믿을 수 있는 것은 자신의 검증과 그 결과 뿐이다. 성능에 대해서 묻고 싶거등 컴퓨터에게 직접 물어보도록.

개발초기 또는 그 이전에 vertical slice를 만들어서 그 아키텍처를 반드시 검증해보도록 하자. 모든 경우를 다 만족할 수 있는 가장 이상적인 아키텍처란 없다. 자신의 요구를 충족할 수 였는 아키텍처는 스스로 찾아서 검증해보는 수밖에.

갈수록 J2EE계에선 실력있는 architect의 필요성이 절실해 진다. 하지만 특정 기술만 선호하는 - 책만 믿고 자신의 눈으로 확인해보려하지 않는 - 그런 시스템 설계자들은 그만 좀 사라져줬으면 하는 바람이다.

 

 

대표적인 J2EE 아키텍처에 대한 비교

  1. 작성자 : 이일민(토비)
  2. 작성일 : 2004년 12월 19일

Rod Johnson의 J2EE Development without EJB를 연말선물로~~!

3장에서는 아키텍처부분을 집중적으로 살펴본다. J2EE아키텍처를 이루고 있는 부부은 크게 3가지로 나눠진다. 잘 알고 있는 3-tier구조의 아키텍처이다.

저자가 주목하고 있는 부분은 Business Service Layer이다. 좋은 아키텍처는 잘 만들어진 Business Service Layer를 가지고 있어야 한다. 비즈니스 로직을 사용자, Web-UI, 리모트 클라이언트에게 제공하는 관문이 되기 때문이다.

좋은 Business Service Layer가 가져야 할 조건은 매우 많다. 기본적으로 J2EE아키텍처의 핵심가치들을 모두 충족해야 함은 물론이고 그 외에도 Presentation layer에 독립적이어야 하고, 트랜잭션 관리가 가능해야 하며, 개발생산성이 높아야 하고, 그 뒤에 있는 Data access layer가 감춰져 있어야 하며, 필요에 따라서 scale out이 가능해야 하고, 테스트성이 좋아야 한다.

대표적인 business service layer들에는 Session EJB, .NET Serviced Component, MVC Web Actions, Service Layer in Lightweight Container등이있다. 결국 이 책에서 얘기하고자 하는 - 지지하고자 하는 - 것은 마지막 service layer running in lightweight container라고 볼 수 있다.

왜 lightweight container의 service layer를 가진 아키텍처가 좋은 가에 대해서 크게 4가지의 대표적인 J2EE Architecture들을 비교해가면서 그 장단점을 설명하고 있다.

대표적인 J2EE Architecture에 대한 비교

  • 첫째는 Class J2EE architecture using remote EJBs. 뭐 더 말할 것도 없이 대부분의 경우에 최악의 아키텍처 되겠다. 그 최악의 복잡함은 수많은 단점을 파생시킨다. 거의 없겠지만 꼭 필요한 케이스가 아니라면 절대 선택하지 말아야 할 아키텍처이다.
  • 둘째는 Local EJB Architecture이다. Remote EJB가 가지는 단점을 많이 축소시켜준 EJB의 타협판인데 - 처음 Local EJB가 나왔을 때 이게 머야 장난치나 하는 생각이 들었다 - 현실적인 요구 또는 불만이 약간 반영된 것으로 보면 될 것 같다. Remote EJB의 단점을 일부 극복했지만 반대로 Remote EJB의 일부 장점들을 잃어버렸고 또 여전히 EJB의 단점들을 그대로 안고 있는 아키텍처이다. EJB의 기본장점을 많이 포기하고 이렇게 땜빵식의 Local EJB를 쓴다면 왜 구지 EJB를 써야하는가가 의문으로 제기될 것이다.
  • 셋째는 Ad hoc J2EE Architecture without EJB이다. 많은 J2EE프로젝들은 EJB없이 잘 개발되어 사용되어지고 있다. 이런 경우 그 아키텍처 구조는 해당 프로젝트의 아키텍트에 따라 다르게 설정되고 그런 면에서 "Ad hoc"이라 할 수 있다. 전형적으로 MVC구조의 web-tier를 가지며 POJO기반의 business logic을 이용한다. 종종 web-tier와 business-logic tier가 혼재하며 자체적으로 만든 singleton이나 factory를 사용한다. 트랜잭션은 JTA등을 이용해서 프로그램적으로 구현한다. Data쪽은 O/R툴이나 JDBC를 수용한다.

EJB가 가진 많은 단점을 극복할 수 있는 좋은 아키텍처이다. EJB의 복잡한 구조와 작업들을 피할 수 있고 어느정도 빠른 생산성이 보장된다. 하지만 EJB가 가지는 장점들 - remoting, business object관리의 표준, business service layer의 존재, declarative transaction management - 을 포기해야 한다. 제일 문제는 비즈니스 오브젝트들을 다루는 표준방법이 부재하다는 것이다. 또한 테스트성 면에서 EJB에 비해서 그다지 차이점이 없다.

뛰어난 아키텍트가 참여했다면 같은 조건의 EJB프로젝에 비해서 이 방법이 훨씬 나은 결과를 가져올 것이다.

  • 넷째는 바로 이 책이 주장하는 "Lightweight Container"기반의 Architecture이다.

세번째 아키텍처와는 달리 lightweight container architecture는 business service layer면에서 EJB와 닮은 점이 많다. EJB가 가지는 단점을 피하면서 EJB의 장점은 살리는 것이 바로 lightweight container가 가지는 목적이랄까? Lightweight container는 J2EE기반이 아니다. J2EE에서 독립적이다. 또 어느 특정 UI(Web-UI)나 Data access기술에도 독립적이다.

경량급 컨테이너 기반 아키텍처의 장/단점

Lightweight container의 주요 관심사는 사용하기 복잡하지 않고 특정기술에 종속적이지 않으면서 - 심지어는 자기 자신에게도 - 다양한 business service layer의 장점들을 수용하는 것이다. 대표적으로 Spring Framework과 PicoContainer가 있다. 엔터프라이즈 서비스의 주요특징중의 하나인 트랙잭션관리라는 면에서 AOP를 이용한 방법을 사용하고 있는데 이 점에선 SpringFramework이 가장 우수하고 통합적인 기능을 제공한다.

단점도 물론 있다. 우선 Local EJB와 마찬가지로 remoting facade를 사용하지 않고 직접적으로 remoting을 사용할 수 없다. 하지만 과연 remoting이 얼마나 필요한지 따져보면 큰 단점이라고 할 수 없다. 두번째는 아직 lightweight container의 standard가 없다는 점이다. 하지만 조만간 Spring이 de facto standard가 되지 않을까 기대해본다. 세번째는 아직 이런 아키텍처에 익숙한 개발자나 아키텍트들이 적다는 것인데 시간이 해결해 줄 문제이다.

다음은 Architectures In Practice라는 주제로 SUN의 Java PetStore로부터 시작해서 각 벤더와 단체에서 내놓은 각종 blueprints나 아키텍처 샘플들을 분석해나가는데... 다들 이런 저런 단점들을 - 또는 수준 낮은 코드도 보인다! - 가지고 있다. 지속적으로 지적된 내용들이다.

마지막으로 Application Server가 필요한 것인가의 문제제기인데. 사실 고가의 복잡한 application server는 꼭 필요한 경우가 아니라면 구지 선택할 이유가 없다는 것이 맞다. 분산트랜잭션을 쓴다거나 리모팅을 반드시 사용해야 할 경우라면 EJB와 WAS를 사용하는 것이 필요할 것이다.

결론

결론적으로 뛰어난 Business Service Layer를 제공하는 것 - EJB와는 비교가 안되는 - 이 책이 제시하고자 하는 Spring Framework이 만들어진 목적이라고 할 수 있을 것이다.

계속해서 이런 주제들을 좀더 세세한 범위에서 깊이 파고 들어가서 분석하고 그 대안으로 사용될 Lightweight Container에 대해서 살펴볼 것이다.

이 책을 읽으면서 그토록 최첨단기술임을 자랑하는 J2EE분야에 (다른 기술쪽도 마찬가지겠지만) 얼마나 많은 미신들이 존재하는지 놀라게 된다. 자기 손으로 확인한번 해보지 않은 기술을 맹신하는 태도는 IT엔지니어로서 일단 실망스러운 것이다. 또는 그렇게 잘못된 믿음으로 사람들을 이끄는 업체나 개발자 스스로 조심해야 할 것이다. 나도 조금 찔리는 부분이다.

 

요구사항을 가장 잘 충족시키는 가장 심플한 것을 찾으라.

  1. 작성자 : 이일민(토비)
  2. 작성일 : 2004년 12월 22일

왜 심플해야 하는가?

이번 장에서는 아키텍처의 "심플함"이라는 면에서 살펴보자. 왜 심플해야 하는가? 그것은 복잡한 것이 나쁘고 잘못된 것이기 때문이다.

필요이상의 복잡한 아키텍처는 반드시 더 많은 돈과 시간을 요구한다. 또한 이 복잡함은 개발자의 생산성 및 애플리케이션의 성능을 떨어뜨릴 뿐만 아니라 많은 버그의 잠재적인 원인이 된다. XP의 가장 중요한 교훈의 하나는 "가능한한 가장 심플한 것을 하라"이다.

그러면 왜 사람들은 복잡한 아키텍처를 사용하거나 복잡한 구조속에서 애플리케이션을 개발하는가? 내 생각에는 우선 복잡한 기술이 주는 이상적인 그러나 필요로 하지 않는 기능들의 유혹이 있기 때문이다. 아무래도 폼이 나지 않는가? 고객에게 장황한 아키텍처의 다이어그램을 그려가면서 멋진 프레젠테이션을 할 때의 반응은 짜릿한 것이다. 뭔가 대단한 기술을 쓰는 것을 자랑하고 싶을 수도 있다. 덕분에 개발단가나 용역비가 상승되기도 한다. 또는 다른 경쟁업체나 유명업체가 사용하고 있다는 것을 은근히 내세워 고객을 자극하기도 편하다. 두번째는 무지함 때문이다. 그냥 남들이 쓰니까. 그것이 유명하다고 하니까. 유명 세미나나 인터넷 아티클에서 뭔가 멋진 기술이라고 소개하니까. 그러니까 나도 이번 프로젝트에 쓰면 되겠다라는 결론을 내리고 개발자들을 다그쳐 그런 아키텍처를 도입하게 한다. 충분한 사전검증도 없이 말이다.

결국 프로젝트는 갈수록 그 복잡한 기술과 아키텍처로 인해 시간이 지연되고 비용은 올라만 간다. 점점 빠듯한 일정을 감당못한 나머지 아키텍처를 무시하고 땜방식 기술들을 마구 끌어들이기도 한다. 결국 후에 아무도 손 못대는 엉망진창인 걸레시스템을 만들어 놓고 나몰라라 떠나기도 한다.

필요없는 아키텍처의 복잡성은 누구에게나 도움이 되지 않는다. 저자가 많은 세미나나 컨퍼런스, 포럼등에서 많난 유명 아키텍트나 컨설턴트들은 J2EE의 기존 아키텍처로 수행한 프로젝트들에서 다 동일한 문제점을 안고 고생을 하거나 실패했던 경험이 있음을 고백했다고 한다.

J2EE 아키텍처의 복잡성은 어디서 기인하는가?

첫째는 필요없는 EJB의 사용이다. EJB는 매우 복잡한 기술이고 역시 복잡한 요구사항이나 기능에만 적합하다.

둘째는 분산객체(distributed object) 기술이다. 분산객체 기술은 최첨단 고급기술의 대명사가 아닌가. 하지만 이 분산객체 기술은 장점보다 단점이 더 많다. 가장 중요한 이슈는 역시 성능이다. 성능은 확장성(scalability)에 반비례하기 때문에 확장성을 위해서 일부 성능을 손해보아야 한다는 것이 그간의 정설이다. 하지만 정말 그런가 확인해 봤는가? 확장성을 위해서라는 이유로 무시하기엔 분산객체기술의 성능은 너무나도 형편없다. 게다가 분산객체는 OO의 장점을 많이 포기해야 한다. 게다가 그 불편한 TO(Transfer Object)를 과다하게 필요로 한다. 결국 분산객체는 많은 리소스 낭비를 가져오게 된다.

일반적으로 EJB를 기반으로한 J2EE아키텍처의 가장 큰 장점으로 주목받아 온 것은 Web tier와 EJB tier를 분리시켜서 독자적으로 수평확장(Scale out)할 수 있게 해서 대용량의 부하를 감당하도록 무한한 확장성을 가질 수 있다는 것이다. 클러스터링된 Web container 머신 4대와 EJB Container서버 8대. 사용량에 따라서 부하가 걸리는 tier의 서버를 증가시켜서 확장성을 극대화 시킨다는 것이 J2EE 아키텍처의 가장 큰 자랑이자 분산객체 기술의 이상형이다.

저자는 이런 생각이 매우 왜곡된 미신일 뿐이라고 말한다. 실제로 co-located된(web-tier와 business logic tier가 같은 머신에서 공존하는) 시스템보다 더 뛰어난 remoting기반의 분산객체구조의 시스템을 본 적이 없다고 말한다. 사실 나만해도 그런 remoting구조의 아키텍처를 최종적으로는 가장 이상적인 구조로 보아왔다. 즉 시스템 규모가 커지면 결국 그리로 가야하지 않는가 생각했던 것이다. 하지만 리모트콜(RMI)을 사용하는 것에서 오는 모든 장점보다 네트웍과 마샬링의 부하에서 오는 단점들이 훨씬 더 크다는데 문제가 있다. J2EE의 분산객체기술은 J2EE/EJB 마케팅의 가장 주요한 포인트였는데 실제로는 현실과는 너무 거리가 있는 아이디어일 뿐이다.

그럼 대안은 무엇인가? 단일서버에서 돌아가는 시스템으로 만족하고 수직확장(Scale up)만을 할 수는 없는 노릇이다. 하지만 presentation layer와 business logic layer가 공존하는(co-located)구조도 얼마든지 확장(scale out)이 가능하다. Co-located architecture는 사실 훨씬 간편하게 확장이된다.

결론적으로 분산객체(독립된 ejb-tier를 가지는 경우) 아키텍처가 더 나은 확장성을 가진다는 생각을 버려야 한다. 구지 필요하다면 최소한의 애플리케이션의 단면(vertical slice)구조를 가지고 테스트해보라. 단위 서버의 효율을 최대로 하여 스케일링의 필요성을 최소화 하는 것이 무턱대고 분산객체를 쓰는 것보다 나음을 기억하자. 분명 J2EE의 분산객체기술은 그 자체로 뛰어난 것임에는 분명하다 하지만 그 용도와 필요성은 매우 극소수의 경우에만 적용된다.

셋째는 J2EE의 모든 기술을 과도하게 적용하려고 하는 것인데 이는 그 시스템에서 필요로하는 요구사항과 상관없는 기술을 적용하고 싶어하는 욕심에서 비롯된 것들이 많다. J2EE가 지원하는 기술들이 실제 그 시스템의 요구사항이 아닌 경우 결국 그것이 시스템의 복잡성을 증가시키는 주요 이유가 될 것이다.

또 한가지 주요한 복잡성의 원인으로 "패턴중독(pattern-sickeness)"가 있다. 패턴은 기본적으로 좋은 것이다. 하지만 J2EE계에는 너무나 많은 독자적인 패턴들이 등장하고 제시되고 있다. 책에서 잡지에서, 인터넷 각 사이트마다 저마다의 패턴들을 만들어 내놓곤 하는데 이 모든 패턴들이 항상 모든 종류의 시스템에 적절한 것이 아니다. 많은 아키텍트들은 얼마나 많고 다양한 패턴을 자신의 시스템에 적용했는가에 너무 많은 관심을 가지곤 한다. 패턴을 적용하는 이유는 심플함을 주기 위해서 이다. 패턴적용이 오히려 시스템을 더 복잡하게 만들고 있다면 다시 심각하게 사용을 고려해보는 것이 바람직하다.

넷째는 문화적인 원인이다. 개발자, 개발회사, 개발그룹 안에는 나름대로 전통과 문화가 존재한다. 때론 이 문화들이 아키텍처를 복잡하게 하는 이유가 되기도 한다.

많은 애플리케이션 서버벤더들이 복잡한 아키텍처와 기술을 조장한다. 자신들의 시스템의 복잡성과 높은 비용을 정당화하기 위한 이유가 아닌가 싶다. Markitecture라는 신조어가 있다. 마케팅을 목적으로 만들어낸 복잡한 구조의 아키텍처를 말한다. 복잡한 다이어그램과 화이트페이퍼에 나오는 환상적인 아키텍처는 고객의 흥미를 끌고 고가의 시스템과 라이센스를 팔아먹기에 적합할지 모른다. 하지만 그것이 현실에서는 얼마나 한계가 있는지 경험해 본 사람은 잘 알 것이다. 영업사원의 말과 해당 업체가 제공하는 교육이나 세미나의 결론을 믿지말고 반드시 스스로 검증하고 확인할 것.

또 개발툴의 복잡성도 문제가 된다. 특히 UML기반의 개발과정은 과연 바람직한 것인지 의문이다. 많은 경우 UML기반의 툴을 이용한 개발은 위험할 수 있다. 중요한 것은 개발현실이다. 과연 UML기반의 툴을 이용해서 개발하는 것이 얼마나 agile methodology에 적합한가 또 working code와 얼마나 잘 연동이 되서 잦은 리팩토링이 가능하게 하는지 코드를 생성하고 개발하는데 얼마나 효과적인지 곰곰히 생각해볼 노릇이다. UML기반의 프로세스 내지는 그 기반의 툴이 얼마나 시스템개발과 아키텍처를 심플하게 해줄 수 있는가 직접 점검해 보라.

어떤 경우는 특정팀의 자만심이 문제가 되기도 하는데 자신들의 시스템은 뭔가 특별하고 대단한 것이라고 생각해서 이미 검증되어 있는 잘 알려진 프레임웍을 쓰려하지 않고 스스로 개발한(in-house) 아키텍처를 이용하려는 경우가 있다. 내 경험으로 보자면 좀 실력이 뛰어나다고 생각하는 젊은 개발자들이 이런 유혹에 잘 빠지는데 항상 결과는 똑같다. 복잡하고 완성도 떨어지는 아키텍처에 스스로 발목잡혀 고생만 하게되는 경우다. 누구나다 개발자로서 한 때는 자신이 마음먹으면 못할 것이 없으며 누구보다도 뛰어난 엔지니어라는 환상을 같게 된다. 인터넷에 유명 포탈에서 다른 사람들의 실수를 보면 비웃으면서 나는 저들보다 낫다고 자만하게 된다. 어떤 사람들은 개발 3-4년차의 엔지니어가 그런 유혹에 잘 빠진다고 하는데… 뭐 아무튼 결론은 항상 겸손해야 한다 이다. 자신은 생각보다 별로 뛰어난 엔지니어가 아닐 경우가 더 많다고 생각하면 항상 맞을 것이다. 내 자신에게도 자꾸 적용해야 할 말이다. 뛰어난 많은 엔지니어들의 고민과 경험 속에서 만들어진 결과물들을 겸허하게 수용해야 할 때가 있음을 기억하도록 하자.

또 하나의 경우는 개발자 자신에게 있기도 한데. 좀 더 고급스러워 보이는 기술을 사용해서 자신의 커리어를 확장시키려는 경우 또는 실제 사용하는 기술의 상세한 내용과 결과를 알지도 못하고 경험도 없으면서 문서작업과 모델링에나 몰두하는 아키텍처들이다. 또는 정말 이유을 알 수 없는 제멋대로 행동을 하는 고집불통 개발자인데 이런 사람은 팀에서 빨리 빼버리는 것이 모두에게 도움이 될 것이다.

시스템을 복잡하게 의도적으로 만드는 경우도 있다. 결국 개발비용을 극대화 시켜서 고객으로부터 과다한 이익을 챙기는 경우인데 솔직이 내가 보기엔 적지 않다. 아무리 고객사 엔지니어가 뛰어나다고 해도 최첨단의 화려한 기술로 가득찬 100페이지짜리 제안서에 20페이지가 넘는 각종 다이어그램을 가져가서 또 유명업체의 기술적인 근거자료들을 제시하면서 설명하면 쉽게 넘어오는 경우가 많다. 하지만 그 결과로 만들어진 코드가 정말 그 제시한 화려한 장점들을 가지고 있는지는 아무도 알 수 없이 끝나는 것이 대부분이다. 오늘날 많은 세계적인 컨설팅 업체들도 전략적으로 그런 행동을 하는 것을 알만한 사람은 다 알 것이다. 근래들어 많은 대기업들과 정부기관들 - 오랫동안 컨설팅회사의 제시한 시스템을 그냥 무비판적으로 받아들여 사용해왔던 - 이 서서히 그런 모습에 의문을 품고 하나씩 검증하며 시스템을 세분화해서 도입하려는 추세를 보이고 있다. 매우 바람직한 일이라고 본다.

얼마나 심플해야 하는가?

다음에 생각해 볼 것은 그럼 과연 얼마나 심플해야 하는가이다. 무조건 심플하기만 하면 좋은가? 혹시 너무 나이브해지는 것은 아닌지?

핵심은 그 심플한 아키텍처가 고객의 실제 요구사항에 충분히 부합하는 것인가 프로젝트 초기에 검증해보라는 것이다. 또 한가지는 심플한 아키텍처라고 하더라도 추가적인 요구사항이 발생함에 따라서 scale up할 수 있어야 한다는 것이다.

이제 J2EE계에도 변화의 바람이 불고 있다.

많은 개발자들이 경험을 통해서 분산아키텍처의 도입을 피하고 있으며 EJB는 그 복잡성으로 인해서 가능한한 사용하지 않으려는 노력이 이루어지고 있다. 심지어는 SUN조차도 말이다. 또 그 대안으로 여러 Lightweight container들이 등장하고 있고 Entity bean의 대안으로 JDO나 Hibernate등이 사용되어지고 있다. 또 agile methodology와 open source기술의 사용이 늘고 있는 점이다. 이런 모든 흐름은 결국 많은 경험을 통해서 개발자들 자신을 통해서 주도되고 있다. 내가 자바와 그 환경을 좋아하는 이유중의 하나는 SUN과 같은 업체가 주도해서 기술과 흐름이 가는 것이 아니고 전세계 흩어진 많은 풀뿌리 개발자들 스스로가 깨닫고 원하는 방향으로 흐름이 이루어지고 있다는 것이다.

요구사항을 가장 잘 충족시키는 - 잘 작동하는 가장 심플한 것을 찾으라. 그 태도가 당신을 진정 뛰어난 J2EE 개발자로 만들어 줄 것이다

 

 

문제 많은 EJB, 그러나 EJB에서 배울 것은 많다.

  1. 작성자 : 이일민(토비)
  2. 작성일 : 2004년 12월 25일

J2EE Development without EJB에는 정말 갈수록 방대한 양의 정보가 있다. 정리해 놓기도 만만치 않다. 그러나 그 수고는 충분히 가치있다고 생각된다. 전세계 수많은 뛰어난 J2EE개발자들의 경험과 생각이 녹아있는 책이기 때문이다. 이 책을 읽는 것 만으로도 배울 수 있는 관련지식과 경험의 규모는 엄청나다. 아직도 안 본 J2EE개발자가 있다면 얼른 구해서 읽으시길.

문제많은 EJB. 그러나 EJB에서 배울 것은 많다. EJB에는 우리가 취해야 할 좋은 점들이 충분히 있다. 또 교훈으로 삼아 피해야 할 나쁜 점도 많다. EJB의 특징과 그 역사, 평가와 대안등을 살펴보는 것은 매우 의미 있는 작업이다.

EJB와 컴포넌트 기술의 발전

EJB의 처음 목적은 엔터프라이즈급의 개발을 간편하게 하도록 하는 것이었다. 그것은 EJB1.0의 스펙을 살펴보면 잘 알 수 있다. EJB의 설계자들은 개발자들이 트랜잭션, 상태관리, 멀티쓰레딩, 리소스풀링이나 복잡한 로우레벨의 API와 같은 시스템적인 부분에 대해서 많은 신경을 쓰지 않고 개발 대상 도메인과 비즈니스로직에 집중할 수 있도록 하려는 것이었다. 또 한가지 강조한 부분은 EJB는 Java의 캐치프레이즈 그대로 한번 만들어지면 어떠한 다른 플랫폼과 서버환경에서도 재컴파일이나 소스코드 변경없이 사용하도록 하려는 것이었다.

EJB가 처음 등장했던 1998년에 당시 엔터프라이즈 컴포넌트 기술은 MS의 MTS와 CORBA정도가 주류로 존재했었다. COM/DCOM기술에 기반을 둔 MTS의 MS에 대한 의존성의 한계와 너무 방대한 스펙과 그에 따른 제약(CORBA는 진정한 애플리케이션 서버 기술로는 볼 수 없다)으로 역시 크게 쓰이지 못하고 있던 CORBA가 일반 개발자의 별다른 주목을 받지 못하고 있던 상황에서 EJB는 Java기반의 매우 열린기술과 이상적이고 간결해 보이는 스펙등으로 사람들의 관심을 끌기 시작했다. 하지만 그때는 아직 Java기술자체가 계속 발전하던 시기였고 EJB의 등장 이후에 Java는 언어적인 면에서 지속적으로 큰 변화들을 가져왔다. 하지만 EJB는 그 초기 등장이후 로컬인터페이스를 가진 EJB2.x에서 일부 최적화가 있었을 뿐 초기의 설계에서 근본적인 변화가 없이 현재에 이르고 있다. EJB가 초기의 기술에서 크게 변화하지 못하고 정체되어 있는 사이에 새로운 개념과 열린구조를 가진 .NET이나 Web Service같은 새로운 기술들이 등장했고 언어자체로 자바도 많은 발전이 있었다.

EJB는 그 스펙의 발전과정에서 여러가지 논쟁들을 가져왔는데 제일 문제가 되었던 부분은 EJB가 컴포넌트 기술과 리모팅 기술을 구분없이 혼재해서 가지고 있다는 점이다. 덕분에 EJB는 리모팅 부분의 다양한 기술을 적용할 수 없는 유연하지 못한 구조일 수 밖에 없었다. 또한 EJB를 오브젝트관점에서 봐야 하는지 컴포넌트로 이해해야 하는지에 대한 부분도 스펙의 발전에서 계속 고민되어진 부분이다. 특정 컴포넌트 기술에 종속적이지 않은 lightwegith container와 같은 오브젝트 기반의 기술도 컴포넌트들이 갖는 많은 특징들과 장점을 가지고 있음은 분명한 사실이다. 또 엄밀히 컴포넌트 기반의 소프트웨어 기술과 오브젝트 기반의 기술을 구분하는 것은 간단한 문제는 아니라고 생각된다.

EJB의 등장과 함께 기대했던 것은 EJB컴포넌트마켓의 발전이다. EJB기반의 다양한 3rd-party 컴포넌트들이 개발되고 또 이런 컴포넌트들을assemble해서 사용할 수 있다는 것이 EJB기술 마케팅의 주요한 포인트 중의 하나였음이 분명하다. 하지만 그 결과는 매우 실망스럽다. EJB컴포넌트 시장은 거의 존재한 적이 없다고 할 수 있을 정도로 미미한 수준이었다. 이는 부분적으로 EJB기술자체의 한계에도 기인하지만 한편으로는 엔터프라이즈 레벨의 기능들이 컴포넌트라는 것으로 만들어져 사용되어질 수 있기에는 너무 복잡하고 너무 특정 설계에 의존적인 것이 주요한 원인이라고 볼 수 있다. 그나마 활발한 컴포넌트 시장이 존재한다고 하는 ActiveX/.NET컴포넌트 시장에도 거의 대부분은 UI기능을 지원하는 컴포넌트만이 명맥을 유지하고 있을 뿐이지 본격적인 엔터프라이즈급의 컴포넌트는 찾아보기 힘들다는 점을 생각해보면 EJB의 컴포넌트 시장에 대한 나이브한 기대 자체에 문제가 있었다고 볼 수 있다.

최근 몇년 사이에 일어난 AOP에 대한 관심과 기술의 발전은 EJB가 가지는 많은 특징들을 좀 더 일반적인 방법으로 대치할 수 있는 가능성을 열어주었다. Interception이라는 관점에서 EJB서비스의 핵심적인 요소들은 AOP를 통해서 쉽게 구현가능해졌다. AOP는 OOP가 가지는 장점을 극대화하면서 이를 더욱 보완할 수 있는 기술임에 틀림이 없다. AOP를 통해서 제시되는 많은 기능들은 사실 EJB를 통해서 그동안 지속적으로 적용되어져 왔던 것이다. 다만 EJB에서는 매우 복잡한 방법과 구조를 통해서 이루어 졌다면 AOP는 그부분을 매우 심플한 방법과 새로운 자바자체의 기술들을 통해서 쉽게 적용할 수 있는 길을 열어준 것이다.

우리가 EJB에서 원하는 것

EJB를 사용한다는 많은 프로젝트에서 사실 SLSB만을 사용하는 경우가 많다. SFSB은 사용빈도가 매우 적다. State를 Business Service Layer에서 관리한 다는 것 자체가 문제이다. 상태정보를 관리하기엔 SFSB보다 HTTP session이 훨씬 더 편하기 때문이다. Entity Bean은 가장 많이 외면된 EJB의 기능중의 하나이다. J2EE진영에서 조차 Entity Bean에 대한 비판은 끊임없이 이어져왔다. Entity Bean을 실전에서 적용해본 개발자 중에서 만족한 사람은 거의 없다고 보인다. 근본적인 EJB의 모든 문제점을 모두 가지고 있는데다 CMP/BMP은 지속적인 스펙발전에도 불구하고 현실적인 문제를 제대로 반영해 줄 수 없는 심각한 한계를 가진 persistence 기술이기 때문이다. JDO나 Hibernate, TopLink등의 제대로 현실 문제를 반영할 수 있는 O/R매핑기술이 널리 적용되기까지 O/R 매핑기술에 대한 부정적인 인식을 만들어온 주범이라고 볼 수 있다.

결국 개발자들에 의해서 선택되어진 것은 SLSB와 MDB정도이다. 최근에 EJB프로젝트에서 주로 사용되어지는 것은 Local Interface기반의 SLSB일 것이다. 결국 EJB는 결국 실제 필요보다 너무 많은 기술을 가지고 있고 필요없이 복잡하다고 할 수 있겠다.

SLSB가 가지고 있는 기능들을 뽑아보자면 선언적 트랜잭션 관리, 리모팅, 클러스터링, 쓰레드관리, 인스턴스 풀링, 리소스 관리, 보안, 비즈니스 오브젝트 관리 정도로 정리될 수 있다.

1) CMT CMT(container-managed transaction)은 EJB의 가장 중요한 기능중의 하나라고 볼 수 있다. 자바코드에서 트랜잭션에 관한 부분을 선언적으로 쓸 수 있게 분리해냈다는 것은 매우 의미있는 것이다. 물론 복잡한 비즈니스로직을 가지는 경우 CMT만으로는 불가능 한 경우가 있기는 하지만 CMT는 그 자체로 매우 가치있는 기능이며 EJB를 사용하게 하는 주요한 이유중의 하나로 볼 수 있다. 하지만 대부분의 시스템구성이 단일DB(그 안에서 다시 clustering을 사용하는 경우를 포함하여)라고 볼 때 애플리케이션 서버 전체적으로 적용되는 JTA기반의 트랜잭션 관리는 대부분의 경우 구지 필요없는 부담이다.

Spring의 AOP기반의 선언적 트랜잭션관리 기능은 복잡하게는 멀티DB기반의 환경을 위한 JTA이용으로부터 단순하게는 JDBC API레벨까지 상황에 맞게 scale up/down이 가능하도록 설계되어 있다. 또한 checked exception에서의 rollback rule을 쉽게 설정하도록 할 수 있고 복잡한 트랜잭션의 경우 JTA보다 심플한 방법으로 프로그램에서 트랙잭션을 관리할 수 있는 방법을 제공한다.

2) Remoting 리모팅과 컴포넌트 이 두가지를 구분하지 않고 혼재해놓은 것이 EJB의 대표적인 문제점의 하나로 볼 수 있다. 대부분의 경우는 리모팅을 필요로하지 않는데다 리모팅을 해야 하는 경우 이부분이 독립적으로 삽입되어져 사용되어질 수 없는 고정적인 구조(EJB2.1에 들어서 비로서 RMI/IIOP에 더불어 web service remoting이 지원되어졌다)를 가지고 있기 때문이다. 이미 언급했던 것처럼 대부분의 경우 co-located되어진 구조가 remote 기반의 구조보다 낫다. 그리고 웹서비스를 제공하기에는 EJB보다 더 나은 방법이 얼마든지 있다.

3) Clustering EJB의 확장성은 매우 편리하고 뛰어난 것으로 제시되어져 왔지만 사실 그렇지 않다. 뛰어난 클러스터링을 지원하는 EJB지원 WAS는 매우 고가인데다 Entity bean과 SFSB는 사실 클러스터링하기에는 너무 제한적이 많은 문제점을 가지고 있다. 결국 SLSB의 클러스터링이 남게 된다. SLSB의 클러스터링의 장점은 사실 제한적이며 성능이나 확장성 면에서 볼때 co-located된 구조가 더 많은 장점이 있다.

4) Thread Management EJB처럼 동시성의 문제 때문에 특정 메소드가 실행되고 있는 중에 전체 bean을 locking하는 방식은 적절하다고 볼 수 없다. 대신에 서블릿이나 Struts Action처럼 instance variable을 가지고 있지 않은 싱글 오브젝트를 이용한다면 복잡한 쓰레드관리를 해야 할 필요가 없다. 또는 각각의 request에 대해서 새로운 인스턴스를 만들어서 쓰는 것도 간편하게 동시성 문제를 해결 할 수 있다. 최신 JVM은 사실 간단한 오브젝트 생성과 삭제에 별 부담을 가지지 않는다. WebWork/XWork이나 Hibernate에서 왜 의도적으로 오브젝트 풀링을 사용하지 않고 있는지 살펴 볼 필요가 있다. 아니면 자바언어의 synchronization 기능이나 concurrency api등을 이용해서 오브젝트를 작성할 수도 있다.

5) Instance Pooling EJB인스턴스 풀링은 EJB가 처음 만들어지던 Java 1.1시절에는 garbage collection상의 문제를 피하기 위한 것과 메모리 절약이라는 측면에서 가치가 있었다. 하지만 GC기술이 충분히 발달했고 메모리가격이 매우 저렴한 지금은 그만한 가치가 없다. 오히려 적절한 instance pool 사이즈와 쓰레드 사이즈를 어떻게 결정해야 하는가하는 난감한만 남아 있을 뿐이다.

6) Resource Pooling DB커넥션과 같은 리소스 풀링은 EJB의 인스턴스 풀링보다 어쩌면 더 중요하다. 하지만 리소스 풀링은 EJB의 기술이 아니라 J2EE애플리케이션 서버 또는 서블릿 컨테이너 레벨에서 준비되어진 기술이다. 따라서 EJB와 상관없이 얼마든지 사용되어 질 수 있다.

7) Security CMT와 더불어 EJB의 선언적 프로그래밍 기능으로 주목받은 것이 바로 보안에 관한 부분이다. 그러나 대부분의 복잡한 보안요구사항들은 EJB가 지원하는 선언적 보안방식으로는 구현하기가 불가능하다. 또한 선언적인 보안설정등은 서블릿컨테이너 레벨에서도 사용가능하다. Spring에서는 AOP와 interceptor chain등을 이용해서 쉽게 복잡한 보안프레임웍을 구성할 수 있게 해준다.

8) Business Object Management EJB의 장점중의 하나는 개발자로 하여금 인터페이스기반의 프로그래밍을 강제하고 있다는 점이다. 인터페이스와 구현의 분리는 좋은 프로그래밍 방식이다. 하지만 EJB만 그런 분리를 지원하는 것이 아니다. 자바언어 자체에서 이미 훌륭하게 인터페이스를 지원하고 있으며 lightweight container도 자체적으로 관리하는 오브젝트에 대해서 인터페이스를 통한 접근을 유용하게 해주는 Factory역할을 해준다. 또 IoC기능의 지원을 통해서 fine-grained된 오브젝트의 의존구조를 컨테이너 레벨에서 관리함으로 매우 심플한 프로그래밍 모델을 제공하고 있다.

우리는 EJB의 여러 장점들에 대해서 부인할 필요는 없다. 동시에 그것들이 EJB를 통해서만 지원되는 것이 아님을 알아야 하며 좀더 심플하고 바람직한 방법을 추구해야 할 것이다.

우리가 EJB로부터 원하지 않는 것

참으로 많다. 다 적기도 귀찮다. 한마디로 요약해서 말하자면 "심플하게 할 수 있는 것을 복잡하게 하게 하는 것"이라고 할 수 있다.

EJB는 나아질 수 있는가?

EJB 3.0이 최근 자바진영의 주된 화제중의 하나이다. 그간의 복잡성을 최대한 배제하고 대폭적으로 심플한 구조와 방법을 채택하겠다는 것이 EJB 3.0 전문가 그룹의 의지이다. 상당히 고무적이다. 하지만 EJB 3.0을 기대하는 것에는 한계가 있다. 시기적으로 제대로 EJB 3.0을 사용하게 될 수 있는 시점은 2006이나 되야 가능 할 것으로 보인다. 또 WAS업체의 마케팅관점에서 간섭을 무시할 수 없다. 복잡해야 비싸게 팔아먹을 수 있다고!

아무래도 계속 지적되었던 EJB문제들에 대한 모든 면에서의 변화를 기대하기는 힘들 것 같다.

미신과 오해들

몇가지 흔한 잘못된 오해들을 꼽아보자. 1) J2EE == EJB? J2EE는 EJB 이상이고 EJB는 자바의 일부일 뿐이다. EJB를 포기하는 것이 J2EE를 버리라는 것은 절대 아니다.

2) 모든 개발자들은 EJB를 이해하고 있다. 640페이지에 달하는 EJB2.1 스펙을 한번이나 다 읽어보기라도 한 사람이 얼마나 될까? 나도 관심있는 주제를 중심으로 훑어만 봤을 뿐이다. EJB와 그 관련기술에 대한 깊은 이해와 지식을 가진 개발자와 아키텍트는 극히 소수이다. 사실 다 이해하기에 너무 복잡하다. 샘플 코드 배끼기 수준의 EJB개발자가 얼마나 많은가?

3) MDB없이는 asynchronous application개발을 할 수 없다. MDB의 상당부분은 EJB가 아니라 J2EE에 기반하고 있다.

4) EJB없는 심플한 시스템을 만들 수는 있으나 그것은 확장성이 없다. 구지 설명할 필요조차 없는 생각이다.

그럼 대안은?

이 책이 이야기 하고 있는 핵심은 EJB를 사용하지 않고 엔터프라이즈 레벨의 서비스를 더 심플하고 생산적인 방법으로 사용할 수 있는 방법에 관한 것이다. 그 평가와 상관없이 EJB는 여전히 그 세력이 막강하다. 엄청난 규모의 WAS제작업체의 파워와 마케팅 능력, 언론플레이는 아직도 대부분의 기업의 의사결정을 담당하는 사람들에게 막대한 영향력을 미치고 있다. 또 많은 개발자들이 아직 EJB외의 대안에 대해서 잘 모르고 안다하더라고 막연한 거부감이나 부담감을 가지고 있는 것이 현실이다. 시간이 점점 지나고 Spring과 같은 좋은 대안들이 현실에서 검증되고 지속적으로 인정받기 시작하면서 EJB는 점점 그 주권을 내주지 않을까 기대해본다.

EJB를 배제한 J2EE시대를 이끌어 나갈 수 있을 것으로 주목받고 있는 기술들을 꼽아 본다면.

  • Spring Framework : 두말할 것 없는 가장 주목받고 있는 EJB이상의 뛰어난 프레임웍. 이 책의 결론이자 검증가능한 증거일 것이다.
  • Nanning Aspect : AOP기반의 솔루션.
  • JBoss 4 : AOP를 통한 POJO기반의 엔터프라이즈 서비스를 이용할 수 있다.
  • PicoContainer : Spring과 유사한 IoC기반의 Lightweight container.
  • Hibernate : POJO기반의 최고의 O/R매핑 솔루션
  • JDO : EJB를 대신할 수 있는 뛰어난 퍼시스턴스 기술의 하나
  • HiveMind : 또하나의 IoC컨테이너.
  • iBatis : 심플한 data access와 transaction방법을 제공
  • GLUE : 뛰어난 성능의 lightweight 웹 서비스 리모팅 솔루션

이런 기술들은 물론 SUN의 J2EE표준이 아니다. 그러나 표준만 써야 할 것인가? J2EE의 표준화 과정의 문제점은 너무나도 많다. 항상 표준만이 옳고 최선의 것이 아니다. 이미 EJB의 발전과정을 통해서 그 문제점에 대해서는 충분히 경험했다. 많은 필드의 개발자들이 만족하고 사용하고 퍼뜨리고 함께하는 것 그것이 진정한 의미의 표준이 아닐까 생각한다.

 

 

경량급 컨테이너와 IoC.

  1. 작성자 : 이일민(토비)
  2. 작성일 : 2004년 12월 25일

책을 정리해 나가면서 보는게 쉬운 일은 아니다. 일단 전체를 이해하고 읽기 위해서 한번 그리고 정리하며 핵심을 뽑아내고 다시 생각해 보기 위해서 한번. 즉 두번씩 읽어야 하기 때문이다. 이제 1/3겨우 봤는데 아직 갈길이 멀다.

Lightweight Container? IoC? 이게 도대체 뭔 말이지?

SpringFramework을 처음 접했을 때 이 두가지 용어가 정확히 무엇을 말하는지 이해하기가 힘들었다. IoC을 소개하는 Martyn Folwer의 아티클을 읽으면 Dependency Injection이라는 새로운 용어가 또 등장한다. 거기다 IoC는 이미 오래전부터 컨테이너의 기본 작동방식인데 뭐 새로운 것도 아니자나 하는 류의 글들을 읽으니 이거 나는 뭔가 세상돌아가는 것도 모르고 살아온 것 같은 절망에 잠시 빠진 기억이 난다. 요즘엔 종종 친구들이나 후배들이 IoC가 도대체 뭐냐고 물어온다. 한참을 개념을 설명해줘도 잘 이해가 안간다는 사람도 있고 또 그걸 뭐하러 쓰냐고 반문하는 사람도 있다.


Lightweight Container

왜 IoC와 Lightweight Container가 필요한가? 앞 장들에서 쭉 얘기 해 온 것은 EJB는 수많은 문제를 가진 배제되야 할 기술이라는 것이다. 그럼 EJB를 쓰지 않고 EJB이전의 방식으로 J2EE애플리케이션을 개발하면 될 것인가? 그것은 아니다. EJB의 비즈니스 서비스 컨테이너로서의 특징과 장점들은 포기하기에 아까운 것들이다. 그렇다고 그런 것들을 독자적으로 직접 구성해서 만들어 쓰는 것은 배보다 배꼽이 더 큰 상황이 될 것이다. 결국 우리에게 필요한 대안은 잘 구성된 - 완성도 높은 - EJB기반이 아닌 비즈니스 서비스 컨테이너이다. 이 컨테이너는 EJB의 단점들을 가지지 않아야 한다. 동시에 EJB의 장점들을 가지고 있어야 한다. 욕심도 많다. 그 욕심을 채워줄 멋진 컨테이너를 이제 알아보자.

컨테이너니 프레임웍이니 하면 알레르기 부터 일으키는 개발자들이 있다. EJB를 쓰면서 많이 고생한 나도 컨테이너 하면 짜증부터 났다. 내가 뭔가 컨트롤 할 수는 없으면서 많은 제약을 가해오는 그 것. 그것이 컨테이너인데…

하지만 컨테이너 없는 J2EE는 기대할 수도 없다. 당장 서블릿과 서블릿이 사용하는 오브젝트들 구동해주는 웹 컨테이너가 없으면 웹기반의 서버프로그래밍은 기대할 수도 없다.

컨테이너의 기본 특징은 Lifecycle Management, Lookup, Configuration, Dependency Resolution으로 볼 수 있다. 그밖에도 Thread Management, Object Pooling, Clustering, Management, Remoting, Exposing remote services, Customization and extensibility등의 부가적인 기능들을 포함하기도 한다.

그럼 lightweight container의 특징은 무엇인가?

  1. lightweight container는 일반 컨테이너처럼 애플리케이션 코드를 관리해 주지만 그 코드내에 컨테이너에 대한 의존적인 부분들이 필요없도록 해준다. 왜 가벼운가? 그것은 코드내에 컨테이너에서 동작하기 위해서 특별히 필요로 하는 부분이 없기 때문이다. 컨테이너를 알지 못하는 오브젝트 또는 알 필요도 없는 오브젝트를 가능하게 해준다는 것이다.
  2. 컨테이너 구동이 빠르다. 가벼우니까 당연히 빠르다.
  3. 컨테이너 내에 오브젝트를 배치(deploy)하기 위한 복잡한 과정이 없다.
  4. 컨테이너 그 자체로 작고 가볍다. 컨테이너는 Pure Java이지 J2EE의존적이 아니다. J2EE를 벗어나 standalone Java나 applet에서도 구동이 가능하다.
  5. 컨테이너에서 동작할 오브젝트가 fine-grained 또는 coarse-grained의 어떤 것도 가능하도록 오브젝트의 배치가 쉽고 단순하며 성능의 오버헤드가 없어야 한다.

오브젝트가 컨테이너에 의존적이지 않는다면 그래서 컨테이너의 API조차 사용할 필요가 없다면 구지 컨테이너가 필요한 이유는 무엇인가? 컨테이너는 여러가지 면에서 반드시 필요한데 첫째는 컴포넌트/오브젝트의 자유로운 삽입(Pluggability)이 가능하도록 하기 위한 calling code의 독립성 때문이다. 둘째는 서비스의 lookup이나 configuration이 일관성을 갖도록 하기 위한 것이다. 셋째는 단일화된 서비스의 접근방법을 제공하기 위한 것이다. 개발자 각자 자기만의 스타일로 싱글톤이나 팩토리를 만들어 쓸 필요가 없어야 한다. 넷째는 비즈니스 오브젝트에 부가적으로 필요로 하는 각종 enterprise service를 제공하기 위해서 이다.


Inversion of Control

컨테이너에 종속적인 코드를 최소화 하기위한 가장 좋은 방법은 IoC와 Dependency Injection을 적절히 사용하는 것이다. IoC는 기본적으로 framework의 가장 중요한 개념중의 하나이다. DI는 IoC의 일종으로 IoC의 장점을 극대화 한것으로 볼 수 있다.

IoC라하면 간단히 말해서 container/framework이 오브젝트를 관리하는 구조라고 생각하면 된다. 즉 오브젝트의 lifecycle관리 및 구동을 container가 담당하는 구조라고 생각하면 된다.

IoC의 구현방법에는 두가지가 있다. 첫째는 Dependency Lookup이다. 이 것은 컨테이너가 callback을 통해서 제공하는 lookup context를 이용해서 필요한 리소스나 오브젝트를 얻는 방식이다. EJB와 Apache Avalon의 구현방법이다. 둘째는 Dependency Injection이다. 이 책이 홍보하는 방법이다. 비즈니스 오브젝트에 look up 코드를 사용하지 않고 컨테이너가 직접 의존구조를 오브젝트에 설정할 수 있도록 지정 해주는 방법이다. 이 것은 다시 Setter Injection과 Constructor Injection으로 나뉜다.

Dependency Lookup은 JNDI등을 이용하는데 오브젝트간에 decoupling을 해주는 면에서 장점이 있기는 하다. 하지만 이렇게 만들어진 오브젝트는 컨테이너 밖에서 실행 할 수 없고 JNDI외의 방법을 사용할 경우 JNDI관련 코드를 오브젝트내에 일일히 변경해 줘야 하며 테스트하기 매우 어렵고 코드양이 매우 증가하고 Strong typed가 아니므로 Object로 받아서 매번 Casting해야 하고 (그래서 primitive type은 wrapper class를 써야 하고) NamingException같은 checked exception을 처리하기 위해서 exception처리구조가 매우 복잡해지는 단점이 있다.

Avalon의 경우는 EJB보다 좀 더 심플한 lookup방법을 제공하지만 거의 대부분의 나머지 단점에서는 자유롭지 못하다.

Dependency Injection은 각 오브젝트가 자신이 의존적인 resource와 collaborator에 대한 lookup의 책임을 가지지 않고 대신 컨테이너가 그 일을 담당하고 오브젝트 내에 주입해주는 방식이다. 따라서 lookup과 관련된 코드들이 오브젝트 내에서 완전히 사라지고 컨테이너에 의존적이지 않은 코드를 작성할 수 있다. 이는 오브젝트가 컨테이너의 존재여부를 알 필요조차도 없기 때문이다. 또 특별한 인터페이스 구현나 클래스의 상속의 필요가 없다.

DI중 Setter Injecton은 JavaBeans의 property구조를 이용한 방식이다. SpringFramework쪽이 주로 이 Setter Injection을 지지하고 있다. 오브젝트가 컨테이너에 의해서 만들어지고 나서 바로 모든 dependency들이 setter method를 통해서 주입이 된다. Setter Injection이 가지는 장점은 JavaBean property 구조를 사용하기 때문에 IDE등에서 개발하기 편리하고 상속시 그 구조가 그대로 전달이 되며 type conversion을 위해서 JavaBean property-editor기능을 사용할 수가 있고 getter method를 통해서 현재 오브젝트의 상태정보를 얻어올 수 있다는 것들이다. 담점으로는 setting 순서를 지정할 수 없다는 것과 모든 필요한 property가 세팅되는 것에 대해서 보장할 수 없다는 점이 있다.

Constructor Injection은 PicoContainer에서 주로 많이 사용하는 방식이다. Setter Injection의 단점을 일부 극복할 수는 있는 장점이 있지만 반대로 단점도 제법 많다. 하지만 뭐 크게 문제가 될만한 것들은 아니라고 본다.

어떤 방식의 Dependency Injection을 쓰느냐는 취향의 문제에 가깝다. 거의 모든 IoC 컨테이너에서는 두가지 방식을 다 지원한다.

Dependency Injection을 쓰기 어려운 경우가 있다. Dependency 구조가 매우 다이나믹해서 미리 지정하기 어려운 경우이다. 가능한 이런 구조는 설계단계에서 피하는 것이 낫지 않을까 싶다. 정 어쩔 수 없는 경우가 아니라면.


IoC Container

SpringFramework

이 책의 저자의 개념과 철학이 모여 만들어진 결과물이다. 이제 버전 1.1대의 매우 새로운 제품이지만 그 인기와 적용되는 속도는 정말 놀랄 만하다. 베타단계부터 꾸준하게 테스트 되고 계속 기능이 확장, 안정되어왔기 때문일 것이다. 가장 활발하게 업데이트 되고 논의 되는 컨테이너이다.

기본적으로 XML을 이용한 메타데이터로 configuration을 지원한다. 사용법은 매우 간편하다. 사실 IoC/DI 관점에서만 보자면 정말 매우 심플하고 가볍다. 몇가지 특징으로는 autowiring를 지원해서 XML작업을 최소화 할 수 있고 다양한 collection구조를 지원하며 각 오브젝트의 lifecycle 메소드를 지원한다는 것이 있다.

꼭 필요한 경우에는 container의 callback기능을 이용해서 직접 lookup하는 방식을 지원하기도 한다. 가능하면 container관련 코드를 전부 제거하면 좋지만 서버환경에서 특정한 경우에는 container레벨의 정보를 직접 사용해야 할 때가 있다.

EJB의 대안으로 제시하는 Lightweight Container가 EJB와는 달리 심플할 수 있는 가장 중요한 요소는 바로 IoC/DI를 사용하기 때문일 것이다. IoC기반의 프로그래밍을 해보지 않은 경우에는 처음에는 조금 접근하기가 간단치 않을 것이다. 그것은 IoC가 어려워서가 아니라 그 구조가 지금까지 해왔던 방식과 반대방향으로 되어있기 때문이다. 그러나 한번 익숙해 지고 나면 이만큼 편리한 것도 없다. Spring으로 몇달간 개발해온 프로그래머들이 공통적으로 하는 말이 있다. "IoC를 쓰기 전엔 도대체 어떻게 개발을 했었는지? 이젠 IoC없는 개발은 상상이 안되네…


 

 

'java core' 카테고리의 다른 글

super.paint() 이용  (0) 2005.12.12
[펌] 간단한 Java Native Interface 예제  (0) 2005.11.05
자바 파서. java parser  (0) 2005.10.20
자바 ftp client 라이브러리.  (0) 2005.10.13
이벤트 모델  (0) 2005.09.16
Posted by '김용환'
,


* JavaCC Home Page- The Java Compiler Compiler
Formally known as Jack. A LL(k) parser generator from SunTest labs for generating recursive descent parsers and compilers that runs on both JDK 1.0.2 and JDK 1.1.
Comes with a bunch of grammars including both Java 1.0.2 and Java 1.1 as well as a couple of HTML grammars.
* JavaCUP Parser Generator
A "Java based Constructor of Useful Parsers (CUP for short)" for generating LALR parsers from simple specifications, similar to YACC.
* Java-Lex: A Lexical Analyzer Generator for Java
Based upon the Lex lexical analyzer generator model. Java-Lex takes a specification file similar to that accepted by Lex, then creates a Java source file for the corresponding lexical analyzer.
* Free Java Language Tools
A listing of several free tools for Java parsing, source and byte-code manipulation, including several grammers for the Java language itself.
* C2J - a C++ to Java translator
by Chris Laffra. "Translates roughly about 85-95 percent of our code correctly", so you will still need to do some checking / editing yourself, but it does a lot of the hard slog for you.
* How to build an interpreter in Java - Part 1
An article by Chuck McManis on using Java to create an interpreter for a scripting language with a generic interpreter class, making it easy to add scripting ability to any Java application.
* OROMatcher regular expression package
A comprehensive regular expression package for Java from ORO Inc. Compatible with Perl5 regular expressions, supports the processing of InputStreams, and free for most uses. They also have TextTools, AwkTools and PerlTools Java libraries to provide added-value on top of the OROMatcher library.
* Microsoft XML Parser in Java
The Microsoft XML Parser is a validating XML parser written in Java. The parser checks for well-formed documents and optionally permits checking of the documents' validity, then the XML document is exposed as a tree through a simple set of Java methods. These methods support reading and/or writing XML structures, such as the Channel Definition Format (CDF) or other text formats based on XML, and thereby enable building applications using XML.
* NXP - Norbert's XML Parser
A (validating) XML parser written in Java. Being used as the basis for DataChannel's DXME product (see below)
* DataChannel XML Development Environment (DXDE)
DXDE is a collection of XML tools including parsers, viewers, and APIs. Includes source code for Xapi-J - a standardized XML API in Java.
* ANTLR
A highly regarded and frequently recommended parser generator, ANTLR (formerly PCCTS) is a language tool that provides a framework for constructing recognizers, compilers, and translators from grammatical descriptions containing C, C++, or Java actions.
* ChannelWorld
ChannelWorld is DataChannel's research collection, covering core topics like XML, DSSSL, Java, IP multicasting and all the people and organizations that contribute to these subjects.
* Roll a New Data Format with XML
An article from JavaPro magazine giving an introduction to XML use in Java, including sample application using Microsoft's XML Parser.
* HtmlStreamTokenizer
A HTML parser written in Java by Arthur Do that is similar to the StreamTokenizer class but is specialized for HTML streams. Generally free for non-commercial use.
* Free-DOM
FREE-DOM is an implementation by Don Park of the W3C Document Object Model (DOM) API in Java.
* SAX : The Simple API for XML
SAX is a Java API package for event-based XML parsing (ie. "callback" based, rather than "parse tree" based), developed collaboratively by the members of the XML-DEV mailing list. SAX is free for both commercial and non-commercial use, and is already being used by a wide range of products and applications.
* XML and Java Tutorial, Part I
A tutorial from the Bean Factory showing how Java can be used to display information in XML documents using a graphical Swing interface and an HTML based interface.
* BCEL - Byte Code Engineering Library
The Byte Code Engineering Library (formerly known as JavaClass) is intended to give users a convenient possibility to analyze, create, and manipulate (binary) Java class files (those ending with .class). Classes are represented by objects which contain all the symbolic information of the given class: methods, fields and byte code instructions, in particular. Such objects can be read from an existing file, be transformed by a program (e.g. a class loader at run-time) and dumped to a file again. An even more interesting application is the creation of classes from scratch at run-time.
* QDox
QDox is a high speed, small footprint parser for extracting class/interface/method definitions from source files complete with JavaDoc @tags. It is designed to be used by active code generators or documentation tools.
* Regular expressions simplify pattern-matching code
Text processing often involves matching text against a pattern. Although Java's character and assorted string classes offer low-level pattern-matching support, that support commonly leads to complex code. To help you write simpler pattern-matching code, Java provides regular expressions. After introducing you to terminology and the java.util.regex package, Jeff Friesen explores many regular expression constructs supported by that package's Pattern class. Then he examines Pattern's methods and the additional java.util.regex classes. In conclusion, he presents a practical application of regular expressions.

 

출처

http://www.swtech.com/java/parser/

'java core' 카테고리의 다른 글

[펌] 간단한 Java Native Interface 예제  (0) 2005.11.05
[펌] 로드 존슨의 J2EE Development Without EJB 정리 컬럼  (0) 2005.10.28
자바 ftp client 라이브러리.  (0) 2005.10.13
이벤트 모델  (0) 2005.09.16
[펌] JVM 관련  (0) 2005.09.15
Posted by '김용환'
,

자바 html parser

etc tools 2005. 10. 20. 19:11

Alternative HTML Parsers

This package was originally written in the latter half of 2002. At that time I evaluated 6 other parsers, none of which were capable of achieving my aims. Most couldn't reproduce a typical HTML document without change, none could reproduce a source document containing badly formatted or non-HTML components without change, and none provided a means to track the positions of nodes in the source text. A list of these parsers and a brief description follows, but please note that I have not revised this analysis since the before this package was written. Please let me know if there are any errors.

  • JavaCC HTML Parser by Quiotix Corporation (http://www.quiotix.com/downloads/html-parser/)
    GNU GPL licence, expensive licence fee to use in commercial application. Does not support document structure (parses into a flat node stream).
  • Demonstrational HTML 3.2 parser bundled with JavaCC. Virtually useless.
  • JTidy (http://jtidy.sourceforge.net/)
    Supports document structure, but by its very nature it "tidies" up anything it doesn't like in the source document. On first glance it looks like the positions of nodes in the source are accessible, at least in protected start and end fields in the Node class, but these are pointers into a different buffer and are of no use.
  • javax.swing.text.html.parser.Parser
    Comes standard in the JDK. Supports document structure. Does not track the positions of nodes in the source text, but can be easily modified to do so (although not sure of legal implications of modifications). Requires a DTD to function, but only comes with HTML3.2 DTD which is unsuitable. Even if an HTML 4.01 DTD were found, the parser itself might need tweaking to cater for the new element types. The DTD needs to be in the format of a "bdtd" file, which is a binary format used only by Sun in this parser implementation. I have found many requests for a 4.01 bdtd file in newsgroups etc on the web, but they all reamain unanswered. Building it from scratch is not so easy.
  • Kizna HTML Parser v1.1 (http://htmlparser.sourceforge.net/)
    GNU LGPL licence. Version 1.1 was very simple without support for document structure. I have since revisited this project at sourceforge (early 2004), where version 1.4 is now available. There are now two separate libraries, one with and one without document structure support. It claims to now also be capable of reproducing source text verbatim.
  • CyberNeko HTML Parser (http://www.apache.org/~andyc/neko/doc/html/index.html)
    Apache-style licence. Supports document structure. Based on the very popular Xerces XML parser. At the time of evaluation this parser didn't regenerate the source accurately enough.

 

출처  - http://jerichohtml.sourceforge.net/

 

Open Source HTML Parsers in Java

NekoHTML

NekoHTML is a simple HTML scanner and tag balancer that enables application programmers to parse HTML documents and access the information using standard XML interfaces. The parser can scan HTML files and "fix up" many common mistakes that human (and computer) authors make in writing HTML documents. NekoHTML adds missing parent elements; automatically closes elements with optional end tags; and can handle mismatched inline element tags.

Go To NekoHTML

HTML Parser

A fast real-time parser for real-world HTML.

Go To HTML Parser

Java HTML Parser

HTML Parser that produces a stream of tag objects, which can be further parsed into a searchable tree structure.

Go To Java HTML Parser

Jericho HTML Parser

A simple but powerful java library for parsing and modifying HTML documents, including analysis of abritrary HTML forms to determine the structure of submitted data.

Go To Jericho HTML Parser

JTidy

JTidy is a Java port of HTML Tidy , a HTML syntax checker and pretty printer. Like its non-Java cousin, JTidy can be used as a tool for cleaning up malformed and faulty HTML. In addition, JTidy provides a DOM interface to the document that is being processed, which effectively makes you able to use JTidy as a DOM parser for real-world HTML.

Go To JTidy

TagSoup

TagSoup is a SAX-compliant parser written in Java that, instead of parsing well-formed or valid XML, parses HTML as it is found in the wild: nasty and brutish, though quite often far from short. TagSoup is designed for people who have to process this stuff using some semblance of a rational application design. By providing a SAX interface, it allows standard XML tools to be applied to even the worst HTML.

Go To TagSoup

HotSax

HotSAX is a fast, small footprint, non-validating SAX2 parser for HTML/XML/XHTML. It can be used in simple web agents, page scrapers, and spiders. It is similar to the Apache Xerces parser, except that it can generate SAX events for badly formatted HTML as well.

Go To HotSax

 

출처 http://java-source.net/open-source/html-parsers

'etc tools' 카테고리의 다른 글

간단하게 사용가능한 ctags 사용  (0) 2006.04.14
[펌] HTML 특수문자표  (0) 2005.11.01
C#과 자바의 비교.  (0) 2005.06.14
[팁] ant에서 alias 사용하기  (0) 2005.06.14
[팁] ant, conditional compiling 조건 수행  (0) 2005.06.14
Posted by '김용환'
,