날짜: 1996-07-06 | 글쓴이: 도아 | 6246 번 | 프린트 | 메일로보내기

제 6강 - 고급기능


넷스케잎 쿠키

넷스케잎 1.1이상의 버전은 소위 쿠키라는 것을 지원한다. 이 쿠기는 브로우저 세션정보를 유지하기위해 고안된 것이다. CGI.pm은 쿠키를 지원하는 여러가지 메소드를 가지고 있다.

쿠기는 CGI 질의 문자열내의 매개변수처럼 name=value 쌍으로 구성된다. CGI 스크립트는 하나 또는 그 이상의 쿠키를 생성하고 이들을 HTTP 헤더를 통해 브로우저로 전송한다. 브로우저는 특정 웹 서버에 속한 쿠키 목록을 유지하고 있다가 이어지는 세션동안 CGI 스크립트에 이들 쿠키를 리턴한다.

반드시 필요한 name=value 쌍 이외에 각각의 쿠키는 추가적인 여러 가지 속성을 가질 수 있다.

  1. 만료기간(expires) 이 것은 쿠키의 만료 시점을 지시하는 시간/날자 문자열(특수한 GMT 형식)이다. 넷스케잎을 종료하고 다시 시작할 지라도 쿠키는 만료일에 도달할 때까지 유지되며 CGI 스크립트로 리턴된다. 만료일이 지정되지 않으면 쿠키는 넷스케잎을 종료할 때까지만 유효하게 된다.

    참고: 넷스케잎의 쿠기는 Netscape(Netscape 4.0미만)폴더나 user/userid(Netscape 4.0이상) 폴더의 cookies.txt라는 파일로 저장된다.

  2. 도메인(domain) 이 것은 쿠키가 유효한 부분 또는 완전한 도메인 명이다. 브로우저는 부분 도메인 명이 일치하는 호스트에대해 쿠키를 리턴한다. 예를들어 도메인 이름을 ".soongsil.ac.kr"로 지정하면 넷스케잎은 ".soongsil.ac.kr."내에 존재하는 컴퓨터(comp.mailx2.com, syscon.soongsil.ac.kr, cupid.soongsil.ac.kr 등)에서 기동되는 웹서버에만 쿠기를 리턴한다. 도메인 명은 적어도 두개이상의 마침표(.)를 포함해야 한다. 이 것은 ".kr"과 같이 최상위 도메인을 사용하지 못하게하기 위한 것이다. 어떠한 도메인도 지정되지 않으면 브로우저는 쿠키를 설정한 서버에만 쿠키를 리턴한다.

  3. 경로(path) 쿠기에 경로 속성을 제공하면 쿠키를 리턴하기전에 스크립트의 URL을 검사한다. 예를들어 "/cgi-bin"이라는 경로를 지정하면 "/cgi-bin/tally.cgi", "/cgi-bin/order.cgi"과 "/cgi-bin/customer_service/complain.cgi"라는 스크립트 각각에 대해서는 쿠키가 리턴되지만 "/cgi-private/site_admin.cgi" 스크립트에는 쿠키가 리턴되지 않는다. 기본적으로 경로는 "/"로 설정되며 따라서 해당 도메인의 모든 CGI 스크립트로 쿠기가 전송된다.

  4. secure "secure" 속성이 설정되면 쿠키는 SSL과 같은 보안 통신로를 통해 CGI 요청이 이루어 지는 경우에만 스크립트로 쿠키를 전송한다.

넷스케잎 쿠기에대한 인터페이스는 cookie() 메소드이다.

$cookie = $query->cookie(-name=>'sessionID',
	-value=>'xyzzy',
	-expires=>'+1h',
	-path=>'/cgi-bin/database',
	-domain=>'.soongsil.ac.kr',
	-secure=>1);
print $query->header(-cookie=>$cookie);

cookie()는 새로운 쿠키를 생성한다. cookie()의 매개변수는 다음과 같다.

-name
쿠기의 이름(반드시 필요). 이것은 임의의 문자열일 수 있다. 비록 넷스케잎이 공백이 아닌 영문자와 숫자로 제한했지만 CGI.pm은 배후에서 쿠키의 특수문자를 자동으로 삽입, 제거함으로서 이러한 제한을 극복했다.

