웹서비스와 EAI의 관계

웹서비스와 EAI의 관계

조 원 석
아이티올로지 CTO

지난 99년 말부터 IBM, 마이크로소프트 등의 거대 기업들로부터 시작돼 최근 가장 큰 화두가 되고 있는 IT테크놀로지로 웹서비스(Web Services)가 있다. 이미 여러 매체에서 웹서비스가 무엇인지 소개했고, 또 많은 기업들이 기존의 레거시(Legacy)시스템에 대해 웹서비스를 이용한 시스템으로의 전환을 검토하고 있다. 아직 국내에서는 현업에 구축 사용되고 있는 사례는 적지만, 현재 또는 가까운 미래에 가장 중요한 기술 중의 하나로 많은 관심을 끌고 있다.

최근 필자가 만나본 기업 전산실의 몇몇 사람들은 마치 웹서비스가 EAI를 대체할 것으로 생각하고 있었다. 하지만 결론부터 말하자면 이것은 잘못된 생각이다.

웹서비스는 어떠한 형태로든 EAI의 한 부분을 대체하거나 나아가 ‘EAI=웹서비스’라는 공식이 적용될 수 있는 것이 절대로 아니고, EAI의 구현을 위한 새로운 테크놀로지이며 기존의 포인트투포인트(Point-to-Point) 방식의 전통적인 시스템간 연결 및 통합 부분을 매우 간단하게 처리할 수 있게 해주는 새로운 구현방식인 것이다.

이에 웹서비스를 이용한 EAI와 전통적인 EAI방식에 대한 차이점을 살펴보기에 앞서 전통적인 EAI에 대해서 간략하게 살펴보기로 하자.

많은 기업들이 ERP, CRM, SCM 등의 다양한 애플리케이션을 적극적으로 사용함에 따라 기업 운영 측면에 있어서 이러한 시스템들에 많이 의존하고 있는 것이 사실이다. 문제는 이러한 각각의 애플리케이션이 개발됐을 때 각 애플리케이션들이 타 시스템과 연동을 하기 위해 만들어지지 않았다는 것이다. 물론 올바른 비즈니스 의사결정을 위해서는 시스템들의 연동이 반드시 필요하다.

IT업계, 특히 웹에이전시 시장에서 최근 많이 회자되고 있는 말이 있는데 바로 e-BI와 Web SI에 대한 것이다. 국내 웹에이전시들이 초기에 기업의 홍보용 홈 사이트를 제작해 주는 일종의 디자인과 마케팅에 초점을 맞춰 왔다면, 최근에는 그 초점을 단순한 홈 페이지 제작이 아닌 ‘Web-Based Solution’ 구축이라고 하는데 맞추고 있다.


<데이터·유저인터페이스 레벨의 EAI

데이터 레벨의 EAI는 기업의 다양한 애플리케이션 통합시 가장 먼저 사용하는 방법이 각 애플리케이션들이 공동의 자료(예를 들면 파일 시스템, 데이터베이스)를 사용토록 하는 것이다. 각각의 애플리케이션들이 하나의 로지컬 데이터베이스를 사용하도록 하거나 흩어져 있는 데이터를 하나의 중앙 데이터베이스(Central Database)로 옮겨주는 애플리케이션을 구축을 하는 것이 데이터 레벨(Data-Level) EAI의 핵심이라고 하겠다.

이러한 EAI는 기업의 애플리케이션들이 복잡한 비즈니스 로직을 갖고 있지 않을 경우나 애플리케이션이 필요로 하는 키(Key)가 데이터뿐인 경우에는 적당한 방법이지만, 기업내부뿐만 아니라 기업과 기업간의 트랜잭션이 필요해 인터넷을 사용하는 경우에는 비즈니스 로직을 재구성해야 한다는 단점이 있다.

유저인터페이스 레벨(User-Interface-Level)의 EAI는 기업의 각 애플리케이션에 접근함에 있어 사용자에게 일관성이 있는 단일화된 인터페이스를 제공하는 방법이다. 백엔드에서 돌고 있는 애플리케이션들은 서로 떨어져 있다고 하더라도 프론트엔드에는 각 애플리케이션마다 별도의 인터페이스를 제공하는 것이 아니라 하나의 단일화된 인터페이스를 사용토록 하는 것이다. 이 방법의 문제점은 각각의 서로 다른 이종간(Heterogeneous) 시스템에 통일된 인터페이스를 제공해야 한다는 어려움이 있다.

<그림 1> 각 시스템을 연동하는 복잡성은 기하급수적으로 증가

<그림 2> 인티그레이션-브로커

<그림 3> 어댑터를 이용한 인티그레이션-버스


애플리케이션 레벨의 EAI

이같은 방법들 보다 더 직접적인 EAI 방식은 기업에서 사용하고 있는 애플리케이션간의 커뮤니케이션이 되도록 하드코딩(hard-coding)된 포인트투포인트 연결을 할 수 있는 소프트웨어를 개발하는 것이다.

이 방식의 주요 초점은 기업내부 혹은 기업간의 비즈니스 프로세스를 처리하는 애플리케이션 로직 컴포넌트간의 인터페이스를 처리하는데 있다. 이 방식을 사용하면 한 애플리케이션의 비즈니스 프로세스가 다른 애플리케이션의 비즈니스 프로세스를 구동시킬 수 있게 된다.

이 방식의 문제는 애플리케이션간의 연결이 타이트한 원투원 메핑(one-to-one mapping)이라는데 있다. 예를 들면 ERP 애플리케이션이 SCM 애플리케이션과 인터랙트하는 컴포넌트가 있다면 이 컴포넌트는 SCM 이외의 다른 애플리케이션과는 사용이 불가능하다는 것이다.

<그림1>에서와 같이 각 시스템의 연동을 위해서 원투원 커넥션(one-to-one connection)을 하다 보면 그 복잡성은 기하급수적으로 증가하게 돼 시스템들의 중간에서 타 시스템간의 연결을 담당을 하게 되는 인티그레이션 브로커(Integration Broker) 방식이 도입되게 된다.

인티그레이션 브로커 방식은 일반적으로 ‘브로커’로 불리는 컴퍼넌트를 사용, 기업 내 시스템의 연결을 처리하는 방식으로 하드코딩된 원투원 커넥션의 단점을 제거하는 것으로 SeeBeyond, NEON, CrossWorld 등에서 솔루션을 제공하고 있다. <그림2>의 인티그레이션 브로커 방식은 포인트투포인트 방식의 복잡성은 해결했지만 인티그레이션 브로커가 지원하는 테크놀로지의 종류에 따라 EAI 솔루션이 결정되는 한계가 있다.

인티그레이션 브로커 방식과 같은 개념으로 약간의 변형을 준 것으로 인티그레이션 버스(Integration Bus) 방식이 있다. 인티그레이션 버스는 어댑터를 이용해 기업전산 시스템 내의 다양한 애플리케이션을 ‘인티그레이션 버스’라고 하는 중앙시스템에 연결, 인티그레이션 버스를 통해 기업전산의 애플리케이션이 커뮤니케이션 하도록 하는 방식으로 Tibco사의 ‘Tibco-RV bus’가 이 방식에 속한다.

이 방식을 사용하기 위해선 각 애플리케이션을 위한 어댑터 개발이 필요해 연결이 필요한 애플리케이션의 수가 적을 경우에만 적합한 방식이다. IT산업은 예전에 각 회사의 Proprietary Technology를 사용 해오다 이제는 표준기술을 사용하여 문제를 해결하는 방향으로 전환함에 따라 썬마이크로시스템이 Java-based, platform-independent EAI Solution인 JCA(Java Connector Architecture)를 제안했다.

JCA는 사실상 Integration Broker 방식과 같은 것으로 차이점이라면 J2EE 기반으로 되어 있다는 점이다. JCA는 J2EE Application Server에 자리를 잡고 이종 기업의 전산시스템간 인터페이스를 제공하는 것이다.

이처럼 EAI의 궁극적인 목적은 기업 내에 존재하고 있는 전산 애플리케이션의 연동을 위해 사용자에게 일관되고 표준화돼 있는 인터페이스를 제공을 하는 것이다.

<그림 4> 썬마이크로시스템즈의 JCA

<그림 5> 일반적인 웹서비스의 구조

<그림 6> 웹서비스의 장점


웹서비스와 EAI

전통적인 방식의 EAI가 기업내의 다양한 전산시스템에 대한 포인트투포인트, 하드코딩 등의 방식을 택하고 있다면, 웹서비스의 경우는 인터넷상에서 동적으로 검색되고 또 통합되는 느슨하게 엮어지는(loosely-coupled) 방법을 택하고 있다는 데에 차이점이 있다. 다시 말해 전통적인 EAI가 스터틱(Static)한 어프로치(Approach)를 하고 있다고 하면, 웹서비스는 EAI를 다이너믹(Dynamic)하게 어프로치 하는 것이라고 할 수 있다.

이러한 웹서비스의 특징을 살펴보면 다음과 같다.

△표준기술에 기반을 두고 있음: 웹서비스는 HTTP, XML, SOAP, WSDL, UDDI의 Internet 표준기술에 기반을 두고 있으며, 기업내의 프로프리터리 인프라스트럭처(Proprietary infrastructure), 운영환경 및 플랫폼의 제약을 받지 않고 애플리케이션을 인터넷에 표출 할 수가 있다.

△비즈니스 프로세스 관리에 용이함: 웹서비스는 비즈니스 로직과 각 로직에 관련이 된 비즈니스의 서비스 부분을 명확하게 분리시킬 수 있다.

△기업 전산환경의 통합에 용이함: 기업의 기반 애플리케이션은 C++, Java, C, AS400, Mainframe에 이르기까지 다양한 테크놀로지로 구성돼 있는데, 이러한 것을 통합한다는 것은 거의 불가능한 일이다. 웹서비스는 이러한 이종간의 시스템을 위에서 명시된 표준기술력을 사용한 래퍼(Wrapper)를 이용, 손쉽게 처리하고 있다.

<그림5>와 같이 웹서비스는 XML, UDDI, WSDL, SOAP과 같은 간단한 인터넷의 표준 테크놀로지를 이용하고 있는데 웹서비스의 가장 큰 장점은 기존의 전통적인 EAI 솔루션이 지니고 있는 기능적인 부분(예를 들면 인티그레이션-브로커나 인티그레이션-버스)에서도 웹서비스를 구축할 수 있다는 것이다. 따라서 기업은 현재 운영하고 있는 전산시스템을 버리고 처음부터 새로운 솔루션을 구축을 하는 것이 아니고 기존의 것을 새로운 테크놀로지로 업그레이드 할 수가 있다는 것이다.

웹서비스와 웹서비스를 구성하고 있는 표준기술들은 서비스를 어떻게 구축하는가를 정의하고 있는 것이 아니다. 웹서비스를 이해하는데 있어 중요한 것은 웹 서비스와 EAI는 서로를 완전히 대체하는 것이 아닌 상호 보완적 관계라는 것이다.


제공 : DB포탈사이트 DBguide.net

by webgosu | 2010/04/08 18:01 | 용어정리 | 트랙백 | 핑백(1) | 덧글(0)

웹서비스

[웹서비스 개요] 웹서비스 등장배경

 
 

1990년대 초 인터넷의 등장은 IT산업의 눈부신 발전을 불러왔으며 이로써 기업의 변화속도도 급속히 가속화되었습니다. 급변화하는 환경에 맞추어 기업들 또한 보다 적극적으로 환경에 대응 변화하고 있습니다. 웹서비스는 이와 같은 IT의 발전 방향과 비즈니스적인 측면이 복합적으로 작용하여 생겨났다고 할 수 있습니다.
90년대 이전까지만 해도 기업의 IT 환경은 기업 업무의 보조수단으로 한정적으로 사용되었습니다. 하지만 인터넷의 보급 이후에는 모든 IT Infra를 개방된 네트워크 상에 공개하였고, 이를 통해 기업과 외부간의 연계 및 통합에 대한 요구가 꾸준히 증가되었습니다.
개방된 인터넷 환경 아래 기업은 오프라인의 비즈니스를 온라인으로 옮겨 새로운 사업기회를 모색하고 짧은 기간 동안 IT infra구축에 투자를 아끼지 않았습니다. 하지만 닷컴 열풍이라고 불리는 90년대 말의 상황이 끝나면서 IT환경의 문제점이 드러나기 시작했습니다. 구체적으로 기업들의 고민은 다음 두 가지로 정리됩니다.
첫째, 닷컴 열풍시 비체계적으로 대규모로 투자한 IT 시스템에 대해 어떻게 활용할 것인가?
둘째, 개방된 인터넷 환경 아래, 끊임없이 요구되는 외부 비즈니스 환경에 대해서는 어떻게 대응해야 할 것인가?
이러한 기업들의 문제인식과 더불어 IT 경기침체에 따른 IT 기업들의 돌파구로 웹서비스가 등장하게 되었습니다.


 
 

