제4장 고급 설정

내용 목차

4.1. 동적 콘텐츠를 위한 설정
4.1.1. CGI
4.1.2. SSI
4.1.3. PHP
4.2. Virtual Hosting
4.2.1. Virtual Host 구조
4.2.2. Mass Virtual Host
4.3. 로그 설정
4.3.1. 로그 파일
4.3.2. Log Format
4.3.3. Common Log Format
4.3.4. 환경 설정
4.4. Tmax 연동
4.4.1. Tmax 연동을 위한 환경설정
4.4.2. 사용예
4.5. JEUS 연동
4.5.1. WebtoB와 JEUS 연결의 특징
4.5.2. JEUS 6 연동 설정(Base+)
4.5.3. 내장 Servlet Engine(JEUS 7) 연동 설정(Enterprise)
4.6. 다른 WAS 연동
4.6.1. WebtoB의 Reverse Proxy를 통한 WAS 연결의 특징
4.6.2. 다중 WAS 연동 설정(Enterprise+)
4.7. URLRewrite
4.7.1. WebtoB 설정
4.7.2. URLRewriteConfig 파일 설정
4.7.3. RewriteCond
4.7.4. RewriteRule
4.7.5. 예제
4.8. Filter 모듈 개발(Enterprise+)

본 장에서는 앞에서 살펴본 기본적인 설정 외에 특수한 작업을 하기 위한 설정에 대하여 설명한다.

4.1. 동적 콘텐츠를 위한 설정

웹 서버가 설치되면 HTML을 이용한 서비스가 가능하다. 즉, WebtoB의 Document Root Directory에 HTML 문서를 두면 브라우저로 호출하여 열람이 가능하다. 본 절에서는 CGI, SSI, PHP를 사용하기 위한 설정과 간단한 예제를 통해 그 설치 예에 대해 설명한다.

4.1.1. CGI

CGI(Common Gateway Interface)는 웹에서 HTML은 의해 여러 가지 정보를 표현하고 홈 페이지를 만드는 기초가 되는 언어이다. 하지만 HTML만으로 다양한 정보를 처리할 수 없고 서버로부터 클라이언트에게 단방향의 정보만 제공한다. 이러한 단점을 보완하기 위해 외부 프로그램을 수행하여 그것의 결과를 HTML 형태로 보여주는 방식이 도입되었다. CGI는 외부 프로그램과 웹 서버 간의 연결 역할을 한다.

넓은 의미로 CGI는 수행하는 외부 프로그램을 포함하여 말하기도 한다. 예를 들어, 홈 페이지에 방문객들의 comment를 받을 수 있는 방명록을 만들 때 웹에서 구현하는 HTML만으로는 해결할 수 없다. 그래서 외부 프로그램이 필요한데, 이때 외부 프로그램과 웹 서버 간에 서로 주고받을 수 있는 규약을 CGI라고 하고, 사용하는 프로그램을 흔히 CGI 프로그램(혹은 CGI 스크립트)이라고 한다. CGI 프로그램은 통상적으로 C/C++이나 Perl 혹은 UNIX 쉘, Tcl/Tk 등을 사용하여 구현한다.

홈 페이지를 interative한 형태로 만들 수 있는 CGI 프로그램의 종류는 매우 다양하고 표준화되어 있다. 방문객 카운터나 방명록뿐만 아니라 웹 게시판, 웹 대화방, 검색엔진, 다양한 배너 보여주기, 업로드가 가능한 자료실, 폼을 이용하여 메일을 띄우는 폼 메일(Form Mail) 등이 CGI 프로그램의 예이다.

CGI는 외부 프로그램이 수행되는 방식이기 때문에 프로그램 자체에 문제가 없다면, 다른 곳에 서로 이식할 수 있다. 어떤 웹 서버에서 동작하는 CGI라면 다른 웹 서버도 문제없이 동작한다. WebtoB 역시 다른 웹 서버와 같은 방식으로 처리하기 때문에 CGI 수행에는 전혀 지장이 없다.

CGI를 제작하는 방법은 매우 다양하고, 여러 가지 방법이 있기때문에 본 안내서에서 깊은 내용을 언급하지는 않고 WebtoB에서 CGI를 사용하기 위한 설정 방법에 대해서만 설명한다.

CGI 설정

CGI 사용을 위해 다음의 각 절에 해당 내용을 설정해야 한다.

  • SVRGROUP 절

    SVRGROUP 절에 CGI 사용을 위한 내용을 설정한다. 설정된 내용은 SERVER 절에서 서버 그룹을 설정하는 데 사용된다.

    다음은 SVRGROUP 절 설정에 대한 예제이다. SvrType 항목을 CGI로 설정하면 서버 그룹은 CGI를 처리한다.

    *SVRGROUP
    cgig       NodeName = mynode, 
               SvrType = CGI
  • SERVER 절

    SERVER 절에 서버 프로세스를 설정한다. 다음은 SERVER 절 설정에 대한 예제이다.

    *SERVER
    cgi        SvgName = cgig, 
               MinProc = 10, 
               MaxProc = 10

    cgi라는 이름의 서버 프로세스가 기동된다. SvgName을 SVRGROUP 절에 설정한 cgig로 설정해서 cgi라 명명된 현재의 서버 프로세스는 cgig라는 서버 그룹에 종속된다. cgig가 SvrType이 CGI로 설정되어 있기 때문에 cgi 서버는 CGI 서비스를 한다.

  • URI 절

    URI 절의 설정을 통해 특정 URI의 요청을 CGI로 처리하도록 설정한다. 다음은 URI가 "/cgi-bin/"로 시작할 경우 CGI로 간주하여 처리하도록 설정한 예제이다.

    *URI
    uri1       Uri = "/cgi-bin/",   
               SvrType = CGI

  • ALIAS 절

    ALIAS 절에 특정 URI에 대해서 실제로 처리하게 되는 물리적인 경로를 설정한다. 해당되는 경로가 DocRoot가 아닌 다른 위치에 있을 경우에만 설정한다.

    다음은 ALIAS 절 설정에 대한 예제이다.

    *ALIAS
    alias1     Uri = "/cgi-bin/",
               Realpath = "${WEBTOBDIR}/cgi-bin/"

4.1.2. SSI

본 절에서는 SSI의 이용 방법과 설정 방법에 대해서 설명한다.

SSI의 이용

SSI(Server Side Includes)은 HTML 페이지에서 다이내믹한 문서를 만들때 유용하게 사용할 수 있다. 예를 들면 Header 파일 등을 더할 수도 있고, 파일의 마지막 수정시간(Last Modified Tiem)을 자동으로 조절할 수 있는 기능들을 문서에 포함시킬 수도 있다.

SSI는 HTML 문서에 'command'를 집어 넣어 사용할 수 있으며, 서버에서는 SSI 문서를 읽어 들이고, SSI 명령어를 찾아보고 그에 맞는 기능을 수행한다. 예를 들면 파일의 Last Modification Time을 수정하는 SSI 명령어가 문서에 포함되어 있으면, 서버는 파일로부터 명령어들을 읽어 들여 명령을 수행하여 파일의 마지막 수정시간을 갱신한다.

WebtoB에서 기본 설정은 HTML 파일 안에 SSI 명령어를 포함하고 있지 않다. 왜냐하면, HTML 파일을 매일 액세스하는 곳에서는 이로 인하여 HTML이 오히려 느리게 작동하기 때문이다. SSI가 필요해서 사용하기 원한다면 WebtoB 환경 파일에 SSI를 위한 서버를 추가로 설정해야 한다.

다음은 SSI를 사용하기 위한 환경설정 예이다.

*SVRGROUP
ssig         NodeName = mynode, SvrType = SSI

*SERVER
ssi          SvgName = ssig, MinProc = 10, MaxProc = 10

SSI Commands

모든 SSI 명령어는 HTML 문서 안에 HTML comments 형식으로 저장되어야 한다.

모든 명령어는 다음 형식을 따르며, 명령어 전체는 comment "<!--... -->"로 처리되어야 한다. arg1, arg2는 인수고 나머지 value1, value2는 인수의 값을 나타낸다.

 <!--#command arg1="value1" arg2="value2" ... -->

다음은 SSI 사용 방법이다. flastmod 명령어는 수정시간을 출력하라는 뜻이고 Value로는 nextel.html이 사용된다. 'file'은 인수가 되는 것이고 'nextel.html'은 값이 된다.

 <!--#flastmod file="nextel.html"-->

다음은 명령어는 인수 이름에 따라 다르게 실행되는 예이다.

 <!--#flastmod virtual="/" -->

echo 명령어로 서버 홈 페이지의 마지막 수정시간을 얻을 수 있다. SSI 명령어가 실행될 때 'environment variables' 값이 설정된다. CGI variables을 포함하고 있고(REMOTE_HOST etc), DOCUMENT_NAME 그리고 LAST_MODIFIED 등을 가지고 있다.

<!--#echo var="LAST_MODIFIED" -->

4.1.3. PHP

본 절에서는 PHP의 이용 방법과 설정 방법에 대해서 설명한다.

PHP의 이용

PHP는 Perl과 유사한 형태의 스크립트 언어로 간편성과 성능으로 인하여 많이 이용되고 있다. 속도, 개발 편의성, 여러 가지 확장 기능 면에서 기존의 Perl보다 발전된 언어로 Linux나 UNIX 계열뿐만 아니라, WIN32용 바이너리 파일을 제공해 Microsoft 계열의 웹 서버에서도 사용된다. PHP는 운영체제에 독립적인 웹 프로그램 개발이 가능한 것이 큰 장점이다.

PHP는 CGI 프로그램에서 할 수 있는 form data를 가져오고 동적인 웹 페이지를 만들거나, Cookie를 보내고 받는 모든 기능의 구현이 가능하다.

PHP의 설정

WebtoB에서 PHP를 이용하기 위해서는 설치 작업이 필요하다. HTML이나 CGI를 이용하는 것과 유사하기 때문에 쉽게 적용할 수 있다.

  • SVRGROUP 절

    PHP에 관련된 그룹을 설정하고 이를 SEVER 절에서 다시 정의한다.

    SVRGROUP 절에 ScriptLoc 항목이 추가되는데, 이는 PHP의 실제 실행 모듈이 있는 위치이다. PHP 모듈이 있는 곳의 경로는 ${WEBTOBDIR}로부터의 상대 경로를 설정해야 한다. ScriptArgs 항목을 설정하여 PHP의 실행 모듈듈을 실행할 때 적용할 옵션을 지정할 수 있다. php.ini 파일등을 지정할 때는 절대 경로를 사용해야 한다.

    다음 예제에서 ScriptLoc에 설정된 모듈 경로는 절대 경로가 아니라 "${WEBTOBDIR}/cgi-bin/php"를 의미이며, ScriptArgs에 설정된 경로는 실제(절대)경로를 의미한다.

    *SVRGROUP
    phpg          NodeName = mynode,
                  ScriptLoc = "/cgi-bin/php", # "${WEBTOBDIR}/cgi-bin/php"를 의미
                  ScriptArgs = "-c /php_conf/php.ini", # php 실행시 실행모듈에 대한 옵션
                  SvrType = PHP
    
    *SERVER
    php           SvgName = phpg, MinProc = 10, MaxProc = 10