-value
쿠기의 값. 이 것은 임의의 스칼라, 배열, 심지어는 연관배열일 수 있다. 예를들어 다음과 같은 방법으로 전체 연관배열을 저장할 수 있다.

$cookie=$query->cookie(-name=>'family information',
	-value=>\%childrens_ages);

-path
쿠키가 유효한 부분 경로 정보(조건부)로서 위에서 설명했다.

-domain
쿠키가 유효한 부분 도메인 정보(조건부)로서 위에서 설명했다.

-expires
쿠키의 만료일(조건부). 형식은 header() 메소드에 대한 절에서 설명했다.

"+1h"  지금부터 한시간

-secure
참으로 설정되면 이 쿠키는 보안 SSL 세션을 통해서만 전송된다.

cookie()
에의해 생성된 쿠키는
<A HREF="perl-cgipm3.htm#CREATING_A_STANDARD_HTTP_HEADER_">header()</A>
메소드에의해 리턴된 문자열내에 HTTP 헤더로 병합된다.

print $query->header(-cookie=>$my_cookie);

다중 쿠키를 생성하기 위해

<A HREF="perl-cgipm3.htm#CREATING_A_STANDARD_HTTP_HEADER_">header()</A>
에 배열을 전달하면 된다.

$cookie1 = $query->cookie(-name=>'riddle_name',
	-value=>"스핑크스의 수수께끼");
$cookie2 = $query->cookie(-name=>'answers',
	-value=>\%answers);
print $query->header(-cookie=>[$cookie1,$cookie2]);

쿠키를 복원하기위해 -value 매개변수 없이

cookie()
메소드를 호출한다.

use CGI;
$query = new CGI;
%answers = $query->cookie(-name=>'answers');
# $query->cookie('answers') 역시 잘 동작한다

쿠기와 CGI 이름공간은 분리되어 있다. 'answers'라는 기명 매개변수와 'answers'라는 쿠키를 가지고 있다면 이들은

param()
cookie()
에의해 독립적으로 리턴된다. 그러나 CGI 매개변수를 cookie로 변환하고, cookie를 CGI 매개변수로 변환하는 것은 쉽다.

# CGI 매개변수를 쿠키로 변환
$c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
# 꺼꾸로
$q->param(-name=>'answers',-value=>[$q->cookie('answers')]);

주의: 넷스케잎 쿠키에대한 몇몇 문서화되지 않은 제한이 있다. 적어도 넷스케잎 2.01에서 필자는 한번에 3개 이상의 쿠키를 설정할 수 없었다. 또한 쿠키의 길이도 제한된다. 많은 양의 정보를 저장할 필요가 있다면 유일한 세션 ID를 생성하고 이 것을 쿠키에 저장한 후 이 세션 ID를 이용해서 서버측의 파일이나 DB에 정보를 저장하는 것이 보다 나은 방법일 것이다.

쿠키를 효과적으로 사용하는 방법을 알아보기 위해서는 cookie.cgi를 본다.

 1 : #!/usr/local/bin/perl
 2 : 
 3 : use CGI qw(:standard);
 4 : 
 5 : @ANIMALS=sort qw/사자 호랑이 곰 새끼돼지 호저 앵무새 얼룩말 암소 타조
 6 :     에뮤 모아 염소 족제비 야크 닭 양 하이에나 도도 놈팡이
 7 :     다람쥐 쥐 생앙쥐 고슴도치 너구리 비비 캥가루 하마
 8 :     기린/;
 9 : 