[웹서비스 개요] 웹서비스의 개념

 

웹서비스에 대한 개념은 표준이라는 단어로 쉽게 설명될 수 있습니다. 표준의 예로 비디오 테이프, 전기 플러그, 기차 레일 등을 들 수 있습니다. 이중에서도 웹서비스의 개념 및 성공요인을 설명하는 데는 기차 레일과 비디오 테이프가 자주 언급됩니다.
동일한 규격으로 지어진 기차 레일 위에는 증기기관차부터 새마을 호, 초고속 KTX까지 운행될 수 있습니다. 기차레일의 예에서 알 수 있듯이 기본적인 표준 인프라가 구축되어 있는 경우에는 그것을 바탕으로 무궁무진하게 활용이 가능합니다. 웹서비스는 IT분야의 최소한도의 기술 표준이라 할 수 있습니다. 웹서비스에서 정의된 기술 표준은 모든 IT기술의 핵심적인 내용의 표준을 지원합니다.

 

 

 

이러한 표준화 작업은 MS, IBM, SUN 등 세계 IT를 이끌어 가는 대기업에서 주도하고 있습니다. 과거 Sony의 Beta 비디오 테이프가 우수한 품질에도 불구하고 마쓰시다 및 JVC 등과 같은 업계 리딩그룹에 의해 만들어진 업계표준 방식인 VHS에 밀려 결국 시장에서 퇴출된 사례는 웹서비스의 성공적인 확산 가능성을 보여줍니다. 웹서비스는 IT 업계가 처음으로 협업하여 만든 IT의 표준 기술로, 앞으로 IT에 제공되는 모든 플랫폼, 솔루션, Tool에 웹서비스 표준이 적용될 것이고, 그러한 확산은 조만간 모든 IT Infra에 적용되고 영향을 미칠 것 입니다.

[웹서비스 개요] 웹서비스의 정의

 

웹서비스는 발전 초기 단계로써, 정의주체별로 약간씩 다르게 정의내려지고 있습니다. 하지만 대부분 다음과 같은 두 가지 의미를 포함합니다. 
 
- 웹서비스란 인터넷을 통한 네트워크 상에, 단일 또는 다수의 비즈니스간 기존 애플리케이션 시스템을 표준화된 기술로서 결합시킴으로써, 모든 비즈니스를 가능하게 하는 것입니다. 
- 웹서비스는 고객이 원하는 정보나 응용 기능 또는 서비스 자체를 제공해 주는 총체적 서비스입니다. 웹서비스는 기존의 다른 소프트웨어처럼 완벽한 정의를 지정하여 구성하는 것이 아니라, 고객의 다양한 요구에 맞춰 서로 주고 받는 데이터 표준에 대한 정의를 규정합니다. 이와 같은 열린 정의를 통해서 매우 유연하고 이질적인 운영시스템, 프로그램 언어간의 커뮤니케이션 차이를 극복해 주는 연결고리 역할을 수행합니다. 
 
위와 같은 개념을 바탕으로 삼성SDS에서는 웹서비스에 대해 다음과 같이 정의하고 있습니다.

 

"웹서비스는 인터넷 기술을 이용한 표준화된 오픈 네트워크를 통해 기업 내 및 기업간 모든 컴퓨터 시스템을 결합시키는 새로운 컴퓨팅 패러다임으로서, 이를 통해 기업의 수익증대와 비용절감의 효과를 얻을 수 있는 활동이다."


현재 W3C(World Wide Web Consortium)가 추진하고 있는 웹서비스 표준 규약에서 웹서비스 아키텍처를 구성하고 있는 기본 표준들은 다음과 같습니다.


 

 
XML은 웹서비스의 가장 근간으로서 빌딩 블록(Building Block)의 역할을 하며 웹서비스의 데이터를 정의하고, 이 데이터가 어떻게 프로세싱 되어야 하는지를 정의하는 언어를 제공함.
 
SOAP는 웹서비스의 통신 프로토콜이라고 할 수 있음. SOAP는 인터넷 상에서 XML 데이터를 교환하는 데 사용되는 메세징 프레임웍을 정의하는 데 사용됨.
 
WSDL은 XML용어의 하나로 프로그램밍 단계의 자동적 통합에 요구되는 모든기술의 세부목록들을 구성하는 언어에 대한 사전(dictionary) 역할을 하는것으로 이해할 수 있음
 
UDDI는 글로벌 전자적 옐로우 페이지의 역할과 검색 역할을 수행함. UDDI는 기업으로 하여금 자신이 서비스의 제공자임을 드러내어,가용한 제품과 서비스 설명을 레지스트리에 공개하도록 해주며 요청자는 잠재된 비즈니스 파트너를 찾는 동시에 서비스 제공자와의 e-Business 시작을 위한 간단한 통합 을 이룰 수 있음.
 
위의 표준기술들은 다음과 같은 형태의 구성을 이룰 것으로 예상됩니다.
 
 
위의 그림은 Service Oriented Architecture(SOA)를 설명한 그림입니다. 서비스 제공자, 요청자, 중개자의 관계로 구성되는 웹서비스의 아키텍처를 흔히 SOA라고 부릅니다.
SOA는 서비스를 기반으로 애플리케이션을 구축하거나 서비스 자체를 구축하도록 제공되는 아키텍처 혹은 소프트웨어 설계 방법을 말하며, "Publish, Find, Bind"의 세 가지 오퍼레이션을 정의하고 있습니다.
E-Business 시대는 특정 프로세스, 제품 또는 서비스에 대한 변경이 요구될 때 긴 개발 기간을 기다려 줄 여유가 없습니다. 언제라도 변경이 요구될 때 바로 새로운 서비스로 교체하여 새로운 기능을 서비스 해 줄 수 있는 SOA 기반의 시스템 체제, 곧 웹서비스가 요구됩니다.

by webgosu | 2010/04/08 16:59 | 용어정리 | 트랙백 | 덧글(0)

PKI(Public Key Infrastructure)

우선, 공개키 암호화에 관해서 간단히 설명한다.
 
A, B 가 서로 통신을 하고자 한다. 대칭키 1234 로 암호화를 할 것이고, A 가 이 대칭키 1234 를 만들었다. 그리고 B 에게 줘야 된다고 할 때,
B 의 public key 를 가져다가 이 대칭키를 감싸면(암호화), 그리고 이 암호화된 데이타를 B 에게 주면, B 는 private key 로 복호화 해서 대칭키1234를 전달받게 된다.
그 후 부터, 서로 주고 받을 데이타는 대칭키 1234로 암호화 하고, 이 키로 복호화 해서 데이터를 전송하게 된다. (다 아는 얘기?? 그래도 복습~!!!)
 
하지만, B 가 public key 를 A 로 주는 과정에서, A 입장에선 B 의 public key 가 B 가 진짜로 보낸 건지, 아니면 C 가 "B의 public key 야. 받어~( 실제는 C 의 public key )" 라고 준건지, 알수가 없다. 즉, A 가 받는 public key 가 확실히 B 것인지, 증명돼야 된다.
 
이를 증명하기 위해 CA 가 존재한다.
 
여기서 잠깐,  public key 는 누구나 가질 수 있지만, private key 는 당사자만 가질 수 있다. 즉 A 의 public key 는 누구나 알 수 있지만, A 의 private key 는
오직 A 만 갖고 있다.  그리고 public key 로 암호화 한 데이타는 private key 로만 풀 수 있다. 즉 A 만 풀 수 있다는 얘기~.
하지만 또 잠깐, private key 로 암호화 한 데이타는 public key 로 풀린다. 즉, private key 로 암호화할 수 있는 사람은 오직 A 뿐. public key 로 풀었다는 것은,
암호화 한 사람이 A 라는 얘기. 이를 전자서명이라고 하며, 자기가 서명했다는 것이 명백하므로 부인할 수 없다.(부인방지)
 
다시 돌아가서, A 가 받은 public key 가 B 의 것이 확실하다는 것을 검증해 줄 무언가가 필요하다. 우리나라에선 CA 가 이 역할을 한다.
B 의 public key 를 CA 의 private key 로 감싸면(암호화) , A 가 받은 이 데이터는 CA 의 public key 로 풀 수가 있다. CA 의 public key 로 풀렸다면?
CA 가 private key로 암호화 했다는 얘기!!!  CA 가 B 의 public key 를 검증했다는 것이 된다. 이를 우리나라에선 공인인증서라고 불린다.
 
공인인증서란? 
B 의 public key 와 B 의 정보, 예를 들면, 만료 기간, 일련번호, 알고리즘명, 등등 의 정보를 통째로 hash 한다. 그리고 이를 CA 의 private key 로 암호화한 데이터 라고 말 할 수 있다.
거꾸로, 이 암호화된 데이터를 CA 의 public key 로 풀면 hash 값이 나오게 되고, B 의 public key 와 만료기간, 일련번호, ... 의 정보를 hash 한 뒤, 앞의 hash 값과 비교 하면 같아야 된다.
 
여기서 해쉬는?
해쉬 알고리즘 을 말하는 것으로, 주로 단방향 암호화에 사용이 된다. 예를 들면, 아이디/비번에서  비번을 주로 이 해쉬 알고리즘으로 암호화 하는데,
단방향이라 보니 암호화는 할 수 있는데, 복호화를 할 수가 없다. 그래서 검증은, 1234 를 해쉬 알고리즘으로 암호화 하고, 고객이 입력한 1234 를 암호화 하고,
암호화 된 데이터를 비교해서 같으면 검증됨.  그래서 보통 비밀번호를 틀리면, 알려주는 게 아니라 초기화를 시켜 준다. 왜냐, 복호화가 안되기 땜.
 
하지만!!!
CA 의 public key 는 누구가 증명하나? CA 의 public key 로 풀어보니 풀렸다! B 의 public key 가 맞군.. 하고 생각했는데, CA 의 public key 가 다른 사람 것이라면?
다른 사람이 B 의 public key 를 자신의 private key 로 감쌌다면?  A 는 완전히 속게 된다. 모지런놈~~!
 
CA 의 public key 가 CA 의 것이 맞는지 검증해 줄 놈이 필요하다. 이놈을 우리나라에선 최상위 CA (Root CA) 라고 부른다.
그리고, 이놈이 CA public key 에 서명을 한다.( Root CA private key 로) 
 
그러면 Root CA public key 검증은?    없다.
즉, 믿어야 된다. 
 
그래서 이니텍 모듈 같은 경우에 설치 시 Root CA public key 를 같이 배포한다. 초창기에는 Root CA 싸이트에서
자기 public key 가 맞는지 검증하는 서비스를 했다고 함. 그 사이트에서 검증이 되면, 본인 PC 에 설치 돼 있는 Root CA public key 는 제대로 된 것임.
 
그렇다면,
CA 의 인증서는 Root CA public key 로 풀려야 하고,
일반 사람, 위에서 B 의 공인인증서는 CA 의 public key로 풀려야 함.
그러면 A 는 B 의 공개키를 안전하게 받을 수가 있음.
 
또 하나의 빈틈 을 방지하고자 RA 가 존재?
 
A 의 공인인증서를 B 가 훔쳐갔고, A 가 인증서를 재발급 받았을 때, B 가 훔친 인증서를 CA 의 public key로 풀면, 풀린다. (???)
즉, 폐기된 인증서인지 아닌지 검증하는 단계가 필요하게 된다. 이를 RA 가 하게 된다. 
이 방식에는 CRL 이랑 OCSP 가 있다.
CRL 은 폐기된 목록을 RA 가 주기적으로 공지를 하게 되고, 이 목록에 없으면 유효한 인증서란 말~
허나 CRL 의 단점은, 실시간이 아니란 얘기! 시간의 빈틈이 생긴다.  그래서 OCSP 가 존재. 이는... 그냥 물어본다는 말.
이게 유효하나요~? 하고 RA 에 물어보고, RA 는 유효하다~ 라고 대답해 준다. 이를 OCSP 라고 하는 거 같음.
 
PKI 끝~!
 
남은 궁금증.
1. A 가 B 에게서 받은 데이터를 CA 의 public key 로 풀면,  B 의 정보와 public key 가 포함된 hash 값이 나올텐데,
B 의 public key 는 어떻게 구하지? CA 에 가서 다운 받을 수 있나?  A 가 갖고 있는 값은, 복호화가 불가능한 hash 값인데?
A 가 받은 데이터 중에 hash 값 외에 그냥 public key 를 같이 보내나?
 
2. Enveloped Data  라고 설명했던 것 같은데, 무엇이었지?
 
3. C:\Program files\NPKI\yessign\User\ 에  SignCert.der, SignPri.key 파일 두 개가 있는데, 이 중 두번째는 private key 같은데,
첫번째는 무엇이지? CA 가 서명한( CA 의 private key로 암호화된 , 나의 정보가 포함된 ) 공인인증서인가?