php3 모듈을 사용하는 경우에는 부가적인 설정이 필요하다. php4는 기본적으로 php라는 확장자를 이용하기 때문에 추가 설정이 필요하지 않으나, php3는 확장자가 ".php3"이기 때문에 파일을 사용하기 위해서 EXT 절에 추가해 주어야 동작한다. 다음은 EXT 절 설정에 대한 예제이다.

*EXT
php3          Mimetype = "application/x-httpd-php3",
              SvrType = PHP

PHP 예

다음의 순서로 PHP의 설치 및 WebtoB에서의 설정이 정상적인지 확인한다.

  1. ${WEBTOBDIR}/docs에 다음과 같이 "phpinfo.php"를 만든다.

    <?
      Phpinfo();
    ?>
  2. 브라우저에서 다음과 같이 요청한다. 해당 페이지는 설치된 PHP에 대한 각종 환경정보를 나타낸다.

    http://<IP address>:<PORT>/phpinfo.php

    [그림 4.1] PHP 테스트 페이지

    PHP 테스트 페이지

4.2. Virtual Hosting

본 절에서는 Virtual Host의 개념과 사용 방법에 대해서 설명한다.

4.2.1. Virtual Host 구조

가상 호스트(Virtual Hosting)는 현재 HTTP 1.1을 지원하는 브라우저에서 적용할 수 있는 웹 서버의 기능으로 하나의 웹 서버를 이용하여 마치 여러 대의 웹 서버가 운영되고 있는 것과 동일한 효과를 낼 수 있다.

예를 들어, "WebtoB Times"라는 이름으로 신문사 홈 페이지를 운영 중이고, 메인 홈 페이지와 사회면 기사를 다루는 홈 페이지, 스포츠 기사를 다루는 홈 페이지를 도메인 이름으로 구분하여 서비스한다고 가정한다. 이 서비스를 하나의 IP 주소와 도메인 이름, 그리고 1대의 웹 서버를 이용해서 운영하려고 할 경우 Virtual Host 기능을 사용한다.

다음 같이 도메인 이름을 분리하여 HTML 문서도 만들고 기타 서비스도 제공한다.

  • webtobtimes.com: 메인 페이지

  • society.webtobtimes.com: 사회면 기사를 다루는 섹션

  • sports.webtobtimes.com: 스포츠 기사를 다루는 섹션

웹 서버에서는 위와 같은 설정을 적용하기 위해 2개의 Virtual Host를 할당하여 각각 society와 sports에 적용해 주면 된다. 이렇게 하면 이들 서비스는 메인 페이지와는 다른 웹 서버에서 운영되는 것과 같은 효과를 줄 수 있으며, 실제 웹 서버 내에서도 문서의 경로 및 기타 모든 설정들을 분리하여 사용할 수 있다. 이렇게 도메인 이름을 분리하여 하나의 IP 주소로 서비스하는 방식을 Name Based Virtual Host라고 한다.

이와 구별되는 방식으로 IP Address Based Virtual Host가 있는데, 이 방식은 다른 IP 주소를 사용하므로 사실상 별개의 도메인이라 할 수 있다. 하나의 사이트가 다량의 IP 주소를 확보하기는 힘들어 크게 사용되지 않는 방식이다.

다음은 위 의 예에서 구상한 Virtual Host의 구조이다. 하나의 IP와 1대의 웹 서버를 이용해 각 도메인의 서비스를 할 수 있으며, 동일 IP에 다른 이름으로 호출된 서비스를 WebtoB의 Virtual Host가 구분하여 서비스할 수 있다.

[그림 4.2] Virtual Host의 구조

Virtual Host의 구조

다음은 위의 "WebtoB Times"는 가상 홈 페이지를 WebtoB에서 구축한 Virtual Host의 설정 예제로 VHOST 절을 적절히 이용해 주면 효과적인 웹 운영이 가능하다.

*VHOST
society
    Docroot = "society_docs/",
    NodeName = webtob,
    Hostname = "society.webtobtimes.com",
    Port = "8080",
    IconDir = "society_icons/",
    LOGGING = "society_accesslog",
    ERRORLOG = "society_errorlog"

sports
    Docroot = "sports_docs/",
    NodeName = webtob,
    Hostname = "sports.webtobtimes.com",
    Port = "8080",
    IconDir = "sports_icons",
    LOGGING = "sports_accesslog",
    ERRORLOG = "sports_errorlog"

4.2.2. Mass Virtual Host

대량의 Virtual Host를 설정함에 있어 각각의 설정이 비슷한 경우 일일이 설정하지 않고 보다 간편하게 이용할 수 있는 설정 방법이 있다.

  • DocRoot 항목 설정

    대량의 Virtual Host에 있어서 DocRoot 설정만 다른 경우 이용할 수 있는 기능으로 각 Virtual Host의 DocRoot는 해당 서버의 도메인 이름 값을 디렉터리 설정 패턴으로 치환함으로서 결정한다.

    Docroot = <literal>    (Default : "docs/")

    예를 들어 클라이언트에서 http://www.tmax.co.kr로 요청했을 때 이 Virtual Host의 DocRoot를 "${WEBTOBDIR}/docs/www/"로 사용하고 싶을 경우 다음과 같이 설정하면 된다. 마찬가지로 http://webtob.tmax.co.kr로 접속하였다면 DocRoot는 "${WEBTOBDIR}/docs/webtob/"가 된다.

    *VHOST
    TmaxSoft
        NodeName = tmax,
        Hostname = "www.tmax.co.kr"
        HostAlias = "webtob.tmax.co.kr"
        Port = "80",
        Docroot = "${WEBTOBDIR}/docs/%1/"

  • Realpath 항목 설정

    여러 개의 Virtual Host를 사용할 때 ALIAS 절의 Realpath를 설정한다. 서버의 도메인 이름 값을 디렉터리 설정 패턴으로 치환함으로써 RealPath 경로를 설정할 수 있다.

    Realpath = <literal>    (Default : mandatory)

    DocRoot를 설정했을 경우와 마찬가지로, "%1"이 클라이언트가 요청한 도메인의 첫 번째 항목으로 치환된다.

    *ALIAS
    alias1        Uri = "/cgi-bin",
                  Realpath = "${WEBTOBDIR}/docs/%1/cgi-bin/"

다음은 디렉터리 설정 패턴에 사용되는 "%" 지시자에 대한 설명이다. 지시자를 사용해서 디렉터리 설정 패턴을 동적으로 설정할 수 있다.

지시자설명
%p요청한 포트 번호로 치환한다.
%nHostname이나 IP 주소의 n번째 요소로 치환한다. 만약 n을 0으로 하면 전체 문자열이 사용된다. 마이너스 기호(-)가 앞에 오면 Hostname이나 IP 주소의 끝에서부터 센다. 플러스 기호(+)가 뒤에 오면 Hostname이나 IP 주소의 나머지가 사용된다.
%n.mn번째 요소의 m번째 문자로 치환한다. 위와 같이 마이너스 기호(-)나 플러스 기호(+)가 붙을 수 있다.
%%단일 퍼센트(%) 표시로 치환한다.

참고

"%" 지시자를 사용하고자 하는 경우 DocRoot/Realpath를 절대 경로로 설정해야 한다. ${env}를 사용할 경우 치환된 경로가 최종적으로 절대 경로면 "%"지시자를 사용할 수 있다.

4.3. 로그 설정

본 절에서는 로그 파일에 대한 개념과 각 포맷별 로그 파일에 대해서 설명한다.

4.3.1. 로그 파일

WebtoB는 웹 서비스에 대한 요청과 응답 등 서비스 관련된 기록을 모두 환경설정에서 지정한 로그 파일에 저장한다. 따라서 로그 파일을 보면 누가 언제 무엇을 요청했고 또 무엇을 가져갔는지 알 수 있으며 웹 서버에 얼마나 많은 접속이 있었는지 가장 많이 보는 페이지는 무엇인지 등을 알 수 있다.

로그 파일은 환경설정에 설정한 위치에 저장되며 웹 서버를 운영할 때 임의의 위치에 저장이 가능하다. 로그를 남기는 과정은 시스템 측면과 Capacity 측면에서 서버에 어느 정도의 부하를 줄 수 있다.

  • 시스템 측면에서 로그는 디스크에 기록하는 작업을 해야 하기 때문에 로그를 남기지 않는 것에 비해 속도가 약간 느려지게 된다. WebtoB에선 내부적으로 효율적인 방법을 이용하지만, 한계가 있는 관계로 약간의 속도 저하는 발생할 수 있다.

  • Capacity 측면에서는 로그를 남기는 공간에 대한 부하를 고려해야 한다. 접속자가 적은 곳에서는 로그 파일의 크기가 작겠지만, 접속자가 아주 많은 곳에서는 하루에 로그 파일이 몇 백 Mbytes에서 수 Gbyte에 이르는 로그를 남길 수 있다. 시스템에 적당한 공간이 남아있지 않다면 불가능하기 때문에 이에 대한 관리가 중요하다.

로그 파일은 웹 서버 관리자에게는 중요한 정보이다. 운영하는 웹 서버에 접속한 사용자의 정보를 바탕으로 좀 더 효율적인 웹 서비스를 구현할 수도 있고 쇼핑몰 운영자에게는 고객들의 정보를 알 수 있는 아주 귀중한 자료이다. 따라서 WebtoB를 이용하는 운영자들은 로그 파일을 특정 위치에 저장하고 관리한다.

WebtoB는 여러 개의 로그 파일을 생성하는데, 사용자 요청과 관련된 액세스 로그와 요청 처리 중 오류 메시지와 관련된 에러 로그, WebtoB 시스템을 위한 시스템 로그로 나누어진다.

구분설명
액세스 로그

액세스 로그는 Transfer 로그라고도 한다. 사용자의 요청과 관련된 일반적인 사항을 기록하며, 사용자가 보낸 요청과 관련된 정보와 서버에서 어떤 응답을 보냈는지 등에 관련된 정보를 알 수 있다. 그러므로 이 정보는 차후에도 많은 이용가치가 있기 때문에 아주 중요하다.

WebtoB의 NODE, SVRGROUP, VHOST 절 등에 모두 설정이 가능하다. 각 절에 모두 설정했을 경우 접속자의 접속 서비스 요청에 따라 그 우선순위가 SVRGROUP, VHOST, NODE 절 순서로 적용된다. 가장 우선순위가 높은 절에 해당하는 로그 파일에 그 내용이 기록된다.

에러 로그에러 로그는 사용자 요청을 처리하는 과정에서 발생한 오류에 대해서 기록한다.
시스템 로그시스템 로그는 WebtoB를 운영 중에 발생한 이벤트를 기록한다. WebtoB를 운영하는 중 문제가 생긴 경우 문제 해결에 큰 도움이 될 수 있는 정보를 제공하게 된다. 따라서 중요한 업무를 수행하는 경우에는 시스템 로그를 저장하여 서버 운영에 문제가 생길 경우 로그를 통하여 문제 해결을 쉽게 할 수 있다. 시스템 로그는 NODE 절에서 설정 가능하다.

4.3.2. Log Format

WebtoB는 LOGGING 절의 Format 항목 설정을 통해 다양한 형태로 액세스 로그를 남길 수 있다.

보통의 경우 Common Log Format(CLF)을 사용하는데, 이는 NCSA 계열의 웹 서버에서 사용하는 Log Format으로 대부분의 웹 서버에서 기본으로 사용하는 Log Format이다. WebtoB에서는 이를 "default"라는 이름으로 제공한다.

4.3.3. Common Log Format