10 : # 쿠키로부터 이전 동물을 복원한다.
11 : # 쿠키는 동물이름을 키로 동물의 수를 값으로한
12 : # 연관배열에 저장된다.
13 : %zoo = cookie('animals');
14 : 
15 : # 'new_animal' 매개변수로부터 새로운 동물을 복구한다.
16 : @new = param('new_animals');
17 : 
18 : # 액션이 'add'면 새로운 동물을 동물원에 추가한다. 그렇치 않으면 
19 : # 이들을 제거한다.
20 : foreach (@new) {
21 :     if (param('action') eq '추가') {
22 : 	$zoo{$_}++;
23 :     } elsif (param('action') eq '삭제') {
24 : 	$zoo{$_}-- if $zoo{$_};
25 : 	delete $zoo{$_} unless $zoo{$_};
26 :     }
27 : }
28 : 
29 : # 새로운 동물을 이전 목록에 추가하고 이들을 쿠키에 둔다.
30 : $the_cookie = cookie(-name=>'animals',
31 : 		     -value=>\%zoo,
32 : 		     -expires=>'+1h');
33 : 
34 : # 쿠키와 만류일을 병합한 헤더를 추력한다.
35 : print header(-cookie=>$the_cookie);
36 : 
37 : # HTML 문서를 만든다.
38 : print start_html('동물 사냥');
39 : 
40 : print <<EOF;
41 : <h1>동물사냥</h1>
42 : 동물원에 추가하려는 동물을 선택하고 "추가"버튼을 클릭한다. 한시간 내에
	다시 이 페이지로 돌아와 보면 동물원의 동물 목록 복구될 것이다. 심지어 
	넷스케잎을 완전히 종료할 수도 있다.
43 : 
44 : <p>
45 : 동일한 동물을 여러번 목록에 추가하라. 
46 : 
47 : <p>
48 : <em>이 스크립트는 넷스케잎 2.0 이상, M$IE 3.0이상에서만 동작한다.</em>
49 : 
50 : <p>
51 : <center>
52 : <table border>
53 : <tr><th>추가/삭제<th>현재 목록
54 : EOF
55 :     ;
56 : 
57 : print "<tr><td>",start_form;
58 : print scrolling_list(-name=>'new_animals',
59 : 		     -values=>[@ANIMALS],
60 : 		     -multiple=>1,
61 : 		     -override=>1,
62 : 		     -size=>10),"<br>";
63 : print submit(-name=>'action',-value=>'삭제'),
64 :     submit(-name=>'action',-value=>'추가');
65 : print end_form;
66 : 
67 : print "<td>";
68 : if (%zoo) {			# 표를 만든다
69 :     print "<ul>\n";
70 :     foreach (sort keys %zoo) {
71 : 	print "<li>$zoo{$_} $_\n";
72 :     }
73 :     print "</ul>\n";
74 : } else {
75 :     print "<strong>동물원이 비었습니다.</strong>\n";
76 : }
77 : print "</table></center>";
78 : 
79 : print <<EOF;
80 : print end_html;
실행결과

cookie.cgi

쿠기에대한 추가적인 정보는 쿠기을 보기바란다. 넷스케잎의 프레임 사용하기

CGI.pm은 넷스케잎의 프레임을 사용해서 브로우저의 여러 프레임에 HTML 문서를 쓰는 것이 가능하다. 프로그램적으로 새로운 프레임을 정의하는 세가지 기법이 있다.

  1. <Frameset> 태그로 문서를 생성 HTTP 헤더를 쓴 후,
    <A HREF="perl-cgipm3.htm#CREATING_THE_HTML_DOCUMENT_HEADE">start_html()</A>
    를 호출함으로서 표준 문서를 생성하는 대신에 페이지에대한 프레임을 정의하는 <FRAMESET> 문서를 생성한다. 프레임 각각에대한 SRC로서
    스크립트
    (적당한 매개변수와 함께)를 지정한다.

    CGI.pm에서는 <FRAMESET> 섹션을 생성하는 어떠한 것도 지원하지 않지만 HTML로 아주 간단히 생성할 수 있다. 보다 자세한 것은 넷스케잎 홈페이지의 프레임에대한 문서를 보기 바란다.

    <A HREF="http://home.netscape.com/assist/net_sites/frames.html">http://home.netscape.com/assist/net_sites/frames.html</A> <a href='http://home.netscape.com/assist/net_sites/frames.html' target='_blank' style='border-bottom: none'><IMG src='/images/external.png' align='middle' border=0 style='border-bottom: 0'></a>

  2. HTTP 헤더내에 문서에대한 목적 창을 지정
    <A HREF="perl-cgipm3.htm#CREATING_A_STANDARD_HTTP_HEADER_">header()</A>
    메소드에 -target 매개변수를 제공할 수 있다.

    print $q->header(-target=>'ResultsWindow');

    이 것으로 넷스케잎은 프레임 이름이 "ResultsWindow"인 프레임으로 스크립트의 출력을 읽게된다. 만약 이 이름의 프레임이 존재하지 않으면 넷스케잎은 새로운 창을 열고 이 창으로 스크립트의 결과를 읽는다. 목적 창의 이름은 다양한 형태로 사용할 수 있다. 보다 자세한 것은 넷스케잎 홈페이의 프레임에대한 문서 를 보기 바란다.

  3. <FORM> 태그에서 문서의 목적창을 지정 FORM 태그에서 읽혀질 프레임을 지정할 수 있다. CGI.pm에서 이 것은 다음과 같은 형식을 갖는다.

    print $q->startform(-target=>'ResultsWindow');

    스크립트가 폼에의해 다시 호출될 때 이 스크립트의 출력은 프레임 이름이 "ResultsWindow"인 창에 출력될 것이다. 해당 프레임이 존재하지 않는다면 새로운 창이 생성될 것이다.