[출처] PKI 설명|작성자 내숭왕자


Diagram of a public key infrastructure

Public Key Infrastructure (PKI) is a set of hardware, software, people, policies, and procedures needed to create, manage, distribute, use, store, and revoke digital certificates [1]. In cryptography, a PKI is an arrangement that binds public keys with respective user identities by means of a certificate authority (CA). The user identity must be unique within each CA domain. The binding is established through the registration and issuance process, which, depending on the level of assurance the binding has, may be carried out by software at a CA, or under human supervision. The PKI role that assures this binding is called the Registration Authority (RA) . For each user, the user identity, the public key, their binding, validity conditions and other attributes are made unforgeable in public key certificates issued by the CA.

The term trusted third party (TTP) may also be used for certificate authority (CA). The term PKI is sometimes erroneously used to denote public key algorithms, which do not require the use of a CA.

by webgosu | 2010/04/07 18:42 | 트랙백 | 덧글(0)

date 관련 함수

출처 : http://www.psoug.org/reference/date_func.html

Date
Current DateCURRENT_DATE
SYSDATE
SELECT TO_CHAR(CURRENT_DATE, 'DD-MON-YYYY HH:MI:SS') FROM dual;

SELECT TO_CHAR(SYSDATE, 'DD-MON-YYYY HH:MI:SS') FROM dual;
Formats
DayMonthYearFill ModeJulian Date
DMMYYFMJ
DDMONYYYY  
DDTH RR  
DAY RRRR  
 
+ AND -
+<date> + <integer>
SELECT SYSDATE + 1 FROM dual;
-<date> - <integer>
SELECT SYSDATE - 1 FROM dual;
 
ADD_MONTHS

Add A Month To A Date
ADD_MONTHS(<date>, <number of months_integer>
SELECT add_months(SYSDATE, 2) FROM dual;

-- but be aware of what it is doing
SELECT add_months(TO_DATE('27-JAN-2007'), 1) FROM dual;

SELECT add_months(TO_DATE('28-JAN-2007'), 1) FROM dual;

SELECT add_months(TO_DATE('29-JAN-2007'), 1) FROM dual;

SELECT add_months(TO_DATE('30-JAN-2007'), 1) FROM dual;

SELECT add_months(TO_DATE('31-JAN-2007'), 1) FROM dual;

SELECT add_months(TO_DATE('01-FEB-2007'), 1) FROM dual;
 
CURRENT_DATE

Returns the current date in the session time zone, in a value in the Gregorian calendar of datatype DATE
 
col sessiontimezone format a30

SELECT sessiontimezone, current_date
FROM dual;

ALTER SESSION SET TIME_ZONE = '-5:0';

SELECT sessiontimezone, current_date
FROM dual;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';

SELECT sessiontimezone, current_date
FROM dual;

ALTER SESSION SET TIME_ZONE = '-7:0';

SELECT sessiontimezone, current_date
FROM dual;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY';
 
DUMP

Returns a VARCHAR2 value containing the datatype code, length in bytes, and internal representation of a value
DUMP(<value> [,<return_format>[,<start_position>[,<length>]]])
 
8Octal
10Decimal
16Hexidecimal
17Single Characters
1008octal notation with the character set name
1010decimal notation with the character set name
1016hexadecimal notation with the character set name
1017single characters with the character set name
col drows format a40

SELECT DUMP(SYSDATE) DROWS FROM dual;

SELECT DUMP(SYSDATE, 8) DROWS FROM dual;

SELECT DUMP(SYSDATE, 16) DROWS FROM dual;
 
GREATEST

Return the Latest Date
LEAST(<date>, <date>, <date>, ...)
CREATE TABLE t (
datecol1 DATE,
datecol2 DATE,
datecol3 DATE)
PCTFREE 0;

INSERT INTO t VALUES (SYSDATE+23, SYSDATE-10, SYSDATE-24);
INSERT INTO t VALUES (SYSDATE-15, SYSDATE, SYSDATE+15);
INSERT INTO t VALUES (SYSDATE-7, SYSDATE-18, SYSDATE-9);
COMMIT;

SELECT * FROM t;

SELECT GREATEST(datecol1, datecol2, datecol3)
FROM t;
 
INTERVAL

Interval to adjust date-time
INTERVAL '<integer>' <unit>
SELECT TO_CHAR(SYSDATE, 'HH:MI:SS')
FROM dual;

SELECT TO_CHAR(SYSDATE + INTERVAL '10' MINUTE, 'HH:MI:SS')
FROM dual;

SELECT TO_CHAR(SYSDATE - INTERVAL '10' MINUTE, 'HH:MI:SS')
FROM dual;
 
LAST_DAY
Returns The Last Date Of A MonthLAST_DAY(<date>)
SELECT * FROM t;

SELECT LAST_DAY(datecol1) FROM t;
 
LEAST
Return the Earliest DateLEAST(<date>, <date>, <date>, ...)
SELECT * FROM t;

SELECT LEAST(datecol1, datecol2, datecol3) FROM t;
 
LENGTH
Returns length in charactersLENGTH(<date>)
SELECT LENGTH(last_ddl_time) FROM user_objects;
 
LENGTHB
Returns length in bytesLENGTHB(<date>)
SELECT LENGTHB(last_ddl_time) FROM user_objects;
Note: Additional forms of LENGTH (LENGTHC, LENGTH2, and LENGTH4) are also available.
 
MAX
Return the Latest DateMAX(<date>)
SELECT * FROM t;

SELECT MAX(datecol1) FROM t;
 
MIN
Return the Earliest DateMIN(<date>)
SELECT * FROM t;

SELECT MIN(datecol1) FROM t;
 
MONTHS_BETWEEN
Returns The Months Separating Two DatesMONTHS_BETWEEN(<latest_date>, <earliest_date>)
SELECT MONTHS_BETWEEN(SYSDATE+365, SYSDATE-365) FROM dual;

SELECT MONTHS_BETWEEN(SYSDATE-365, SYSDATE+365) FROM dual;
 
NEW_TIME

Returns the date and time in time zone zone2 when date and time in time zone zone1 are date
Before using this function, you must set the NLS_DATE_FORMAT parameter to display 24-hour time.
SELECT NEW_TIME(TO_DATE('11-10-99 01:23:45',
'MM-DD-YY HH24:MI:SS'), 'AST', 'PST') "New Date and Time"
FROM dual;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';

SELECT NEW_TIME(TO_DATE('11-10-99 01:23:45',
'MM-DD-YY HH24:MI:SS'), 'AST', 'PST') "New Date and Time"
FROM dual;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY';
 
NEXT_DAY
Date of next specified date following a dateNEXT_DAY(<date>, <day of the week>)

Options are SUN, MON, TUE, WED, THU, FRI, and SAT
SELECT NEXT_DAY(SYSDATE, 'FRI') FROM dual;
 
ROUND
Returns date rounded to the unit specified by the format model. If you omit the format, the date is rounded to the nearest dayROUND(<date_value>, <format>)
SELECT ROUND(TO_DATE('27-OCT-00'),'YEAR') NEW_YEAR
FROM dual;
 
Spelled Out Using TO_CHAR

Spelled Demo
DDSPHH24SPMISPMMSPSSSP
SELECT TO_CHAR(TO_DATE('10:30:18', 'HH24:MI:SS'), 'HH24SP:MISP:SSSP')
FROM dual;

SELECT TO_CHAR(TO_DATE('01-JAN-2008', 'DD-MON-YYYY'), 'DDSP-MONTH-YYYYSP')
FROM dual;

SELECT TO_CHAR(TO_DATE('01-JAN-2008', 'DD-MM-YYYY'), 'DDSP-MMSP-YYYYSP')
FROM dual;

SELECT TO_CHAR(TO_DATE(sal,'J'), 'JSP')
FROM emp;
 
SYSDATE
Returns the current date and time set for the operating system on which the database residesSYSDATE
SELECT SYSDATE FROM dual;
 
TRUNC

Convert a date to the date at midnight
TRUNC(<date_time>)
CREATE TABLE t (
datecol DATE);

INSERT INTO t (datecol) VALUES (SYSDATE);

INSERT INTO t (datecol) VALUES (TRUNC(SYSDATE));

INSERT INTO t (datecol) VALUES (TRUNC(SYSDATE, 'HH'));

INSERT INTO t (datecol) VALUES (TRUNC(SYSDATE, 'MI'));

COMMIT;

SELECT TO_CHAR(datecol, 'DD-MON-YYYY HH:MI:SS')
FROM t;

Selectively remove part of the date information

Special thanks to Dave Hayes for reminding me of this.
TRUNC(<date_time>, '<format>')
SELECT TO_CHAR(SYSDATE, 'DD-MON-YYYY HH:MI:SS')
FROM dual;

-- first day of the month
SELECT TO_CHAR(TRUNC(SYSDATE, 'MM'), 'DD-MON-YYYY HH:MI:SS')
FROM dual;

SELECT TO_CHAR(TRUNC(SYSDATE, 'MON'), 'DD-MON-YYYY HH:MI:SS')
FROM dual;

SELECT TO_CHAR(TRUNC(SYSDATE, 'MONTH'), 'DD-MON-YYYY HH:MI:SS')
FROM dual;

-- first day of the year
SELECT TO_CHAR(TRUNC(SYSDATE, 'YYYY'), 'DD-MON-YYYY HH:MI:SS')
FROM dual;

SELECT TO_CHAR(TRUNC(SYSDATE, 'YEAR'), 'DD-MON-YYYY HH:MI:SS')
FROM dual;

Dates in WHERE Clause Joins
SELECT SYSDATE FROM dual;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';

SELECT SYSDATE FROM dual;

/

/

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY';

CREATE TABLE t (
datecol DATE);

INSERT INTO t
(datecol)
VALUES
(SYSDATE);

SELECT * FROM t;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';

SELECT * FROM t;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY';

SELECT * FROM t;

SELECT SYSDATE FROM dual;

SELECT * FROM t
WHERE datecol = SYSDATE;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';

SELECT * FROM t;

SELECT SYSDATE FROM dual;

SELECT TRUNC(SYSDATE) FROM dual;

SELECT * FROM t
WHERE TRUNC(datecol) = TRUNC(SYSDATE);

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY';
 
VSIZE
Returns The Number Of Bytes Required By A ValueVSIZE(e IN DATE) RETURN NUMBER
SELECT VSIZE(SYSDATE) FROM dual;
 
Date Calculations

Returns A Day A Specified Number Of Days In The Future Skipping Weekends
CREATE OR REPLACE FUNCTION business_date (start_date DATE,
Days2Add NUMBER) RETURN DATE IS
 Counter  NATURAL := 0;
 CurDate  DATE := start_date;
 DayNum   POSITIVE;
 SkipCntr NATURAL := 0;
BEGIN
  WHILE Counter < Days2Add LOOP
    CurDate := CurDate+1;
    DayNum := TO_CHAR(CurDate, 'D');

    IF DayNum BETWEEN 2 AND 6 THEN
      Counter := Counter + 1;
    ELSE
      SkipCntr := SkipCntr + 1;
    END IF;
  END LOOP;
  RETURN start_date + Counter + SkipCntr;
END business_date;
/

Business Date function, above, enhanced by Larry Benton to handle negative values for the days2add parameter.
CREATE OR REPLACE FUNCTION business_date (start_date DATE, 
days2add NUMBER) RETURN DATE IS
 Counter NATURAL := 0;
 CurDate DATE := start_date;
 DayNum POSITIVE;
 SkipCntr NATURAL := 0;
 Direction INTEGER := 1;  -- days after start_date
 BusinessDays NUMBER := Days2Add;
BEGIN
  IF Days2Add < 0 THEN
    Direction := - 1; -- days before start_date
    BusinessDays := (-1) * BusinessDays;
  END IF;

  WHILE Counter < BusinessDays LOOP
    CurDate := CurDate + Direction;
    DayNum := TO_CHAR( CurDate, 'D');

    IF DayNum BETWEEN 2 AND 6 THEN
      Counter := Counter + 1;
    ELSE
      SkipCntr := SkipCntr + 1;
    END IF;
  END LOOP;

  RETURN start_date + (Direction * (Counter + SkipCntr));
END business_date;
/

Returns The First Day Of A Month
CREATE OR REPLACE FUNCTION fday_ofmonth(value_in DATE)
RETURN DATE IS
 vMo VARCHAR2(2);
 vYr VARCHAR2(4);
BEGIN
  vMo := TO_CHAR(value_in, 'MM');
  vYr := TO_CHAR(value_in, 'YYYY');
  RETURN TO_DATE(vMo || '-01-' || vYr, 'MM-DD-YYYY');
EXCEPTION
  WHEN OTHERS THEN
    RETURN TO_DATE('01-01-1900', 'MM-DD-YYYY');
END fday_ofmonth;
/
 
Time Calculations

Returns The Number Of Seconds Between Two Date-Time Values
CREATE OR REPLACE FUNCTION time_diff (
DATE_1 IN DATE, DATE_2 IN DATE) RETURN NUMBER IS

NDATE_1   NUMBER;
NDATE_2   NUMBER;
NSECOND_1 NUMBER(5,0);
NSECOND_2 NUMBER(5,0);

BEGIN
  -- Get Julian date number from first date (DATE_1)
  NDATE_1 := TO_NUMBER(TO_CHAR(DATE_1, 'J'));

  -- Get Julian date number from second date (DATE_2)
  NDATE_2 := TO_NUMBER(TO_CHAR(DATE_2, 'J'));

  -- Get seconds since midnight from first date (DATE_1)
  NSECOND_1 := TO_NUMBER(TO_CHAR(DATE_1, 'SSSSS'));

  -- Get seconds since midnight from second date (DATE_2)
  NSECOND_2 := TO_NUMBER(TO_CHAR(DATE_2, 'SSSSS'));

  RETURN (((NDATE_2 - NDATE_1) * 86400)+(NSECOND_2 - NSECOND_1));
END time_diff;
/
Calculating time from seconds

Posted by John K. Hinsdale
12/30/06 to c.d.o.misc
SELECT DECODE(FLOOR(999999/86400), 0, '',
              FLOOR(999999/86400) || ' day(s), ') || 
   TO_CHAR(TO_DATE(MOD(999999, 86400),'SSSSS'), 'HH24:MI:SS') AS elapsed
FROM dual;

Obtain counts per ten minute increment

Posted by Michele Cadot
03/09/08 to c.d.o.misc
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';

SELECT TRUNC(SYSDATE) + dbms_random.value(0,86400)/86400
FROM dual
CONNECT BY LEVEL <= 10;

WITH data AS (
  SELECT TRUNC(SYSDATE)+dbms_random.value(0,86400)/86400 h
  FROM dual
  CONNECT BY LEVEL <= 10)
SELECT TO_CHAR(h,'DD/MM/YYYY HH24:MI:SS') h, TO_CHAR(TRUNC(h)
 + TRUNC(TO_CHAR(h,'SSSSS')/600)/144, 'DD/MM/YYYY HH24:MI:SS') "10m"
FROM data
ORDER BY h;
 

by webgosu | 2009/07/21 21:24 | ORACLE | 트랙백 | 덧글(0)

WebTob + Jeus 연동후 처리

webtob는 ws(webserver)입니다. ws가 처리 할 수 있는 건 html, htm, gif, jpg, cgi 등 정적인 파일들 이며, jsp, servlet, ejb와 같은 동적인 파일들은 was인 jeus에서 처리 합니다.

그러므로, jsp 파일들은 jeus에 등록된 context의 WEB-INF/jeus-web-dd.xml 파일의 docbase (또는, jeus-web-dd.xml 파일이 없다면, JEUSMain.xml 에 등록된 application의 path) 에서 해당 파일을 찾아 처리하게 됩니다.

==========================================================================
참고) 모든 요청은 webserver인 webtob에서 받아 자신이 처리 할 것인지, jeus로 넘길 것인지를 판단하여 처리합니다.
판단 하는 기준은 $WEBTOBDIR/config/http.m or sample.m 파일의 *uri 절 , *ext 절을 보고 나누어 집니다.

