본문 바로가기

Common Gateway Interface/Perl

Perl(CGI)로 쿠키 주고 받기 예제

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

Perl(CGI)로 쿠키 주고 받기 예제


이번 포스팅에서는 Perl(CGI)로 쿠키를 생성, 전달 및 삭제하는 과정에 대해 정리해본다.

 

0. 준비 사항


다음의 명령어를 이용해 CGI, Cookie 모듈을 설치한다. 자세한 내용은 본 블로그의 서버 구축 관련 포스팅에 정리되어 있다.

$ sudo cpan install CGI
$ sudo cpan install CGI::Cookie

 

1. 쿠키로 전달할 데이터 입력받기(cookie-submit.cgi)


다음과 같이 쿠키 변수에 보관할 문자열을 받는 폼을 구성한다. 이 폼은 다음에 보여질 웹 페이지인 cookie-export.cgi에 전달될 것이다.

#!/usr/bin/perl


print "Content-type: text/html;charset=UTF-8\n\n";

###############################################################################
# 웹 페이지 헤더 - 본문 경계
###############################################################################

print "<!DOCTYPE html>";
print "<html lang=\"ko\">";
print "<head>";
print "<meta charset=\"utf-8\" />";
print "<title>데이터 입력</title>";
print "<style>* { font-family: sans-serif; } code { font-family: monospace; }</style>";
print "</head>";
print "<body>";
print "<article>";
print "<h1>Step 1. 데이터 입력</h1>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>1-1. 데이터 입력</h2>";
print "<hr />";
print "<p>쿠키에 저장할 문자열을 입력하세요.</p>";
print "<form method=\"post\" action=\"cookie-export.cgi\">";
print "<label>쿠키변수 #1 :<input type=\"text\" name=\"cookie_text1\" /></label><br />";
print "<label>쿠키변수 #2 :<input type=\"text\" name=\"cookie_text2\" /></label><br />";
print "<input type=\"submit\" />";
print "</form>";
print "<p>&nbsp;</p>";
print "</section>";
print "<p>&nbsp;</p>";
print "<footer>";
print "<p><a href=\"cookie-submit.cgi\">쿠키 작성</a> | <a href=\"cookie-export.cgi\">쿠키 생성</a> | <a href=\"cookie-import.cgi\">쿠키 전달</a> | <a href=\"cookie-delete.cgi\">쿠키 삭제</a></p>";
print "</footer>";
print "</article>";
print "</body>";
print "</html>";

 

다음은 위 소스 코드의 실행 결과이다. 웹 브라우저를 통해 두 개의 쿠키 변수를 입력받을 수 있다. 여기에 예시 문자열들을 적은 후 [제출] / [쿼리 전송] / [Submit] 등으로 표시되는 전송 버튼을 누른다. POST 방식으로 다음 웹 페이지에 전달될 것이다.

 

2. 쿠키를 생성하여 데이터를 보관하기(cookie-export.cgi)


앞서 전달된 데이터를 이 페이지에서 읽어들인다. CGI 모듈은 HTTP 헤더로부터 POST 방식으로 전달된 데이터를 읽어올 수 있는데 자세한 내용은 http://tapito.tistory.com/598를 참조한다.

쿠키를 생성하는 방법은 웹 페이지의 헤더 부분에 Set-Cookie: 항목을 추가하는 것이다. Set-Cookie에 이어서 추가되는 쿠키 문자열에는 쿠키 변수의 이름, 쿠키 변수의 값, 쿠키 변수에 접근 가능한 도메인, 쿠키 변수의 시한 등이 포함되어 있으며 이러한 규격에 맞추어 쿠키 문자열을 생성하기 위해서는 CGI::Cookie 객체를 사용하는 것이 편리하다.

#!/usr/bin/perl

use CGI qw/:standard/;
use CGI::Cookie;

my $objCGI = CGI->new;
my $objCookie1 = undef;
my $objCookie2 = undef;

