The qDecoder Project

For CGI Newbies


  1. 제가 사용하는 서버가 어떤 기종(Platform) 입니까?
  2. CGIWrap을 거쳐 CGI를 사용하라고 하던데…
  3. CGIWrap을 사용하지 않고 같은 효과를 낼순 없습니까?
  4. 쿠키(Cookie)는 먹는 것입니까?
  5. SSI가 무엇이며, 어떨 때 사용합니까?
  6. 파일 업로딩이 어떻게 가능한가요?

  1. 제가 사용하는 서버가 어떤 기종(Platform) 입니까?

    CGI는 보통 C/C++, Perl, PHP 등의 언어로 제작됩니다. 이중 Perl, PHP등의 언어로 짜여진 CGI 스크립트는 서버의 종류와 상관없이 실행이 가능하지만, C/C++로 짜여진 프로그램은 직접 프로그램을 컴파일하지 않는 이상, 플랫폼별로 제공되는 실행파일을 얻어야 합니다. 웹사이트를 구축하다보면, 여러 종류의 CGI를 혼용해서 사용하게 되므로, 다음과 같이 자신이 사용하는 서버의 종류를 파악해 두십시요.

    $ uname -a
    SunOS sun 5.5.1 Generic_103640-14 ... (SunOS 5.5.1 = Solaris 2.5.1)
    $ uname -a
    FreeBSD freebsd.nobreak.com 2.2.8-STABLE ... (FreeBSD 2.2.8)
    

    대표적으로 많이 사용되는 운영체제는 크게 Solaris, FreeBSD, Linux 등이 있습니다. 시스템 기종에 의존적인 제품들은, 반드시 자신의 서버 기종에 맞는 파일을 사용하여야 합니다.

  2. CGIWrap을 거쳐 CGI를 사용하라고 하던데…

    CGIWrap은 사용자의 CGI가 웹서버의 uid/gid가 아닌 사용자의 uid/gid로 동작하도록, 웹서버와 CGI를 연결해 주는 프로그램입니다. 유닉스 시스템은 기본적으로 멀티-유저 환경이기 때문에, 사용자간의 권한 범위를 제한하기 위해서 uid(User ID), gid(Group ID)라는 개념을 사용합니다.

    누구나 시스템의 주요파일을 수정할 수 있다면, 정말 문제겠지요? 여러분의 홈페이지를 인터넷에 펌핑하는 웹서버 또한, 특정 uid/gid를 갖고 운용되기 때문에, 호출되는 CGI는 여러분의 uid가 아니라, 웹서버의 uid로 실행되게 됩니다. 예로, 전화번호부 CGI ‘phone.cgi’가 있다고 가정합니다. 이 CGI는 이름과 전화번호를 입력받아, phone.txt 파일에 내용을 추가하도록 구현되어 있습니다.

    웹서버는 nobody/nobody로 운영되고, 여러분의 uid/gid는 nobreak/power 라고 할 때, CGI의 실행결과로 생성된 phone.txt 파일은 어떤 소유주를 갖게 될까요? CGIWrap을 거치지 않았을 경우엔 웹서버의 uid/gid인 nobody/nobody를 갖습니다. 그렇다면, 여러분은 phone.txt 파일을 쉘상에서는 수정하거나 삭제하질 못하겠지요.

    이러한 문제로 인해 CGIWrap이 개발되었고, 사용됩니다. CGIWrap을 사용하면 phone.cgi가 사용자의 권한으로 실행되어 phone.txt가 nobreak/power로 생성됩니다. 하지만 CGIWrap을 사용하기 위해서는 지정된 디렉토리에 CGI가 위치하여야 하고, 퍼미션이 제한되는 등의 번거로운면이 없지않아 있습니다. CGIWrap을 사용할때에는 다음과 같이 링크하십시요.

    http://도메인명/cgi-bin/cgiwrap/사용ID/CGI파일
    http://www.nobreak.com/cgi-bin/cgiwrap/nobreak/phone.cgi
    

    한가지 주의할 점은, 지정된(public_html/cgi-bin) 위치에 CGI를 위치하여야 CGIWrap이 찾을 수 있다는 것입니다. 시스템마다 다를 수 있으니, 해당 ISP의 서비스 안내서를 참고 하십시요.

  3. CGIWrap을 사용하지 않고 같은 효과를 낼순 없습니까?

    반드시 CGIWrap을 사용해야만 자신의 uid/gid로 CGI를 실행할 수 있는 것은 아닙니다. CGI 퍼미션을 다음과 같이 6755로 조정하십시요.

    $ chmod 6755 phone.cgi
    $ ls -al
    -rwsr-sr-x   1 nobreak  power      148526 Jan  4 04:12 phone.cgi
    

    6755 퍼미션은 ‘실행 + set-uid + set-gid’을 뜻합니다. set-uid/set-gid 비트란 본 파일이 실행될 때, 호출하는 프로세스의 권한이 아닌, 파일자체의 uid/gid 값을 위임받으라는 의미입니다. 따라서, 본 파일의 소유주는 nobreak/power 이므로, 웹서버(nobody/nobody)가 CGI를 호출할 때에도, CGI는 nobreak/power로 실행되게되며, phone.txt 또한 nobreak/power로 생성됩니다. 이때에는 일반적인 HTML과 같이 링크 합니다.

    http://www.nobreak.com/~nobreak/cgi-bin/phone.cgi
    

    주의: 본 방법은 Perl, Shell 스크립트에는 적용되지 않고, C/C++ 등으로 짜여져 독립적으로 실행될 수 있는 프로그램에만 가능합니다. 이는, Perl로 짜여진 스크립트 perlphone.cgi는 실제 ‘perl perlphone.cgi’와 같이 실행되어, perlphone.cgi가 단순히 소스파일로만 해석되기 때문입니다. perl 자체가 아닌, 소스파일에 부여된 set-uid 비트는 의미가 없습니다.

  4. 쿠키(Cookie)는 먹는 것입니까?

    일반 응용 프로그램과, CGI 프로그램의 가장 큰 차이라고 하면, 정보가 유지되지 않는 것을 꼽을 수 있습니다. 쿠키는 클라이언트(브라우저)에 정보를 저장해 두었다가, 특정 URL에 연결할 때 저장된 정보를 서버에 재 전송하는 시스템을 말합니다. 게시판에 글을 작성한 후, 다시 글을 쓰려고 할때 성명과 Email이 자동으로 표시되는 것과 쇼핑몰에서의 장바구니 등은 이러한 쿠키 기능을 활용한 것입니다.

    쿠키는 웹의 한계를 극복하기 위해 만들어졌습니다. 웹에 사용되는 통신 규약인 HTTP 프로토콜은 정보의 링크를 뛰어 다니는 Hyper Text를 위주로 했기 때문에, 단방향으로 제공되는 정보만이 고려되었고 인터넷 트래픽을 줄이며 빠르게 뛰어다닐 수 있도록 비연결지향적으로 설계되었습니다.

    따라서, telnet, ftp와 달리 서버, 클라이언트간 연결에 초기화 작업이 필요 없고, 요청이 있을 때마나 서버에 접속을 하게 됩니다. 언뜻 보면 매우 비효율적일 듯 하지만, 이는 웹에서 매우 효과적으로 트래픽을 차단합니다. 네트워크가 10 바이트를 수용하고, 하나의 연결이 1 바이트라고 할 때, 웹이 telnet과 같은 방식으로 동작한다면, 10명의 사람이 넷스케이프를 띄워 놓으면 다른 사람은 인터넷을 사용할 수 없게 되지만, 웹은 클릭을 해서 정보를 송/수신하는 순간에만 자원을 사용하기 때문에, 더 많은 인원이 동시에 인터넷을 사용할 수가 있습니다.

    하지만, 이로 인해 새로운 연결과 이전 연결과의 고리가 없어지기 때문에, 필요한 과거 정보를 저장하기 위한 수단으로 쿠키가 구상되었습니다.

  5. SSI가 무엇이며, 어떨 때 사용합니까?

    SSI란 Server Side Include의 약자입니다. 어떻게 보면, 정적이지 않은 가공된 자료라는 점에서 CGI와 흡사합니다. SSI는 요청된 HTML 문서가 송신되기 전에, 문서상의 약속기호를 웹서버가 전 처리하는 것을 말합니다.

    회사 홈페이지에 100개의 문서가 있고, 모든 문서 상단에 “Product, Download, Contact”라는 링크가 있습니다. 만약, “Product”라는 문구를 “Products”라고 수정을 해야 한다면, 100개의 문서를 모두 수정해야 할까요? 일반적으론 그렇습니다. 하지만, SSI가 사용되었다면 간단하게 수정될 수 있을 것 입니다.

    ‘titlelink.html’라는 파일에 “Product, ….”를 작성하고, 모든 문서에 다음과 같은 라인을 포함합니다.

    <!--#include virtual="/titlelink.html"-->
    

    웹서버는 HTML 문서를 송신전에 해석하여 태그 위치에 titlelink.html 내용을 삽입한후 뿌려줍니다. 100개의 문서는 순간적으로 변신하겠지요. ‘<!–#……–>’는 주석이 아니라, SSI 약속 기호입니다.

    다음은 금일 날자와, 현재 문서명, 마지막 수정일을 표시하는 예 입니다.

    Today is <!--#config timefmt="%m/%d %Y"--><!--#echo var="DATE_LOCAL"-->,
    This document, <!--#echo var="DOCUMENT_NAME" -->, was last modified at
    <!--#config timefmt="%m/%d %Y(%H:%M:%S)"--><!--#echo var="LAST_MODIFIED"-->.
    

    다음과 같이 보여질 것입니다:

    Today is 10/07 2008,
    This document, ko-newbies.qsp, was last modified at 12/13 2007(17:59:30).
    

    CGI를 포함하여 시스템 명령까지도 그 출력 결과를 포함할 수 있습니다.

    <!--#include virtual="/cgi-bin/CrazyWWWBoard.cgi?db=test"-->
    <!--#exec cmd="/bin/ls /home"-->
    

    SSI 문서는 보통 .shtml 확장자를 갖습니다. test.shtml과 같은 파일을 만들어 SSI 지원여부를 확인하시기 바랍니다. SSI를 여러모로 활용하면 수월하게 웹사이트를 가꿀 수 있을 것 입니다.

    주의: 본 예는 NCSA, Apache 웹서버에서 정확히 동작하며, 다른 웹서버일 경우 조금씩 차이가 있습니다.

  6. 파일 업로딩이 어떻게 가능한가요?

    파일 업로딩은 ‘multipart/form-data’ 인코딩을 통해 서버측에 전송됩니다. 다음은 HTML 태깅 예입니다.

    <form method="post" action="https://qdecoder.org" enctype="multipart/form-data"> <input type="file" name="filename"> <input type="submit" value="전송"> </form>
    지금과 같이 ‘multipart/form-data’로 명시된 경우엔 환경변수 ‘CONTENT_TYPE’으로 취할 수 있는 분리자 boundary 문자열로 다음과 같이 입력되는 표준입력(stdin)의 인자를 해석하여야 합니다.
    환경변수 CONTENT_TYPE
    multipart/form-data; boundary=---------------------------16079141025132
    
    STDIN
    -----------------------------16079141025132
    Content-Disposition: form-data; name="filename"
    index.html
    -----------------------------16079141025132
    Content-Disposition: form-data; name="binary"; filename="X:public_htmlindex.html"
    Content-Type: text/html
    내용
    -----------------------------16079141025132--
    

    주의) 각 섹션간에는 환경변수로 얻은 boundary 문자열 앞에 “–“를 추가하여 분리하고, 문서의 끝은 앞, 뒤에 “–“가 삽입된 boundary로 구분됩니다.

    stdin으로 전달받은 각 변수는 ‘–boundary’ -> 변수명 -> CR + LF -> 변수값의 순서로 해석할 수 있으며, 변수값은 URL Encoding방식과 달리 특수문자(한글 및 제어문자)도 변형없이 전달됩니다.

    Upload될 파일이 Mimetype에 등록되어 있지 않을경우 ‘Content-Type: Mimetype’ 행은 출력되지 않습니다.


[Home] [About] [Examples] [Changes] [Download] [SVN Repository] [Install] [Reference]