예)
*URI
uri0  Uri = "/examples/",   Svrtype = JSV         <-- jeus 로 넘김
uri1  Uri = "/",   Svrtype = JSV                            <-- jeus 로 넘김
uri2  Uri = "/html/", Svrtype = HTML                 <-- webtob에서 처리

*EXT
htm           MimeType = "text/html", SvrType = HTML        <-- webtob에서 처리
html            MimeType = "text/html", SvrType = HTML        <-- webtob 에서 처리
jsp             Mimetype = "application/jsp",  Svrtype=JSV     <--- jeus에서 처리
gif             MimeType = "image/gif", SvrType = HTML
jpeg            MimeType = "image/jpeg", SvrType = HTML
jpg             MimeType = "image/jpeg", SvrType = HTML
js              MimeType = "application/x-javascript", SvrType = HTML
css             MimeType = "text/css", SvrType = HTML
swf             MimeType = "application/octet-stream", SvrType = HTML
hwp             MimeType = "application/octet-stream", SvrType = HTML
doc             MimeType = "application/msword", SvrType = HTML
ppt             MimeType = "application/vns.ms-powerpoint", SvrType = HTML

by webgosu | 2009/06/11 23:55 | JEUS | 트랙백 | 덧글(0)

하나의 서버에 두개의 노드 설정

A라는 애플리케이션은 8080포트로, B라는 애플리케이션은 8090 포트로 서비스 설정방법

 

일단 웹투비쪽 설정을 보겠습니다. 가상호스트를 사용하게 됩니다.
웹투비 설정파일(http.m)의 몇군데를 수정하셔야 합니다.

*NODE
노드명    DocRoot="/aaa/a1",
                PORT="8080",
                ServiceOrder="ext,uri",
                IndexName = "index.html"

*VHOST
vhost1    DocRoot="/aaa/a2",
                PORT="8090",
                ServiceOrder="ext,uri",
                HostName="서버IP또는 도메인",
                NodeName="노드명",
                IndexName = "index.html"

*SVRGROUP
htmlg    NODENAME="노드명", SVRTYPE = HTML
jsvg       NODENAME="노드명", SVRTYPE = JSV
jsvg2     NODENAME="노드명", SVRTYPE = JSV, VhostName = vhost1

*SERVER
html               SVGNAME=htmlg, MinProc=1, MaxProc=5
MyGroup       SVGNAME=jsvg, MinProc=5, MaxProc=5
MyGroup2     SVGNAME=jsvg2, MinProc=5, MaxProc=5

*URI
uri1    Uri = "/", SvrType = JSV, VhostName=vhost1, SvrName = MyGroup2
uri2    Uri = "/", SvrType = JSV, SvrName = MyGroup

*EXT
사용할 확장자와 마임타입을 추가하고 SvrType 에 웹투비면 HTML, 제우스면 JSV를 써준다.

여기서 MyGroup, MyGroup2 가 설정되었고 Min/MaxProc 값 등은 제우스 설정과 맞춰야 한다.

제우스단에서는 2개의 컨테이너를 사용하도록 하고
WEBMain.xml 파일의 <webtob-listener>설정 부분을 수정하시기 바랍니다.
<webtob-listener>
    <registration-id>MyGroup(2)</registration-id>

이때 8080으로 서비스할 컨테이너의 경우는 MyGroup으로, 8090으로 서비스할 컨테이너의 경우는 MyGroup2 로 설정하셔야 웹투비에 정의된 SERVER로 연결이 되며, 서비스 수행이 가능합니다. WebApplication 배포는 서비스할 컨텍스트를 해당 컨테이너에 배포 하시면 됩니다.

개략적으로 설명을 드렸습니다. 설정부분은 꼭 넣어야 하는 부분, 수정해야 하는 부분을 위주로 작성하였으니 빨간색 부분을 기존의 환경과 비교하시면서 수정하시면 됩니다.

by webgosu | 2009/06/11 23:53 | JEUS | 트랙백 | 덧글(0)

WebtoB+Jeus 가상호스트설정

www.bbb.co.kr 와 www.bbb.co.kr/aaa 는 도메인 주소와 포트번호가
동일하므로 VHOST를 이용한 구분은 불가능합니다.
URI 설정을 이용하여 Context Path "/" 와 "/aaa" 를 구분하여
처리하면 됩니다.

설정 예는 다음과 같습니다.

===========================================================
상략

*NODE
nodename    WEBTOBDIR = "/home/jeus42/webserver",
           SHMKEY    = 54000,
           DOCROOT   = "/home/Jeus42/webserver/docs",
           PORT      = "8080",
           JSVPORT   = 9900,
           HTH       = 1

*SVRGROUP
htmlg       NODENAME = "nodename", SvrType = HTML
jsvg        NODENAME = "nodename", SVRTYPE = JSV

*SERVER
html        SVGNAME  = htmlg, MinProc = 1,  MaxProc = 2
MyGroup     SVGNAME  = jsvg,  MinProc = 25, MaxProc = 30
HpGroup     SVGNAME  = jsvg,  MinProc = 25, MaxProc = 30

*URI
uri1        Uri      = "/aaa/", Svrtype = JSV, SvrName = "MyGroup"
uri2        Uri      = "/", Svrtype = JSV, SvrName = "HpGroup"

하략
=====================================================================

그리고 A장비_servlet_engine1 의 WEBMain.xml(jeus4.x)
설정중 webtob-listener 설정을 하나 더 추가하여 B장비 웹투비의
MyGroup과 연결해야 합니다. webtob-listener는 반복구조를 가집니다.
즉, 하나의 엔진이 여러 웹투비와의 연결을 제공합니다. 

by webgosu | 2009/06/11 23:50 | JEUS | 트랙백 | 덧글(0)

JEUS&WEBTOB 가이드

이 문서는 ww.tmax.co.kr 에서 개발/배포하는

웹서버(WebToB)와 웹어플리케이션서버(JEUS)의 설치 및 시동, 연동, 경로설정에 관한 자료입니다.

(버젼 : JEUS4.2, WEBTOB3.1.6(build3), j2sdk1.4.1_07)

 

 

### 설치/시동/테스팅/종료 ###

----------------------------------------------------------------------------------------

1. 필요 프로그램

- j2sdk1.4.1_07 (http://java.sun.com)       # j2sdk1.4.1_07 이하 버젼 권장 (1.4.2버젼대에서는 문제발생할 수 있음)

- jeus42.exe (http://www.tmax.co.kr)

- webtob_3.1.6(build3).exe (http://www.tmax.co.kr)

----------------------------------------------------------------------------------------

2. j2sdk1.4.1_07 설치

- path 맨 앞에 C:/jdk1.4.1_07/bin 설정

- classpath에 . 설정

----------------------------------------------------------------------------------------

3. JEUS42 설치

- JEUS42.exe를 실행 

  (windows2003 서버의 경우 installing... uninstall부분에서 정지시는 windows2000호환성모드로 다시 실행)

- http://www.tmax.co.kr의 download링크를 클릭 (회원가입필요)

  JEUS license를 신청 -> 이메일을 통해 license부여받음 (90일 사용가능)

  부여받은 license파일을 제우스홈\license에 복사 (덮어쓰기)

- 설치 후 다음 세개의 파일을 자신의 환경에 맞게 편집

  1) 제우스홈\config\노드명\JEUSMain.xml 

  2) 제우스홈\webhome\servlet_home\webapps\examples\web-inf\web.xml
  3) 제우스홈\config\노드명\노드명_servlet_engine1\WEBMain.xml

-------------------------------------------------------------------------------------

4. webtob3.1.6 설치

- webtob_3.1.6(build3).exe 실행하여 설치 

  (windows2003에서 installing... uninstall부분에서 정지시는 windows2000호환성모드로 다시 실행)

- http://www.tmax.co.kr의 download링크를 클릭 (회원가입필요)

  WEBTOB license를 신청 -> 이메일을 통해 license.dat부여 (90일 사용가능)

  부여받은 license.dat파일을 c:\webtob\license에 복사 (덮어쓰기)

-------------------------------------------------------------------------------------

5. PATH 설정 후 리부팅 : 자신의 환경에 맞게 설정하고 시스템을 리부팅

  (Program Files처럼 공백을 포함한 디렉토리를 가진 경로는 맨뒤로...)

ex) PATH=C:\J2SDK1.4.1_07\bin;C:\webtob\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOW
S\System32\Wbem;C:\webtob\bin;C:\Jeus42\lib\etc\ant\bin;C:\Jeus42\bin;C:\Jeus42\lib\system

-------------------------------------------------------------------------------------

6. WEBTOB 환경설정

  1) 웹투비홈\config\sample.m을 카피해서 http.m을 생성

  2) wscfl -i http.m을 커맨드창에서 실행 (webtob 환경설정)

  정상결과 예)

        Current configuration:
                Number of client handler(HTH) = 1
                Supported maximum user per node = 975
                Supported maximum user per handler = 975
        CFL is done successfully for node(노드명(노드명))

---------------------------------------------------------------------------------------

7. 시동

1) webtob를 실행

- webtob 실행 :  wsboot

2) JEUS를 실행

- 우선 command창을 두개 띄웁니다.(제우스, 제우스관리자)

- 제우스창에 "jeus + 엔터"

- 제우스관리자창에 "jeusadmin 노드명 -U유져명 -P제우스패스워드 ->boot

- 제우스창에 에러(Exception)가 없다면 실행 성공!!!

--------------------------------------------------------------------------------------