frameset.cgi은 입력폼과 그 응답을 인접 프레임으로 전송하는 방법을 보이고 있다.

 1 : #!/usr/local/bin/perl
 2 : 
 3 : use CGI;
 4 : $query = new CGI;
 5 : print $query->header;
 6 : $TITLE="프레임셋의 예";
 7 : 
 8 : # 호출을 구분하기위해 경로정보를 사용한다.
 9 : # 
10 : # (1) 프레임셋을 생성한다
11 : # (2) 질의폼을 생성한다.
12 : # (3) 질의 경과를 생성한다.
13 : 
14 : $path_info = $query->path_info;
15 : 
16 : # 어떠한 경로정보도 제공되지 않으면 프레임셋을 생성한다.
17 : if (!$path_info) {
18 :     &print_frameset('프레임셋의 시험');
19 :     exit 0;
20 : }
21 : 
22 : # 경로정보가 존재하면 질의 폼이나 질의 결과를 생성한다.
23 : &print_html_header;
24 : &print_query if $path_info=~/query/;
25 : &print_response if $path_info=~/response/;
26 : &print_end;
27 : 
28 : # 프레임 셋을 생성한다.
29 : sub print_frameset {
30 :     $script_name = $query->script_name;
31 :     print <<EOF;
32 : <html><head><title>$TITLE</title></head>
33 : <frameset cols="300,*" FRAMEBORDER="No">
34 : <frame src="$script_name/query" name="query">
35 : <frame src="$script_name/response" name="response">
36 : </frameset>
37 : EOF
38 :     ;
39 :     exit 0;
40 : }
41 : 
42 : sub print_html_header {
43 :     print $query->start_html($TITLE);
44 : }
45 : 
46 : sub print_end {
47 :     print $query->end_html;
48 : }
49 : 
50 : sub print_query {
51 :     $script_name = $query->script_name;
52 :     print "<H1>질의</H1>\n";
53 :     print $query->startform(-action=>"$script_name/response",-TARGET=>"response");
54 :     print "이름이 모니? ",$query->textfield('name');
55 :     print "<P>원하는 것은 모니?<P>",
56 :     $query->checkbox_group(-name=>'words',
57 : 			       -values=>['여자','아내','여동생','여자애']);
58 : 
59 :     print "<P>좋아하는 색은? ",
60 :     $query->popup_menu(-name=>'color',
61 : 		       -values=>['빨간색','녹색','파란색','꼭지색']),
62 :     "<P>";
63 :     print $query->submit('보내기');
64 :     print $query->endform;
65 : }
66 : 
67 : sub print_response {
68 :     print "<H1>질의결과</H1>\n";
69 :     unless ($query->param) {
70 : 	print "<b>짜식, 물어보라니까.</b>";
71 : 	return;
72 :     }
73 :     print "니 이름: <EM>",$query->param(name),"</EM>\n";
74 :     print "<P>원하는 것: <EM>",join(", ",$query->param(words)),"</EM>\n";
75 :     print "<P>원하는 색깔: <EM>",$query->param(color),"</EM>\n";
76 : }
실행결과

frameset.cgi 종속 서식 파일(CSS)의 제한적인 지원

CGI.pm은 HTML 3의 종속 서식 파일(CSS)를 제한적으로 지원한다. 서식을 자신의 문서에 병합하기위해