W3C에서 정의하고 있는 Common Log Format은 다음과 같다.

remotehost rfc931 authuser [date] "request" status bytes 

다음의 항목 순서로 로그를 생성해서 WebtoB 환경 파일에 지정된 위치에 저장한다.

항목설명
remotehost

Remote Host 이름을 저장한다(DNS Host 이름을 사용할 수 없거나 DNSLookup이 off이면 IP 주소를 입력한다).

Remote Host에 대한 자세한 내용은 http://www.w3.org/Daemon/User/Config/General.html-%20DNSLookup을 참고한다.

rfc931사용자의 Remote 로그 이름을 저장한다.
authuser인증된 사용자의 사용자 이름을 저장한다.
[date]요청한 날짜와 시간을 저장한다.
"request"클라이언트가 요청한 내용을 저장한다.
status

클라이언트로 응답한 HTTP Status Code를 저장한다.

Status Code에 대한 자세한 내용은 http://www.w3.org/Protocols을 참고한다.

bytes전송한 문서의 콘텐츠 길이를 저장한다.

다음은 WebtoB에서 저장하여 기록하는 로그 파일의 예이다.

143.248.148.42 - - [13/Feb/2001:16:46:13 +0900] "GET / HTTP/1.1" 304 -
143.248.148.42 - - [13/Feb/2001:16:46:14 +0900] "GET /index_pb.gif HTTP/1.1" 304 -
143.248.148.42 - - [13/Feb/2001:16:46:18 +0900] "GET /index.html HTTP/1.1" 200 7118
143.248.148.42 - - [13/Feb/2001:16:46:18 +0900] "GET /usage.png HTTP/1.1" 304 -
143.248.148.42 - - [13/Feb/2001:16:46:37 +0900] "GET /usage_200102.html HTTP/1.1" 404 148
143.248.148.42 - - [13/Feb/2001:16:47:21 +0900] "GET /index.html HTTP/1.1" 304 -
143.248.148.42 - - [13/Feb/2001:16:47:21 +0900] "GET /usage.png HTTP/1.1" 200 2509
143.248.148.42 - - [13/Feb/2001:16:47:24 +0900] "GET /usage_200102.html HTTP/1.1" 404 148
143.248.148.42 - - [13/Feb/2001:16:47:55 +0900] "GET /index.html HTTP/1.1" 304 -
143.248.148.42 - - [13/Feb/2001:16:47:55 +0900] "GET /usage.png HTTP/1.1" 304 -
143.248.148.42 - - [13/Feb/2001:16:47:57 +0900] "GET /usage_200102.html HTTP/1.1" 200 30798

위의 로그 내용에서 맨 앞은 접속한 사용자의 IP 주소를 나타낸 것이고, 뒤의 하이픈(-)들은 각각 rfc931과 AuthUser를 기록해야 한다. 그러나, 사용자에 관련된 정보가 없기 때문에 하이픈(-)으로 기록한다.

뒤에 [ ] 안에 있는 정보가 사용자가 접속한 시간을 나타낸 것이고, 그 뒤에 따옴표("")안의 정보는 사용자 요청 중 HTTP 프로토콜의 Request Line이다. Request Line 뒤의 숫자는 그에 해당하는 Response Status Code이다. 그리고 마지막으로 나타나는 숫자는 사용자에게 서버가 전달한 Byte 수이다.

4.3.4. 환경 설정

WebtoB에서 Log Format은 LOGGING 절에 Format 항목에 설정한다.

WebtoB에서 위와 같은 로그를 저장하기 위해서는 다음과 같이 환경설정을 해야 한다.

*NODE
webmain
    WebtoBDir = "$WEBTOBDIR",
    SHMKEY = 69000,
    DOCROOT = "docs/",
    Port = "5469",
    Logging = "accesslog",
    ErrorLog = "errorlog"

*LOGGING
accesslog
    Format = "default",
    Filename = "log/access.log",
    Option = "Sync"
errorlog
    Format = "",
    Filename = "log/error.log",
    Option = "Sync"

NODE 절에 Logging이라는 항목이 바로 액세스 로그를 기록하기 위한 것이다. 이에 대한 설정은 LOGGING 절에서 설정한 "accesslog"로 설정되어 있다. 에러 로그는 ErrorLog라는 항목으로 설정된다. 위의 예에서는 LOGGING 절에서 설정한 "errorlog"로 설정되어 있다.

Format 항목은 다음과 같은 지시자를 사용하여 사용자가 원하는 형태로 액세스 로그를 저장할 수 있다.

포맷설명
DEFAULT

Default Log File Format이다.

(약자: "%h %t \"%r\" %s %b %D")

COMMON

Common Log File Format이다.

(약자: "%h %l %u %t \"%r\" %s %b")

COMBINED

Combined Log File Format이다.