8. 테스팅

- JEUS기본포트는 8088, webtob기본포트는 8080

- JSP 기본경로

제우스홈\webhome\servlet_home\webapps\examples
           http://127.0.0.1/examples/

- Servlet 기본경로

제우스홈\webhome\servlet_home\webapps\examples\WEB-INF\classes
    http://127.0.0.1/examples/

--------------------------------------------------------------------------------------

9. 종료

1) JEUS종료

- 제우스관리자창에 down -> jeusexit

2) WEBTOB종료

- 웹투비창에 wsdown -i

--------------------------------------------------------------------------------------

 

 

 

 

### JEUS/WEBTOB 연동하기 ###

--------------------------------------------------------------------------------------

1. webtob 설정

   - 웹투비홈/config/http.m의 각 항목에 추가합니다.

   *NODE

       JSVPORT = 9900

   *SVRGROUP

       jsvg     NODENAME=노드이름, SVRTYPE=JSV

   *SERVER

      MyGroup    SVGNAME=jsvg, MinProc=10, MaxProc=10

   *URI

      uri2    Uri="/examples/", Svrtype=JSV

--------------------------------------------------------------------------------------

2. jeus 설정

   - 제우스홈/config/노드이름/노드이름_servlet_engine1/WEBMain.xml 수정

        <webserver-connection>
            <webtob-listener>
                <listener-id>webtob1</listener-id>
                <port>9900</port>
                <hth-count>1</hth-count>
                <webtob-address>IP 혹은 127.0.0.1(동일서버에 JEUS와 WEBTOB존재시)</webtob-address>
                <registration-id>MyGroup</registration-id>
                <thread-pool>
                    <min>4</min>
                    <max>10</max>
                    <step>2</step>
                    <max-idle-time>30000</max-idle-time>
                    <max-wait-queue>4</max-wait-queue> 
                </thread-pool>
            </webtob-listener>
        </webserver-connection>


--------------------------------------------------------------------------------------

3. 제우스홈/bin/jeus.properties 조정

    - JEUS_WSDIR 부분을 주석처리 하거나 삭제

    - PATH 에서 $JEUS_HOME/webserver 부분도 제거

--------------------------------------------------------------------------------------

4. webtob 와 jeus 를 부팅 후 확인

   http://주소:8080/exapmples/index.jsp 에서 테스팅 페이지 보기

--------------------------------------------------------------------------------------

 

 

### DB 연동 ###

--------------------------------------------------------------------------------------

* MySQL 커넥션풀 샘플 (WEBMain.xml에 추가)

JEUS에서 제공하는 ConnectionPool은 JDBC Drive를 통해 얻은 Connection의 관리는 
엔진에서 해주는 것이므로 JDBC Driver를 $JEUS_HOME/lib/datasource 아래에 두고
DBConnectionPool은 container.xml에 DataSource는 JeusMain.xml에 다음과 같이 
설정을 하시면 사용하실 수가 있습니다. 
 
1) DBConnectionPool
------------------------------------------------------------------------------
<DBConnectionPool MaxUseCount="-1" 
                  ConnectionPoolType="shared" 
                  CloseDelayMillis="-1" 
                  MaxActiveTimeSecs="-1" 
                  ConnectionPoolID="mysql-shared" 
                  ConnectionArguments="user=root;password=" 
                  DriverClassName="org.gjt.mm.mysql.Driver" 
                  DynamicIncrement="true" 
                  ConnectionURL="jdbc:mysql://localhost:3306/mysql" 
                  LoginDelayMillis="-1" 
                  CloseLongActiveConnection="false" 
                  ConnectionTimeOutSecs="10"> 
        <DBPoolControl MaxCapacity="30" 
                   InitCapacity="20" 
                   MaxIdleTimeSecs="300" 
                   IncrementRate="4" /> 
        <DBAConnection ForcedClose="false" />
</DBConnectionPool>
 
 
2) DataSource
------------------------------------------------------------------------------
<DataSource> 
    <Database> 
            <Vendor>others</Vendor> 
            <ExportName>mysql</ExportName> 
            <DataSourceClassName>
                jeus.jdbc.driver.blackbox.BlackboxConnectionPoolDataSource
            </DataSourceClassName> 
            <Property> 
                <Name>URL</Name> 
                <Type>java.lang.String</Type> 
                <Value>jdbc:mysql://localhost:3306/mysql</Value> 
            </Property> 
            <Property> 
                <Name>DriverClassName</Name> 
                <Type>java.lang.String</Type> 
                <Value>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</Value> 
            </Property> 
            <Property> 
                <Name>Password</Name> 
                <Type>java.lang.String</Type> 
                <Value></Value> 
            </Property> 
            <Property> 
                <Name>User</Name> 
                <Type>java.lang.String</Type> 
                <Value>root</Value> 
            </Property> 
            <DataSourceType>ConnectionPoolDataSource</DataSourceType> 
            <ConnectionPool> 
                <MinPoolSize>4</MinPoolSize> 
                <MaxPoolSize>4</MaxPoolSize> 
                <IncreasingStep>1</IncreasingStep> 
                <ResizingPeriod>10</ResizingPeriod> 
                <OperationTimeout>30000</OperationTimeout> 
                <WaitForFreeConnection> 
                    <WaitingTime>10000</WaitingTime> 
                </WaitForFreeConnection> 
            </ConnectionPool> 
        </Database> 
  </DataSource>
--------------------------------------------------------------------------------------

* Oracle 커넥션풀 샘플 (JEUSMain.xml의 </node>하단에 추가)

    <resource>
        <data-source>
            <database>
                <vendor>oracle</vendor>
                <export-name>오라클UID</export-name>
                <data-source-class-name>oracle.jdbc.pool.OracleConnectionPoolDataSource</data-source-class-name>
                <data-source-type>DataSource</data-source-type>
                <database-name>디비명</database-name>
                <data-source-name>oracle.jdbc.pool.OracleConnectionPoolDataSource</data-source-name>
                <network-protocol>tcp</network-protocol>
                <user>scott</user>
                <password>tiger</password>
                <port-number>1521</port-number>
                <server-name>아이피 또는 127.0.0.1</server-name>
                <driver-type>thin</driver-type>
                <connection-pool>
                    <pooling>
                        <max>20</max>
                        <step>1</step>
                        <period>500000</period>
                    </pooling>
                </connection-pool>
            </database>
        </data-source>
    </resource>

--------------------------------------------------------------------------------------

* DB2

  1) JEUS 3.x ($JEUS_HOME/config/<NODENAME>/JeusMain.xml
        <Database> 
            <Vendor>db2</Vendor> 
            <ExportName>db2local</ExportName> 
            <DatabaseName>SAMPLE</DatabaseName> 
            <DataSourceClassName>COM.ibm.db2.jdbc.DB2ConnectionPoolDataSource</DataSourceClassName>
            <DataSourceName/> 
            <ServiceName/> 
            <Description/> 
            <NetworkProtocol/> 
            <Password>jeus2013</Password> 
            <PortNumber>포트번호</PortNumber> 
            <ServerName>DB서버 IP</ServerName> 
            <User>db2inst1</User> 
            <DataSourceType>LocalXADataSource</DataSourceType> 
            <ConnectionPool> 
                <MinPoolSize>2</MinPoolSize> 
                <MaxPoolSize>4</MaxPoolSize> 
                <IncreasingStep>1</IncreasingStep> 
                <ResizingPeriod>600000</ResizingPeriod> 
                <OperationTimeout>30000</OperationTimeout> 
                <WaitForFreeConnection> 
                    <WaitingTime>10000</WaitingTime> 
                </WaitForFreeConnection> 
            </ConnectionPool> 
        </Database>  
  2) JEUS 4.x ($JEUS_HOME/config/<NODENAME>/JEUSMain.xml
           <database>
                <vendor>db2</vendor>
                <export-name>db2XADatasource1</export-name>
<data-source-class-name>COM.ibm.db2.jdbc.DB2XADataSource</data-source-class-name>
                <data-source-type>XADataSource</data-source-type>
                <database-name>sample</database-name>
                <description>Customer DB</description>
                <password>db2inst1</password>
                <encryption>false</encryption>
                <port-number>포트번호</port-number>
                <server-name>DB서버 IP</server-name>
                <user>db2inst1</user>
                <connection-pool>
                    <pooling>
                        <min>2</min>
                        <max>4</max>
                        <step>1</step>
                        <period>600000</period>
                    </pooling>
                    <wait-free-connection>
                        <enable-wait>false</enable-wait>
                        <wait-time>10000</wait-time>
                    </wait-free-connection>
                    <operation-to>30000</operation-to>
                </connection-pool>
            </database>
--------------------------------------------------------------------------------------


 

 

### TIPS ###

--------------------------------------------------------------------------------------

* 파일경로설정

1) 파일 실제경로 (기본값)

- servlet : 제우스홈\webhome\servlet_home\webapps\examples\WEB-INF\classes

- jsp : 제우스홈\webhome\servlet_home\webapps\examples

2) 기존의 examples 컨텍스트 이외에 새로운 aaa라는 컨텍스트를 추가하는 방법 (컨텍스트 설정법)
- WEBMain.xml에서 다음 부분을 추가한다. 
  <context> 
    <context-name>aaa</context-name> 
    <context-path>/aaa</context-path> 
  </context> 
- aaa 컨텍스트의 DD(deployment descriptor)파일을 작성 
  제우스홈\config\노드명\[SERVLET_ENGINE_NAME]\jeus-web-dd_examples.xml 파일을 jeus-web-dd_aaa.xml 파일로 복사  

  하여 편집. context-name, docbase 만 설정하면 됩니다. WEBMain.xml의 이름과 동일해야 함. 
  <?xml version="1.0"?> 
  <!DOCTYPE jeus-web-dd PUBLIC "-//Tmax Soft., Inc.//DTD JEUS WEB Deployment Info 4.0//EN" 
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-web-dd.dtd"> 
  <jeus-web-dd> 
    <context> 
        <context-name>aaa</context-name> 
        <docbase>서버의 물리적 절대경로</docbase> 
        <auto-reload> 
            <enable-reload>true</enable-reload> 
            <check-on-demand>true</check-on-demand> 
        </auto-reload> 
    </context> 
  </jeus-web-dd> 
- WebtoB의 환경설정파일(http.m)의 URI 절에 aaa 컨텍스트 경로를 다음과 같이 추가한다. 
  *URI 
  uri8 Uri = "/aaa/",Svrtype = JSV 
- WebtoB의 환경파일 수정 후에는 반드시 환경파일 컴파일 후 WebtoB를 재기동 : wscfl -i http.m 
- JEUS 를 재기동



--------------------------------------------------------------------------------------

* index.jsp를 자동으로 인식시키려면

- 제우스홈\config\노드명\[SERVLET_ENGINE_NAME]\webcommon.xml 파일에 index.jsp추가

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>

--------------------------------------------------------------------------------------

* jspwork 디렉토리 변경

1. JEUS 3.x
$JEUS_HOME/config/<HOSTNAME>/<SERVLET_ENGINE_NAME>/container.xml의
<JSPEngine> 태그 안에 JspWorkDir을 설정하면 됩니다.
<Container>
  ...
  <ContextGroup>
    ...
    <JSPEngine ... 
      JspWorkDir="/app/jwork" 
      ...
    />
2. JEUS 4.x
$JEUS_HOME/config/<HOSTNAME>/<SERVLET_ENGINE_NAME>/WEBMain.xml의
<jsp-engine> 태그 안에 <jsp-work-dir>를 설정하면 됩니다.
<web-container>
  <context-group>
    ...
    <jsp-engine>
      ...
      <jsp-work-dir>/app/jwork</jsp-work-dir>
      ...
    </jsp-engine>
--------------------------------------------------------------------------------------

* 폴더관리 (webtob, jeus 연동시)

- image, js, css, html 등은WebToB홈\docs 에 폴더로 관리해서 WEBTOB가 처리

- jsp, servlet은 context를 별도 설정 (컨텍스트 설정법 참조)해서 JEUS가 처리

--------------------------------------------------------------------------------------

* 오라클 데이터베이스 사용시 C:/jeus/lib/datasource 폴더에 classes12.zip 복사

--------------------------------------------------------------------------------------

* trouble shooting

- Out Of Memory 에러

  JVM에서 사용할 수 있는 memory가 부족할 때 발생합니다. 
  이것을 해결하는 방법으로는 버전별로 다음과 같이 JEUS 환경 파일에서
  추가하면 됩니다. -Xms가 min 값이고 -Xmx가 max 값입니다.
  1) JEUS 3.x ($JEUS_HOME/config/<HOSTNAME>/JeusMain.xml)
  <JeusSystemConfig>
      <NodeConfig>
          ...
          <EngineContainer>
              ...
              <CommandOption>-Xms256m -Xmx256m<CommandOption>
  2) JEUS 4.x ($JEUS_HOME/config/<HOSTNAME>/JEUSMain.xml)
  <jeus-system>
      <node>
          ...
          <engine-container>
             ...
              <command-option>-Xms256m -Xmx256m<command-option>