<A HREF="perl-cgipm3.htm#CREATING_THE_HTML_DOCUMENT_HEADE">start_html()</A>
메소드에 -style 매개변수를 지정할 수 있다. 이 매개변수의 값은 <STYLE> 섹션에 직접 병합하려는 경우에는 스칼라이며, 그렇지 않은 경우에는 해쉬 참조이어야 한다. 후자의 경우에 하나 또는 그 이상의 -src-code를 갖는 해쉬를 제공해야 한다. -src는 외부 서식 파일의 URL을 지정할 때 사용하며 -code는 <STYLE> 섹션으로 병합될 스칼라 값을 지정할 때 사용한다. -code 내의 서식 정의는 -src내의 동일한 이름보다 우선순위가 높다.

-style에의해 지정된 해쉬에 -type 매개변수를 추가함으로서 서식의 형식을 지정할 수 있다. 지정하지 않으면 서식은 기본적으로 'text/css'가 된다.

문서의 몸체내에서 서식을 참조하기위해 임의의 HTML 태그(메소드)에 -class 매개변수를 사용할 수 있다.

print h1({-class=>'Fancy'},'Welcome to DoA's World!!!');

또는 진행중에 스타일을 정의하기 위해 -style 매개변수를 사용할 수 있다.

print h1({-style=>'Color: red;'},'너 죽어봐라l');

텍스트의 일부분에 서식을 적용하기 위해 새로운 span()div() 태그를 사용할 수도 있다.

print span({-style=>'Color: red;'},
	h1('지옥에 온것을 환영한다.'),
	"지금부터 죽지도 살지도 못하는 고통을 맛보게 될 것이다. 우하하~~~"
);

주의: span()div() 메소드를 사용하기위해서는 ":html3" 정의를 가져와야 한다. CSS를 사용하는 간단한 예가 여기 있다. CSS에대한 보다 자세한 정보는 도아의 CSS 강좌를 보기바란다.

 1 : #!/usr/local/bin/perl
 2 : 
 3 : use CGI qw/:standard :html3/;
 4 : 
 5 : # 이 서식은 페이지에 직접 병합된다.
 6 : $newStyle=<<END;
 7 : <!-- 
 8 : 	P.Tip {
 9 : 		margin-right: 50pt;
10 : 		margin-left: 50pt;
11 : 		color: red;
12 : 	}
13 : 	P.Alert {
14 : 		font-size: 30pt;
15 : 		font-family: sans-serif;
16 : 		color: red;
17 : 	}
18 : -->
19 : END
20 : 
21 : print header();
22 : print start_html( -title=>'서식을 이용한 CGI',
23 : 	-style=>{-src=>'http://qaos.com/style.css',
24 : 		-code=>$newStyle}
25 : );
26 : print h1('서식을 이용한 CGI'),
27 : 	p({-class=>'note'},
28 : 		"CSS를 사용하면 문서는 훨씬 읽기 쉬워지며 작성하기 쉬워진다!"),
29 : 	span({-style=>'color: magenta'},
30 : 		"음, 하하하~~`",
31 :	p({-class=>'tip'}),
32 : 	"진짜로 그렇치!",
33 :	p({-class=>'alert'}),
34 :	"아니라고 생각하니?"
35 : );
36 : print end_html;
실행결과

css.cgi NPH 스크립트 사용하기

NPH(Non-Parsed-Header) 스크립트는 완전한 HTTP 헤더를 직접 브로우저로 전송함으로서 서버를 완전히 우회하는 기법이다. 이 것은 다소 성능상의 잇점이 있지만 주로 서버에의해 직접 지원하지 않는 HTTP 확장(서버 밀기와 PICS 헤더와 같은)의 잇점을 취하기 위해 사용한다.

서버들은 NPH CGI를 설계할 수 있는 다양한 방법을 제공한다. 많은 Unix 서버는 스크립트의 이름이 "nph-"로 시작하는 지를 조사한다. 반대로 매킨토시의 WebSTAR 서버와 Money$oft의 IIS서버는 스크립트 출력의 첫 행을 조사함으로서 NPH 스크립트인지 아닌지를 결정한다.

CGI.pm은 특별한 NPH 모드로 NPH 스크립트를 지원한다. 이 모드에 있으면서

<A HREF="perl-cgipm3.htm#CREATING_A_STANDARD_HTTP_HEADER_">header()</A>
<A HREF="perl-cgipm3.htm#GENERATING_A_REDIRECTION_HEADER">redirect()</A>
메소드를 호출하는 경우 CGI.pm은 필요한 추가적인 헤더정보를 출력한다.

Money$oft의 IIS는 NPH 모드를 필요로 한다. 2.30 판에서처럼 CGI.pm은 자동적으로 스크립트가 IIS하에서 기동되는지를 검출하고 스스로 이 모드로 출력한다. 따라서 사용자가 따로 이 모드를 설정할 필요는 없다.

CGI.pm을 NPH 모드에서 사용하는 여러가지 방법이 존재한다.

use 문
간단하게 스크립트로 가져올 심볼 목록에 "-nph" 프라그마를 추가한다.

use CGI qw(:standard -nph)

nph() 메소드 호출
use CGI;를 사용한 후 임의의 지점에서 "0"이아닌 매개변수로 nph()를 호출한다.

CGI->nph(1)

header()redirect() 문에서 -nph 매개변수를 사용

print $q->header(-nph=>1);
서버 밀기(몰밀지)

CGI.pm은 서버 밀기를 구현하는(multipart 문서를 만드는)데 필요한 세가지 형식의 함수를 지원한다. 이들 함수는 Ed Jordan에의해 제공되었다. 이들을 이름 공간으로 가져오기 위해 ":push" 집합을 가져와야 한다. 또한 스크립트를 NPH모드로 두고 버퍼링 문제를 피하기위해 $|를 1로 설정해야 한다.

다음은 서버 밀기를 예시하기위한 간단한 예이다.

 1 : #!/usr/local/bin/perl
 2 : BEGIN{
 3 : 	unshift(@INC, '/home/artech/public_html/cgi');
 4 : }
 5 : use CGI qw/:push -nph/;
 6 : $| = 1;
 7 : print multipart_init(-boundary=>'----------------herewego');
 8 : while (1) {
 9 :     print multipart_start(-type=>'text/plain'),
10 :     "현재 시간은 ",scalar(localtime),"이야.\n",
11 :     multipart_end;
12 :     sleep(1);
13 : }
실행결과

nph-multipart.cgi

이 스크립트는 multipart_init()를 호출함으로서 서버 밀기를 초기화한다. 그리고 multipart_start()를 호출함으로서 새로운 multipart 섹션이 시작되며 무한루프에 들어간다. 현재의 로칼 시간을 출력하고 multipart_end()로 multipart 섹션을 종료한다. 1초 후 다시 루프가 시작된다.

multipart_init()
multipart_init(-boundary=>$boundary); multipart 시스템을 초기화 한다. -boundary 인자는 문서의 각 부분을 분리하는데 사용되는 MIME 경계 문자열을 지정한다. 제공하지 않으면 CGI.pm이 타당한 경계 문자열를 생성한다.

multipart_start()
multipart_start(-type=>$type) 지정된 MIME 형식을 사용해서 multipart 문서의 시작한다. 지정하지 않으면 text/html로 가정된다.

multipart_end()
multipart_end() multipart를 종료한다. 각각의
multipart_start()
에대해 한번의
multipart_end()
를 호출해야 한다.

서버 밀기 응용프로그램에 관심이 있는 사용자는 또한 CGI::Push 모듈을 조사해 보기 바란다.



다음글: 제 7강 - 기타 (5875)1996-07-07
이전글: 제 5강 - 폼문서 생성하기 (7259)1996-07-05

세상사는 이야기

  • 찾아라! 아이폰 순정용 >
  • 만원대 피젯 스피너를 >
  • 망하는 길을 택한 쿠팡 >
  • 물놀이에 적당한 가성 >
  • 컴퓨터를 IPTV로 2, po >
  • 컴퓨터를 IPTV로 만들 >
  • Warning.or.kr도 우회 >
  • 한국의 100대 부자, 어 >
  • 세상을 바꾼 크롬: 크 >
  • 장난(?)으로 시작한 여 >


  • RSS 구독 (익명 | 회원 | 강좌 | 포럼)
    (C) 1996 ~ 2017 QAOS.com All rights reserved.