검색결과 리스트
분류 전체보기에 해당되는 글 253건
- 2008.08.14 [SQL] 오라클 함수 모음
- 2008.08.07 [C#]오피스 불러올 시 WebBrowser 컨트롤 사용 시 고려 사항
- 2008.07.31 [C#]WinAPI적용
- 2008.07.31 [C#]원격제어 마우스. 키보드. 입력 구조체
- 2008.07.30 [C#]Namespace 정리
- 2008.07.17 [C#]MSDN
- 2008.07.12 [JSP]초보 Java 웹 개발자들을 위한 학습 로드맵
- 2008.07.10 [Java]어셈블리 언어 프로그램에서 자바 애플리케이션 실행
- 2008.07.05 [C#]Inside C# 번역본 입니다.
- 2008.07.04 [C#]환경변수 설정
글
* 단일 행 함수
-함수가 정의된 SQL문이 실행될 때 각각의 ROW에 대해 수행되며 ROW 당 하나의 결과를 리턴 해줍니다.
-인수로는 상수,변수,표현식들이 사용될 수 있습니다.
-SELECT,WHERE,ORDER BY 절에 사용할 수 있습니다.
구 분 | 함수 | 내 용
---------------------------------------------------------------------------------------
LOWER 모든 문자를 소문자로
UPPER 모든 문자를 대문자로
INITCAP 첫 글자는 대문자,나머지는 소문자로
CANCAT 첫 번째 문자와 두 번째 문자를 연결
SUBSTR 문자의 길이를 리턴할 때
LENGTH 문자의 길이를 리턴할 때
NVL 널값을 다른 값으로 대체할 때
NVL2 조건에 의해 널값을 다른 값으로 대체할 때
SUBSTR 특정 문자의 문자열중 필요 부분만 선별하여 사용
문자 RTRIM 서브 스트림의 정확한 위치와 길이를 요구(오른쪽)
함수 LTRIM 서브 스트림의 정확한 위치와 길이를 요구(왼쪽)
RPAD 문자열을 제외한 공간에 지정한 문자열로 대체(오른쪽)
LPAD 문자열을 제외한 공간에 지정한 문자열로 대체(왼쪽)
TRANSLATE 첫 문자는 탐색집합의 첫 문자로 대체(2번째도 동일)
REPLACE 특정 문자열을 다른 문자열로 대체
SOUNDX 같은 단어 또는 유사한 사운드 단어를 음성학적으로
LENGTH 문자의 실제 길이를 변환할 때
LENGTHB 문자열의 실제 길이를 변환할 때
INTSTR 문자열 내의 특정 스트림의 위치
NULLIF 조건이 같으면 NULL,다르면 지정된 값을 리턴할 때
COALESCE 조건에 따라 여러 가지 값을 리턴할 때
-----------------------------------------------------------------------------------------
시스템 USER 현재 DB 사용자
함수 USERID 현재 DB 사용자에게 할당되는 사용자번호
-----------------------------------------------------------------------------------------
*문자함수의 예제
EX) -2개의 문자값을 결합합니다.
SQL>SELECT CONCAT(CONCAT(ename, ' is a '),job)
FROM emp;
CONCAT(CONCAT(ENAME,'ISA
---------------------------------
SMITH is a CLERK
ALLEN is a SALESMAN
-정의된 문장 단어의 첫 번째 문자를 대문자로 변환
SOL> SELECT INITCAP( 'the soap') FROM DUAL;
INITCAP(
-----------
The Soap
-정의된 문장의 왼쪽 나머지 공간을 지정한 문자로 채웁니다.
SQL> SELECT LPAD( 'Page 1' , 15 , '*.') FROM DUAL;
LPAD( 'PAGE1',15
---------------------
*.*.*.*.*Page 1
-정의된 문장의 왼쪽부터 지정된 단어가 발견되면 제거합니다.
SQL> SELECT LTRIM( 'xyxXxyLAST WORD','xy') FROM DUAL;
LTRIM('XYXXX
-------------------
XxyLAST WORD
-정의된 문장에서 해당 문자가 발견되면 지정된 문자로 변경합니다.
SQL> SELECT REPLACE( 'JACK and JUE' , 'J' , 'BL') FROM DUAL;
REPLACE( 'JACKA
-----------------------
BLACK and BLUE
-정의된 문자의 오른쪽 나머지 공간을 지정한 문자로 채웁니다.
SQL> SELECT RPAD(ename, 11 ,'ab' ) FROM emp WHERE ename = 'TURNER' ;
RPAD(ENAME , 11 ,'AB')
---------------------------
TURNERababa
-정의된 문자의 오른쪽부터 지정된 단어가 발견되면 제거합니다.
SQL> SELECT RTRIM( 'TURNERyxXxy' , 'xy') FROM DUAL ;
RTRIM( 'TU
-------------
TURNERyxX
-정의된 문장의 지정된 위치부터 해당 길이 만큼만 추출합니다.
SQL> SELECT SUBSTR( 'ABCDEFG' , 3 , 2 ) FROM DUAL ;
SU
-------
CD
-정의된 문장의 뒤에서부터 지정된 위치의 해당 길이 만큼만 추출합니다.
SQL> SELECT SUBSTR ( 'ABCDEFG' , -3 , 2 ) FROM DUAL ;
SU
--------
EF
-문자 'Q'를 ASCII 코드로 변환합니다.
SQL> SELECT ASCII ( 'Q' ) FROM DUAL ;
ASCII ( 'Q' )
---------------
81
-정의된 문장에서 지정된 위치에 존재하는 문자의 위치 값을 찾아 줍니다.
SQL> SELECT INSTR ( 'CORPORATE FLOOR' , 'OR' ,3 ,2 ) FROM DUAL ;
INSTR ( 'CORPORATEFLOOR' , 'OR' , 3 , 2 )
---------------------------------------------
14
-정의된 문장의 길이를 변환합니다.
SQL> SELECT LENGTHB ( '가나다라마바사') FROM DUAL ;
LENGTH( '가나다라마바사' )
---------------------------
14
-정의된 단어 중에 가장 높은 값을 찾아줍니다.
SQL> SELECT GREATEST ( 'HARRY' , 'HARIOT' ,'HALORD' ) FROM DUAL ;
GREAT
---------
HARRY
-정의한 컬럼이 NULL이면 지정한 값으로 대체합니다.
SQL> SELECT NVL (sal , 0 ) , NVL( ename , '*' ) , NVL(hiredate , '01-JAN-02' ) FROM emp ;
NVL(SAL , 0 ) NVL(ENAME , NVL(HIRE
------------------------------------------------
800 SMITH 80/12/17
*시스템 함수
-현재 어떤 사용자로 데이터 베이스에 접속하였는지 알 수 있습니다.
SQL> SELECT USER FROM dual ;
USER
-------
SCOTT
* 숫자함수/날짜함수
------------------------------------------------------------------------------
구 분 함 수 내 용
------------------------------------------------------------------------------
ROUND 해당 소수점 자리에서 반올림할 때
TRUNC 해당 소수점 자리에서 절삭할 때
MOD(m/n) m을 n으로 나누고 남은 나머지를 리턴할 때
ABS 숫자 값을 절대값으로 바꾼다
SIGN 숫자가 양수:+1, 음수:-1, 0:0
숫자함수 FLOOR 실수값을 정수값으로
CEIL 그 수보다 가장 크거나 작은값을 리턴
POWER 해당 수에 대한 지수값을 표현
LOG 로그값으로 변환
SIN SIN값
COS COS값
TAN TAN값
------------------------------------------------------------------------------
SYSDATE 현재 시스템 날짜를 보여줄 때
ADD_MONTHS 지정한 날짜에 몇 월을 추가한 결과의 월을 계산할 때
LAST_DAY 해당 월의 마지막 날짜를 알고자 할 때
날짜함수 NEW_TIME 해당 표준시로 시간을 변환할 때
NEXT_DAY 해당 날짜의 다음 지정한 날짜로 현환할 때
NONTH_BETWEEN 지정된 월 간의 월수를 알고자 할 때
------------------------------------------------------------------------------
* 숫자함수 예제....
-정의된 값을 절대값으로 변환 합니다
SQL> SELECT ABS(-15) FROM DUAL ;
ABS(-15)
-----------
15
-정의된 값의 올림된 값으로 변환합니다
SQL> SELECT CEIL(15.7) FROM DUAL ;
CEIL(15.7)
-------------
16
-정의된 값의 내림된 값으로 변환합니다
SQL> SELECT FLOOR(15.7) FROM DUAL ;
FLOOR(15.7)
---------------
15
-정의된 산술식의 COSINE 값으로 변환합니다
SQL> SELECT COS(180*3.14/180) FROM DUAL ;
COS(180*3.14/180)
--------------------
-.99999873
-정의된 숫자의 지수승값을 계산합니다
SQL> SELECT EXP(4) FROM DUAL ;
EXP(4)
---------
54.59815
-뒤에 정의된 수로 앞에 정의된 수를 나눈 나머지 값을 반환합니다
SQL> SELECT MOD(11,4) FROM DUAL ;
MOD(11,4)
------------
3
-정의된 수를 지정한 자리 수에서 반올림합니다
SQL> SELECT ROUND(15.193 , 1) FROM DUAL ;
ROUND(15.193 , 1)
-------------------
15.2
-정의된 값이 음수이면 -1 , 0 이면 0, 양수이면 1을 리턴합니다
SQL> SELECT SIGN(-15) FROM DUAL ;
SIGN(-15)
------------
-1
-정의된 수를 지정한 자리 수 에서 절삭합니다
SQL> SELECT TRUNC(15.97 , 1) FROM DUAL ;
TRUNC(15.79 , 1)
-----------------
15.7
* 날짜 함수 예제
-현재 시스템 날짜를 제공합니다
SQL> SELECT SYSDATE FROM DUAL ;
SYSDATE
-----------
06/11/13
-해당 날짜에 지정한 달 수만큼 더합니다
SQL> SELECT HIREDATE , ADD_MONTHS(HIREDATE , 1)
FROM EMP WHERE EMPNO = 7782 ;
HIREDATE ADD_MONT
--------------------------
81/06/09 81/07/09
-정의된 날짜의 달에서 마지막 일이 몇 일인지 알 수 있습니다
SQL> SELECT HIREDATE , LAST_DAY(HIREDATE)
FROM EMP WHERE EMPNO = 7782 ;
HIREDATE LAST_DAY
--------------------------
81/06/09 81/06/30
-정의된 두 날짜간의 차이 값을 알 수 있습니다
SQL> SELECT HIREDATE , MONTHS_BETWEEN(SYSDATE , HIREDATE)
FROM EMP WHERE EMPNO = 7782 ;
HIREDATE MONTHS_BETWEEN(SYSDATE , HIREDATE)
------------------------------------------------------------
81/06/09 252.930883
-정의된 날짜를 녀도 값을 기준으로 반올림 합니다
SQL > SELECT
ROUND(TO_DATE(' 27-OCT-98' , 'DD-MON-YY' ) ,
'YEAT' ) FROM DUAL ;
ROUND(TO
------------
99/01/01
변환 함수
---------------------------------------------------------------------------
구 분 함 수 내 용
---------------------------------------------------------------------------
TO_CHAR 숫자,날짜 타입의 Data를 varchar2타입으로 변환
변환함수 TO_NUMBER 숫자를 포함하는 문자 String을 number 타입으로 변환
TO_DATE 문자 String을 날짜 타입으로 변환
---------------------------------------------------------------------------
*날짜 형식 요소
---------------------------------------------------------------------------
형식 요소 설 명
---------------------------------------------------------------------------
MM 달 수(ex : 10)
MON 월 이름을 3자리 문자로 표현(ex : JAN , FEB , MAR 등)
MONTH 월 이름(ex : JANUARY,FEBUARY,MARCH 등)
DD 날짜 (ex : 14)
D 주의 일수 (ex : 4)
DY 요일 이름을 3자리 문자로 표현(ex : SUN , MON , TUE 등)
DAY 요일 이름(ex : SUNDAY , MONDAY 등)
YYYY 년도 4자리 수 (ex : 2002)
YY 년도의 마지막 2자리(ex : 02)
----------------------------------------------------------------------------
*시간 형식 요소
----------------------------------------------------------------------------
형식 요소 설 명
----------------------------------------------------------------------------
9 숫자(ex : 9999 → 1534)
0 자리 수가 비면 0으로 채워줌 ( ex : 09999 → 01534 )
$ 금액에 $를 표시해줌 (ex : $99999 → $1534 )
. 명시한 위치에 소수점을 표시함 (ex : 99999.99 → 1534.00 )
, 명시한 위치에 콤마를 표시함 (ex : 999,999 → 1,534 )
----------------------------------------------------------------------------
변환 함수 예제들.....
-현재 날짜가 한 주에서 몇번째 일인지 알 수 있습니다
SQL> SELECT SYSDATE , TO_CHAR ( SYSDATE , 'D' )
FROM dual ;
SYSDATE TO_CHAR
--------------------------
02/09/26 5
-정의된 날짜의 출력 포맷을 DD-MM-YY로 출력합니다
SQL> SELECT ename , TO_CHAR(hiredate , 'DD-MM-YY' ) HIREDATE
FROM emp ;
ENAME TO_CHAR(hiredate , 'DD-MM-YY' )
------------------------------------------------
SMITH 17 11 90
ALLY 20 02 91
......................
-일자를 출력할 때 0 값을 제거합니다(09 → 9 , 01 → 1)
SQL> SELECT ename , TO_CHAR (hiredate , 'fmDD-MM-YY' ) HIREDATE
FROM emp ;
ENAME TO_CHAR(hiredate , 'fmDD-MM-YY' )
---------------------------------------------------
....................................
MARTIN 9 09 91
....................................
-문자 100을 숫자값으로 출력합니다
SQL> SELECT TO_NUMBER ( '100' ) FROM dual ;
TO_NUMBER
--------------
100
-현재 시간을 AM , PM 표기법으로 출력합니다
SQL> SELECT TO_CHAR( SYSDATE , 'AM HH:MI ' )
FROM dual ;
TO_CHAR(
-----------
오전 10 : 10
-숫자값을 출력할 때 금액표시를 합니다
SQL> SELECT TO_CHAR( 12506 , '$9099,999' ) FROM dual ;
TO_CHAR(
-----------
$010,234
-정의된 날짜를 지정한 포맷으로 출력합니다
SQL> SELECT TO_DATE( '01-JUL-99' , 'DD-MM-YY' )
FROM dual ;
TO_DATE(
-----------
99/07/01
-정의된 시간을 지정한 포맷으로 출력합니다
SQL> SELECT TO_DATE( '01:30' , 'HH24:MI' ) FROM dual ;
TO_DATE
----------
13:30
단일행함수
* NVL2 ( Colum, Express1, Express2 )
-해당 컬럼이 null이면 Express-2 의 값을 , null이 아니면 Express-1의 값을 리턴해 줍니다.
오라클 이전 버전에서 사용되던 NVL함수는 정의된 컬럼의 값이 null인 경우 지정한 값으로
대체하는 기능을 가지고 있었습니다. 반대로, NVL2 함수는 정의된 컬럼의 값이 지정한
값인 경우 null값으로 대체된다.
NVL2 함수는 해당 컬럼이 null 값이 아니면 Express2의 값을 리턴해 주고 null 값이면
Express3의 값을 리턴해 주는 기능을 가지고 있습니다.
SQL> SELECT empno, ename, nv12( comm, comm.*1.1, 0 )
FROM emp ;
EMPNO ENAME COMM NVL2( COMM, COMM*1.1, 0 )
----------------------------------------------------------
7369 SMITH 0
7499 ALLEN 300 330
7521 WARD 500 550
7566 JONES 0
..............................................
->COMM이 null인 경우 null이 아닌 경우
* NULLIF ( Express1, Express2 )
-Express-1과 Express-2의 값을 비교하여 그 값이 같으면 null을 리턴하고 다르면 Express-1의
값을 리턴해 줍니다.
NULLIF 함수는 Express-1 과 Express-2 의 값을 비교하여 그 값이 같으면 null 값을 리턴하고
서로 다른 값을 가지고 있으면 Express-1의 값을 리턴해 주는 함수입니다.
LENGTH(first_name)의 값과 LENGTH(last_name)의 값을 NULLIF 함수로 비교하여 같으면
null 값을 화면에 출력하고 다르면 LENGTH(first_name)의 값을 화면에 출력합니다.
SQL> SELECT empno, ename, nullif( comm, 0 )
FROM emp ;
EMPNO ENAME COMM NULLIF( COMM, 0 )
--------------------------------------------------
7369 SMITH
7370 ALLEN 300 300
7521 WARD 500 500
7566 JONES
7654 MARTIN 1400 1400
.....................................
->COMM이 NULL이므로 NULL, COMM이 NULL이 아니므로 COMM값으로...
*COALLESCE 함수
이 함수는 EXPRESS-1의 값이 NULL값이 아니면 EXPRESS-1의 값을 화면에 출력해 주고
NULL 값이면 EXPRESS-2의 값을 EXPRESS-1의 값과 EXPRESS-2의 값모두 NULL이면
EXPRESS-N의 값을 화면에 출력해 주는 함수입니다. 문법에서 정의된 각 컬럼에서 NULL이
아닌 첫 번째 컬럼의 값을 돌려줍니다.
SQL> SELECT coalesce( comm,sal ) FROM emp ;
COALESCE( COMM,SAL )
-------------------------
800
300
SQL> SELECT coalesce ( comm, 100 ) FROM emp ;
COALESCE( COMM,100 )
-------------------------
100
300
500
->이 문법은 COALESCE([컬럼],[값]) 문법에서 정의된 컬럼이 NULL이면 정의된 값을
더한 결과를 돌려줍니다. 원래 NULL이지만 100을 더한 값이 출력됩니다.
*TRIM함수
이 함수는 오라클 8i 버전에서 추가된 함수이며 이전 버전에서 제공되던 LTRIM 함수와
RTRIM 함수를 결합한 형태의 함수입니다. TRIM 함수는 문자값의 왼쪽 또는 오른쪽 부분에
정의한 문자값이 존재하면 그 문자를 절삭시키는 기능을 가지고 있습니다. TRIM 함수는
3가지 종류의 기능을 가지고 있습니다.
-먼저,LEADING은 이전의 LTRIM 함수와 동일한 기능을 가지고 있습니다.정의된 컬럼의 값
왼쪽에 해당 문자열이 존재하면 문자값을 절삭시켜서 화면에 출력합니다.
SQL> SELECT ename, TRIM( LEADING 'A' FROM ename ) as TRIM
FROM emp
WHERE ename LIKE 'A%' ;
ENAME TRIM
-------------------------
ALLEN LLEN
ADAMS DAMS
-TRAILING은 이전의 RTRIM 함수의 기능을 가지고 있으며 컬럼값의 오른쪽에 존재하는 문자값을
절삭해줍니다.
SQL> SELECT ename, TRIM( TRAILING 'N' FROM ename ) as TRIM
FROM emp
WHERE ename LIKE '%N' ;
ENAME TRIM
---------------------
ALLEN ALLE
MARTIN MARTI
-BOTH는 왼쪽, 오른쪽에 해당 문자열이 있으면 절삭해 주는 기능을 가지고 있습니다.
SQL> SELECT ename, TRIM( BOTH 'A' FROM ename ) as TRIM
FROM emp
WHERE ename LIKE 'A%' ;
ENAME TRIM
--------------------
ALLEN LLEN
ADAMS DAMS
->ENAME 컬럼에서 마지막 문자가 'A'인 값은 발견되지 않았고 첫번째 문자가 'A'인
사원은 ALLEN과 ADAMS
설정
트랙백
댓글
글
WebBrowser 컨트롤 사용 시 고려 사항
WebBrowser 컨트롤을 사용할 때는 다음 사항을 고려해야 합니다.- WebBrowser 컨트롤은 문서를 비동기적으로 탐색합니다. WebBrowser1.Navigate를 호출하면 문서를 완전히 로드하기 전에 해당 Visual C# 응용 프로그램에 컨트롤이 반환됩니다. 포함된 문서를 자동화할 계획이라면 해당 문서가 완전히 로드된 시기를 알리도록 NavigateComplete2 이벤트를 사용해야 합니다. Office 문서 개체에 대한 참조를 가져오기 위해 전달되는 WebBrowser 개체의 Document 속성(이전 코드에서 oDocument로 설정됨)을 사용합니다.
- WebBrowser 컨트롤은 메뉴 병합을 지원하지 않습니다.
- Internet Explorer 최신 버전(5.0 이상)에서도 아래의 코드를 사용하여 도킹된 도구 모음을 표시할 수 있습니다.
// This is a toggle option, so call it once to show the // toolbars and once to hide them. This works with Internet Explorer 5 // but often fails to work properly with earlier versions. Object refmissing = System.Reflection.Missing.Value; axWebBrowser1.ExecWB(SHDocVw.OLECMDID.OLECMDID_HIDETOOLBARS,
Object refmissing = System.Reflection.Missing.Value;
axWebBrowser1.ExecWB(SHDocVw.OLECMDID.OLECMDID_HIDETOOLBARS,
SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,
ref refmissing, ref refmissin); - 하나의 프로젝트에서 둘 이상의 WebBrowser 컨트롤을 사용하여 동일한 종류의 Office 문서를 로드하면 문제가 발생하는 것으로 알려져 있습니다. 즉, 컨트롤 모두 Word 문서만 로드하거나 Excel 스프레드시트만 로드하는 경우 문제가 발생합니다. 프로젝트당 컨트롤을 하나만 사용하고 한 번에 한 가지 문서만 탐색하는 것이 좋습니다.
가장 일반적인 문제는 Office 명령 모음이 사용할 수 없는 것처럼 나타나는 것입니다. 같은 폼에 WebBrowser 컨트롤이 두 개 있고, 두 컨트롤 모두 Word 문서를 로드하며, 앞의 예제 코드를 사용하여 도구 모음을 표시한 경우 하나의 도구 모음만 활성화되어 제대로 작동합니다. 다른 도구 모음은 사용 불가능하게 될 수 있습니다. - 다른 명령 단추의 Click 이벤트(또는 적절한 코드 부분)에서 WebBrowser의 현재 내용을 지우려면 아래의 코드를 사용하여 기본 빈 페이지로 이동하도록 합니다.
AxWebBrowser1.Navigate("about:blank");
참조
WebBrowser 컨트롤을 사용하는 것에 대한 자세한 내용은 Microsoft 기술 자료의 다음 문서를 참조하십시오.304562 INFO: Visual Studio .NET Does Not Provide an OLE Container Control for Win Forms
243058 HOWTO: Use the WebBrowser Control to Open an Office Document
162719 HOWTO: Use the WebBrowser Control from Visual Basic 5.0
202476 BUG: Cannot Edit Word Document in OLE or WebBrowser Control
188271 HOWTO: Print Contents of the Web Browser Control From VB
191692 PRB: Shdocvw.dll Is Not Included in PDW Setup Package
238313 PRB: Accessing the Internet Explorer Document Object Model From Visual Basic
설정
트랙백
댓글
글
[DIlImport("라이브러리")]
int GetWindowText(HWND hWnd, LPTSTR lpString, int nMaxCount);
을 C#으로 변형하면
public static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);
출처 : http://jijanghun.tistory.com/21
설정
트랙백
댓글
글
설정
트랙백
댓글
글
Mcrosoft.JSharp : JSharp.NET 을 사용한 컴파일과 코드 생성 제공
Mcrosoft.VisualBasic : VisualBasic.NET 을 사용한 컴파일과 코드 생성 제공
Mcrosoft.Win32 : 윈도우 레지스트리 참조와 윈도우 시스템 이벤트 제공
System : 일반적으로 사용되는 값 타입과 레퍼런스 데이타 타입, 이벤트와 이벤트 핸들러, 인터페이스 , 속성, 예외 등을 포함하며, 가장 중요한 네임스페이스이다.
System.Collections : 리스트와 큐 배열, 해쉬 테이블, 사전 등과 같은 컬렉션 타입 제공
System.ComponentModel : 컴포넌트의 런타임과 디자인 타임 때 사용 제공
System.Configuration : .NET 프레임 워크 설정 세팅을 위해 참조 제공
System.Data : ADO.NET 타입 제공
System.Data.SqlClient : Sql Server.NET 데이터 타입 제공
System.Data.SqlTypes : 윈시SQL서버 데이터 타입 제공
System.Diagnostics : 디버깅과 트래킹을 위한 애플리케이션, 윈도우의 이벤트 로그 클래스제공
System.DirectoryService : LDAP이나 NDS와 같은 서비스 제공자를 사용하여 동적 디렉토리 참조 제공
System.Drawing : 윈도우 GDI+ 그래픽 타입 제공
System.Globalization : 언어 수용과 관련되 타입, 스티링 정렬 순서, 나라/지역, 달력,날짜, 통화와 같은 숫자 형태 제공
System.IO : 스트림과 파일에 읽고 씀
System.Messaging : 메시지가 큐에 넣어 보내고 받고 관리하는 기능(MSMQ) 제공
System.Net : DNS와 HTTP같은 간단한 네트위크 프로토콜 API제공
System.Net.Sockets : TCP/UDp 소켓 API제공
System.Reflection : 적재된 타입과 멤버 참조 제공
System.Reflection.Emit : 메타데이터/IL 생성과 PE파일 생성 제공
System.Resources 애플리케이션 리소스위 생성과 관리 제공
System.Runtime.InteropService : COM 객체와 원시 API 참조 제공
System.Runtime.Remoting : 분산 객체의 생성과 설정 제공
System.Runtime.Remoting.Channels : 원격 채널관리와 채널 싱크(sink) 제공
System.Runtime.Remoting.Channels.Http : HTTP(SOAP) 채널 관리 제공
System.Runtime.Remoting.Channels.Tcp : TCP(이진) 채널 관리 제공
System.Runtime.Remoting.Lifetime : 원격 객체의 생명주기 관리 제공
System.Security : CLR 보안 시스템 하의 참조 제공
System.Security.Permissions : 정책에 기반한 오퍼레이션과 리소스 참조 제한 제공
System.Security.Policy : CLR 보안 정책 시스템에 적용될 규칙이 정의된 코드 그룹, 멤버쉽 상태 , 증거 제공
System.Security.Principal : 규칙 기반의 보안이 사용된 주요 클래스, 인터페이스, 열거형 제공
System.ServiceProcess : 윈도우 서비스 설치와 실행 제공
System.Text : ASCII, 유니코드, UTF-7, UTF-8 과 같은 텍스트 인코딩과 전환 제공
System.Text.RegularExpression! : 이미 만들어져 있는 정규 표현식 엔진 참조 제공
System.Threading : 멀티 쓰레드 프로그래밍을 위한 클래스와 인터페이스 제공
System.Timers : 특정한 시간 간격으로 이벤트를 발생시키는 타이머 컴포넌트 제공
System.Web : HttpApplication, HttpRequest. HttpResponse 와 같은 ASP.NET 클래스에서 사용하는 기능을 포함한 브라우저/ 서버간의 통신 제공
System.Web.Configuration : ASP.NET설정 클래스와 열거형 제공
System.Web.Services : 웹 서비스 제작과 사용 제공
System.Web.Services.Description : WSDL을 사용한 웹 서비스 제공
System.Web.Services.Discovery : DISCO를 통한 웹 서비스 제공
System.Web.SessionState : ASP.NET세션 상태 참조 제공
System.Web.UI : ASP.NET 웹 페이지와 컨트롤 생성
System.Web.UI.Design : 웹 폼을 제공하기 위한 디자인 제공
System.Web.UI.Design.WebControls : 웹 컨트롤을 제공하기 위한 다지인 제공
System.Web.UI.HtmlControls : HTML 서버 컨트롤 생성 제공
System.Web.UI.WebControls : Web 서버 컨트롤 생성 제공
System.Windows.Forms : 윈도우 폼 기반의 사용자 인터페이스와 컨트롤 생성 제공
System.Windows.Forms.Design : 윈도우 품을 위한 디자인 제공
System.Xml : 표준 XML제공
System.Xml.Schema : 표준 XML스키마 제공
System.Xml.Serialization : XML문서 또는 스트림 객체의 직렬화 제공
System.Xml.XPath : XPath 파서와 평가 엔진 제공
System.Xml.Xsl : XSL전환 제공
설정
트랙백
댓글
글
Visual C#에 대한 MSDN 사이트 이다.
하지만 Java를 이용하던 개발자들을 위한 비교를 해 둔 사이트.
http://msdn.microsoft.com/ko-kr/library/ms228360(VS.80).aspx
설정
트랙백
댓글
글
Java는 웹 관련 프레임워크들이 너무 다양하고, Ruby나 Python 같은 경우에는 RubyOnRails나 Djanog 처럼 하나의 프레임워크 안에 기능별 프레임워크들도 모두 다 All in one 형태로 들어 있어서 혼란을 주지 않는 반면, Java는 각 영역별로 프레임워크가 모두 다르고, 또한 각 영역별로 존재하는 프레임워크들의 종류도 많아서 초보 개발자들에게 극심한 혼란을 주고 있다.
그래서 나름대로 Java Web 개발자들을 위한 학습 로드맵을 정리해 보았다.
1. Java 그 자체
많은 웹 개발자들이 마치 JSP 코드를 짤 줄 알면 그걸로 Java 웹 개발을 할 줄아는 것이라 생각하고 Java 그 자체를 소홀히 하는 것을 본다.
말도 안되는 소리이다. Java를 모르고서 Java 웹 개발을 제대로 한다는 것은 어불 성설이다. Java 그 자체를 먼저 공부하라.
특히 Java 5 문법을 숙지하길 권한다. 이제 우리나라도 점차 Java 5가 대세가 되어 가고 있다. 대부분의 프레임워크들과 WAS(JSP와 서블릿을 구동하는 서버)도 모두 Java 5를 기준으로 바뀌었으며, JVM 자체도 버전이 높을 수록 성능이 더 좋다.
2. JSP와 Servlet 그리고 Model 1
모델 1은, JSP 하나에 DB에 접속해서 쿼리를 날리는 등의 모든 업무적인 기능(Business Logic)을 넣고, 그 아래에 HTML 코드를 박아 넣는 식으로 개발하는 것을 의미한다.
아직도 많은 개발자들이 여기에 길들여져 있는데, 일단 JSP 자체에 대한 기본기를 익힌 뒤로는 재빨리 버려야 할 습관이다.
그리고 많은 개발자들이 Servlet을 무시하고 JSP만 하는 것을 보곤 하는데, Servlet에 대한 학습이 제대로 이뤄지지 않으면 더 나은 웹 개발이 곤란하다. Servlet에 대한 기초 개념을 확실히 잡길 권한다.
3. Model 2 - 프레임워크의 등장
JSP로 열심히 개발을 하다보니 프로젝트 규모도 커지기 시작하고, JSP 파일 크기도 수천줄에 달하는등 엄청나게 커진다.
그런데 이 JSP에다 두서없이 모든 기능을 다 때려 넣다보니 JSP마다 똑같은 기능들이 Copy&Paste로 들어가고, JSP 안에 들어 있는 Java 코드들에서 에러가 발생하면 찾아내서 디버깅 하는 일이 지옥같이 느껴지기 시작한다.
여기서 Model 2가 구원자로 등장한다.
Model 2는 말만 멋드러졌지 실제로는 간단한 개념이다.
JSP에서 수행하던 DB 쿼리 등의 작업을 Servlet에게 넘겨주고 JSP에서는 오로지 화면 출력만 담당하는 것이다.
Servlet에서 DB 쿼리등 화면 출력과는 상관없는 비지니스 로직을 일단 먼저 모두 수행하고, 그 결과를 request.setAttribute("key",결과객체);로 담은 다음 JSP 페이지로 포워딩(forward)을 하면 JSP에서는 request.getAttribute("key")로 그 객체를 받아서 화면에 뿌려주기만 한다.
이런 업무 수행단/화면 출력단의 철저한 역할 분리가 Model 2이다.
여기서 이러한 각 역할을 "MVC - Model View Controller" 라고 한다. 그래서 Model 2는 MVC와 동일한 의미로 사용하기 도 한다. MVC의 의미는 공부하면서 찾아보라.
이게 뭐가 좋냐고? 개발 기간이 좀 길어지고 프로젝트 규모가 쬐끔 커지고, 기존 프로젝트를 유지보수를 해보면 얼마나 좋은지 몸소 뼈져리게 느끼게 된다.
Model 2의 기능을 정형화해서 쉽게 구현하게 해주는 것이 MVC Framework들의 역할이다.
가장 유명한 Model 2 웹 프레임워크들은 다음과 같은 것들이 있다.
* 스트럿츠 1 - Struts 1
* 스트럿츠 2 - Struts 2
* 스프링 MVC - Spring MVC
* 기타 덜 유명한 Wicket, Stripes, JSF, Tapestry 등.
Struts 1은 MVC의 효시라고 할 수 있다. 우리에게 MVC라는 축복을 주기는하였으나, 나온지 오래된 만큼 낡은 개념들이 많이 녹아있고 쓸데 없이 복잡하고 배우기도 어려운 편이다.
오히려 Struts 2와 Spring MVC가 더 배우기 쉬울 것이며, 개발도 더 쉽다. 현재 추세는 Struts 2와 Spring MVC이다. 대형 포탈이나 SI 업체들도 Spring/Struts 2를 주로 채택하는 추세로 가고 있는 것으로 알고 있다.
둘 중 하나의 개념만 확실히 이해해도 다른 것을 배우는데 어려움이 별로 없으므로 그냥 둘중에 골라서 배우길 권한다. 나는 Spring을 선호한다.
그리고 MVC 프레임워크를 사용하기 시작하면서 View를 만드는 JSP에 대해서도 재조명이 시작된다. 기존에 Java 코드를 JSP에 직접 넣던 관행을 버리고 JSTL과 태그 라이브러리를 사용하거나 아예 JSP를 버리고 다른 템플릿 엔진으로 만들기도 한다. 이에 관해서는 맨 마지막에.
4. 퍼시스턴스 프레임워크 : JDBC 반복 작업에 짜증이 나기 시작하다.
현대 웹 개발에서 가장 큰 역할을 차지하는 것은 뭐니뭐니해도 단연 Database 작업이다.
지금까지는 아마도 JDBC에서 DB 커넥션을 맺고, 쿼리를 날리고 그 결과 ResultSet을 JSP로 넘겨주어서 출력하는 식으로 했을 것이다.
이미 다들 알고 있겠지만 JDBC를 사용하면 똑같은 코드가 굉장히 많이 반복해서 나온다. 한마디로 "삽질"의 전형이 JDBC 작업이다.
이것을 깨달은 많은 개발자들이 조금 어정짱하게 반복작업을 해결해주는 Util 클래스들을 프로젝트별로 만들어서 사용하곤 한다.
하지만, 물론 이에 대해 정형화하고 깔끔하고 훨씬 더 사용하기 쉬게 만들려는 노력이 이미 수년에 걸쳐 이루어졌다.
이렇게 DB관련된 작업을 정형화한 것들을 Persistence Framework 라고 한다.
* 아이바티스 - iBATIS : SQL Mapper - JDBC보다 더 쉽게 배우고, 더 편하게 사용한다.
* 하이버네이트 - Hibernate : 객체지향을 객체지향답게, 개발 기간을 엄청나게 단축시켜주다.
퍼시스턴스 프레임워크의 양대 산맥은 iBATIS와 Hibernate이다. 이 둘 모두 우리나라에 책이 나와 있다.
iBATIS는 SQL Mapper의 한 종류이고, Hibernate는 ORM의 한 종류이다.
이 둘의 차이는 iBATIS는 개발자가 SQL 쿼리를 직접 작성한 것을 객체에 매핑시켜주는 것이고, ORM은 DB 스키마와 객체간의 관계를 설정파일로 만들면 자동으로 쿼리를 만들어주는 것이다.
자, 이 둘을 보면 미국에서는 Hibernate가 인기가 좋고, 우리나라에서는 iBATIS가 사실상 SI 업계를 평정했다.
그러니까, 일단은 우리나라에서는 iBATIS를 공부하면 된다고 보면 된다.
이렇게 말하니까 마치 이 둘이 경쟁자 같은데, 사실 이 둘은 경쟁 상대라기 보다는 보완해주는 역할을 한다. SI에서 처럼 DB 테이블이 정규화 되어 있지 않은 경우에는 Hibernate같은 ORM을 사용하면 프로젝트를 말아먹을 수 있다.
iBATIS는 테이블 정규화에 무관하게, 개발자가 작성한 SQL을 객체로 매핑하기 때문에 DB 스키마가 마구 꼬여 있는 상황에서도 유연하게 작동하고, 개발자가 직접 SQL 튜닝을 할 수 있다는 장점이다.
그리고 Hibernate는 배우기가 굉장히 어려운 프레임워크이고 튜닝이 매우 어렵다. Hibernate책을 보면 캐싱을 통해 성능을 향상시키라고 하지만 캐싱은 iBATIS도 못지않게 잘 지원한다. 하지만 일단 배우면, 그로인한 코딩 생산성이 iBATIS가 감히 넘볼 수 없을 정도록 급격히 향상된다.
Hibernate는 DB 정규화가 잘되어 있는 웹 포탈 업체나 패키지 소프트웨어 제작시에 강력히 권장할만 하다.
5. IoC와 DI - 객체의 생성주기와 의존성을 관리하고 싶어지다
사실 내가 경험한 SI를 보면 4단계 까지만 가도 막장은 아닌 프로젝트라고 본다. 아직도 신규 프로젝트를 하면서도 Model 1에 JDBC로 코딩하는 것을 많이 보았기 때문이다.
앞서, MVC라는 형태로 웹 애플리케이션의 역할을 철저하게 분할해서 처리하라고 했었다.
이제 여기서 좀 더 역할을 분할하기 시작한다.
Database를 관장하는 코드(DAO)와 Database 처리 결과를 가지고 그외 비지니스 로직을 추가로 수행하는 코드(Service), 그리고 웹으로 들어온 요청을 받아서 비지니스 로직을 호출하고, 그 결과를 다시 웹(HTML 등)으로 내보내는 코드(Controller)로 분할을 하면 유지보수가 더 쉽고, DB가 Oracle에서 DB2 로 변경되는 식의 중대 변화가 있을 때도 DAO만 바꾸면 되는 식으로 변화에 대한 대처가 유연해 진다는 것을 깨닫기 시작한다.
이제는 각 역할별로 클래스를 분할하고 컨트롤러 객체는 서비스 객체에 서비스 객체는 DAO 객체에 의존해서 작동하도록 코드를 바꾸기 시작한다. 그리고 객체의 생성과 파괴 주기도 관리해야만 하게 된다. 객체를 하나만 생성하면 되는데 불필요하게 매번 new를 할 필요는 없으니까.
이렇게 객체의 생성/파괴 주기를 관리하고 객체간의 의존성을 관리해주는 프레임워크를 IoC 컨테이너라고 부른다.
1. Spring Framework
2. EJB 3.0
사실상 대세는 Spring Framework로 굳어졌다. EJB 3.0은 내가 안써봐서 뭐라 말은 못하겠다.
Spring MVC는 이 Spring Framework의 일부분이다.
Spring은 또한 AOP도 지원한다.
AOP 의 개념이 상당히 어려운 편이라서 개념 자체를 확실히 한마디로는 표현하지 못하겠다. 어쨌든 개발자들에게 가장 쉽게 다가오는 표현으로 하자면, AOP는 동일한 패턴으로 반복적으로 해야하는 일을 설정을 통해 자동으로 해주는 것이다.
이에 관한 가장 보편적인 예가 바로 트랜잭션이다.
지금까지는 아마도 비지니스 로직이 시작될 때 트랜잭션이 시작되고, 비지니스 로직이 끝날 때 트랜잭션을 종료하는 코드를 매번 작성해서 넣었을 것이다.
AOP를 사용하면, 비지니스 로직의 역할을 하는 메소드가 무엇인지 설정파일에 넣어주기만 하면 자동으로 메소드가 시작될 때 트랜잭션을 시작시키고, 메소드가 끝날 때 트랜잭션을 종료시켜준다. 물론 예외가 발생하면 트랜잭션을 rollback도 해준다. 따라서 Spring을 사용한 프로젝트에서는 트랜잭션 관련 코드를 볼 수 없을 것이다.
Spring 프레임워크는 기본적으로 IoC 컨테이너 역할을 하는 것이 핵심이다. 따라서 Spring을 사용한다고 해서 꼭 Spring MVC를 사용할 필요는 없다. Struts 2 + Spring + iBATIS 나 SpringMVC + Spring + Hibernate 등... 어떠한 조합이라도 가능하다.
6. 그 외
◈ Template Engine : JSP 보다 더 간결하면서 강력한게 필요해!
* JSP + JSTL : Sun이 지정한 산업표준이다. JSTL은 당연히 쓰고 있으리라 믿는다.
* Freemarker : 가장 권장할 만하다.
* Velocity : 굉장히 배우기 쉽다. JSTL보다 더 빨리 배워서 쓸 수 있다. 가독성도 좋다. 그러나 Freemarker 만큼 편하고 강력하지는 못하다.
많은 사람들이 Java 웹 개발을 그냥 "JSP 개발"이라고도 부르는데, MVC가 도입되고, Freemarker 같은 다른 템플릿 엔진을 사용하게 되면 더이상 JSP는 코빼기도 안보이게 된다. 그러므로.. JSP 개발이라는 말은 쓰지 않았으면 좋겠다.
◈ Layout Engine
* Sitemesh : 헤더 푸터 처럼 동일 패턴이 반복되는 레이아웃을 관리해준다.
◈ XML 도우미 : W3C DOM은 너무 어렵고 난잡하다. 좀 더 편한 XML관련 개발을 원한다면..
* JDOM : Java 표준으로 지정됐다고 한다.
* DOM4J
둘 다 비슷하게 편한거 같다. 예전엔 JDOM을 썼었는데, 나 같은 경우 현재 프로젝트에서는 DOM4J를 사용한다. Hibernate가 DOM4J를 사용하기 때문에, 별도의 라이브러리 더 넣는게 귀찮아서.
◈ 단위 테스트
* jUnit : 코드를 철저하게 테스트하자.
◈ 소스코드 버전관리
* CVS
* Subversion : 현재 대세는 Subversion
내가 최고 막장으로 꼽는 프로젝트는 아직도 FTP로 소스 관리하는 프로젝트이다. 이런 프로젝트에는 절대로 참여하지 않을 것이라고 굳게 맹세하고 또 맹세했다. --;
소스 코드 버전관리는 여러 개발자들이 동시에 개발할 때 소스코드를 저장하고 충돌을 관리해주며, 소스 변경 내역을 계속해서 추적해서 과거 소스로 언제든지 돌아갈 수 있도록 도와준다.
현재 대세는 Subversion이지만 CVS로도 버전관리의 이점을 충분히 만끽할 수 있다. 그리고.. 사실 CVS가 사용법을 익히기는 더 쉽다.
◈ 자동 빌드
* Ant : Ant 면 만사 Ok!
* Maven
아직도 javac 로 컴파일하고 있고, FTP로 파일 올려서 복사하고 있다면.. 이 모든일을 자동으로 명령 한방에 처리하도록 해야 실수도 적고, 퇴근도 일찍한다.
Ant로 빌드와 배포를 자동화 하자.
결론
내가 권하는 조합은
* SI 업체에서 일하는 경우 : Struts 2 혹은 SpringMVC + iBATIS + JSP/JSTL + 가능하다면 Spring Framework
* 웹 포털등과 같은 업계, 패키지 소프트웨어 제작 업체 : Struts 2 혹은 Spring MVC + Hibernate + Spring Framework + Freemarker + Sitemesh
출처 : http://kwon37xi.egloos.com/ 까먹지말자!
설정
트랙백
댓글
글
자바 네이티브 인터페이스(JNI)는 기본 언어 프로그램과 자바 가상 시스템(JVM) 사이의 통신 설정에 사용할 수 있는 메커니즘입니다. JVM과 C/C++ 코드 간의 상호 작용에 대해서는 JNI 관련 설명서나 JNI에 관한 기술 문서에서 자세히 다룹니다. 또 자바 SDK는 자바 코드를 사용한 C/C++ 프로그램 호출을 용이하게 하는 헤더 파일 생성 유틸리티도 제공합니다.
그러나 자바와 어셈블리 언어 코드의 연동에 대해 다룬 문서는 찾아보기가 어렵습니다. 저는 이전 기사를 통해 자바 애플리케이션에서 어셈블리 언어 프로그램을 호출하는 방법을 설명한 바 있습니다. 이번에는 어셈블리 언어 코드로 자바 메소드를 호출하는 데모 애플리케이션을 통해 ASM 프로세스에서 자바 프로그램을 호출하는 방법에 대해 소개하겠습니다. 이 자바 메소드는 Swing JDialog
를 띄워서 실제로 실행되었음을 보여 줍니다.
ASM 기능의 자바를 선택하는 이유
자바를 구현하려면 JNI가 꼭 필요합니다. JVM의 일부 기능은 기본 플랫폼과의 상호 작용을 통해서만 구현되기 때문입니다. 그러나 이것 말고도 자바 클래스는 흔히 다른 언어로 작성된 애플리케이션을 보완하는 데 유용합니다. 자바는 고급 기능을 아주 간단하게 구현할 수 있도록 하는 광범위한 API를 제공하기 때문입니다.
얼마 전에 저는 몇 가지 소스에서 실시간 데이터를 수집하고 수집된 데이터를 순환 버퍼에 저장하여 버퍼가 가득 차면 새 데이터로 예전 데이터를 덮어쓰게 하는 애플리케이션 작업에 참여한 적이 있습니다. 지정된 트리거 이벤트가 디지털 입력에서 감지되면 정해진 수의 데이터 샘플을 버퍼에 저장하여 트리거 이전과 이후의 데이터 스냅샷을 볼 수 있도록 했습니다. 이때 원본 애플리케이션은 어셈블리 언어로 작성했습니다.
이 애플리케이션을 몇 달 사용해 본 결과, 트리거 이벤트가 발생할 때마다 애플리케이션이 권한 있는 감독자에게 스냅샷을 메일로 보내도록 하면 정말 편리하겠다는 생각이 들었습니다. 물론 그런 확장 기능을 어셈블리로 작성할 수도 있었지만, 팀원들은 이런 경우에는 자바로 확장 기능을 만든 다음, ASM 프로그램으로 기능을 연결하는 것이 더 쉽다는 의견이었습니다. 저는 ASM 지향의 JNI로 작업해 본 경험이 있었기 때문에 그것이 가능하다는 것을 알았고, 실제로 그 프로젝트는 금새 구현되어 성공을 거두었습니다.
이러한 애드온을 활용할 수 있는 어셈블리로 작성된 레거시 애플리케이션이 많은 것으로 알고 있습니다. 그러나 JNI를 유용하게 쓸 수 있는 것은 레거시 애플리케이션의 개조만이 아닙니다. 믿지 않는 분들도 많으시겠지만, 아직도 신규 프로그램의 특정 부분을 어셈블리 언어로 작성하는 경우가 있습니다.
얼마 전 발표된 어떤 기사에서 저자는 "핫 코드 경로를 최대한 효율적으로 만들기 위해 아직도 제품에 어셈블리 언어를 사용하는 썬 파트너들이 많다는 사실을 발견했다. 최신 컴파일러는 종전보다 훨씬 효율적인 코드를 만들어내지만, 컴파일러로 작성한 코드는 각각의 마이크로프로세서 명령에서 최대한 성능을 짜내는 방법을 알고 있는 엔지니어가 수작업으로 작성한 어셈블리에 비해 성능이 떨어진다. 프로그래머의 재량이 발휘될 여지가 많은 어셈블리 언어는 여전히 강력한 최적화 도구로 남아 있으며 현명하게 사용하면 성능을 높일 수 있다"고 주장했습니다. 이러한 "혼합 언어" 애플리케이션에서 ASM 기능의 자바를 사용할 수 있다는 것은 분명히 이익이 됩니다.
여기서 제시하는 방법은 ASM이 아닌 언어의 자바 코드를 호출할 때도 사용할 수 있습니다. JInvoke
를 .dll로 다시 작성하는 경우, 예를 들어 FORTRAN 언어로 작성한 코드를 여기에 링크하여 자바 메소드를 호출할 수 있습니다.
저는 레거시 ASM 코드의 JNI를 다음 두 가지에 사용했습니다.
- 기능 향상: 앞서 언급했듯이 기존 ASM 애플리케이션에 메일링 기능을 추가했습니다.
- 인터페이스 향상: 쌍방향 사용자 인터페이스를 추가했습니다(대부분 AWT이지만 일부 Swing도 포함).
이렇게 향상된 애플리케이션을 Windows 2000 및 XP에서 실행해 보았습니다. 사용한 자바 버전은 1.3, 1.4, 1.6입니다. 그 결과, 모든 애플리케이션이 원활하게 작동되었습니다.
권장 다운로드
제가 데모 코드에 사용한 어셈블리 언어의 버전은 MASM32입니다. 전체 MASM32 번들을 무료로 다운로드할 수 있으며, 자바-ASM의 상호 작용을 시험하려면 이 번들을 컴퓨터에 설치해야 합니다. Iczelion의 사이트에는 MASM 프로그래밍에 대한 매우 유용한 튜토리얼 세트가 있습니다. JNI에 관한 문서 중 최고는 Sheng Liang의 책 The Java Native Interface: Programmer's Guide and Specification입니다.
이 책도 무료로 다운로드할 수 있습니다. 이 기사에 수록된 자바 코드 샘플(AsmToJava
)을 실행하려면 SDK(최소한 JRE)가 필요합니다. 데모에서 어셈블리 언어를 사용한 JInvoke
부분은 .exe 파일로 컴파일했으며 MASM 번들 없이도 실행됩니다. 소스 코드를 수정하여 다시 컴파일하려는 경우에만 어셈블러/링커가 필요합니다.
기본 원리
JNI는 종합적인 JVM 인터페이스입니다. 이 인터페이스는 주로 풍부한 함수로 알아볼 수 있습니다. 기본 코드는 이러한 함수를 호출하여 구현된 JVM과 상호 작용합니다. 자세한 함수 설명은 Sheng Liang의 책을 참조하십시오. 이러한 함수는 대부분 JVM을 만들어야만 액세스가 가능하지만 JNI에서 몇 가지 기본 함수를 직접 내보낼 수도 있습니다. 나중에 자세히 다루겠지만, 두 번째 유형의 함수로 JVM을 인스턴스화하여 다른 JNI 함수를 호출할 수도 있습니다.
일단 JVM이 작성되면 JVM 인스턴스가 있어야만 구현 가능한 JNI 함수에 어셈블리 언어 프로그램이 액세스할 수 있게 됩니다. 이러한 모든 JNI 함수에 대한 포인터는 함수 테이블이라는 테이블에 저장됩니다. JVM을 로드하는 ASM 코드는 사실상 포인터인 JNIEnv
라는 변수를 수신합니다. 그리고 JNIEnv
는 함수 테이블에 대한 실제 포인터가 들어 있는 메모리의 특정 위치를 가리킵니다. 그림 1은 이러한 액세스 체인을 보여 줍니다.
그림 1. JNI 함수 액세스
보시다시피 JNI 함수에 대한 각 포인터는 길이가 4바이트입니다. 따라서 함수 테이블의 시작 주소에 해당 함수 색인의 4배를 더하여 정의된 위치에서 원하는 함수의 포인터를 찾을 수 있습니다. 함수 색인은 0을 기준으로 합니다. 즉, 첫 번째 함수의 포인터는 색인 0, 두 번째 함수의 포인터는 색인 1과 같이 이어집니다. Sheng Liang의 책에는 모든 JNI 함수의 색인 값이 나열되어 있습니다.
ASM 코드로 자바 프로그램을 호출하려면 다음 단계를 실행해야 합니다.
- JVM 인스턴스화
- 클래스 찾기
- 메소드 ID 확인
- 메소드 호출
각 단계를 자세히 살펴보기 전에, 이 프로그램 및 유사 프로그램을 손쉽게 작성하기 위해 include 파일을 사용하는 방법부터 알아보겠습니다. 자바와 기본 코드 사이의 상호 작용은 JNI로 노출된 함수를 통해 이루어지므로 기본 프로세스에서 이러한 함수를 반복적으로 호출할 필요가 있습니다. 따라서 이 활동을 처리하기 위해 매크로를 사용하겠습니다. 그러면 길이가 상당히 길고 비슷한 코드를 반복해서 작성할 필요가 적어지며 오타로 인해 프로그램에 버그가 생길 위험도 줄일 수 있습니다.
매크로
ASM 코드에서 함수를 호출할 때는 함수 테이블에서 해당 함수의 포인터를 찾은 뒤 그 포인터를 사용하여 원하는 함수를 호출해야 합니다. 앞서 설명했듯이, 포인터를 찾으려면 JNIEnv
포인터 체인을 따라 함수 테이블의 시작 주소를 확인한 다음, 해당 함수의 색인을 사용하여 함수 포인터를 검색해야 합니다. 함수 테이블의 시작 주소를 확인하는 첫 번째 작업에는 항상 동일한 코드를 사용하며 다음과 같은 매크로로 처리할 수 있습니다.
;This macro returns the pointer to
;Function Table in fnTblPtr
GetFnTblPtr MACRO envPtr, fnTblPtr
mov ebx, envPtr
mov eax, [ebx]
mov fnTblPtr, eax
ENDM
위의 코드로 정의되는 매크로는 매개변수 두 개를 취합니다. 첫 번째는 JNIEnv
포인터이고, 두 번째는 이 매크로가 해당 포인터를 반환하게 될 함수 테이블의 위치를 가리킵니다. 매크로는 함수 테이블 포인터를 eax
로 로드한 다음, 이를 fnTblPtr
에 저장합니다. 프로그램 자체에 이 매크로를 정의하여 사용할 수도 있습니다. 아니면 여기서 선택한 방법처럼 이러한 매크로를 모두 include 파일에 정의한 다음, include
문을 통해 ASM 프로그램과 함께 이 파일을 사용해도 됩니다. 여기서 사용한 include 파일은 jav_asm.inc입니다. 이 파일은 GetFnTblPtr
매크로뿐 아니라 이 예제에 필요한 다른 매크로도 모두 정의합니다. 또한 jav_asm.inc는 매크로 외에도 JVM을 작성하는 함수의 원형은 물론 해당 함수의 매개변수로 사용할 구조도 정의합니다. 끝으로, java_asm.inc는 사용하기 편리하도록 모든 JNI 함수에 기호 이름을 지정해 줍니다.
함수 테이블에 대한 포인터가 확인되었으면 원하는 함수의 포인터를 검색해야 합니다. 여기 사용되는 코드도 색인 부분을 제외하면 항상 동일합니다. 이 작업은 다음 매크로로 처리합니다.
;This macro returns the pointer
;to a function in fnPtr.
GetFnPtr MACRO fnTblPtr, index, fnPtr
mov eax, index
mov ebx, 4
mul ebx
mov ebx, fnTblPtr
add ebx, eax
mov eax, [ebx]
mov fnPtr, eax
ENDM
이 매크로는 index
값에 4를 곱하고 그 결과를 함수 테이블의 시작 주소(fnTblPtr
참조)에 더하여 액세스할 함수의 포인터를 확인합니다. 그런 다음, 이 포인터를 fnPtr
에 저장합니다.
나머지 세 매크로도 처리하는 매개변수의 수만 제외하면 거의 동일합니다.
;The next 3 macros push parameters as per
;stdcall and call the function through fnPtr
CallFunction2 MACRO param1, param2, fnPtr
push param2
push param1
call [fnPtr]
ENDM
CallFunction3 MACRO param1, param2, param3, fnPtr
push param3
push param2
push param1
call [fnPtr]
ENDM
CallFunction4 MACRO param1, param2, param3, param4, fnPtr
push param4
push param3
push param2
push param1
call [fnPtr]
ENDM
보시다시피 이들 매크로는 fnPtr
을 제외하고 stdcall
을 위해 매개변수를 역순으로 푸시(push)한 다음, fnPtr
을 포인터로 사용하여 해당 함수를 호출합니다.
이로써 기본적인 빌딩블록이 완성되었습니다. 이제 데모 애플리케이션의 4단계 시퀀스를 살펴보겠습니다.
JVM 인스턴스 작성
JInvoke
는 명령줄에서 자바 애플리케이션을 실행할 때 java
명령이 하는 것과 거의 비슷한 방식으로 JVM 인스턴스를 작성합니다. 구현된 자바 가상 시스템(JVM)은 기본 애플리케이션이 가상 시스템을 로드할 수 있도록 하는 호출 인터페이스라는 메커니즘을 제공합니다. java
명령은 이 호출 인터페이스를 사용하는 C 프로그램을 호출하여 자바 애플리케이션을 실행하고, JInvoke
도 바로 이 인터페이스를 사용합니다. JVM을 로드하는 코드는 다음과 같습니다.
.
.
.
va vm_args <>
jvmo JavaVMOption <>
.
.
.
mov jvmo.optionString, offset opzero
mov va.options, offset jvmo
mov va.version, 00010002h
mov va.nOptions,1
mov va.ignoreUnrecognized, TRUE
invoke JNI_CreateJavaVM, offset JavaVM, offset JNIEnv,
offset va
여기서는 우선 구조 두 개를 선언하겠습니다. 이미 설명했듯이 이 구조는 jav_asm.inc에 정의되어 있습니다. JVM을 작성하려면 몇 가지 매개변수를 지정해야 합니다. 지정된 매개변수는 이 구조를 통해 JNI_CreateJavaVM
함수로 전달됩니다.
이 예제에서는 AsmToJava
클래스의 main
메소드를 호출하겠습니다. 제 컴퓨터의 C:\j2sdk1.4.2_05\testjni 폴더에 클래스 파일이 들어 있습니다. JNI 사양에 설명된 방법에 따라 opzero
문자열로 이 경로를 정의합니다. opzero
가 jvmo
구조로 로드되고, 그 다음에 jvmo
에 대한 오프셋이 va
구조로 로드됩니다. JNI_CreateJavaVM
함수로 전달되는 마지막 매개변수는 va
입니다. 따라서 로드된 JVM은 우리가 원하는 클래스를 어디서 찾아야 하는지 알게 됩니다.
JNI_CreateJavaVM
은 반환과 동시에 성공한 경우에는 eax
에 0을, 실패한 경우에는 eax
에 음수값을 반환합니다. 함수로 JVM 인스턴스를 작성하는 데 성공한 경우에는 JVM 인터페이스에 대한 포인터와 해당하는 JNIEnv
포인터를 각각 JavaVM
및 JNIEnv
에서 사용할 수 있습니다.
JNI_CreateJavaVM
함수로 반환된 JInvoke
는 즉시 eax
의 내용을 확인합니다. 값이 0이 아니면 JVM이 로드되지 않은 것입니다. 사용자에게 이를 알리는 메시지가 표시되고 프로세스는 종료됩니다.
.if eax == 0
.
.
.
.else
invoke MessageBox, 0, addr Fail1Text,
addr Caption, 16; failed to create JVM
.endif
한편, eax
의 내용이 0이라면 해당하는 메시지를 담은 메시지 상자(그림 2)가 표시되고 다음 단계가 실행됩니다.
.if eax == 0
invoke MessageBox, 0, addr VmText,
addr Caption, 64; indicate success
그림 2. JVM이 로드되었음을 알리는 메시지
단, JInvoke
는 개념 제시를 위한 수단에 불과하므로 여기서는 가장 간단한 방법으로 JVM 인스턴스를 작성했음을 말씀드립니다. Sheng Liang이 책에서 설명했듯이 이 밖에도 다양한 매개변수를 지정할 수 있습니다.
클래스 찾기
JVM을 로드한 뒤, JInvoke
는 원하는 자바 애플리케이션의 시작 지점이 될 클래스를 찾아야 합니다. 아래 코드는 이를 위해 FindClass
함수를 호출합니다.
GetFnTblPtr JNIEnv, fntblptr
GetFnPtr fntblptr, FI_FC, fnptr ; ptr to FindClass
CallFunction2 JNIEnv, offset ProcName,
fnptr ; call FindClass
.if eax != 0
mov classid, eax
invoke MessageBox, 0, addr FcText,
addr Caption, 64; class found
이 클래스 경로는 앞서 jvmo
구조에 로드되었으며(mov jvmo.optionString, offset opzero
) 이미 JVM에 알려져 있습니다. FindClass
함수는 클래스를 찾을 수 있는 경우에는 eax
에 해당 ID를 반환하고, 그렇지 않으면 0을 반환합니다. 클래스가 발견되면 해당 ID를 저장한 다음, 메시지 상자(그림 3)를 표시하여 사용자에게 알립니다.
그림 3. 클래스가 발견되었음을 알리는 메시지
클래스를 찾을 수 없는 경우에는 해당하는 메시지와 함께 프로세스가 종료됩니다. 그림 4는 호출한 함수가 성공하지 못했을 때 표시되는 메시지의 예입니다.
그림 4. 클래스를 찾을 수 없음을 알리는 메시지
메소드 ID 확인
메소드를 호출하려면 해당 ID를 확인해야 합니다. 정적 메소드의 ID를 반환하는 함수는 GetStaticMethodID
입니다. 여기서는 AsmToJava
클래스의 main
메소드를 호출하기 위해 이 함수를 사용하겠습니다. 이 함수에는 JNIEnv
외에 다음과 같은 매개변수를 사용할 수 있습니다.
- 해당 메소드가 속한 클래스의 ID. 이전 단계에서 참조한
classid
변수입니다. - 메소드 이름.
methodname
문자열입니다. - 메소드의 매개변수와 반환 유형을 지정하는 메소드 설명자. 여기서 사용할 메소드의 설명자는
methodsig
문자열입니다. 이 경우에 매개변수는String array
이고 반환 유형은void
입니다. JNI 사양에 관한 Sheng Liang의 책에는 메소드 및 변수의 설명자를 작성하는 방법이 나와 있습니다.
GetStaticMethodID
호출은 지금까지 살펴본 다른 함수 호출과 매우 유사합니다.
GetFnPtr fntblptr, FI_GSMID, fnptr ; ptr to GetStaticMethodID
CallFunction4 JNIEnv, classid, offset methodname,
offset methodsig, fnptr ; GetStaticMethodID
.if eax != NULL
mov methid, eax
invoke MessageBox, 0, addr GsmiText, addr Caption, 64
GetStaticMethodID
는 eax
에 ID를 반환합니다. 메소드 ID를 확인하는 데 실패한 경우에는 대신 NULL
이 반환됩니다. 그리고 JInvoke
는 eax
의 내용을 확인하여 다음 단계(그림 5)로 진행할지 아니면 프로세스를 종료할지를 결정합니다.
그림 5. 메소드 ID가 확인되었음을 알리는 메시지
대상 메소드 호출
반환 유형 void
로 정적 메소드(여기서는 main
메소드 호출)를 호출하는 JNI 함수는 CallStaticVoidMethod
입니다. 다음은 이 함수의 포인터를 확인한 후 필요한 매개변수로 호출하는 코드입니다.
GetFnPtr fntblptr, FI_CSVM, fnptr ; get CallStVM ptr
CallFunction3 JNIEnv, classid, methid, fnptr; call CallStVM
자바 애플리케이션이 성공적으로 실행되었음을 알리는 대화 상자가 나타납니다.
그림 6. 자바 메소드 호출 성공
호출한 자바 메소드가 반환되면 JInvoke
는 종료됩니다.
그림 7. 프로세스 종료를 알리는 메시지
ExitProcess
함수를 호출하면 해당 프로세스의 모든 스레드가 정지되며 해당 프로세스에서 작성된 자바 스레드도 정지됩니다. 그러므로 이 방식으로 자바 프로그램을 실행할 때는 필요한 활동이 모두 완료된 뒤에 호출한 자바 메소드가 반환되도록 하는 것이 중요합니다. 실제로 호출 프로세스의 종료 및 JVM에 관한 문제에는 세심한 주의를 기울여야 합니다. 자세한 내용은 Windows API 설명서와 최신 JNI 사양을 참조하십시오.
결론
여기서는 어셈블리 언어 코드로 자바 애플리케이션을 실행하는 데 사용할 수 있는 기본적인 방법을 소개했습니다. 자바 환경에서 안전하게 작업하려면 기본 프로그램에 적절한 오류 확인 기능을 통합해야 합니다. Sheng Liang은 기본 코드의 예외 처리를 비롯하여 다양한 확인 예제를 다루고 있습니다. JNI와 연동되는 ASM 프로그램에는 가급적 이러한 오류 확인 메소드를 사용해야 합니다.
jav_asm.inc 파일을 사용하면 JNI 함수 색인을 손쉽게 지정할 수 있습니다. 번호 대신 기호 이름을 사용하여 색인을 지정하면 오류가 발생할 가능성이 적어집니다. 매크로를 사용하는 것도 오류 감소에 도움이 됩니다. 여러분의 코드에 자유롭게 이 파일을 사용하시고, 필요에 따라 수정하셔도 좋습니다. 그러나 면책 조항 없이 이 파일을 재배포하는 일은 없도록 주의해 주십시오.
JInvoke
를 실행할 때 jvm.dll을 찾을 수 없다는 오류 메시지가 나타날 수 있습니다. 이 경우에는 jvm.dll이 포함된 디렉토리 경로를 PATH
환경 변수에 추가해야 할 수 있습니다. 이 DLL은 대개 자바 SDK 루트 폴더의 jre\bin\client 디렉토리에 들어 있습니다. 예를 들어, 제 컴퓨터에서 자바 1.4 릴리스의 해당 경로는 C:\j2sdk1.4.2_05\jre\bin\client입니다. 그러나 자바 1.3을 사용한다면 jre\bin\classic 폴더를 추가해야 합니다. 올바른 경로를 선택하도록 주의하십시오.
끝으로, JInvoke
의 include
문에 명명된 파일 경로는 사용자 컴퓨터의 디렉토리 구조에 따라 결정된다는 점을 지적하고 싶습니다. JInvoke
에 지정되어 있는 경로는 내 컴퓨터에 해당되는 경로입니다. JInvoke.exe의 경우에는 사용자 시스템에 MASM 구성요소(특히 .inc 또는 .lib 파일)가 로드되지 않아도 실행이 가능합니다. 코드를 수정하여 재컴파일하고 싶으면 해당 디렉토리를 설정한 방식에 맞게 경로 정보를 수정해야 합니다. 그리고 AsmToJava
클래스 파일을 opzero
에 정의된 디렉토리에 로드해야 합니다. 아니면 이 클래스의 경로를 적용하여 opzero
를 변경해도 됩니다. 그 경우에는 JInvoke
의 소스 파일을 재컴파일해야 합니다. 이때 다른 경로 이름도 위의 설명과 같이 수정해야 한다는 점을 잊지 마십시오.
참고 자료
- src.zip: JInvoke 및 AsmToJava의 소스 코드 JInvoke.exe, AsmToJava 클래스 파일과 jav_asm.inc 파일.
- "자바 애플리케이션에서 어셈블리 언어 프로그램 호출." 이 기사에는 보충 정보와 유용한 추가 설명이 수록되어 있습니다.
- The Java Native Interface Programmer's Guide and Specification(자바 네이티브 인터페이스 프로그래머 안내서 및 사양), 저자 Sheng Liang.
- Iczelion의 홈 페이지
Biswajit Sarkar는 프로그램 방식의 산업 자동화를 전문으로 하는 전기공학 엔지니어입니다.
이 글의 영문 원본은
Launch Java Applications from Assembly Language Programs
에서 보실 수 있습니다.
출처 : http://sdnkorea.com
설정
트랙백
댓글
글
설정
트랙백
댓글
글
Windows Application 이 전의 Console 부분을 먼저 정확히 집고 가야합니다.
그러기 위해서는 번거롭더라도 .Net 툴이 아닌 메모장이나 EditPlus등과 같은 툴을
이용하여 연습하는 것이 필요합니다.
그러기 위해서는 csc.exe(C# 컴파일러)에 대한 환경 설정이 필요합니다.
PATH를 잡기위해 경로에 C:\Windows\Microsoft.NET\Framework\v2.0xxxx
을 추가해 주면 됩니다.
아 이때 참고하실 점은 콘솔 창이 띄워져 있으면 콘솔 창을 닫고 해주세요
콘솔 창이 열린 상태라면 적용이 안된답니다.
RECENT COMMENT