- 노드명에 '-' 문자를 썼을 경우 또는 노드명에 공백이 있는 경우

  wscfl -i http.m 부분에서 오류 -> 노드명을 ""으로 묶어준다.

- 8080포트 사용하려고 할때 XDB 인증창이 뜬다면... 

  =====> 오라클의 XDB포트와 충돌하는 경우이므로 오라클의 XDB포트를 아래와 같이 변경해준다.

  [시작] -> [프로그램] -> [Oracle - OraHome92] -> [Configuration and Migration Tools] 

  -> [Database Configuration Assistant]   선택

  프로그램이 실행이되면.....

  [다음] 버튼을 Click -> [데이터베이스의 데이이터베이스 옵션구성] 선택 -> [사용 가능한 데이터베이스] 선택 

  -> [표준데이터베이  스 기능...] 버튼을 Click -> Oracle XML DB 의 [사용자 정의 ...] 버튼을 Click 

  -> [포트 번호 구성] 항목의 [사용자 정의 값 지정] 을 선택하셔서 HTTP 포트를 바꿔줍니다. 

  그리고 FTP 및 WebDAV 포트는 기본 설정인 2100 을 사용합니다. -> [확인] 버튼을 Click 하시고 

  [다음] 버튼을 Click 하셔서 데이터베이스를 실행할 기본모드를 선택하시고 [완료] 버튼을 눌러주시면 

  요약 메세지창이 뜨고 [확인] 버튼을 눌러주시면 XDB 의 Port 설정이 끝나게 됩니다.

- 다음과 같은 nullpointer exception 발생시

  <<__Exception__>>
  java.lang.NullPointerException
          at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:20
  5)
          at javax.servlet.GenericServlet.log(GenericServlet.java:300)
          at javax.servlet.GenericServlet.init(GenericServlet.java:257)
          at jeus.servlet.common.WebContainerManager.startContainer(WebContainerMa
  nager.java:538)
          at jeus.servlet.syscontext.SystemContext.startup(SystemContext.java:64)
          at jeus.servlet.deployment.SystemWebContainer.startup(SystemWebContainer
  .java:35)
          at jeus.server.SystemEngineController.startEngine(SystemEngineController
  .java:26)
          at jeus.server.JeusServer.boot(JeusServer.java:720)
          at jeus.server.ControlThread.acceptRequests(ControlThread.java:181)
          at jeus.server.ControlThread.run(ControlThread.java:86)
  java.lang.NullPointerException : null
  [SystemEngineController] fail to start System Engine [devserver_system_engine] :
   jeus.server.JeusServerException
  <<__!Exception__>>
  [2005.05.26 10:30:05][2] [ControlThread] command (210.117.198.62:1063) : disconn
  ect()

 =====> j2sdk1.4.1_07 이하 버젼으로 jdk를 다시 설치한 수 jeus/webtob 다시설치 해보세요.

- C:\Program Files\Java\j2re1.4.1_07\bin\server\jvm.dll 파일을 찾지 못할때

  =====> C:\j2sdk1.4.1_07\jre\bin\server 폴더를 카피해서 

             C:\Program Files\Java\j2re1.4.1_07\bin 폴더에 복사하세요.

--------------------------------------------------------------------------------------

* 클래스파일 변경시 실시간으로 변경 반영