(약자: "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\")

%a요청을 보낸 장비의 IP 주소를 표시한다. %h와 동일하다.
%b응답의 Byte를 표시한다.
%cWebtoB 내부 캐시에서 응답이 생성되었는지를 표시한다. 이 경우 "hc"로 표시한다.
%{_attr_name_}CHTTP Request의 Cookie Header 값 중 '_attr_name_'에 해당하는 값을 표시한다.
%d응답이 전송된 시간을 표시한다.
%D요청을 처리하는 데 소요된 시간을 표시한다. (단위: millisecond)
%{ENV_NAME}e환경변수 ENV_NAME을 출력한다.
%gWebtoB가 내부적으로 사용하는 요청 식별자를 출력한다.
%h요청을 보낸 장비의 IP 주소를 표시한다.
%H사용한 HTTP 버전을 표시한다.
%{HEADER_FIELD}iHTTP Request의 HEADER_FIELD Header 값을 표시한다.
%{_id_name_}J

요청을 JEUS로 포워딩하여 처리하는 경우 내부적으로 사용하는 요청의 식별정보를 표시한다.

  • _id_name이 JSVCid이면 Client ID이다.

  • _id_name이 JSVReqSeq이면 Request Sequence이다.

%mHTTP Request 메소드를 표시한다.
%pRequest가 도착한 서버의 포트 번호를 표시한다.
%qHTTP Request의 query 값을 표시한다.
%rHTTP Request의 Request line 전체를 표시한다.
%RHTTP Request의 Request line 전체를 표시한다. CheckURL이나 URLRewrite 기능에 의해 변경된 Request line을 표시한다.
%s응답에 사용된 HTTP Status Code를 표시한다.
%t요청처리를 마친 시간을 표시한다.
%TRequest를 처리하는 데 소요된 시간을 표시한다. (단위: 초)
%uHTTP 인증에 사용된 user 이름을 표시한다.
%UHTTP Request URI를 표시한다.
%vHost Header 필드 값을 표시한다.
%z응답이 압축된 경우 압축 전/후의 응답 크기와 압축률을 표시한다.

CLF에 해당되는 "%h %l %u %t \"%r\" %s %b"는 "default"라는 이름으로 제공한다. 위의 예에서 보면 액세스 로그는 "default"로 설정되어 있으므로 실제로 적용되는 Log Format은 CLF를 준수하는 형태로 로그에 기록된다.

또한, %d 옵션과 함께 { }안에 strftime 함수에서 제공하는 날짜 및 시간의 여러 가지 형식을 지정할 수 있다. 기본값은 %t와 동일하게 "[13/Feb/2001:16:47:24 +0900]"와 같은 형태로 기록된다.

지시자를 사용하여 다음과 같은 형태의 Format을 만들어 낼 수 있다.

custom_log1
    Format = "%h %l %u %t \"%r\" %s %b", 
    Filename = "log/custom1.log"
custom_log2
    Format = "[%{%Y.%m.%d %H:%M:%S}d] %a \"%r\" %s %T", 
    Filename = "log/custom2.log"

4.4. Tmax 연동

WebtoB는 aps 라이브러리를 이용하여 TP-Motinor 제품 Tmax와 연동이 가능하다. Tmax와 연동을 위해서 Tmax를 별도로 설치해야 한다.

WebtoB에서는 WBAPI를 이용하여 클라이언트 프로그램만 작성하며 서버 프로그램은 Tmax에 있는 것을 사용한다. 즉, WebtoB의 클라이언트 프로그램에서 Tmax의 서버 프로그램으로 요청을 보내고 그 응답을 받아와서 WebtoB의 클라이언트(웹 브라우저)로 결과에 대한 응답을 줄 수 있다.

4.4.1. Tmax 연동을 위한 환경설정

Tmax와 연동은 WBAPI를 이용하는 것이므로 환경 파일 작성 방법 역시 그와 동일하다.

다음은 환경 파일의 예이다.

<apsl.m>

*DOMAIN
webtob_apsl

*NODE
tmaxi2
    WebtoBDir="$WEBTOBDIR", 
    SHMKEY = 74125,
    Docroot = "docs/",
    Port = "8797", 
    HTH = 1,
    Logging = "log1",
    AppDir = "ap/",
    ErrorLog = "log2"

*SVRGROUP
htmlg    NodeName = "tmaxi2", SvrType = HTML
webapg  NodeName = "tmaxi2", SvrType = WEBSTD

*SERVER
wbsvrinit  SvgName = webapg, MinProc = 10, MaxProc = 10
wbquery    SvgName = webapg, MinProc = 10, MaxProc = 10 
wbsession  SvgName = webapg, MinProc = 10, MaxProc = 10 

*SERVICE
test       SvrName = wbsvrinit
query      SvrName = wbquery
wbsession  SvrName = wbsession

*URI
uri1      Uri = "/svct/", SvrType = WEBSTD

*LOGGING
log1
    Format = "default",
    Filename = "log/access.log",
    Option="Sync"
log2
    Format = "",
    Filename = "log/error.log",
    Option="Sync"

4.4.2. 사용예

위에 제시한 apsl.m에 해당하는 클라이언트 프로그램과 사용에 대한 내용은 “Appendix C. Tmax 연동”을 참고한다.

4.5. JEUS 연동

WebtoB는 차세대 웹 애플리케이션 서버(Web Application Server : WAS)인 JEUS와 연동되어 일반 웹 서버에서 제공하지 못하는 기능들을 구현할 수 있다. 일반적인 웹 서비스를 포함한 전자상거래에서는 보안과 트랜잭션 등이 반드시 보장되어야 한다. 또한 대용량의 데이터를 다루는 일이나 사용자의 관리 등의 측면에서 웹 애플리케이션 서버인 JEUS를 이용하는 것이 바람직하다.

설정 방법에 있어서 WebtoB Base 이상에서 제공되는 JEUS와의 연동 방법과 WebtoB Standard에서 제공되는 내장 Servlet Engine과의 연동 방법은 JEUS 버전별 항목 이름에만 다소 차이가 있으며 기본 원리는 동일하다.

WebtoB와 JEUS 연동을 위해 설정해야 할 파일은 다음과 같다

  • WebtoB 환경 파일 (예: http.m)

  • JEUS 환경 파일 : WEBMain.xml

WebtoB와 JEUS 연동을 위해 서로의 값을 똑같이 설정해야 하는 항목은 다음과 같다.

  • WebtoB-JEUS 간 연결 포트 번호

  • HTH 수

  • 서버 이름(WebtoB의 JSV 설정 서버이름과 JEUS의 Registration ID)

  • 프로세스 수(WebtoB의 MinProc/MaxProc와 JEUS의 Thread-pool 수)

4.5.1. WebtoB와 JEUS 연결의 특징

WebtoB와 JEUS의 연결은 JEUS가 WebtoB에게 연결하는 구조로 되어 있다. WebtoB는 외부 네트워크에서 서비스하고, JEUS는 내부 네트워크에서 운영할 경우 유용하다. 그 이유는 내부 네트워크의 방화벽에서 in-bound로 연결되는 것을 엄격히 관리하지만, out-bound 연결은 관대하게 관리하기 때문이다.

JEUS가 WebtoB에 연결하는 경우 WebtoB가 먼저 기동하고 WebtoB가 JEUS의 연결을 기다리고 있는 상태에서 JEUS를 기동할 것을 권장한다. JEUS는 기동하면서 WebtoB와 연결하게 되는데, 만약 WebtoB가 기동되지 않은 경우 주기적으로 연결을 재시도된다. JEUS가 연결을 재시도할 때 마다 JEUS의 로그에 에러 메시지가 기록된다. 연결에 성공하면 JEUS의 로그에 연결이 성공되었다는 메시지가 저장되고, 이후 Servlet이나 JSP 등 JEUS의 Servlet Engine을 이용해야 하는 사용자의 요구는 이 연결을 통해서 JEUS에 전달되어 처리된다. 그리고 WebtoB는 그 결과를 받아 클라이언트에게 전송해 준다.

WebtoB와 JEUS와의 연결은 persistent connection이므로 중간에 네트워크 오류나 서버의 문제가 생기지 않는 이상은 연결을 끊지 않는다.

4.5.2. JEUS 6 연동 설정(Base+)

비교적 간단한 비즈니스 로직을 수행하는 중소규모의 온라인 서비스를 제공하고자 할 경우에는 WebtoB Servlet Engine과의 연동만으로도 서비스가 가능하지만, 대규모의 전자상거래 시스템을 구축하려 한다면 WebtoB와 JEUS을 연동하여 이용하는 것을 권장한다.

참고

본 절에서는 JEUS 6 이상과의 연동을 기준으로 설명한다. JEUS 7 연동은 "4.5.3. 내장 Servlet Engine 연동 설정(Enterprise)" 내용을 참고한다.

WebtoB 환경 파일 설정

  • NODE 절

    다음과 같이 HTH 개수와 JEUS와의 연결을 맺을 JsvPort를 설정한다.

    *NODE고
              …
            HTH = 1,
            JsvPort = 9999,

    HTH에 설정된 값은 WebtoB에서 HTH 프로세스의 개수로서 이 값과 JEUS 환경 파일 중 WEBMain.xml의 <webtob-listener> 하위에 있는 <hth-count> 항목 값과 일치해야 한다. 또한 JsvPort는 웹 컨테이너와 연결을 맺을 포트 번호로서 실제 웹 브라우저로 요청받는 포트 번호와는 무관하다. JEUS 환경 파일 WEBMain.xml의 <webtob-listener>하위에 있는 <port> 항목 값과 일치해야 한다.

  • SVRGROUP 절

    SVRTYPE이 JSV인 서버 그룹을 설정한다.

    *SVRGROUP 
    jsvg       SvrType = JSV
  • SERVER 절

    서비스와 실제로 웹 컨테이너와 연결하여 작업을 할 서버를 설정한다.

    *SERVER
    MyGroup    SvgName = jsvg, MinProc = 4, MaxProc = 10

    서버의 이름으로 MyGroup이고, 서버 그룹의 이름은 SVRGROUP 부분에서 설정한 jsvg이다.

    MinProc은 웹 컨테이너와의 최소 연결 개수이고, MaxProc은 웹 컨테이너와의 최대 연결 개수이다. 이 개수들은 JEUS 환경 파일 중 WEBMain.xml의 <webtob-listener> 하위에 있는 <thread-pool> 설정값과 각각 일치하거나 커야 한다.

  • URI 절

    URI 부분은 어떤 URI가 요청이 되었을 때 어떤 서버를 수행시킬지를 지정하는 것으로 서버(MyGroup)의 서비스에 대한 URI를 설정한다.

    다음은 "/examples/" URI에 대해 JSV 서버(MyGroup)의 서비스를 수행하도록 설정하는 예이다.

    *URI
    uri1     Uri = "/examples/",
             SvrType = JSV,
             SvrName = MyGroup

JEUS 6 환경 파일 설정

WebtoB 연결 설정을 위해 아래 경로에 있는 WEBMain.xml을 수정해야 한다.

$JEUS_HOME/config/<node_name>/<node_name>_servlet_<engine_name>/

< WEBMain.xml>

<webtob-listener>
  <listener-id>webtob1</listener-id>
  <port>9999</port>
  <webtob-address>localhost</webtob-address>
  <registration-id>MyGroup</registration-id>
  <hth-count>1</hth-count>
  <thread-pool>
    <min>10</min>
    <max>10</max>
    <step>0</step>
    <max-idle-time>30000</max-idle-time>
  </thread-pool>
</webtob-listener>

WEBMain.xml 파일에서 확인하고 수정해야 할 항목은 <webserver-connection> 하위에 있는 <webtob-listener> 하위 항목들이며 각 항목에 대한 설명은 다음과 같다.

태그설명
<port>WebtoB Servlet Engine 웹 컨테이너와 WebtoB와의 연결을 맺을 포트 번호를 설정하는 것으로 WebtoB 설정의 NODE 절의 JsvPort 값과 일치해야 한다.
<webtob-address>연결을 맺을 WebtoB의 IP 주소를 설정한다.
<registration-id>WebtoB와 처음 연결을 맺을 때 등록과정 중 사용할 등록 ID로 WebtoB SERVER 설정 중 연결하고자 하는 서버 이름(예: MyGroup)과 같아야 한다.
<hth-count>WebtoB의 NODE 절의 HTH와 같은 값을 설정한다. 실제 연결은 WebtoB의 각 HTH에게 연결하기 때문에 이 값이 일치해야 한다.
<thread-pool>, <min>,<max>Thread Pool에 최소한 유지되어야 하는 Thread의 개수와 최대 개수를 정의하는 것으로 WebtoB 환경 파일에 정의한 MyGroup 서버에 대한 MinProc/MaxProc 값과 일치하거나 적어야 한다.

하나의 컨텍스트 그룹은 여러 개의 웹 서버 연결을 가질 수 있는데 각각의 연결마다 포트 번호가 달라야 한다. 이렇게 여러 개의 웹 서버 연결을 가지는 것은 웹 서버가 여러 노드에 존재할 때나 다른 종류의 웹 서버로부터 요청을 받을 때에 사용한다.

Servlet Engine 기동 및 종료

명령어 모드에서 다음의 단계별로 WebtoB와 WebtoB Servlet Engine을 기동시키도록 한다.

  1. WebtoB 환경 파일을 컴파일한다.

    C:\> wscfl –i http.m
  2. WebtoB를 기동시킨다.

    C:\>wsboot
  3. 아래 명령어를 사용하여 JEUS Manager를 시작한다.

    C:\>jeus
  4. JEUS를 부팅하기 위해서 인증 과정을 거쳐 jeusadmin 콘솔 툴을 이용한다.

    C:\>jeusadmin webmain
    Login name>administrator
    Password>
    JEUS 6.0 Jeus Manager Controller
    webmain>

    webmain은 JEUS를 시작한 노드로써 해당 노드에 대해 권한이 있는 UserName과 그에 따른 Password 인증 과정을 거쳐야 jeusadmin 명령어를 이용할 수 있다.

    참고

    ID는 기본으로 adminstrator이고, Password 값은 설치 과정에서 입력한 값을 기억하여 입력한다.

  5. 다음과 같이 JEUS를 부팅하여 WebtoB와 연동시키므로써 원하는 서비스를 이용하게 된다.

    webmain> boot

    부팅 과정은 2단계로 이루어진다.

    1. JEUS 서비스를 시작한 후 각각의 엔진을 시작한다.

    2. JEUS 서비스 시작 과정을 살펴보면 위 명령은 JEUS Manager로 전달된다.

  6. JEUS 서비스와 엔진을 종료하고 싶으면 다음 명령을 수행한다.

    webmain> down
  7. 다음과 같은 명령어를 이용해 JEUS 서버를 종료한다.

    webmain>jeusexit

예제

“A.2. WebtoB와 JEUS 연동 환경설정 파일”을 참고한다.

4.5.3. 내장 Servlet Engine(JEUS 7) 연동 설정(Enterprise)

WebtoB Enterprise 이상부터 제공되는 Servlet Engine 연동을 위한 설정은 앞서 설명한 JEUS와의 연동 설정 방법과 동일하다. 단, 현재 Servlet Engine으로 제공되는 버전은 JEUS 7에 해당하므로 앞서 설명한 JEUS 6 이상에서의 설정과는 항목 이름에서 약간의 차이가 있다.

WebtoB 환경 파일 설정

“4.5.2. JEUS 6 연동 설정(Base+)”의 “WebtoB 환경 파일 설정”의 방법과 동일하다.

내장 Servlet Engine 환경 파일 설정

WebtoB와 연결 설정을 위해서는 아래 경로에 있는 domain.xml을 수정해야 한다.

${WEBTOBDIR}/jeus/domains/domain1/config/domain.xml

<domain.xml>

<webtob-connector>
  <name>webtob</name>
  <network-address>
     <port>9999</port>
     <ip-address>localhost</ip-address>
  </network-address>
  <hth-count>1</hth-count>
  <thread-pool>
     <number>10</number>
  </thread-pool>
  <registration-id>MyGroup</registration-id>
  <output-buffer-size>8192</output-buffer-size>
  <reconnect-interval>5000</reconnect-interval>
</webtob-connector>

domain.xml 파일에서 확인하고 수정해야 할 항목은 <webtob-connector> 하위에 있는 항목들이며 각 항목에 대한 설명은 다음과 같다.

태그설명
<network-address>, <port>WebtoB Servlet Engine이 WebtoB와의 연결을 맺을 포트 번호를 설정하는 것으로 WebtoB 설정 중 NODE 절의 JsvPort 값과 일치해야 한다.
<network-address>, <ip-address>연결을 맺을 WebtoB의 IP 주소를 지정한다.
<hth-count>WebtoB의 NODE 절의 HTH와 같은 값을 설정한다. 실제 연결은 WebtoB의 각 HTH에게 연결하기 때문에 이 값이 일치해야 한다.
<thread-pool>, <number>Thread Pool에 유지되어야 하는 Thread의 개수를 정의하는 것으로 WebtoB 환경 파일에 정의한 MyGroup 서버에 대한 MaxProc 값과 일치하거나 적어야 한다.
<registration-id>WebtoB와 처음 연결을 맺을 때 등록 과정 중 사용할 등록 ID로 WebtoB 환경 파일에서 SERVER 부분의 서버 이름(MyGroup)과 같아야 한다.

내장 Servlet Engine 기동 및 종료

명령어 모드에서 다음의 단계별로 WebtoB와 WebtoB 내장 Servlet Engine을 기동시키도록 한다. 자세한 설정 방법은 JEUS 7 Fix#4의 매뉴얼을 참고하도록 한다.

  1. WebtoB 환경 파일을 컴파일한다.

    C:\> wscfl –i http.m
  2. WebtoB를 기동시킨다.

    C:\>wsboot
  3. 아래 명령어를 사용하여 JEUS의 DAS를 기동한다.

    C:\>startDomainAdminServer -u administrator -p <password>
  4. 아래 명령어를 사용하여 JEUS의 MS를 기동한다.

    C:\>startManagedServer -domain jeus_domain -server server1 -u administrator -p <password>

    JEUS MS가 정상적으로 부트되면 examples가 deploy되는데 이를 확인하기 위해서는 웹 브라우저에서 "http://localhost:8088/examples/"을 호출한다.

  5. 다음은 jeusadmin에 접속하는 방법이다.

    C:\>jeusadmin -u administrator -p <password>
    Attempting to connect to 127.0.0.1:9736.
    The connection has been established to Domain Administration Server adminServer in the domain jeus_domain.
    JEUS7 Administration Tool
    To view help, use the 'help' command.
    [DAS]jeus_domain.adminServer>

    JEUS 관리자의 사용자 이름과 패스워드를 입력한다. 일반적으로 관리자의 계정은 'administrator'이고 패스워드는 Servlet Engine을 설치할 때 입력한 값이다. 잠시 후 프롬프트가 다시 뜨면 JEUS가 제대로 기동되었고, 다시 명령어를 받을 수 있는 상태가 되었다는 것을 나타낸다.

  6. WebAdmin을 통해서 Servlet Engine을 관리할 수 있다.

    http://localhost:9736/webadmin

    웹 브라우저를 열어서 주소 창에 위와 같이 주소를 입력한다. JEUS 관리자의 계정과 패스워드를 입력하고 [Login] 버튼을 클릭한다. 일반적으로 관리자의 계정은 'administrator'이고 패스워드는 JEUS를 설치할 때 입력한 값이다.

  7. JEUS 서비스와 엔진을 종료하고 싶으면 다음 명령을 수행한다.

    [DAS]jeus_domain.adminServer>local-shutdown
  8. 다음과 같은 명령어를 이용해 jeusadmin을 종료한다.

    exit

예제

“A.2. WebtoB와 JEUS 연동 환경설정 파일”을 참조한다.

4.6. 다른 WAS 연동

WebtoB는 Reverse Proxy를 이용하여 JEUS뿐만 아니라 타 WAS와 연동이 가능하다. WAS는 일반적으로 HTTP Listener를 가지고 있는데, WebtoB는 reverse proxy 설정을 통해 WAS의 HTTP Listener와 연결을 맺어 연동하게 된다.

WebtoB Enterprise 이상에서 제공되는 Reverse Proxy Group 설정을 통해 다중 WAS 구성이 가능하다.

WebtoB와 WAS 연동을 위해 설정해야 할 파일은 다음과 같다

  • WebtoB 환경 파일 (예: http.m)

  • WAS 환경 파일 (예: WEBMain.xml)

WebtoB와 WAS 연동을 위해 WAS에서 확인해야할 내용은 다음과 같다. (여기에서는 타 WAS의 설정을 다루지 않으며, 필요한 경우 타 WAS의 매뉴얼을 참고하도록 한다.)

  • WebtoB가 WAS로 연결할 HTTP Listener 설정(Listen IP, Port, thread 수)

  • WebtoB와 WAS의 연결을 persistent connection으로 유지하고자 하는 경우 PING 체크를 위한 application 설정

  • Sticky Session routing을 사용하고자 하는 경우 routing id

  • WebtoB와 WAS간 SSL 암호화 통신을 하고자 하는 경우 HTTP Listener에 대한 SSL 설정

4.6.1. WebtoB의 Reverse Proxy를 통한 WAS 연결의 특징

WebtoB와 WAS의 연결은 WebtoB가 Reverse Proxy 설정을 통해 WAS에게 연결하는 구조이다. WebtoB는 외부 네트워크에서 서비스하고, WAS는 내부 네트워크에서 운영할 경우에도 유용하다. 외부 네트워크에서 서비스 하는 WebtoB가 내부 서버(WAS)로부터 받은 응답을 rewriting할 수 있기 때문이다.

WebtoB는 클라이언트로부터 HTTP 요청을 받은 시점에 WAS로 연결을 시도한다. 만약 WAS가 기동되지 않았다면 클라이언트에게 503 에러를 응답하게 된다. 연결에 성공하면 WebtoB는 이 연결을 통해서 사용자의 요청을 WAS에게 전달하고그 결과를 받아 클라이언트에게 전송해 준다.

WebtoB는 WAS와의 연결을 persistent connection으로 설정하여 재사용할 수 있는데 이를 위해서는 WebtoB와 WAS의 PING 체크를 위한 설정이 필요하다. Min, Max를 설정한 경우 클라이언트의 동시 요청량에 따라 동적으로 connection을 관리한다. 또한, WebtoB와 WAS는 SSL 통신이 가능하다.

4.6.2. 다중 WAS 연동 설정(Enterprise+)

다중 WAS를 구성하고자 하는 경우 WebtoB Enterprise에서 제공되는 Reverse Proxy Group 설정을 사용하면 되고, 하나의 WAS만 연동하고자 한다면 Reverse Proxy 설정만 사용하면 된다.

WebtoB 환경 파일 설정

  • REVERSE_PROXY_GROUP 절

    다음과 같이 Reverse Proxy를 그룹으로 묶어서 하나로 관리할 항목들을 설정한다.

    *REVERSE_PROXY_GROUP
    rproxyG1
             VhostName = "vhost1",
             PathPrefix = "/before/",
             RegExp = "\.(do|jsp)$",
             ServerPathPrefix = "/after/",
             RewriteHtmlUrl = "/after/ /before/",
             HtmlUrl = "a href",
             HtmlUrl = "img src",
             HtmlUrl = "link href",
             HtmlUrl = "script src",
             HtmlUrl = "frame src",
             HtmlUrl = "td background",
             HtmlUrl = "table background",
             HtmlUrl = "iframe src",
             HtmlUrl = "OBJECT CODEBASE",
             RewriteHtmlMaxSize = 4194304,
             WBRoutingCookieKey = "W2BRID"
            #SessionIDCookieKey = "JSESSIONID"

    위 설정은 "/before/"로 시작하는 요청을 "/after/"로 변경하여 서비스하기 위한 설정이된다.

    다중 WAS를 구성하는 것은 각각의 WAS에서 동일한 서비스를 하기 위한 목적이기 때문에 VhostName, PathPrefix, RegExp, ServerPathPrefix 항목은 Reverse Proxy Group과 Reverse Proxy가 동일하게 설정하거나 Reverse Proxy Group에만 설정해야 한다.

    WAS의 Sticky Session routingid와 상관없이 자체 routingid를 사용하고자 하는 경우 WBRoutingCookieKey 설정을 사용하면 된다.

  • REVERSE_PROXY 절

    Reverse Proxy Group명과 WAS의 HTTP Listener 정보(Ip:Port) 및 각 WAS별 연동정보를 설정한다.

    *REVERSE_PROXY
    rproxy1
             ServerAddress = "127.0.0.1:8088",
             ReverseProxyGroupName = "rproxyG1",
             MinPersistentServerConnections = 1,
             MaxPersistentServerConnections = 20,
             PersistentServerCheckTime = 50,
             PersistentServerTimeout = 300,
             PersistentServerCheckUrl = "/after/ping.html",
             MaxWebSocketConnections = 20
            #StickySessionRoutingID = "was1_servlet_engine",
            #ProxySSLFlag = Y,
            #ProxySSLName = pssl1
    
    rproxy2
             ServerAddress = "127.0.0.1:8089",
             ReverseProxyGroupName = "rproxyG1",
             MinPersistentServerConnections = 1,
             MaxPersistentServerConnections = 20,
             PersistentServerCheckTime = 50,
             PersistentServerTimeout = 300,
             PersistentServerCheckUrl = "/after/ping.html",
             MaxWebSocketConnections = 20
            #StickySessionRoutingID = "was2_servlet_engine",
            #ProxySSLFlag = Y,
            #ProxySSLName = pssl1

    위 설정은 rproxyG1 그룹에 속하는 rproxy1(127.0.0.1:8088), rproxy2(127.0.0.1:8089) 설정을 한 경우이며, 요청은 RR(Round Robin) 방식으로 분배된다. 하나의 Reverse Proxy 내에서 연결이 여러개 존재할 때 요청은 각 연결에 대하여 FA(First Assign) 방식으로 분배된다.

    MaxPersistentServerConnections은 동시 요청을 최대로 처리할 수 있는 연결 수를 설정한다. MaxPersistentServerConnections보다 많은 요청이 동시에 들어온다면 WebtoB가 큐잉하게 된다.

    MinPersistentServerConnections은 요청이 없더라도 지속적인 연결을 유지하고자 하는 연결 수를 설정한다. MinPersistentServerConnections을 넘어선 연결들은 PersistentServerTimeout 시간 동안 어떠한 요청도 들어오지 않으면 끊어지게 된다.

    PersistentServerCheckTime은 WAS와의 연결을 지속적으로 유지하기 위해 PING 메시지를 보내는 주기이다. 이 값은 WAS의 HTTP Listener에 대한 KeepAliveTimeout보다 작게 설정해야 한다. 그렇지 않으면 WAS에서 먼저 연결을 끊어버릴 것이기 때문이다. 해당 주기마다 WebtoB는 WAS에 주기적으로 PING 메시지를 보내고 이에 대한 응답을 받음으로써 각 연결들을 지속적으로 유지하게 된다. 이를 바탕으로 WebtoB는 WAS와의 연결에 대하여 connection pool을 구성하게 되고 각 connection을 동적으로 관리할 수 있게 된다.

    PING 메시지는 PersistentServerCheckUrl 설정을 가지고 만들어진 HTTP HEAD Request이다. 위와 같이 설정하게 되면 PING 메시지는 "HEAD /after/ping.html HTTP/1.1"가 된다. HEAD 메소드는 HTTP Response Header만 받고자 하는 메소드이기 때문에 PING 메시지에 대한 응답(PONG 메시지)을 최소화 하는데 유용하다. 이를 위해 WAS에서는 반드시 "/after/ping.html" application을 준비해야 한다.

    WAS와의 connection을 WebSocket으로 사용하는 경우 MaxWebSocketConnections 설정을 통해 WebSocket으로 사용하고자 하는 connection 수를 제한할 수 있다.

    Reverse Proxy Group에 WBRoutingCookieKey를 설정한 경우 rproxy1, rproxy2에 대해 자체 routing하게 된다. rproxy1에서 처리된 응답에 대해 WBRoutingCookieKey와 rproxy1을 Base64로 인코딩된 값을 Set-Cookie 헤더 추가해준다. 이후 동일 클라이언트로부터의 요청을 받은 경우 Cookie의 해당 값을 이용하여 rproxy1로 요청을 routing하게 된다. WBRoutingCookieKey를 사용하지 않는 경우에 StickySessionRoutingID는 Reverse Proxy Group의 SessionIDCookieKey설정과 함께 Sticky Session routing을 사용하는 경우 설정한다. WAS에서 "Set-Cookie" Responose Header에 JSESSIONID로 만들어 주는 값의 dot(.)이후의 엔진명을 넣어주면 된다.

    ProxySSLFlag, ProxySSLName은 WebtoB와 WAS의 연결에 대해 SSL 암호화 통신을 할 경우 설정한다.

  • PROXY_SSL 절

    WebtoB와 WAS의 SSL 암호화 통신을 할 경우 설정한다.

    *PROXY_SSL
    pssl1          
             Verify = 2,
             VerifyDepth = 1,
             RequiredCiphers = "ALL:!ADH:!EXPORT56:RC4+RSA:!SHA:+HIGH: +MEDIUM:+LOW:+SSLv2:+EXP:+eNULL",
             CACertificateFile="$(WEBTOBDIR)/ssl/server.crt",
             CheckPeerValidPeriod = Y

    위 설정은 WebtoB가 WAS로 연결을 맺을 때 SSL 연결을 위한 설정이다. WebtoB가 클라이언트가 되고 WAS가 서버가 되기 때문에 WAS는 서버를 위한 SSL 설정을 해야 한다. 이렇게 설정된 경우 WebtoB는 WAS로 연결을 맺을 때 TCP 연결 이후 SSL Handshake 과정을 요청한다.

    SSL Handshake 과정에서 서버 인증서를 검증하고자 하는 경우 Verify를 2로 설정하고 그렇지 않다면 0으로 설정하면 된다. 서버 인증서를 검증하는 경우 반드시 CACertificateFile을 설정해야 한다.

설정, 통계 및 connection 상태 정보 확인

wsadmin 모드에서 Reverse Proxy Group, Reverse Proxy에 대한 설정, 통계 및 각 연결에 대한 상태 정보를 확인한다.

  1. Reverse Proxy Group 설정 확인

    wsadmin> cfg -rpg
        REVERSE_PROXY_GROPUP(0): Name = rproxyG1,
             VhostName = "vhost1",
             PathPrefix = "/before/",
             ServerPathPrefix = "/after/",
             RewriteHtmlMaxSize = 4194304,
             RewriteHtmlUrl = "/after/ /before/",
             HtmlUrl = "a href",
             HtmlUrl = "img src",
             HtmlUrl = "link href",
             HtmlUrl = "script src",
             HtmlUrl = "frame src",
             HtmlUrl = "td background",
             HtmlUrl = "table background",
             HtmlUrl = "iframe src",
             HtmlUrl = "OBJECT CODEBASE",
             SessionIdCookieKey = "JSESSIONID",
             FlexibleStickySessionRouting = N       # (N:0, Y:1),
             ReverseProxyEntries = 2

  2. Reverse Proxy 설정 확인

    wsadmin> cfg -rp
        REVERSE_PROXY(0): Name = rproxy1,
             ReverseProxyGroupName = "rproxyG1",
             VhostName = "vhost1",
             PathPrefix = "/before/",
             ServerPathPrefix = "/after/",
             ServerAddress = "127.0.0.1:8088",
             HttpInBufSize = 16384,
             RewriteHtmlMaxSize = 4194304,
             RewriteHtmlUrl = "/after/ /before/",
             HtmlUrl = "a href",
             HtmlUrl = "img src",
             HtmlUrl = "link href",
             HtmlUrl = "script src",
             HtmlUrl = "frame src",
             HtmlUrl = "td background",
             HtmlUrl = "table background",
             HtmlUrl = "iframe src",
             HtmlUrl = "OBJECT CODEBASE",
             MinPersistentServerConnections = 1,
             MaxPersistentServerConnections = 20,
             PersistentServerCheckTime = 50,
             PersistentServerTimeout = 300,
             PersistentServerCheckUrl = "/after/ping.html",
             ProxySslFlag = N
        REVERSE_PROXY(1): Name = rproxy2,
             ReverseProxyGroupName = "rproxyG1",
             VhostName = "vhost1",
             PathPrefix = "/before/",
             ServerPathPrefix = "/after/",
             ServerAddress = "127.0.0.1:8089",
             HttpInBufSize = 16384,
             RewriteHtmlMaxSize = 4194304,
             RewriteHtmlUrl = "/after/ /before/",
             HtmlUrl = "a href",
             HtmlUrl = "img src",
             HtmlUrl = "link href",
             HtmlUrl = "script src",
             HtmlUrl = "frame src",
             HtmlUrl = "td background",
             HtmlUrl = "table background",
             HtmlUrl = "iframe src",
             HtmlUrl = "OBJECT CODEBASE",
             MinPersistentServerConnections = 1,
             MaxPersistentServerConnections = 20,
             PersistentServerCheckTime = 50,
             PersistentServerTimeout = 300,
             PersistentServerCheckUrl = "/after/ping.html",
             ProxySslFlag = N

  3. Proxy SSL 설정 확인

    wsadmin> cfg -pssl
        PROXY_SSL(0): Name = pssl1,
             Verify= 2,
             VerifyDepth = 1,
             CheckPeerValidPeriod = Y       # (N:0, Y:1),
             CACertificatePath = "/home/tmax/server/webtob/ssl/",
             CACertificateFile = "/home/tmax/server/webtob/ssl/server.crt",
             Protocols = "SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2",
             RequiredCiphers = "ALL:!ADH:!EXPORT56:RC4+RSA:!SHA:+HIGH: +MEDIUM:+LOW:+SSLv2:+EXP:+eNULL"

  4. Reverse Proxy Group 단위의 통계 및 연결 정보 확인

    wsadmin> st -rpg
    
    --------------------------------------------------------------------------------
     hth  (rpgi)rpgname  rproxyname     count(qcnt)    avg cons   remote_ipaddr:port
    --------------------------------------------------------------------------------
       0  ( 0)rproxyG1   rproxy1            1(   0) 0.0025    1        127.0.0.1:8088
       0  ( 0)rproxyG1   rproxy2            1(   0) 0.0021    1        127.0.0.1:8089
       

    다음은 출력 항목에 대한 설명이다.

    항목설명
    count요청 처리 수
    qcntReverse Proxy Group 단위의 큐잉된 요청 수(위와 같은 경우 rproxy1, rproxy2의 qcnt는 동일)
    avg평균 처리시간(초)
    consWAS와 연결된 connection 수
  5. Reverse Proxy별 connection 단위의 통계 및 상태 정보 확인

    wsadmin> st -rp
    
    HTH 0: RDY
     ------------------------------------------------------------------------------ 
     (rpi)rproxy_name  rpgname     status     count  idle spri  clid  ssl websocket
     ------------------------------------------------------------------------------ 
     (  0)rproxy1      rproxyG1       RDY         1    14    1    -1   N      N
     (  1)rproxy2      rproxyG1       RDY         1    10    2    -1   N      N
       

    다음은 출력 항목에 대한 설명이다.

    항목설명
    status해당 connection의 상태 정보
    count요청 처리 수
    idleidle 시간(초)
    spriconnection에 대한 내부 관리 index
    clid요청 처리 중인 클라이언트 index
    sslWAS와의 SSL 사용 여부
    websocketconnection이 websocket으로 사용되고 있는지 여부

4.7. URLRewrite

Apache의 mod_rewrite를 WebtoB에 포팅한 기능으로 rule-based URL rewriting 기능을 제공한다.

4.7.1. WebtoB 설정

URLRewrite 기능을 사용하기 위해서는 NODE 절의 'URLRewrite' 항목은 'Y'로 설정되어야 하고 URLRewriteConfig 항목에 Condition과 Rule에 관련된 설정을 해야 한다.

다음은 URLRewrite 기능을 사용하기 위한 NODE 절 설정에 대한 예제이다.

*NODE
mynode
    URLRewrite = Y,
    URLRewriteConfig = "${WEBTOBDIR}/config/rewrite.conf"

4.7.2. URLRewriteConfig 파일 설정

URLRewriteConfig에는 Apache의 mod_rewrite의 기능 중 RewriteCond와 RewriteRule 설정을 사용할 수 있다. 모든 설정을 사용할 수 있는 것은 아니며, 뒤에서 설명할 몇 가지 기능은 사용할 수 없다.

참고

다음에 설명하는 URLRewriteConfig 설정 내용은 "Apache 2.2 mod_rewrite"를 참고하여 작성한 내용이다. 설명된 내용 중 WebtoB에서 동작하지 않는 기능이 있을 수 있으니 유의해야 한다.

4.7.3. RewriteCond

RewriteCond는 rewriting 조건을 명시하며, 다음과 같은 형식으로 설정한다. TestString과 CondPattern을 매칭하여 조건이 맞을 경우 RewriteRule 설정대로 해당되는 패턴을 교체한다.

RewriteCond <TestString> <CondPattern> [flags]
  • <TestString>

    TestString에는 다음과 같은 예약어와 일반 문자열을 사용할 수 있다.

    • $N (0 <= N <= 9)

      • RewriteRule의 Pattern 중 괄호로 묶인 패턴을 참조한다.

    • %N (1 <= N <= 9)

      • RewriteCond의 CondPattern 중 괄호로 묶인 패턴을 참조한다.

      • $N과 %N은 다음과 같은 Regex Back-Reference 구조를 가진다.

        [그림 4.3] Regex Back-Reference

        Regex Back-Reference

    • %{SERVER_VARIABLE_NAME}

      CGI에서 사용하는 서버 환경변수 중 일부와 몇 가지 추가적인 변수를 참조한다.

      • %{ENV:variable}은 환경변수를 참조한다.

      • %{HTTP:header}는 HTTP Request Header를 참조한다.

      • 이외에도 다음과 같은 변수를 사용할 수 있다.

        변수설명
        HTTP headers

        HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE,

        HTTP_FORWARDED, HTTP_HOST, HTTP_PROXY_CONNECTION,

        HTTP_ACCEPT

        connection & request

        REMOTE_ADDR, REMOTE_PORT, REMOTE_USER, REMOTE_METHOD,

        QUERY_STRING, AUTH_TYPE

        server internals

        DOCUMENT_ROOT, SERVER_NAME, SERVER_ADDR, SERVER_PORT,

        SERVER_PROTOCOL, SERVER_SOFTWARE

        date and time

        TIME_YEAR, TIME_MON, TIME_DAY, TIME_HOUR, TIME_SEC,

        TIME_WDAY, TIME

        specialsTHE_REQUEST, REQUEST_URI, HTTPS

        참고

        Apache의 mod_rewrite에서 제공하는 %{SSL:variable}, %{LA-U:variable}, %{LA-F:variable},

        REMOTE_HOST, REMOTE_IDENT, SCRIPT_FILENAME, SCRIPT_USER, SCRIPT_GROUP,

        SERVER_ADMIN, API_VERSION, REQUEST_FILENAME, IS_SUBREQ는 사용할 수 없다.

  • <CondPattern>

    CondPattern은 Perl compatible reqular expression을 사용할 수 있으며, 다음과 같은 추가적인 패턴을 사용할 수 있다.

    지시자설명
    !PatternPattern에 매칭되지 않는 경우를 지정한다.
    <CondPatternTestString이 CondPattern보다 사전순서상 앞에 있을 경우를 매칭한다.
    >CondPatternTestString이 CondPattern보다 사전순서상 뒤에 있을 경우를 매칭한다.
    =CondPatternTestString이 CondPattern과 일치하는 경우를 매칭한다.
    -dTestString을 path로 간주하여 디렉터리일 경우를 매칭한다.
    -fTestString을 path로 간주하여 파일일 경우를 매칭한다.
    -sTestString을 path로 간주하여 파일 사이즈가 0보다 큰 경우를 매칭한다.
    -lTestString을 path로 간주하여 symbolic link일 경우를 매칭한다.
    -xTestString을 path로 간주하여 실행 파일일 경우를 매칭한다.
    -FTestString을 path로 간주하여 서버 설정상 접근이 가능한 경우를 매칭한다.
    -UTestString을 URL로 간주하여 서버 설정상 접근이 가능한 경우를 매칭한다.

    참고

    모든 패턴에는 '!'을 붙여서 반대 의미로 매칭할 수 있다.

    참고로 다음은 Regex vocabulary에 대한 설명이다.

    지시자설명
    .matches any single character
    +repeats the previous match one or more times
    *repeats the previous match zero or more times
    ?makes the match optional
    ^matches the beginning of the string
    $matches the end of the string
    ( )groups several characters into a single unit, and captures a match for use in backreference
    [ ]a character class - matches one of the characters
    [^ ]negative character class - matches any character not specified
  • [flags]

    CondPattern에 [flags]를 사용하여 패턴 매칭 방식을 변경할 수 있다.

    지시자설명
    nocase|NC패턴을 매칭할 때 대소문자를 구분하지 않는다.
    ornext|ORRewriteCond 다음에 또 다른 RewriteCond가 있을 경우 다음 RewriteCond와 logical OR로 조합되도록 설정한다. 명시적으로 설정하지 않았을 경우는 항상 AND로 다음 조건과 조합한다.
    novary|NVHTTP Header를 TestString으로 사용할 경우 Vary Header가 Response에 추가되지 않도록 한다.

    다음은 [OR] flag 사용한 예이다.

    RewriteCond %{HTTP_HOST}  ^host1.*  [OR]
    RewriteCond %{HTTP_HOST}  ^host2.*  [OR]
    RewriteCond %{HTTP_HOST}  ^host3.*
    RewriteRule ...

    [OR] flag를 사용하지 않을 경우 3개의 RewriteCond/RewriteRule을 각각 생성해야 한다.

4.7.4. RewriteRule

RewriteRule은 rewriting 동작을 결정하며, 다음과 같은 형식으로 설정한다. 사용자 요청이 RewriteCond에 매칭되는 경우 RewriteRule 설정에 의해 사용자 요청 중 Pattern을 Substitution으로 교체한다.

RewriteRule <Pattern> <Substitution> [flags]
  • <Pattern>

    • Pattern은 Perl compatible reqular expression을 사용할 수 있으며, '!'을 사용하면 패턴에 매칭되지 않는 경우를 지정할 수 있다.

      참고

      '!'을 사용할 경우 괄호로 묶은 그룹 패턴($N)을 사용할 수 없다. 패턴이 매칭되지 않는 경우이므로, 그룹 패턴($N)에 값이 없기 때문이다.

    • RewriteRule만 단독으로 설정할 경우 패턴 매칭은 URL-path를 사용하며, RewriteCond와 함께 사용될 경우 마지막에 매칭된 패턴을 사용한다.

  • <Substitution>

    URL을 어떤것으로 교체할지 설정하며, 다음과 같은 값을 사용할 수 있다.

    설정값설명
    file-system path'/'로 시작하는 file-system의 절대 경로를 설정할 경우 해당 파일을 사용자 응답에 사용한다. 단, 설정한 경로가 file-system에 존재해야 한다.
    URL-path일반적인 URL-path를 설정할 경우 해당 리소스를 사용한다.
    Absolute URL"http://<hostname>/file.html"처럼 Absolute URL을 사용할 경우에는 hostname이 서버와 일치하면 scheme과 hostname을 제외한 나머지를 URL-path처럼 사용하고, 일치하지 않을 경우 외부 서버로 redirect하도록 처리한다.
    -'-'는 교체하지 않는다는 의미이다.
    $N (N=0..9)RewriteRule의 패턴 중 N번째 그룹 패턴을 지칭한다.
    %N (N=1..9)마지막에 매칭된 RewriteCond의 패턴 중 N번째 그룹 패턴을 지징한다.
    %{VARNAME}서버에서 제공하는 VARNAME을 참조한다. RewriteCond의 TestString에 적용되는 항목을 사용할 수 있다.
    ?

    기본적으로 Query string은 변경되지 않지만, 이를 교체하고 싶을 경우 '?'를 Substitution안에 추가한다. Query string을 삭제하고자 하는 경우 Substitution의 마지막이 '?'로 끝나도록 한다.

    참고

    Apache의 mod_rewrite에서 제공하는 RewriteMap을 지원하지 않기 때문에 '${mapname:key|default}'는 사용할 수 없다.

  • [flags]

    • RewriteRule의 세부 동작을 [flags]의 설정을 통해 조절할 수 있다.

    • flags는 콤마(,)를 사용하여 여러 개를 설정할 수 있으며, 다음과 같은 값을 사용할 수 있다.

      • B (escape backreferences)

        Substitution에 사용되는 backreference($N 혹은 %N)는 URL의 %-encoding을 unescape하여 사용한다. [B] 옵션을 사용하면, URL의 %-encoding을 그대로 사용할 수 있다.

        예를 들어, 다음과 같이 설정했을 경우 "/C%2b%2b"가 unescape되어 "index.php?show=/C++"로 매핑되지만, [B] 옵션을 사용했을 경우에는 "index.php?show=/C%2b%2b"로 매핑할 수 있다.

        RewriteRule ^(.*)$ index.php?show=$1
      • chain|C (chained with next rule)

        이 옵션을 설정했을 경우 rule이 매칭되지 않았을 때 다음 rule은 체크하지 않게 된다. 그 다음 rule또한 [C] 옵션을 사용했다면, 마찬가지로 건너뛰게 된다.

      • cookie|CO=NAME:VAL:domain[:lifetime[:path[:secure[:httponly]]]] (set cookie)

        응답에 Set-Cookie Header를 추가하여 사용자 브라우저에 Cookie를 추가한다.

      • discardpathinfo|DPI (discard PATH_INFO)

        디렉터리별 context를 구성한 환경에서 RewriteRule은 URI와 PATH_INFO를 구별하여 매번 rule을 적용할 때 마다 URI와 PATH_INFO를 결합하게 되는데, URI가 여러 번 매칭되는 경우 PATH_INFO가 여러 번 붙게 된다.

        [DPI] 옵션은 PATH_INFO를 구분하지 않고 RewriteRule을 적용하도록 한다.

      • env|E=VAR:VAL (set environment variable)

        환경변수에 VAR=VAL를 추가한다. VAL에는 regexp backreferences($N 혹은 %N)를 사용할 수 있다. 이 환경변수는 SSI나 CGI에서 사용할 수 있으며, RewriteCond의 패턴 중 %{ENV:VAR}으로 사용할 수 있다.

      • forbidden|F (force URL to be forbidden)

        "403 Forbidden" 응답을 보낸다.

      • gone|G (force URL to be gone)

        "410 Gone" 응답을 보낸다.

      • handle|H=Content-handler (force Content handler)

        Content-handler를 설정한다.

      • last|L (last rule)

        rewriting 과정을 이곳에서 종료하도록 한다. C의 break 명령과 유사한 기능을 하는 옵션이다.

      • next|N (next round)

        지금까지 변경된 URL을 가지고 처음부터 다시 rewriting 과정을 수행하도록 한다. C의 continue 명령과 유사한 기능을 하는 옵션이다. 무한루프가 발생할 수 있으니 주의해야 한다.

      • nocase|NC (no case)

        패턴에 대소문자를 구분하지 않도록 한다. [A-Z]와 [a-z]를 똑같이 취급한다.

      • noescape|NE (no URI escaping of output)

        rewriting 과정에서 URL을 %-encoding하지 않도록 한다.

      • nosubreq|NS (not for internal sub-requests)

        내부 요청일 경우 rewriting을 중지하도록 한다.

      • passthrough|PT (pass through to next handler)

        rewriting을 수행한 결과를 다른 handler가 사용할 수 있도록 한다.

      • qsappend|QSA (query string append)

        query string을 rewriting하는 경우 기존의 query string을 덮어쓰는 대신, 이를 그대로 유지하면서 새로운 query string을 추가하고자 하는 경우 이 옵션을 설정한다.

      • redirect|R[=code] (force redirect)

        Substitution이 Absolute URL일 경우 hostname이 서버의 호스트와 일치하는 경우에도 강제로 다시 redirect하도록 한다.

        code를 지정하지 않았을 경우 302 Moved Temporarily가 사용되며, code에는 Status Code를 직접 입력하거나, temp(default), permanent, seeother를 설정할 수 있다.

      • skip|S=num (skip next rules)

        다음 num개의 rule를 건너뛰도록 한다.

      • type|T=MIME-type (force MIME-Type)

        응답의 Content-Type을 설정한다.

4.7.5. 예제

URL Rewrite의 예제는 다음과 같다.

  • 예제 1

    다음은 "www.test.com/"과 같은 URL 패턴을 매칭하여, "www.test.com/rewrite.html"로 변환하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex1
    RewriteCond %{HTTP_HOST} ^www\.test\.com$       # if {Host} == "www.test.com"
    RewriteRule ^/$ /rewrite.html [L]               # then "/" > "/rewrite.html"
  • 예제 2

    다음은 "www.test.com/temp/xxx.html"과 같은 요청을 할 때 temp 디렉터리에 xxx.html 파일이 없는 경우 "www.test.com/temp/temp_error.html"로 변환하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex2
    RewriteCond %{REQUEST_FILENAME} !-f             
    # if {요청파일명} != 파일을 가리키거나 포함
    RewriteRule ^/([^/]+) /$1/$1_error.html [L]     
    # then "/temp/xxx.html" > "/temp/temp_error.html"
  • 예제 3

    다음은 "http://www.test.com:80"과 같은 요청을 할 때 "https://www.test.com:443"으로(http 요청을 https 요청으로) 변환하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex3
    RewriteCond %{HTTP_HOST} ^www\.test\.com$       
    # if {Host} == "www.test.com"
    RewriteCond %{SERVER_PORT} 80                   
    # AND {Port} == "80"
    RewriteRule .* https://www.test.com:443$0 [R]    
    # then > "https://www.test.com:443$0"   ($0: request uri)
  • 예제 4

    다음은 "www.test.com/xxx.html"과 같은 URL 패턴을 매칭하여 Request URI는 무시하고 무조건 "www.test_new.com/"으로 변환하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex4
    RewriteCond %{HTTP_HOST} ^www\.test\.com$       # if {Host} == "www.test.com"
    RewriteRule .* http://www.test_new.com [R]       # then > "http://www.test_new.com"
  • 예제 5

    다음은 "www.test.com/test.html"과 같은 URL 패턴을 매칭하여 "www.test_new.com/test.html"로 변환하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex5
    RewriteCond %{HTTP_HOST} ^www\.test\.com$       
    # if {Host} == "www.test.com"
    RewriteRule .* http://www.test_new.com$0 [R]     
    # then > "http://www.test_new.com$0"   ($0: request uri)
  • 예제 6

    다음은 Request Method가 POST이고 Referer Header가 없을 경우 "403 Forbidden" 에러로 처리하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex6
    RewriteCond %{REQUEST_METHOD} POST              # if {Method} == "POST"
    RewriteCond %{HTTP_REFERER} =""                 # AND {Referer} == ""
    RewriteRule . - [F]                             # then > 403 Forbidden Return
  • 예제 7

    다음은 "/../" 으로 시작하는 요청의 경우 "/403.html"로 처리하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex7
    RewriteRule ^/\.\./ /403.html [L]               # "/../"로 시작 > "/403.html"
  • 예제 8

    다음은 "aaa.test.com/xxx.html"로 요청할 경우 "www.test.com/aaa/xxx.html"로, "bbb.test.com/xxx.html"로 요청할 경우 "www.test.com/bbb/xxx.html"로 처리하는

    # url rewrite config - ex8
    RewriteCond %{HTTP_HOST} ^(aaa|bbb)\.test\.com  
    # if {Host} == ("aaa.test.com" OR "bbb.test.com")
    RewriteRule .* /%1$0 [L]                         
    # then "/xxx.html" > "/(aaa|bbb)/xxx.html" (%1: RewriteCond의 첫 번째 괄호, $0: request uri)
  • 예제 9

    다음은 "www.test.com/test.do?query=value1"로 요청할 경우 "www.test.com:8080/test.do?query=value1"로, "www.test.com/test.do?query=value2&.."으로 요청할 경우 "www.test.com:8080/test.do?query=value2&.."로 Query string에 따라 포트 변경 처리를 하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex9
    RewriteCond %{QUERY_STRING} ^query=value1$ [OR] 
    # if {QueryString} == "query=value1" 
    RewriteCond %{QUERY_STRING} ^query=value2&      
    # OR {QueryString} == "query=value2&.." 
    RewriteRule .* http://www.test.com:8080$0 [R]    
    # then > "http://www.test.com:8080$0"   ($0: request uri)
  • 예제 10

    다음은 "aaa.test.com/test.html"로(www 로 시작하지 않는) 요청할 경우에 "www.test.com/aaa/test.html"로 처리하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex10
    RewriteCond %{HTTP_HOST} !^www\.test\.com$          
    # if {Host} != www.test.com
    RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9]+)\.test.com$ 
    # AND {Host} == "(영문숫자조합).test.com"
    RewriteRule  .* /%1/$0 [L]                           
    # then > "(영문숫자조합)/$0"   (%1: RewriteCond의 첫 번째 괄호, $0: request uri)
  • 예제 11

    다음은 Request Header에 Referer Header가 없이 css나 js 파일을 요청하는 경우 403 Forbidden으로 처리하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex11
    RewriteCond %{HTTP_REFERER} !.        # if {HTTP_REFERER} == ""
    RewriteRule \.(css|js)$ - [F]         # then "*.css|*.js" > 403 Forbidden Return
  • 예제 12(REQEUST_URI)

    다음은 "/user@somehost.com/"과 같은 URL 패턴을 매칭하여 "/req_test.jsp?blogId=user@somehost.com"으로 변환하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex12 (REQEUST_URI)
    RewriteCond %{REQUEST_URI} /([a-zA-Z0-9_-]+(@([a-zA-Z0-9_-]+).(com|net|co.kr))?)/?$
    RewriteRule . /req_test.jsp?blogId=%1 [PT,L]
  • 예제 13(HTTP_HOST)

    다음은 HTTP Request Header의 호스트가 "tmaxsoft.com"으로 끝나고, URL이 "/redirect/"로 시작하는 경우를 매칭하여 "http://www.tmaxsoft.com/redirect.html"로 redirect하도록 하는 URLRewriteConfig 설정 예제이다.

    # url rewrite config - ex13 (HTTP_HOST)
    RewriteCond %{HTTP_HOST} tmaxsoft.com$
    RewriteCond %{REQUEST_URI} /redirect/.*$
    RewriteRule . http://www.tmaxsoft.com/redirect.html [R,L]

