인코딩
- 공백: +로 대치
- 폼의 이름과 값: name=value
- 이름, 값의 쌍: name1=value1&name2=value2
- 특수문자: %HH
HTTP의 동작원리
HTTP의 동작원리를 알아보기위해 telnet을 이용해 보자. 다음은 telnet을 이용해서 웹서비스를 제공받는 예이다. Unix 명령행에서 다음과 같이 입력해 보기바란다.
GET에 의한 문서의 요청
% telnet syscon.soongsil.ac.kr 80
Trying 203.253.15.34 ...
Connected to syscon.soongsil.ac.kr.
Escape character is '^]'.
GET /~artech/cgi-bin/rguest.cgi?key=김 HTTP/1.0
HTTP/1.0 200 OK
Server: Microsoft-PWS/3.0
Date: Wed, 10 Sep 1997 18:02:48 GMT
Content-Type: text/html
Accept-Ranges: bytes
Last-Modified: Tue, 09 Sep 1997 16:32:24 GMT
Content-Length: 708
<html>
<head>
<TITLE>Welcome to DoA's World !!!</TITLE>
</head>
...
</html>
Connection closed by foreign host.
POST에 의한 문서의 요청
% telnet syscon.soongsil.ac.kr 80
Trying 203.253.15.34 ...
Connected to syscon.soongsil.ac.kr.
Escape character is '^]'.
POST /~artech/cgi-bin/wguest.cgi HTTP/1.0
content-length: 45
realname=JaeGeun&comments=No+Comments
HTTP/1.0 301 Moved
Location: /~artech/cgi-bin/rguest.cgi
Connection closed by foreign host.
위의 예에서 알 수 있듯이 HTTP는 다음과 같은 방법으로 동작한다.
DNS->IP % tn comp.mailx2.com 80
Trying 210.206.89.230...
IP 이용 접속 Connected to comp.mailx2.com.
Escape character is '^]'.
HTTP 요청 GET /~artech/cgi-bin/rguest.cgi?key=김 HTTP/1.0
HTTP 응답 HTTP/1.0 200 OK
Content-type: text/html
Last-modified: Saturday, 07-Mar-98 04:33:36 GMT
Content-length: 947
<html>
...
<html>
접속해제 Connection closed by foreign host
클라이언트는 TCP/IP를 통해 DNS를 IP로 변환한다. 이렇게 변환된 IP를 이용해서 원격호스트에 접속하고, HTTP를 통해 문서를 요청한다. 서버는 파일 시스템으로부터 클라이언트가 요청한 문서를 읽어 HTTP를 통해 클라이언트에 전송한다. 전송이 끝나면 서버는 TCP/IP 접속을 종료하게된다.
즉, HTTP는 접속, 요청, 응답, 접속해제의 네 단계로 진행된다.
CGI의 동작
CGI도 웹상에서 HTTP를 통해 동작하므로 HTTP와 동일한 절차에 따라 동작한다. 다만 한가지 차이는 일반적인 문서의 경우에는 파일 시스템으로부터 문서를 읽어 전송하지만 CGI의 경우에는 파일이 아니라 CGI를 실행한 결과를 클라이언트에 전송 한다는 점이다.
TCP/IP DNS를 IP로 변환(Lookup Host)
TCP/IP IP를 이용해서 접속(Contacting Host)
HTTP HTTP 명세에 따라 문서요청(Request Message)
Server 서버의 상태를 환경변수로 저장하고 CGI 호출
CGI 환경 변수를 이용, 적당한 처리를 한 후, 결과를 서버에 전달
Server CGI 출력에 헤더를 더해 응답 메시지 구성
HTTP HTTP 명세에 따라 응답(Replay Message)
TCP/IP 접속해제
일반적인 경우 웹상에서의 요청은 하이퍼링크(Hyper Link)를 통해서 이루어지지만 CGI의 요청은 주로 Form 태그나 Isindex 태그를 통해서 이루어진다. 또한 보통의 요청일 경우에는 웹 서버는 곧바로 요청한 문서를 파일 시스템으로부터 읽어들인 다음 클라이언트 측으로 전달하게 된다. 그러나 요청된 URL이 CGI 프로그램일 경우는 그 CGI 프로그램을 호출해서 CGI 프로그램이 동적으로 생성하는 문서를 클라이언트 측으로 전달하게 된다.
사용자가 Form 태그의 제출(Submit) 버튼을 클릭하면 클라이언트는 현재의 시간, 날짜와 같은 시스템 정보와 사용자의 ID, 사용자의 도메인명과 같은 사용자 정보를 포함한 요청 메시지(Request Message)를 웹 서버에 전송한다.
웹 서버는 요청된 URL이 어떤 종류의 파일(SSI, CGI, Perl)인가를 분석한 후, CGI 프로그램일 경우 요청 헤더(Request Header)에 포함된 상태정보를 환경변수(QUERY_STRING, CONTENT_LENGTH 등등)로 설정하고 나서 CGI 프로그램을 실행시키게 된다.
그러면 CGI 프로그램은 다른 서비스를 이용하기 위해 다른 프로그램을 다시 또 호출하거나 아니면 직접 처리를 한 다음 사용자에게 보여줄 문서를 표준 출력으로 보내게 된다. 그러면 이것을 받은 서버는 다시 클라이언트 측으로 네트워크를 통해 결과를 전송하게 된다. 따라서 어떤 CGI 프로그램을 작성하느냐에 따라서 다양한 서비스를 제공할 수 있다.
CGI 프로그램
CGI는 입력과 출력을 정의한 게이트웨이의 표준안이며, 이 표준안에 따라 작성한 프로그램이 CGI프로그램이다. 따라서 CGI는 어떠한 프로그래밍 언어로도 작성할 수 있으며, 심지어는 도스의 배치파일로도 작성할 수 있다.
어떠한 언어를 사용할 것인가 하는 문제는 CGI 프로그래머의 취향에 달린 문제이지만 C/C++, Fortran등과 같은 컴파일 언어는 CGI 프로그램을 수행하는 시간면에서 잇점이 있지만 매번 프로그램을 컴파일을 해야한다는 점 때문에 Perl, Tcl, Shell 등과 같은 스크립트 언어가 CGI 프로그래밍 언어로 많이 사용되고 있다.
CGI 프로그램과 일반프로그램의 차이
| [hello.pl]
#! /usr/local/bin/perl
print "Hello, World!"; |
[hello.cgi]
#! /usr/local/bin/perl
print "Content-Type: text/html\n\n";
print "<html><body>\n";
print "Hello, World!\n";
print "</body></html>"; |
hello.cgi의 실행예
hello.cgi
위의 두 프로그램 모두 화면상에 "Hello, World!"라는 메시지를 출력한다. 그러나 hello.pl이 "Hello, World!"라는 메시지만 화면에 출력하는 반면에 hello.cgi는 CGI 표준에따라 "Content-type: text/html\n\n"을 먼저 출력한다.
일반적으로 인터넷 표준인 MIME(Multipurpose Internet Mail Extension)은 접미사(Suffix 또는 확장자)에의해 파일형식을 구분하는 방법이다. 그러나 CGI는 임의의 MIME 형식을 출력할 수 있다. 앞서의 예에서 보면 방명록의 경우에는 text/html이라는 MIME 형식을 출력하지만 웹 카운터는 image/gif 라는 MIME 형식을 출력한다.
따라서 CGI의 출력은 접미사(Suffix 또는 확장자)에의해서는 구분할 수 없으므로 CGI 명세에서는 CGI의 첫 번째 출력은 현재 출력되는 문서가 어떤 형식의 문서인지를 브로우저가 알 수 있도록 헤더 정보를 출력하도록 규정하고 있다. 헤더 정보는 "Content-Type: Main-Type/Sub-Type\n\n"의 형식에 반드시 맞추어야 한다.
즉, 먼저 문서 형식을 타나내는 헤더정보라는 것을 알려주는 "Content-Type:"에 문서의 형식을 "Main-Type/Sub-Type"의 형태로 출력하고 헤더와 Body를 구분하기위해 공백 라인을 하나 추가해야 한다.
이 형식에 맞지 않은 경우, 서버는 보통 "Document contains no data"나 "500 Internal Server Error"라는 오류 메시지를 출력하게 된다. Content-Type은 일반 텍스트 파일일 경우는 "text/plain", HTML 문서일 경우는 "text/html", JPEG 이미지일 경우는 "images/jpeg"등이 가능하며 각각의 파일에 따라서 MIME 유형이 정의되어 있다.
따라서 HTML 문서로 인식할 수 있도록 하기 위해서는 문서의 본 내용이 출력되기 전에 "Content-Type: text/html\n\n"이란 헤더를 반드시 출력해야만 한다.
두번째로 문서를 Content-Type에 맞게 출력해야만 한다. 위의 예에서는 Content-Type이 text/html이므로 "Hello, World!"의 앞뒤로 "<html><body>", "</body></html>"를 추가했다.
CGI 프로그램의 실행
명령행에서 CGI 프로그램의 실행
CGI 작성시 한가지 주의할 점은 CGI 프로그램 역시 실행 프로그램이라는 점이다. 일반 프로그램과의 차이점은 일반 프로그램은 주로 명령행에서 실행되는 반면 CGI 프로그램은 주로 Web에서 실행된다는 것이다. CGI 프로그램도 실행 프로그램이므로 반드시 명령행에서 먼저 실행한 후 웹 상에서 실행해야 한다.
위의 예는 Perl Script로 작성됐으므로 hello.cgi를 실행파일로 만들기위해서는 다음과 같은 명령으로 실행권한을 주어야 한다.
% chmod 755 cgi_program
% cgi_program
웹상에서 실행
명명행에서 CGI가 정상적으로 수행되었으면 클라이언트의 위치(Location)상자에 CGI의 URL을 직접입력함으로서 CGI를 실행시킬 수 있다. 즉,
http://ix.bit.co.kr/~artech/cgi-bin/hello.cgi
위의 명령을 수행해서 "Hello World!"라는 메시지가 출력되면 CGI는 정상적으로 수행된 것이다.
웹과 시스템의 디렉토리 구조
다음 그림은 Unix 시스템 경로와 URL 사이의 관계를 나타낸 것이다. 괄호로 표시된 것은 해당 URL에대한 시스템 경로이며, 회색으로 표시한 디렉토리의 하위 디렉토리만 웹에서 접근 가능하다.
또한 (Server)로 표시한 디렉토리는 웹서버 설정에의해 접근 가능한 디렉토리이다.
CGI 작성시 유의 사항
다음은 CGI 프로그램을 작성할 때 유의할 사항이다. CGI 프로그램에서 500 Internal Server Error가 발생하는 이유는 다음 주의 사항을 지키지 않았기 때문이다. 반드시 다음 유의 사항을 숙지하고 꼭 지켜주기 바란다.
- 확장자
CGI의 확장자는 가급적 .cgi로 한다. 서버의 설정에 따라 확장자가 .cgi가 아닌경우에는 CGI가 실행되지 않을 수도 있다.
- 디렉토리
CGI는 가급적 cgi-bin 디렉토리에서 기동한다. 대부분의 웹서버의 설정이 cgi-bin 디렉토리에서만 CGI 실행이 가능하도록 되어 있다.
- 퍼미션
CGI 프로그램을 실행하는 중에 가장 빈번하게 발생하는 문제는 퍼미션 문제이다. 반드시 다음 사항에 따라 퍼미션을 확인한 후 CGI를 실행하기 바란다.
CGI 프로그램: 755 chmod 755 guest.cgi
데이터파일: 666 chmod 666 guest.dat
읽기/쓰기용 디렉토리: 777 chmod 777 upload
- Unix 명령행에서 실행
명령행에서 CGI를 실행하고 CGI의 출력이 다음과 같은 형식인가 꼭 확인한다.
명령행: > ctype.cgi
헤 더: Content-type: text/html
빈 줄:
본 문: <html>
본 문: <body>
본 문: ...
본 문: </body>
본 문: </html>
- Web에서 실행
http://ix.bit.co.kr/~artech/cgi-bin/guest.cgi