소스가 WEB-INF/classes 아래에 있으면 리부팅이 필요 없습니다. 
단, 확인 하실 것이 container.xml(WEBMain.xml)에 context 태그 내에 AutoReload="true"가 설정되어 있으면 됩니다.
WEB-INF/lib/*.jar는 라이브러리와 같이 수정하지 않는다는 의미를 포함하고 있으므로(J2EE 스펙에 준하면...) 
jar 파일 내의 수정은  반드시 제우스를 리부팅 해야 적용됩니다.
--------------------------------------------------------------------------------------

* 인클루드된 파일 변경시 즉시 적용(<%@ include 자동 반영하기)

JSP의 include의 방식에는 <%@ include (action), <jsp:include (directive) 가 있다.

이 중 <jsp:include (action) 는 include하는 JSP(a.jsp)와 include되는 JSP(b.jsp)가 각각 별도의 servlet으로 변환된다.
a.jsp가 수행 도중 b.jsp의 include 구문을 만나면 b.jsp로 제어권이 넘어가서 수행된 후 다시 a.jsp로 제어권이 넘어와서 계속 수행된다.
그래서 b.jsp가 변경된 경우 변경사항이 자동으로 반영된다.

그리고 <%@ include (directive)는 include하는 JSP(a.jsp)와 include되는 JSP(b.jsp)가  하나의 servlet으로 변환되어서 a.jsp 내에 b.jsp가 완전히 포함되는 형태로 변환된다.
<%@ include (directive)의 목적은 JSP가 Servlet으로 변환되어 컴파일 될 때에
특정 코드나 text를 포함하기 위해서 이다.
따라서 b.jsp가 변경된 경우 a.jsp는 b.jsp가 변경되었는지 모르기 때문에 include 된 JSP의 변경시 이것을 인지하지 못한다.

<%@ include (directive) 를 사용하는 경우 JSP container가 include된 파일이 변경된 경우 자동으로 반영해 주기 위해서는 include하는 파일이 수행될 때 마다 include된 파일의 변경 여부를 검사해서 변경되었다면 include 하는 파일을 recompile 해 주어야 한다.
이것은 JSP container에게는 상당히 부하를 주는 작업이다.
그래서 JSP Spec에서는 include된 파일의 변경시 반영 여부는 명시하지 않고 있다.

JEUS에서는 개발과 운영의 편의성을 위해서 이것을 옵션으로 지정하여 변경시 자동 반영이 되게 설정할 수 있다.
하지만 이 옵션을 true로 설정하는 경우 불필요한 검사가 들어가게 되므로 수행 속도에 지장을 주게됩니다. 반드시 JSP 파일의 변경이 빈번한 경우에만 설정하면 된다.

1. JEUS 3.x
$JEUS_HOME/config/<HOSTNAME>/<SERVLET_ENGINE_NAME>/container.xml에 설정
---------------------------------------------------------
<Container>
    ...
    <ContextGroup>
        ...
        <JSPEngine ...
            CheckIncludedJspFile="true"
            ... />
2. JEUS 4.x
$JEUS_HOME/config/<HOSTNAME>/<SERVLET_ENGINE_NAME>/WEBMain.xml에 설정
---------------------------------------------------------
<web-container>
    ...
    <context-group>
        ...
        <jsp-engine>
            ...
            <check-included-jspfile>true</check-included-jspfile>
            ...
        </jsp-engine>
        ...
    </context-group>
    ...
</web-container>
--------------------------------------------------------------------------------------

* http.m 샘플

*DOMAIN
WebtoB

*NODE
devserver WEBTOBDIR="C:/webtob", 
  SHMKEY = 54000,
  DOCROOT="C:/tmax/webdocs",
  IndexName="index.jsp,index.html,index.htmm",
  PORT = "80", 
  LOGGING = "log1",
  ERRORLOG = "log2",
  HTH = 1,
  JSVPORT = 9900

*SVRGROUP
htmlg  NODENAME = devserver, SvrType = HTML
cgig  NODENAME = devserver, SVRTYPE = CGI
ssig  NODENAME = devserver, SVRTYPE = SSI
jsvg  NODENAME = devserver, SVRTYPE=JSV

*SERVER
html  SVGNAME = htmlg, MinProc = 3, MaxProc = 10
cgi  SVGNAME = cgig, MinProc = 3, MaxProc = 10
ssi  SVGNAME = ssig, MinProc = 3, MaxProc =10
MyGroup  SVGNAME=jsvg, MinProc=10, MaxProc=10

*URI
uri1  Uri = "/cgi-bin/", Svrtype = CGI
uri2  Uri="/examples/", Svrtype=JSV
uri3  Uri="/", Svrtype=JSV

*ALIAS
alias1  URI = "/cgi-bin/", RealPath = "C:/webtob/cgi-bin/"

*LOGGING
log1  Format = "DEFAULT", FileName = "C:/webtob/log/access.log", Option = "sync"
log2  Format = "ERROR", FileName = "C:/webtob/log/error.log", Option = "sync"

*EXT
htm  MimeType = "text/html", SvrType = HTML
--------------------------------------------------------------------------------------

* JEUSMain.xml 샘플

<?xml version="1.0"?>
<!DOCTYPE jeus-system PUBLIC "-//Tmax Soft, Inc.//DTD JEUS Main Config 4.0//EN"
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-main-config.dtd">
<jeus-system>
    <node>
        <name>devserver</name>
        <class-ftp>true</class-ftp>
        <sequential-start>true</sequential-start>
        <enable-webadmin>true</enable-webadmin>
        <system-log>
            <level>debug</level>
        </system-log>
        <engine-container>
            <name>container1</name>
            <engine-command>
                <type>servlet</type>
                <name>engine1</name>
                <startup-mode>xml</startup-mode>
            </engine-command>
            <tm-config>
                <pooling>
                    <min>10</min>
                    <max>20</max>
                    <step>2</step>
                    <period>600000</period>
                </pooling>
                <active-timeout>300000</active-timeout>
                <commit-timeout>120000</commit-timeout>
                <capacity>20000</capacity>
            </tm-config>
        </engine-container>
    </node>
</jeus-system>

--------------------------------------------------------------------------------------

* WEBMain.xml 샘플

<?xml version="1.0"?>
<!DOCTYPE web-container PUBLIC "-//Tmax Soft., Inc.//DTD WEB Main Config 4.0//EN"
                               "http://www.tmaxsoft.com/jeus/dtd/4.0/web-main-config.dtd">
<web-container>
    <context-group>
        <group-name>MyGroup</group-name>
        <group-docbase>webapps</group-docbase>
        <session-config>
            <timeout>20</timeout>
            <shared>true</shared>
        </session-config>
        <logging>
            <error-log>
                <target>stdout</target>
                <level>information</level>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
            </error-log>
            <user-log>
                <target>file</target>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
            </user-log>
            <access-log>
                <target>file</target>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
                <log-format>
                    <time-format>default</time-format>
                </log-format>
            </access-log>
        </logging>
        <context>
            <context-name>examples</context-name>
            <context-path>/examples</context-path>
        </context>
  <context> 
   <context-name>ngi</context-name> 
   <context-path>/</context-path> 
  </context> 
        <webserver-connection>
            <webtob-listener>
                <listener-id>webtob1</listener-id>
                <port>9900</port>
                <hth-count>1</hth-count>
                <webtob-address>127.0.0.1</webtob-address>
                <registration-id>MyGroup</registration-id>
                <thread-pool>
                    <min>4</min>
                    <max>10</max>
                    <step>2</step>
                    <max-idle-time>30000</max-idle-time>
                    <max-wait-queue>4</max-wait-queue> 
                </thread-pool>
            </webtob-listener>
        </webserver-connection>
    </context-group>
</web-container>
--------------------------------------------------------------------------------------

 

 

 

### 실무 적용 예 (버츄얼호스팅 사용) ###

-------------------------------------------------------------------------------------- 

프로젝트 실제환경을 로컬에서 구현해 작업해야 하는 상황에서...

두대의 IBM서버로 돌아가는 JEUS/WEBTOB의 환경설정 입니다.

 

<<< 실제환경 >>>

---------------------------------------------------------------------------

- 서버1 : WindowsServer2003Standard, 웹서버 (WEBTOB)

- 서버2 : WindowsServer2003Standard, 웹컨테이너 (JEUS), DB(Oracle9i)

- 두 서버는 9999포트를 통해 연동한다.

- images,css,js는 서버1에 jsp,java는 서버2에 위치시킨다.

- 서버구조는 1 WEBSERVER, 2 CONTAINER (원래 4개에서 필요한 두개만 가동)

- 윈도우 hosts파일에 localhost2, localhost3 추가

----------------------------------------------------------------------------

 

<<< sample.m >>>

*DOMAIN
WebtoB

*NODE
realchokyCompaq
  WebtobDir="C:/webtob",
  Shmkey=54000,
  Docroot="C:/center",
  HTH=1,
  port="9900",
  JSVPort=9999,
  IndexName="index.jsp,index.htm,index.html",
  Logging="log1",
  ErrorLog="log2"

*VHOST
center
  NodeName="realchokyCompaq",
  HostName="localhost2",
  DocRoot="C:/center",
  Port="9900",
  SSLFlag=N,
  IndexName="index.jsp,index.htm,index.html"

admin
  NodeName="realchokyCompaq",
  HostName="localhost3",
  DocRoot="C:/admin",
  Port="9900",
  IndexName="index.jsp,index.htm,index.html"

*SVRGROUP
htmlg
  NodeName="realchokyCompaq",
  SvrType=HTML

jsvg
  NodeName="realchokyCompaq",
  SvrType=JSV,
  VHostName=center

jsvg2
  NodeName="realchokyCompaq",
  SvrType=JSV,
  VHostName=admin

*SERVER
html
  SvgName=htmlg,
  MinProc=30,
  MaxProc=60

Center
  SvgName=jsvg,
  MinProc=30,
  MaxProc=30,
  HttpInBufsize=0,
  HttpOutBufsize=0

Admin
  SvgName=jsvg2,
  MinProc=10,
  MaxProc=10,
  HttpInBufsize=0,
  HttpOutBufsize=0

*URI
images
  Uri="/images/",
  SvrType=HTML

center
  Uri="/",
  SvrType=JSV,
  VhostName=center

admin
  Uri="/",
  SvrType=JSV,
  VhostName=admin

*LOGGING
log1
  FileName="C:/webtob/log/access.log",
  Format="DEFAULT",
  Option="sync"

log2
  FileName="C:/webtob/log/error.log",
  Format="ERROR",
  Option="sync"

*EXT
htm
  Mimetype="text/html",
  Svrtype=HTML

jsp
  Mimetype="application/jsp",
  Svrtype=JSV

 

 

<<< JEUSMain.xml >>>

 

<?xml version="1.0"?>
<!DOCTYPE jeus-system PUBLIC "-//Tmax Soft, Inc.//DTD JEUS Main Config 4.0//EN"
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-main-config.dtd">
<jeus-system>
    <node>
        <name>realchokyCompaq</name>
        <class-ftp>true</class-ftp>
        <sequential-start>true</sequential-start>
        <system-log>
            <level>debug</level>
        </system-log>
        <engine-container>
            <name>container1</name>
            <engine-command>
                <type>servlet</type>
                <name>engine1</name>
                <startup-mode>xml</startup-mode>
            </engine-command>
            <tm-config>
                <pooling>
                    <min>10</min>
                    <max>20</max>
                    <step>2</step>
                    <period>600000</period>
                </pooling>
                <active-timeout>300000</active-timeout>
                <commit-timeout>120000</commit-timeout>
                <capacity>20000</capacity>
            </tm-config>
        </engine-container>
        <engine-container>
            <name>container2</name>
            <engine-command>
                <type>servlet</type>
                <name>engine2</name>
                <startup-mode>xml</startup-mode>
            </engine-command>
            <tm-config>
                <pooling>
                    <min>10</min>
                    <max>20</max>
                    <step>2</step>
                    <period>600000</period>
                </pooling>
                <active-timeout>300000</active-timeout>
                <commit-timeout>120000</commit-timeout>
                <capacity>20000</capacity>
            </tm-config>
        </engine-container>
    </node>
    <resource>
        <data-source>
            <database>
                <vendor>oracle</vendor>
                <export-name>오라클UID</export-name>
                <data-source-class-name>oracle.jdbc.pool.OracleConnectionPoolDataSource</data-source-class-name>
                <data-source-type>DataSource</data-source-type>
                <database-name>디비명</database-name>
                <data-source-name>oracle.jdbc.pool.OracleConnectionPoolDataSource</data-source-name>
                <network-protocol>tcp</network-protocol>
                <user>아이피</user>
                <password>패스워드</password>
                <port-number>1521</port-number>
                <server-name>아이피 혹은 127.0.0.1</server-name>
                <driver-type>thin</driver-type>
                <connection-pool>
                    <pooling>
                        <max>20</max>
                        <step>1</step>
                        <period>500000</period>
                    </pooling>
                </connection-pool>
            </database>
        </data-source>
    </resource>
</jeus-system>

 

 

<<< WEBMain.xml (컨테이너 1) >>>

 

<?xml version="1.0"?>
<!DOCTYPE web-container PUBLIC "-//Tmax Soft., Inc.//DTD WEB Main Config 4.0//EN"
                               "http://www.tmaxsoft.com/jeus/dtd/4.0/web-main-config.dtd">
<web-container>
    <context-group>
        <group-name>Center</group-name>
        <group-docbase>webapps</group-docbase>
        <servlet-home>c:\</servlet-home>
        <context>
            <context-name>Center</context-name>
            <context-path>/</context-path>
        </context>
        <session-config>
            <shared>true</shared>
            <timeout>20</timeout>
        </session-config>
        <webserver-connection>
            <webtob-listener>
                <listener-id>Center</listener-id>
                <port>9999</port>
                <output-buffer-size>0</output-buffer-size>
                <webtob-address>127.0.0.1</webtob-address>
                <thread-pool>
                    <min>30</min>
                    <max>30</max>
                </thread-pool>
            </webtob-listener>
        </webserver-connection>
        <logging>
            <error-log>
                <target>stdout</target>
                <buffer-size>0</buffer-size>
                <level>information</level>
            </error-log>
            <user-log>
                <buffer-size>0</buffer-size>
            </user-log>
            <access-log>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
                <log-format>
                    <time-format>default</time-format>
                </log-format>
            </access-log>
        </logging>
    </context-group>
</web-container>

 

 

<<< jeus-web-dd_Center.xml >>>

 

<?xml version="1.0"?>
<!DOCTYPE jeus-web-dd PUBLIC "-//Tmax Soft., Inc.//DTD JEUS WEB Deployment Info 4.0//EN"
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-web-dd.dtd">
<jeus-web-dd>
    <context>
        <context-name>center</context-name>
        <docbase>center</docbase>
        <auto-reload>
            <enable-reload>true</enable-reload>
            <check-on-demand>true</check-on-demand>
        </auto-reload>
    </context>
</jeus-web-dd>

 

 

 

<<< WEBMain.xml (컨테이너 2) >>>

 

<?xml version="1.0"?>
<!DOCTYPE web-container PUBLIC "-//Tmax Soft., Inc.//DTD WEB Main Config 4.0//EN"
                               "http://www.tmaxsoft.com/jeus/dtd/4.0/web-main-config.dtd">
<web-container>
    <context-group>
        <group-name>Admin</group-name>
        <group-docbase>webapps</group-docbase>
        <servlet-home>c:\</servlet-home>
        <context>
            <context-name>Admin</context-name>
            <context-path>/</context-path>
        </context>
        <session-config>
            <shared>true</shared>
            <timeout>20</timeout>
        </session-config>
        <webserver-connection>
            <webtob-listener>
                <listener-id>Center</listener-id>
                <port>9999</port>
                <output-buffer-size>0</output-buffer-size>
                <webtob-address>127.0.0.1</webtob-address>
                <thread-pool>
                    <min>30</min>
                    <max>30</max>
                </thread-pool>
            </webtob-listener>
        </webserver-connection>
        <logging>
            <error-log>
                <target>stdout</target>
                <buffer-size>0</buffer-size>
                <level>information</level>
            </error-log>
            <user-log>
                <buffer-size>0</buffer-size>
            </user-log>
            <access-log>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
                <log-format>
                    <time-format>default</time-format>
                </log-format>
            </access-log>
        </logging>
    </context-group>
</web-container>


 

 

<<< jeus-web-dd_Admin.xml >>>

 

<?xml version="1.0"?>
<!DOCTYPE jeus-web-dd PUBLIC "-//Tmax Soft., Inc.//DTD JEUS WEB Deployment Info 4.0//EN"
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-web-dd.dtd">
<jeus-web-dd>
    <context>
        <context-name>admin</context-name>
        <docbase>admin</docbase>
        <auto-reload>
            <enable-reload>true</enable-reload>
            <check-on-demand>true</check-on-demand>
        </auto-reload>
    </context>
</jeus-web-dd>


--------------------------------------------------------------------------------------

 

 

이 문서는 실무에서 자주 사용되는 웹/웹어플서버인 JEUS/WEBTOB를 접하면서 생기게된

설정문제와 기타 문제들을 정리해볼 목적으로 만들어 졌습니다. 오류사항이 있으면 메일을 보내주세요.

기타 문의는 http://www.tmax.co.kr 개발자포럼을 이용하세요.

 

- 작성자 : realchoky (realchoky@naver.com)

- 최초작성일 : 2004. 9. 13

- 최종수정일 : 2005. 5. 31 

by webgosu | 2009/06/11 23:46 | 기타 | 트랙백 | 덧글(0)

Logging설정 for JEUS5

소개

문서는 JEUS 5 관리자를 사용한 logging 설정 방법 customization 방법, log4j 사용법 등을 설명한다.

기본logger 파일

최초 JEUS 설치 , JEUS log default console handler 사용하기 때문에 JEUS manager 모든 engine container log message stdout형태로 출력된다. 또한 web container access log $JEUS_HOME/logs/<노드명>/<노드명>_<컨테이너명>/servlet/accesslog/access.log 출력 된다.

관리자접속

관리자에 접속하는 방법은 다음과 같다. 관리자는 JEUS_BASEPORT + 8 포트를 사용하므로 JEUS_BASEPORT default 9736이므로 관리자는 9744 사용하고, 해당 Port 대해 방화벽이 열려 있어야 한다.

http://IPAddress:9744/webadmin/

 

관리자로 log 설정하기

1. JEUS Server log 설정

관리자접속노드명을선택하면오른쪽화면에서에러로그설정항목을있다.




로거추가를
선택하면 logging level 설정 화면이 나오는데, logging level 다음과 같다.

FATAL<NOTICE<INFORMATION<DEBUG<SEVERE<WARNING<INFO<CONFIG<FINE<FINER<FINEST<ALL

- default level INFO

- 개발자는보통 FINE

logging level 선택 확인을 누르면 아래와 같이 jeus logger 추가된 것을 있다.




추가된
jeus logger 선택하면 로그핸들러 생성화면을 있는데, 핸들러의 종류는 다음과 같다.

console-handler, file-handler, smtp-handler, socket-handler, user-handler

- default console-handler

사용하고자 하는 핸들러를 선택하면 아래와 같이 로그 핸들러 생성 화면이 나타난다. 항목 확인 생성버튼을 누르면 JEUS Server log 생성된다.





웹관리자에서
생성한 JEUS Server log $JEUS_HOME/config/<노드명>/JEUSMain.xml xml 형태로 추가된다.

<<JEUSMain.xml>>

<jeus-system xmlns="http://www.tmaxsoft.com/xml/ns/jeus">

<node>

...

<system-logging>

          <level>INFO</level>

          <handler>

              <file-handler>

                  <name>handler1</name>

                  <level>FINEST</level>

                  <valid-day>1</valid-day>

              </file-handler>

          </handler>

      </system-logging>

위와 같이 file-handler, 1 단위로 생성했을 경우 log , $JEUS_HOME/logs/<노드명> JeusServer_<날짜>.log 형식으로 남게 된다. <system-logging><level> log level <handler>에서 설정한 <level> 보다 우선한다.  log 실시간으로 확인하기 위해서 tail 명령어를 사용하거나,

test:/home/main/jeus5/logs/test> tail -f JeusServer_<날짜>.log

또는 사용자 profile 아래와 같이 alias 설정하는 방법이 있다.

alias jlog='tail -f ${JEUS_HOME}/logs/`hostname`/JeusServer_`date +%Y%m%d`.log'

 

2. Container log 설정

Container log Container 마다 별도로 log 관리 있다는 장점이 있다.

Container log설정은 위와 마찬가지로 관리자를 사용한다. 관리자에 접속 컨테이너명을 선택하면 오른쪽 화면에서 에러 로그 설정 항목을 있다.

logging 설정은 JEUS Server log 설정을 참고한다.






웹관리자에서
생성한 Container log $JEUS_HOME/config/<노드명>/JEUSMain.xml xml 형태로 추가된다.

<<JEUSMain.xml>>

<jeus-system xmlns="http://www.tmaxsoft.com/xml/ns/jeus">

    <node>

        <name>test</name>

        <engine-container>

            <name>container1</name>

            ...

            <system-logging>

                <level>INFO</level>

                <handler>

                    <file-handler>

                        <name>handler1</name>

                        <level>FINE</level>

                        <valid-day>1</valid-day>

                    </file-handler>

                </handler>

            </system-logging>

        </engine-container>

Container log file-handler, 1 단위로 생성했을 경우 log , $JEUS_HOME/logs/<노드명>/<노드명>_<컨테이너명> <노드명>_<컨테이너명>_<날짜>.log 형식으로 남게 된다. <system-logging><level> log level <handler>에서 설정한 <level> 보다 우선한다. log 실시간으로 확인하기 위해 tail 명령어를 사용하거나 사용자 profile 아래와 같이 alias 설정하는 방법이 있다.

alias clog='tail -f ${JEUS_HOME}/logs/`hostname`/`hostname`_container1/`hostname`_container1_`date +%Y%m%d`.log'

Container log에서 ConsoleHandler 사용할 경우 Console 외의 JEUS Server log 같이 출력 된다.

 

JEUS logging 패턴

JEUS logging JDK1.4에서 포함된 java.util.logging 패키지에 있는 Logging API 따른다. JEUS logging 환경은 JEUS_HOME/bin/logging.properties 설정되어 있다. logging.propertis 보면 JEUS default ConsoleHandler 사용하고, logging level INFO 임을 있다. handler 추가할 경우는 다음과 같이 콤마로 분리한다.

handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

또한 console 출력되는 log level 아래의 항목에서 지정할 있다.

java.util.logging.ConsoleHandler.level = FINE

FileHandler 사용할 경우, log 기본적으로 사용자 디렉토리에 출력되지만 경로나 출력 포맷 (XMLFormatter or SimpleFormatter)등을 지정할 있다.

java.util.logging.FileHandler.pattern = /home/main/MyLog.log

java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

ConsoleHandler 마찬가지로 log level 출력 포맷을 지정할 있고, 특정 class 에서의 log level 설정도 가능하다.

아래는 logging.properties 설정한 항목을 테스트 있는 예이다.

<<shbean.jsp>>

<%

        com.SHBean a = new com.SHBean();

%>

 

<<SHBean.java>>

package com;

import java.util.logging.*;

public class SHBean{

        Logger logger = null;

        public SHBean(){

                logger = Logger.getLogger(getClass().getName());

                logger.setLevel(Level.FINEST);

 

logger.info("info test");

                logger.severe("severe test");

                logger.fine("fine test");

                logger.finest("finest test");

 

        }

}

logging.properties 아래와 같이 설정할 경우,

<<logging.properties>>

handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

java.util.logging.FileHandler.pattern = /home/star/MyLog.log

java.util.logging.FileHandler.limit = 50000

java.util.logging.FileHandler.count = 1

java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

java.util.logging.ConsoleHandler.level = FINE

java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

...

아래와 같은 결과를 얻을 있다.

<<JeusServer_20080404.log>>

...

<<JeusServer_20080404.log>>

 

2008. 4. 4오후 6:11:16 com.SHBean <init>

정보: info test

2008. 4. 4오후 6:11:16 com.SHBean <init>

심각: severe test

2008. 4. 4오후 6:11:16 com.SHBean <init>

자세히: fine test


access log
비활성화

별도의 설정이 없을 경우 Web Container 1개의 access-log 생성된다. access log 에는 Context Group 대한 모든 요청과 사용자 접근에 관한 log 남는다. access log 기본 위치는, $JEUS_HOME/logs/<노드명>/<노드명>_<컨테이너명>/servlet/accesslog/<GroupName>/access.log 기본 log file이다.  

그런데 접근이 빈번한 사이트에서는 access log 양이 수가 있으므로 access logging 기능을 사용하지 않는 것이 좋다. access log default true 이기 때문에, $JEUS_HOME/config/<노드명>/<노드명>_servlet_<엔진명>/WEBMain.xml 에서 설정을 변경 있다. 아래와 같이 <logging><access-log><enable> false 하면 된다.

<<WEBMain.xml>>

<web-container xmlns="http://www.tmaxsoft.com/xml/ns/jeus">

    <context-group>

        ...

<logging>

<access-log>

<enable>false</enable>

...

참고해야 사항은 access log <valid-day> 명시하지 않으면 하나의 파일에 남기 때문에 1 단위로 출력하기 위해서는 위의 태그를 명시해야 한다.

 

log 파일경로변경

1. log home 변경

log home디렉토리 위치 변경은 $JEUS_HOME/bin/jeus 에서 -Djeus.log.home 추가하고 원하는 log 위치를 명시한다.

-Djeus.log.home=/home/main/logs      \

 

2. handler 사용할 file name설정

JEUS 4 버전까지는 전체적인 log home 경로 변경만 가능하였지만, JEUS 5에서는 사용자가 세부적인 log 대한 위치를 정할 있다. 다음과 같이<file-name>태그를 통하여 handler 사용할 file name 설정할 있다.

<<JEUSMain.xml>>

<jeus-system xmlns="http://www.tmaxsoft.com/xml/ns/jeus">

<node>

...

<system-logging>

          <level>INFO</level>

          <handler>

              <file-handler>

                  <name>handler1</name>

                  <level>FINEST</level>

                  <valid-day>1</valid-day>

<file-name>7/home/main/Mylog.log</file-name>

              </file-handler>

          </handler>

      </system-logging>

 

log4j API이용한 logging

JEUS에서 log4j 사용할 경우 log4j-1.xxx.jar 파일은 위치는 통상적으로 다음 경로에 있다.

- $JEUS_HOME/lib/application  ...

- context 아래의 WEB-INF/lib ...

- 임의의경로 : /home/main/log4j/log4j-1.xxx.jar

임의의경로에넣을경우, JEUSMain.xml <user-class-path> 태그에경로를설정함 ...

그리고 log4j.properties classpath 포함되는 디렉토리에 위치시키는데 다음과 같이 있다.

- $JEUS_HOME/lib/application  ...

- context 아래의 WEB-INF/classes ...

- 파일위치 : /home/main/log4j/log4j.properties

임의의경로에넣을경우, JEUSMain.xml <user-class-path> 태그에경로를설정함 ...

예를 들어 ①과 경로에 모두 log4j.properties 있는 경우 ①의 위치한 log4j.properties 실행된다.

log4j.properties 에서 아래와 같이 로그파일의 경로를 상대경로로 설정할 경우, JEUS restart 때마다 파일의 위치는 가변적이다. , restart 시점의 경로에 로그파일이 발생하게 된다.

<<log4j.properties>>

...

log4j.appender.dailyfile.Threshold = DEBUG

log4j.appender.dailyfile = org.apache.log4j.DailyRollingFileAppender

log4j.appender.dailyfile.File = logfile.log

log4j.appender.dailyfile.layout = org.apache.log4j.PatternLayout

by webgosu | 2009/06/11 23:36 | JEUS | 트랙백 | 덧글(0)

인코딩 - 8859_1의 비밀(?)

Open source로 구해지는 java source code를 들여다 보면 
하고 많은 문자셋들 중에 유독 '8859_1'을 많이 보게 된다.

'아니 저런 특정 문자셋을, 그것도 8비트밖에 지원하지 않는 문자셋을 코드에다 박아 버리면 
 쓰는 사람들은 어쩌란 거지?'

이런 생각이 들 때가 있을 것이다.
한때 나도 그랬었고..

그러나 정말 잘못 쓴 경우도 있겠지만, 많은 경우 '8859_1'의 사용은 나름 합리성을 띄고 있다.
이를 이해하려면 '8859_1'이 다른 문자셋들과 어떻게 다른가를 알아야 한다.

이전 글에서 언급했 듯이, '8859_1'은 1바이트에 해당하는 256개의 코드에 대해, 즉 0x00 ~ 0xff 까지의 모든 코드에 대해 대응되는 문자를 갖고 있다.

반면 8859_1보다 많은 문자를 거느리고 있는 'EUC-KR', 
이것의 확장형인 'MS949' 나 심지어 모든 글자를 다 포함한다고 여겨도 될 만한 'UTF-8' 조차
가진 문자는 확실히 많지만 모든 바이트 열에 대해 대응되는 문자를 갖고 있는 것은 아니다.

이를 확인하기 위해 다음을 실행해 보자.

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 256; i++) {
            for (int j = 0; j < 256; j++) {
                byte[] bytes = new byte[] {(byte) i, (byte)j };
                String str = new String(bytes, "MS949");
                if (str.charAt(0) == 0xfffd) {
                    System.out.println("for byte sequence{0x" + hex(i) + ", 0x" + hex(j)
                            + "} no character exists... getBytes()[0]=" + str.getBytes("MS949")[0]);
                } else if (str.length() > 1) {
                    // 첫 바이트를 하나의 글자로 인식. i만 취하고 j 루프는 중지.
                    System.out.println("For character{" + hex(i) + "} char = "
                            + str.charAt(0));
                    break;
                } else {
                    System.out.println("for character{" + hex(i) + ", " + hex(j)
                            + "} char = " + str);
                }

            }
        }
    }
    
    /*
     * byte 출력용.
     */
    public static String hex(int i ){
        String hex = Integer.toHexString(i); 
        return (hex.length() > 2) ? hex.substring(hex.length() - 2) : hex;
    }