4.8. Filter 모듈 개발(Enterprise+)

WebtoB를 설치할 때 제공되는 usrinc/httpfilt.h 파일은 ISAPI(Internet Server Application Program Interface) Filter Interface를 제공한다. 해당 파일을 include하여 Filter 모듈을 개발할 수 있다. WebtoB Enterprise에서 제공되는 Filters process를 사용할 수 있다.

다음은 클라이언트 및 요청 정보 등을 확인하는 filter sample source 예제이다.

/**
 * file: sample.c for sample_filter
 * Linux 32bit에서 compile 예
 *   $ cc -m32 -D_REENTRANT -fPIC -I/webtob/usrinc -g -pthread -o sample.so sample.c -shared
 */ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include "httpfilt.h"


#define REDIRECT_PAGE "302 Moved Temporarily"

int wb_handler; /* WebtoB HTH count for only filters process */
time_t current_time;

int init()
{
  int n;

  /* set current time */
  time(&current_time);

  n = 0;
  /* n = init_check(); */

  return n;
}

void url_redirect(HTTP_FILTER_CONTEXT *pfc, char *url)
{
  pfc->ServerSupportFunction(pfc,
                             SF_REQ_SEND_RESPONSE_HEADER,
                             (LPVOID) REDIRECT_PAGE,
                             (LPDWORD) url,
                             0);
  return;
}