# 쿠키 작성은 웹 페이지의 첫 부분에 가장 먼저 수행되어야 함.
# 이를 위해 쿠키를 작성하는 부분이 먼저 코딩됨.
if ($objCGI->param('cookie_text1') ne undef)
{
	# 이전 페이지로부터 'cookie_text1' 이름의 폼 데이터가 전달된 경우
	# 현재 시점으로부터 12시간동안 유효한 쿠키를 생성한 후 이 쿠키에 문자열을 보관한다.
	$objCookie1 = new CGI::Cookie(-name=>'cookie_text1', -value=>($objCGI->param('cookie_text1')), -expires=>'+12h');
	
	# 이 웹 페이지의 헤더에 쿠키를 추가하여 전송한다.
	print "Set-Cookie: ", $objCookie1->as_string, "\n";
}

if ($objCGI->param('cookie_text2') ne undef)
{
	# 이전 페이지로부터 'cookie_text2' 이름의 폼 데이터가 전달된 경우
	# 현재 시점으로부터 12시간동안 유효한 쿠키를 생성한 후 이 쿠키에 문자열을 보관한다.
	$objCookie2 = new CGI::Cookie(-name=>'cookie_text2', -value=>($objCGI->param('cookie_text2')), -expires=>'+12h');

	# 이 웹 페이지의 헤더에 쿠키를 추가하여 전송한다.
	print "Set-Cookie: ", $objCookie2->as_string, "\n";
}

print "Content-type: text/html;charset=UTF-8\n\n";

###############################################################################
# 웹 페이지 헤더 - 본문 경계
###############################################################################

print "<!DOCTYPE html>";
print "<html lang=\"ko\">";
print "<head>";
print "<meta charset=\"utf-8\" />";
print "<title>쿠키 생성</title>";
print "<style>* { font-family: sans-serif; } code { font-family: monospace; }</style>";
print "</head>";
print "<body>";
print "<article>";
print "<h1>Step 2. 쿠키 생성</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>2-1. 이전 페이지에서 작성된 데이터</h2>";
print "<hr />";
if ($objCGI->param('cookie_text1') eq undef)
{
	# 이전 페이지로부터 'cookie_text1' 이름의 폼 데이터가 전달되지 않은 경우
	# 웹 페이지에는 "undef" 문자열을 보인다.
	print "<p>쿠키변수 #1 : <code><span style=\"color: red;\">undef</span></code></p>";
}
else
{
	# 이전 페이지로부터 'cookie_text1' 이름의 폼 데이터가 전달된 경우
	# 웹 페이지에도 이 내용을 보인다.
	print "<p>쿠키변수 #1 : <code>", $objCGI->param('cookie_text1'), "</code></p>";
}
if ($objCGI->param('cookie_text2') eq undef)
{
	# 이전 페이지로부터 'cookie_text2' 이름의 폼 데이터가 전달되지 않은 경우
	# 웹 페이지에는 "undef" 문자열을 보인다.
	print "<p>쿠키변수 #2 : <code><span style=\"color: red;\">undef</span></code></p>";
}
else
{
	# 이전 페이지로부터 'cookie_text2' 이름의 폼 데이터가 전달된 경우
	# 웹 페이지에도 이 내용을 보인다.
	print "<p>쿠키변수 #2 : <code>", $objCGI->param('cookie_text2'), "</code></p>";
}
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>2-2. 쿠키 문자열 생성</h1>";
print "<hr />";
print "<p>쿠키변수 #1 :</p>";
if ($objCGI->param('cookie_text1') eq undef)
{
	# 이전 페이지로부터 'cookie_text1' 이름의 폼 데이터가 전달되지 않은 경우
	# 웹 페이지에는 "undef" 문자열을 보인다.
	print "<pre><code><span style=\"color: red;\">undef</span></code></pre>";
}
else
{
	# 이전 페이지로부터 'cookie_text1' 이름의 폼 데이터가 전달된 경우
	# 본 웹 페이지가 클라이언트에 전송한 쿠키 문자열의 전문을 보여준다.
	print "<pre><code>", $objCookie1->as_string, "</code></pre>";
}
print "<p>쿠키변수 #2 :</p>";
if ($objCGI->param('cookie_text2') eq undef)
{
	# 이전 페이지로부터 'cookie_text2' 이름의 폼 데이터가 전달되지 않은 경우
	# 웹 페이지에는 "undef" 문자열을 보인다.
	print "<pre><code><span style=\"color: red;\">undef</span></code></pre>";
}
else
{
	# 이전 페이지로부터 'cookie_text2' 이름의 폼 데이터가 전달된 경우
	# 본 웹 페이지가 클라이언트에 전송한 쿠키 문자열의 전문을 보여준다.
	print "<pre><code>", $objCookie2->as_string, "</code></pre>";
}
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>2-3. 다음 작업</h2>";
print "<hr />";
print "<ul><li><a href=\"cookie-import.cgi\">쿠키 전달</a></li></ul>";
print "</section>";
print "<p>&nbsp;</p>";
print "<footer>";
print "<p><a href=\"cookie-submit.cgi\">쿠키 작성</a> | <a href=\"cookie-export.cgi\">쿠키 생성</a> | <a href=\"cookie-import.cgi\">쿠키 전달</a> | <a href=\"cookie-delete.cgi\">쿠키 삭제</a></p>";
print "</footer>";
print "</article>";
print "</body>";
print "</html>";

 

 