주루룩 많은 행을 출력하지만 보면 대응되지 않는 글자가 존재함을 알 수 있다.

대략 그림으로 나타내면 다음과 같다.

인식하는 바이트 값이 0x~0x7f 일 경우에는 8859_x 에서 사용되는 글자를 그대로 쓰며 이 때는 한 바이트가 하나의 글자와 매핑된다.
바이트 값이 0x81 이상일 경우에는 그 다음 바이트가 필요하며, 두 바이트를 가지고 하나의 글자를 구성한다. 그리고 이 때 '없는 글자'가 생긴다.
당장 {0x81, 0x00} ~ {0x81, 0x40} 에 해당하는 값에 대해 대응되는 글자가 없다.
없는 글자는 java char로 0xfffd (아마도 UTF-16BE로 {0xff 0xfd} 에 매핑되는 글자) 로 저장되었다가, 다시 MS949로 인코드하면 0x63 글자로 매핑된다. 이 글자가 물음표 '?' 이다
 
모르는 글자를 인코드 할 때 0x63 코드를 매핑하는 것은 Sun JDK에서의 대응 방식이다.
모르는 글자에 대한 대응에는 표준이 없는지 다른 vendor - 이를테면 IBM - 의 JDK에서는 좀 다르게 구현하는 것 같다.
(한편 바이트 값이 0x80이나 0xff 같을 때 이를 디코드하면 그 한 바이트가 '모르는 글자 0xfffd'로 매핑된다. 일반화할 수 있는 규칙은 아닌 것 같다..)
 
다음과 같이 인코드 - 디코드를 많이 거치게 되면 인코드 할 때도, 디코드 할 때도 매핑이 불가한 경우를 만나게 되어 글자들이 깨진다. 이 때의 깨진 글자들은 복구가 절대 안 된다.
그래서 저런 식으로 부주의하게 인코드-디코드를 해 버리면 원래 호환되는 0x00~0x7f 이외의 한글 같은 글자들은 여지없이 깨져 버리고.. 되돌릴 수도 없게 된다.
 
그러나 8859_x 는 모든 바이트 코드에 대한 글자들을 구비하고 있으므로, 이해가 안 되는 이상한 글자로 매핑할 망정 코드를 보존하면서 디코드가 가능하다.
그래서 디코드만 하고, 이를 다시 인코드 할 경우에는 글자 깨짐이 발생하지 않는다.
 
8859_1 뿐만 아니라 8859_2 도 "보관"할 때 가지는 문자가 틀리지만 역시 깨짐 없이 바이트를 보존할 수 있다.
 
물론 그렇게 "보관"한 문자나 인코드가 원활히 되지, 아무 문자열이나 인코드를 하려 한다면
'자기 문자셋에 존재하지 않는 문자를 인코드'하는 경우가 발생해 글자가 깨질 것이다.
이를테면 아래와 같은 경우 당연히 문자셋에 없는 글자를 인코드하려 하므로 글자가 깨진다.
이렇게 되면 '원래 문자열이 2글자였다' 정도 외엔 아무 정보도 남지 않게 된다. (JDK vendor에 따라서는 이마저도 알 수 없게 될 것이다)
 
-----------------------------
 
실제 네트워크를 오가는 데이터는 바이트열의 형태이지만
이를 프로그래밍 언어에서 다룰 때는 문자열로 간주하고 작업할 때가 많다.
그게 편하기 때문이기도 하고,
문자열로서 의미를 가지는 경우가 많기 때문이기도 할 것이다.
 
가장 많이 쓰이는 경우가 웹 어플리케이션에서의 파일 다운로드, 아마도 그 다음이 소켓통신 (헤더를 읽어들이거나 생성할 때) 같은 경우일 것이다.
<< 다운로드 시 설정>>

response.addHeader("Content-disposition", "attachment;filename=" + ... + "" );

이 때 인코딩/디코딩 작업이 필요한데, 디코드 시 바이트들을 깨뜨리지 않고 문자열로 얻고 싶다면 '8859_x'을 쓰는 것이 현명한 방책이라 하겠다.

물론 그 중에서도 많은 서버들이 위의 filename 을 ISO-Latin1(혹은 Latin1, 8859_1) 로 인코딩 해 보내기 때문에 같은 Latin 계열이라도 '8859_1' 즉 'Latin1'을 택하는 것이 좋다.
이는 표준이라고 하는데 문서 확인은 안 해 봤다. (어디 있는지 찾기 정말 힘들던데..)

by webgosu | 2009/03/26 16:59 | 트랙백 | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