/**
 * called when WebtoB is booted..
**/
BOOL WINAPI
GetFilterVersion(HTTP_FILTER_VERSION * pVer)
{
  DWORD dwRet;

  /* Version 4.0 */
  /* pVer->dwFilterVersion = MAKELONG(0, 4); */
  pVer->dwFilterVersion = HTTP_FILTER_REVISION;
  strncpy(pVer->lpszFilterDesc, "filter sample", SF_MAX_FILTER_DESC_LEN);

  /* init when webtob is booting.. */
  wb_handler = 1; /* default */
#if 0 
  /* only filters process is used.. */
  if (0 < pVer->dwFlags) {
    wb_handler = pVer->dwFlags;
    pVer->dwFlags = 0;
    dwRet = init();
    if (dwRet < 0) {
      /* init failed.. */
      return 0;
    }
  }
#endif

  /* flags */
  pVer->dwFlags = (
        SF_NOTIFY_SECURE_PORT        |
        SF_NOTIFY_NONSECURE_PORT     |
        SF_NOTIFY_READ_RAW_DATA      |
        SF_NOTIFY_PREPROC_HEADERS    |
        SF_NOTIFY_URL_MAP            |
        SF_NOTIFY_AUTHENTICATION     |
        SF_NOTIFY_SEND_RAW_DATA      |
        SF_NOTIFY_LOG                |
        SF_NOTIFY_END_OF_NET_SESSION |
        SF_NOTIFY_ORDER_DEFAULT
        );

  return 1;
}


