본문 바로가기

Common Gateway Interface/Perl

[옛 강좌] 19. Perlprog - GuestBook 1

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

 이 게시물은 지금은 폐쇄되어 접속되지 않는 Kim Young Soo(http://hours.interpia98.net/~unisoo/)님의 웹 사이트에 2001년경 게시된 내용을 바탕으로 오늘날 웹 환경에 맞게 내용을 덧붙였습니다.

Perlprog - GuestBook 1

Description

방명록 만들기 1 - 폼, 입력, 저장


GuestBook 만들기 1

 최소한의 기능만을 갖춘 방명록을 만들어 보죠. 폼에서 데이타를 받아서 저장하고, 그것을 읽어서 일정한 폼에 되돌려 줄수 있는 방명록을 만들어 보도록 하겠습니다. 세번에 나누어서 하겠습니다. 궁금하신점은 게시판을 이용해 주세요.

HTML Form

<form action="../cgi-bin/guest_book.cgi" method=post>
	<table border=0 bgcolor=white width=550>
		<tr>
			<td align=right width=100 bgcolor=#d2eefe><font size=2 color=#376eda><b>Name :</b></font></td>
			<td><input type=text name="username" size=20 maxlength=20></td>
		</tr>
		<tr>
			<td align=right bgcolor=#d2eefe><font size=2 color=#376eda><b>하실말씀 :</b></font></td>
			<td><textarea name="body" rows=10 cols=40></textarea></td>
		</tr>
		<tr>
			<td colspan=2><input type=submit value="Submit"><input type=reset value="Clear"></td>
		</tr>
	</table>
</form>
					

 위의 폼은 방명록 입력양식이지요. 많이 넣지 않았습니다. 이름과 내용을 넣을수 있는 자리만 만들었어요. 이 글을 읽는 분은 <form>태그에 대해서 어느정도 아신다는 가정하에 합니다. 모르시면 게시판에 질문남겨 주세요.

GET 전송방식

 CGI에서는 변수를 서버로 보내는 방법이 POSTGET 두 가지가 있습니다. 저는 여기서 POST 방법을 썼구여, 이 두 가지 타입에 대해 간단히 알아보겠습니다.

 여러분들이 심마니나 야후에서 정보검색을 하신적이 있으실 겁니다. 그 때 주소부분의 URL을 보시면 그게 무쟈게 길어요. www.simmani.com/........./...../ 이러면서 나갑니다. 이것은 GET방식으로 데이터를 전송한겁니다.

 GET방식을 이용하면 사용자가 입력한 내용이 변형되어(공백은 '+'로 특수문자는 아스키값으로...) 긴 문자열이 된후 서버로 전송이 됩니다.

 이 전송된 데이터는 %ENV환경변수의 'QUERY_STRING'에 접근함으로서 사용할 수 있지요.

 만약에 위의 폼에서 방식을 GET으로 바꾸고 이름에 'uni'를, 내용에 'hahaha'를 입력했을경우, 브라우저의 주소란에는 'http://..../cgi-bin/....?username=uni&body=hahaha' 라고 나올겁니다. CGI파일이름과 변수사이에는 '?'가 변수명과 변수 사이에는 '='가 또 그 값들 사이는 '&'가 들어 값니다. 이 값을 받아서 우리는 CGI 프로그램을 할 때 사용할 수 있죠.

 이 방식의 단점은 그 데이터의 길이가 제한되었다는 것과, 비밀번호와 같은 내용을 입력 할 경우 그 내용이 그대로 노출된다는 거죠.

POST 전송방식

 POST 방식은 이거와는 다르게 사용자가 입력한 변수의 내용들이 브라우져에 출력되지 않습니다. POST방식으로 보내면, 그 내용을 품어서 인코딩되어서 서버로 보내지죠.

 그러면 우리는 환경변수 'CONTENT_LENGHT'를 써서 이 변수들을 사용할 수 있습니다. 위 환경변수는 보내진 데이터의 총 길이를 담고 있습니다.

 GET으로 보내진 데이터를 받을 때:

$temp = $ENV{'QUERY_STRING'}; # <-- 보내진 데이터를 바로 받습니다.

 POST로 보내진 데이터를 받을 때:

read(STDIN, $temp, $ENV{'CONTENT_LENGHT'}; # <-- 표준입력(STDIN)으로 들어온 값을 CONTENT_LENGTH의 길이만큼 읽어서 $temp에 저장하라는 내용입니다.

 그 다음의 프로그램 과정은 동일합니다.

guest.cgi - 데이터 저장

 그럼 이제 guest.cgi라는 파일을 만들어서 시작하겠습니다.

#! /usr/perl/bin # <-- 이건 아시죠?

read(STDIN, $temp, $ENV{'CONTENT_LENGTH'}); # <-- $temp에 넘어온 변수를 저장합니다.

@guest = split(/&/, $temp); # <-- 넘어온 변수를 '&'를 기준으로 분리해서 @guest에 차례로 저장합니다.

# ...
					

split() 함수는 기준이 되는 문자('&')로해서 문자열을 나누어 주는 역할을 합니다. 위에서 변수가 서버로 넘어 올때 값1=내용1&값2=내용2&값3=내용3... 이렇게 넘어온다고 했죠. 이렇게 하게되면 @guest에는 '값=내용'의 값이 차례로 저장됩니다.

foreach $item(@guest)
{
	($key, $value) = split(/=/, $item);
	
	$value =~ tr/+/ /;
	$value =~ s/%(..)/pack("c", hex($1))/ge;
	$fields{$key} = $value;
}
					

 위의 내용을 차근히 보죠.

foreach 에서는 @guest의 값을 차례로 ($guest[0], $guest[1]..) $item 변수에 저장합니다. 더 이상 @guest에 값이 없을 때까지 순환을 하게 됩니다.

($key, $value) = split(/=/, $item); 는 넘어온 $item 문자열을 '='를 기준으로 $key, $value에 저장합니다. 이렇게 되면, $key에는 username을 $value에는 uni가 들어가게되죠.

$value =~ tr/+/ /;는 위에서 분리된 value의 값에서 '+' 기호를 공백으로 바꾸어줍니다. 위에서 얘기했죠? 서버로 넘어올때 공백은 '+'로 바뀌어서 넘어온다구여. 이걸 다시 원래대로 바꾸어 주는 겁니다.

$value =~ s/%(..)/pack("c", hex($1))/ge; 는 아스키값으로 바뀐 특수문자들을 원래대로 바꾸어주는 라인입니다.

위에서 쓰인 tr///s/// 는 치환이나 대치를 할때 쓰입니다. 처음//사이에는 치환할 문자, 그 다음//사이에는 치환할 문자가 오게 되죠. tr과 s의 차이는 tr에는 그냥 바꿀 문자가 오는 거지만, s에는 ///사이에 문서패턴이나 정규표현이 오게되죠. 패턴에 대해서는 기초문법강의를 참조 하세요.

순환문의 마지막에 오는 $fields{$key} = $value; 는 %fields라는 결합배열에 키값과 그 키값에 대응하는 값을 저장하는 과정입니다.

흠... 위 6라인으로 넘어온 데이터를 원래대로 환원하였습니다. 데이타가 아무리 많아도 위 여섯 라인이면 깨끗하게 해결이 되죠. 위 6라인은 두고두고 쓰입니다. 이해하시고 기냥 외워두시는게 더 좋은거 같아여....

$fields{'body'} =~ s/\n\n/ /g;
$fields{'body'} =~ s/\n/ /g;
					

위의 세 라인은 body의 내용에서 엔터가 들어간 곳을 공백으로 바꾸어 주는 역할을 합니다. '\n'는 개행문자죠. 기초 문법을 참조 하세요.

 이제 데이터를 사용할 준비가 끝났군요. 그럼 파일에 저장을 할까요?

open (FILE, ">guestbook.txt") || die "Can't use DBM file";
print FILE "$fields{'username'}::$fields{'body'}\n";
close (FILE);
					

 위의 내용은 잘 아시겠죠? 단 FILE에 프린트 할때 각각의 내용사이에 '::'를 넣어주었습니다. 일종의 분리자죠. 이 내용을 다시 읽을 때 :: 를 기준으로 읽게 됩니다.

 이번엔 여기까지만 하겠습니다. 아직 더 붙일 내용이 많아여. 사용자가 입력을 제대로 했는지 확인도 해야되고, 누군가 ::를 입력했다면 다음에 읽을 때 이상한 결과가 나오겠죠. 그리고 입력한 날짜도 넣구 싶고, 이어서 계속 합니다.


NOTES

이번엔 여기까지만 하겠습니다. 아직 더 붙일 내용이 많아여. 사용자가 입력을 제대로 했는지 확인도 해야되고, 누군가 ::를 입력했다면 다음에 읽을때 이상한 결과가 나오겠죠. 그리고 입력한 날짜도 넣구 싶고, 흠.... 이런 내용은 다음에 하도록 하겠습니다.

이 문서는 Perl 패키지내의 pod2html를 이용하여 만들었습니다. - Kim Young Soo