3. 생성된 쿠키를 읽어오기(cookie-import.cgi)


perl 소스로 전달된 클라이언트의 쿠키를 읽기 위하여 $ENV{'HTTP_COOKIE'} 환경 변수를 사용 가능하다. split을 직접 수행하여 원하는 쿠키 변수의 값만을 추출할 수도 있지만 fetch CGI::Cookie를 사용하는 쪽이 더 편리하다.

#!/usr/bin/perl

use CGI qw/:standard/;
use CGI::Cookie;

my %objCookies = fetch CGI::Cookie; # HTTP_COOKIE 환경변수로부터 자동으로 쿠키 변수들을 분리함
my $index = 0;

print "Content-type: text/html;charset=UTF-8\n\n";

###############################################################################
# 웹 페이지 헤더 - 본문 경계
###############################################################################

print "<!DOCTYPE html>";
print "<html lang=\"ko\">";
print "<head>";
print "<meta charset=\"utf-8\" />";
print "<title>쿠키 전달</title>";
print "<style>* { font-family: sans-serif; } code { font-family: monospace; }</style>";
print "</head>";
print "<body>";
print "<article>";
print "<h1>Step 3. 데이터 전달</h1>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>3-1. 이전 페이지에서 전달된 쿠키</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<pre><code>$ENV{'HTTP_COOKIE'}</code></pre>"; # 이 곳에서 HTTP_COOKIE 환경변수의 전문을 보여줌.
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>3-2. "fetch CGI::Cookie" 실행 결과</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<pre><code>";
foreach $item(%objCookies)
{
	# fetch CGI::Cookie의 실행 결과는 결합형 배열(associated array)로 반환된다.
	# 결합형 배열의 각 항목에는 어떤 내용들이 들어있는지를 확인하기 위하여
	# foreach 구문으로 각 항목을 웹 페이지에 출력할 것이다.
	print "\$objCookies[$index] = \"$item\";<br />";
	$index++;
}
print "</code></pre>";
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>3-3. 다음 작업</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<ul><li><a href=\"cookie-delete.cgi\">쿠키 삭제</a></li></ul>";
print "</section>";
print "<p>&nbsp;</p>";
print "<footer>";
print "<p><a href=\"cookie-submit.cgi\">쿠키 작성</a> | <a href=\"cookie-export.cgi\">쿠키 생성</a> | <a href=\"cookie-import.cgi\">쿠키 전달</a> | <a href=\"cookie-delete.cgi\">쿠키 삭제</a></p>";
print "</footer>";
print "</article>";
print "</body>";
print "</html>";

 