/**
 * run-time callback
**/
DWORD WINAPI HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType, VOID * pvNotification)
{
  DWORD dwRet;

  /* init when the first request.. */
  dwRet = init();
  if (dwRet < 0) {
    /* init failed.. */
    char redirect_page[256];

    sprintf(redirect_page, "Location: %s\r\n", "error.html");
    url_redirect(pfc, redirect_page);

    return SF_STATUS_REQ_FINISHED;
  }

  printf("\n\n start -> HttpFilterProc: NotificationType=%d, hth=%d \n",
         NotificationType, pfc->ulReserved);

  /* Direct the notification to the appropriate routine for processing. */
  switch (NotificationType) {
    case SF_NOTIFY_PREPROC_HEADERS:
      dwRet = process_preproc_headers(pfc, (PHTTP_FILTER_PREPROC_HEADERS) pvNotification);
      break;
    case SF_NOTIFY_SEND_RAW_DATA:
      dwRet = SF_STATUS_REQ_FINISHED_KEEP_CONN;
      break;
    case SF_NOTIFY_READ_RAW_DATA:
    case SF_NOTIFY_URL_MAP:
    case SF_NOTIFY_AUTHENTICATION:
    case SF_NOTIFY_LOG:
    case SF_NOTIFY_END_OF_NET_SESSION:
    default:
      dwRet = SF_STATUS_REQ_NEXT_NOTIFICATION;
      break;
  }
  return dwRet;
}