위 페이지의 실행 결과이다. [3-1] 항목에서 $ENV{'HTTP_COOKIE'} 환경변수의 전문을 보여줌으로써 웹 페이지에 쿠키가 어떤 형태로 전달되는 지를 확인할 수 있다. 일련의 변수이름=값;으로 구성되어 있으며, 큰 따옴표("), 느낌표(!), 세미콜론(;) 등의 기호들은 각각 %22, %21, %3B 등으로 인코딩되어 있음을 볼 수 있다.

 

4. 쿠키를 삭제하기(cookie-delete.cgi)


쿠키를 삭제하는 방법은 간단하다. 동일한 이름의 쿠키를 유효 기간을 과거 시점으로 지정하여 클라이언트에 전송하면 된다. 즉,
쿠키를 보관할 때: -expires=>'미래시점'
쿠키를 지울 때: -expires=>'과거시점'
을 하면 된다.

#!/usr/bin/perl

use CGI qw/:standard/;
use CGI::Cookie;

my %objCookies = fetch CGI::Cookie;
my $txtCookies = "";
my $objCookie = undef;
my $index = 0;

# 쿠키 작성은 웹 페이지의 첫 부분에 가장 먼저 수행되어야 함.
# 이를 위해 쿠키를 작성하는 부분이 먼저 코딩됨.
foreach $item(%objCookies)
{
	# 'fetch CGI::Cookie'의 수행 결과 반환되는 결합형 배열은
	# "쿠키이름", "쿠키내용" 순으로 항목이 반복됨을 이전 페이지인 cookie-import.cgi에서 확인하였다.
	# 그러므로 0번째, 2번째, 4번째... 순으로 쿠키의 이름만 들어있는 항목만을 골라 
	# 해당 이름과 같으나 만료시점이 과거(24시간 전)로 된 새 쿠키를 생성하여 클라이언트에 전송할 것이다.
	if (($index % 2) eq 0)
	{
		# 이름은 같으나 내용은 없고 만료일시는 24시간전의 시점인 새 쿠키를 만든다.
		$objCookie = new CGI::Cookie(-name=>$item, -value=>'', -expires=>'-24h');
		print "Set-Cookie: ", $objCookie->as_string, "\n";
		# 웹 브라우저로도 이 쿠키의 내용을 보여주기 위하여 문자열 변수에 쿠키 문자열의 전문을 추가한다.
		$txtCookies .= $objCookie->as_string;
		$txtCookies .= "\n";
	}

	$index++;
}

print "Content-type: text/html;charset=UTF-8\n\n";

###############################################################################
# 웹 페이지 헤더 - 본문 경계
###############################################################################

print "<!DOCTYPE html>";
print "<html lang=\"ko\">";
print "<head>";
print "<meta charset=\"utf-8\" />";
print "<title>Delete Cookie</title>";
print "<style>* { font-family: sans-serif; } code { font-family: monospace; }</style>";
print "</head>";
print "<body>";
print "<article>";
print "<h1>Step 4. 쿠키 삭제</h1>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>4-1. 이전 페이지에서 전달된 쿠키</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<pre><code>$ENV{'HTTP_COOKIE'}</code></pre>";
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>4-2. 새로 작성할 쿠키 문자열</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<pre><code>$txtCookies</code></pre>";
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>3-3. 다음 작업</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<ul><li><a href=\"cookie-submit.cgi\">쿠키 작성</a></li><li><a href=\"cookie-import.cgi\">쿠키 전달</a></li></ul>";
print "</section>";
print "<p>&nbsp;</p>";
print "<footer>";
print "<p><a href=\"cookie-submit.cgi\">쿠키 작성</a> | <a href=\"cookie-export.cgi\">쿠키 생성</a> | <a href=\"cookie-import.cgi\">쿠키 전달</a> | <a href=\"cookie-delete.cgi\">쿠키 삭제</a></p>";
print "</footer>";
print "</article>";
print "</body>";
print "</html>";

 

실행 결과는 다음과 같다. 새로 전송된 쿠키의 만료일시가 과거로 되어 있기 때문에 해당 쿠키는 클라이언트에서 삭제될 것이다.

 

이 페이지에서 새로고침을 눌러 페이지를 다시 로드한다. 본 페이지로 전달될 쿠키가 이미 삭제되고 없기 때문에 쿠키 문자열은 더 이상 나타나지 않을 것이다.