/**
 * process_preproc_headers
 *  GetHeader()
 *   - get the request header information
 *  GetServerVariable()
 *   - get the server variable information
 *  AddResponseHeaders()
 *   - add Response Header
 *  SetHeader()
 *   - add Request Header
 *  ServerSupportFunction()
 *   - set 302 Redirect page
**/ 
DWORD process_preproc_headers(HTTP_FILTER_CONTEXT *pfc, HTTP_FILTER_PREPROC_HEADERS *pvNotification)
{
  /* watch out buffer size */
  int size;
  char request_method[32];
  char request_uri[8192];
  char client_ip[256];
  char server_port[32];
  char content_type[256];
  char content_length[256];
  char body[10240];
  char s_header[8192];
  char cookie[8192];
  char add_res_header[8192];
  char redirect_page[8192];

  int redirect_test = 0;
  int setcookie_test = 1;

  /* ssl y/n */
  printf("Request is SSL? %d \n", pfc->fIsSecurePort);

  /* get request method */
  size = sizeof(request_method);
  memset(request_method, 0, size);
  /* pvNotification->GetHeader(pfc, "method", request_method, &size); */
  pfc->GetServerVariable(pfc, "REQUEST_METHOD", request_method, &size);
  printf("Request Method? %s \n", request_method);

  /* get request url */
  size = sizeof(request_uri);
  memset(request_uri, 0, size);
  /* pvNotification->GetHeader(pfc, "url", request_uri, &size); */
  pfc->GetServerVariable(pfc, "REQUEST_URI", request_uri, &size);
  printf("Request url? %s \n", request_uri);

  /* get client ip */
  size = (int) sizeof(client_ip);
  memset(client_ip, 0, size);
  pfc->GetServerVariable(pfc, "REMOTE_ADDR", client_ip, &size);
  printf("Client ip? %s \n", client_ip);

  /* get server port */
  size = (int) sizeof(server_port);
  memset(server_port, 0, size);
  pfc->GetServerVariable(pfc, "SERVER_PORT", server_port, &size);
  printf("Server Port? %s \n", server_port);

  /* get Content-Type Request Header */
  size = (int) sizeof(content_type);
  memset(content_type, 0, size);
  pvNotification->GetHeader(pfc, "Content-Type", content_type, &size);
  printf("Content-Type? %s \n", content_type);

  /* get Content-Length Request Header */
  size = (int) sizeof(content_length);
  memset(content_length, 0, size);
  pvNotification->GetHeader(pfc, "Content-Length", content_length, &size);
  printf("Content-Length? %s \n", content_length);

  /* get Cookie Request Header */
  size = (int) sizeof(cookie);
  memset(cookie, 0, size);
  pvNotification->GetHeader(pfc, "Cookie", cookie, &size);
  printf("Cookie? %s \n", cookie);

  /* get special header */
  size = sizeof(s_header);
  memset(s_header, 0, size);
  pvNotification->GetHeader(pfc, "Special-Header", s_header, &size);
  printf("Special-Header? %s \n", s_header);

  /* get body data */
  if (content_length) {
    size = (int) sizeof(body);
    memset(body, 0, size);
    pvNotification->GetHeader(pfc, "body", body, &size);
    printf("Body? %s \n", body);
  }

  /* add Response Header on processing request */
  if (setcookie_test) {
    sprintf(add_res_header, "Set-Cookie: %s=%s; path=/; domain=test\r\n", "TestKey", "TestValue");
    pfc->AddResponseHeaders(pfc, add_res_header, 0);
  }
  sprintf(add_res_header, "AddResponseHeader: test");
  pfc->AddResponseHeaders(pfc, add_res_header, 0);

  /* add Request Header */
  pvNotification->SetHeader(pfc, "addReuestHeader", "test value");

  /* 302 redirect */
  if (redirect_test) {
    sprintf(redirect_page, "Location: %s\r\n", "test/redirect.html");
    url_redirect(pfc, redirect_page);

    return SF_STATUS_REQ_FINISHED;
  }

  return SF_STATUS_REQ_NEXT_NOTIFICATION;
}