본문 바로가기

Common Gateway Interface/Perl

Perl(CGI)로 세션 주고 받기 예제

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

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


이번 포스팅에서는 Perl(CGI)로 세션을 생성 및 사용하고 삭제하는 과정에 대해 정리해본다.

 

0. 준비 사항


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

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

 

macOS 한정 CGI::Session이 설치되지 않는 경우

다음과 같이 force 옵션을 써서 강제로 설치할 수 있다.

$ sudo cpan
cpan> force install CGI::Session

 

Debian/Ubuntu 한정 cpan을 통한 설치 대신 패키지를 통한 설치가 원활하다.

$ sudo apt-get install libcgi-session-perl

 

RedHat/CentOS 한정 마찬가지로 패키지를 통한 설치가 원활하다.

$ sudo yum install perl-CGI-Session

 

1. 세션으로 전달할 데이터 입력받기(session-submit.cgi)


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

#!/usr/bin/perl

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

my $objCGI = undef;
my $objCookie = undef;
my $objSession = undef;

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=\"session-export.cgi\">";
print "<label>세션변수 #1: <input type=\"text\" name=\"session_text1\" /></label><br />";
print "<label>세션변수 #2: <input type=\"text\" name=\"session_text2\" /></label><br />";
print "<input type=\"submit\" />";
print "</form>";
print "<p>&nbsp;</p>";
print "</section>";
print "<footer>";
print "<p><a href=\"session-submit.cgi\">세션 작성</a> | <a href=\"session-export.cgi\">세션 생성</a> | <a href=\"session-import.cgi\">세션 전달</a> | <a href=\"session-delete.cgi\">세션 삭제</a></p>";
print "</footer>";
print "</article>";
print "</body>";
print "</html>";

 

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

 

2. 세션을 생성하여 데이터를 보관하기(session-export.cgi)


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

세션 객체를 생성하는 함수는 다음과 같다.

new()
new( $sid )
new( $query )
new( $dsn, $query||$sid )
new( $dsn, $query||$sid, \%dsn_args )
new( $dsn, $query||$sid, \%dsn_args, \%session_params )

 

세션이 정상적으로 생성되었다면, id() 함수로 생성된 세션 ID를 가져올 수 있는데, 이를 클라이언트로 전달하기 위해 쿠키를 사용한다. 쿠키 변수의 이름은 CGISESSID를 쓰는 것이 CGI::Session 모듈에서 자동으로 식별하기에 유리하다. 사용자 방식대로 세션을 명시적으로 불러오려면 다른 이름을 사용해도 문제없다.

세션에 데이터를 기록하는 함수는 다음과 같이 2개의 매개변수를 갖는 param 함수로 정의되어 있다.

param($name, $value)
param(-name=>$name, -value=>$value)

 

세션에 데이터를 기록한 뒤에는 flush 함수를 호출해주는 것이 원활한 작동을 보장한다.

flush()

 

#!/usr/bin/perl

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

my $objCGI = undef;
my $objCookie = undef;
my $objSession = undef;
my $idSession = undef;

$objCGI = CGI->new;

# 쿠키 작성은 웹 페이지의 첫 부분에 가장 먼저 수행되어야 함.
# 이를 위해 쿠키를 작성하는 부분이 먼저 코딩됨.
# 이전 페이지로부터 두 개의 텍스트가 모두 전달되었다면 세션 생성
if (($objCGI->param('session_text1') ne undef) && ($objCGI->param('session_text2') ne undef))
{
	# 12시간동안 유효한 세션 객체 생성
	$objSession = new CGI::Session("driver:File", undef, {Directory=>'/tmp'});
	$objSession->expire('+12h');
	$objSession->param(-name=>'session_text1', -value=>$objCGI->param('session_text1'));
	$objSession->param(-name=>'session_text2', -value=>$objCGI->param('session_text2'));
	$objSession->flush();

	# 생성된 세션의 식별 ID를 쿠키를 통해 클라이언트에게 전달
	# 현재 시점으로부터 12시간동안 유효한 쿠키를 생성한 후 이 쿠키에 문자열을 보관한다.
	# 중요:
	# 세션 ID를 전달하는 쿠키 변수의 이름은 CGI::Session 모듈이 자동으로 읽어오도록 할 경우 'CGISESSID'일 것이 권장되지만,
	# 기존 모듈과의 호환을 고려하지 않는다면 다른 이름을 써도 무방함.
	$idSession = $objSession->id;
	$objCookie = new CGI::Cookie(-name=>'CGISESSID', -value=>$idSession, -expires=>'+12h');
	
	# 쿠키로 세션 ID 전송
	print "Set-Cookie: ", $objCookie->as_string, "\n";
}

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

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

print "<!DOCTYPE html>";
print "<html lane=\"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. 세션 생성</h1>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>2-1. 이전 페이지에서 작성된 데이터</h2>";
print "<hr />";
if ($objCGI->param('session_text1') eq undef)
{
	# 이전 페이지에서 세션 변수에 넣을 문자열이 전달되지 않았을 경우
	print "<p>세션변수 #1 : <code><span style=\"color: red;\">undef</span></code></p>";
}
else
{
	# 이전 페이지에서 세션 변수에 넣을 문자열이 전달되었을 경우
	print "<p>세션변수 #1 : <code>", $objCGI->param('session_text1'), "</code></p>";
}
if ($objCGI->param('session_text2') eq undef)
{
	# 이전 페이지에서 세션 변수에 넣을 문자열이 전달되지 않았을 경우
	print "<p>세션변수 #2 : <code><span style=\"color: red;\">undef</span></code></p>";
}
else
{
	# 이전 페이지에서 세션 변수에 넣을 문자열이 전달되었을 경우
	print "<p>세션변수 #2 : <code>", $objCGI->param('session_text2'), "</code></p>";
}
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>2-2. 쿠키 문자열 생성</h2>";
print "<hr />";
if ($objCookie eq undef)
{
	# 세션 ID를 전달하는 쿠키 객체가 생성되지 않은 경우
	print "<pre><code><span style=\"color: red;\">undef</span></code></pre>";
}
else
{
	# 세션 ID를 전달하는 쿠키 객체가 생성된 경우
	print "<pre><code>", $objCookie->as_string, "</code></pre>";
}
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>2-3. 다음 작업</h2>";
print "<hr />";
print "<ul><li><a href=\"session-import.cgi\">세션 전달</a></li></ul>";
print "</section>";
print "<p>&nbsp;</p>";
print "<footer>";
print "<p><a href=\"session-submit.cgi\">세션 작성</a> | <a href=\"session-export.cgi\">세션 생성</a> | <a href=\"session-import.cgi\">세션 전달</a> | <a href=\"session-delete.cgi\">세션 삭제</a></p>";
print "</footer>";
print "</article>";
print "</body>";
print "</html>";

 

 

3. 생성된 세션을 읽어오기(session-import.cgi)


쿠키를 통해 CGISESSID 또는 기타 이름의 세션 ID가 있는 변수를 가져온다. 이를 통해 세션 객체를 불러올 수 있다. 세션 객체를 불러오는 방법은 상기 new() 함수의 $sid 매개변수를 통하는 방법과 load() 함수를 이용하는 방법이 있다. 전자의 경우 지정된 세션 ID가 없을 때 새로 세션 객체를 만든다음 이를 웹 페이지에 반환할 수 있지만, 후자의 경우 세션 생성 없이 undef를 반환한다. load() 함수의 선언은 다음과 같다.

load()
load( $query||$sid )
load( $dsn, $query||$sid )
load( $dsn, $query, \%dsn_args )
load( $dsn, $query, \%dsn_args, \%session_params )

 

#!/usr/bin/perl

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

# HTTP 헤더로부터 쿠키를 파싱하여 가져온다.
my %objCookies = fetch CGI::Cookie;
my $objSession = undef;

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>";
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>3-2. 세션 변수 읽기</h2>";
print "<hr />";
if ($objCookies{'CGISESSID'} eq undef)
{
	# 쿠키로부터 전달된 'CGISESSID' 변수가 없는 경우
	print "<pre><code><span style=\"color: red;\">undef</span></code></pre>";
}
else
{
	# 쿠키로부터 전달된 'CGISESSID' 변수가 있는 경우
	$objSession = new CGI::Session(undef, (scalar $objCookies{'CGISESSID'}->value), {Directory=>'/tmp'});

	if ($objSession->param('session_text1') eq undef)
	{
		# 첫 번째 세션 변수가 저장되어있지 않은 경우
		print "<p>세션변수 #1 : <code><span style=\"color: red;\">undef</span></code></p>";
	}
	else
	{
		# 첫 번째 세션 변수가 저장된 경우
		print "<p>세션변수 #1 : <code>", $objSession->param('session_text1'), "</code></p>";
	}

	if ($objSession->param('session_text2') eq undef)
	{
		# 두 번째 세션 변수가 저장되어있지 않은 경우
		print "<p>세션변수 #2 : <code><span style=\"color: red;\">undef</span></code></p>";
	}
	else
	{
		# 두 번째 세션 변수가 저장된 경우
		print "<p>세션변수 #2 : <code>", $objSession->param('session_text2'), "</code></p>";
	}
}
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>3-3. 다음 작업</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<ul><li><a href=\"session-delete.cgi\">세션 삭제</a></li></ul>";
print "</section>";
print "<p>&nbsp;</p>";
print "<footer>";
print "<p><a href=\"session-submit.cgi\">세션 작성</a> | <a href=\"session-export.cgi\">세션 생성</a> | <a href=\"session-import.cgi\">세션 전달</a> | <a href=\"session-delete.cgi\">세션 삭제</a></p>";
print "</footer>";
print "</article>";
print "</body>";
print "</html>";

 

위 페이지의 실행 결과이다.

 

4. 세션을 삭제하기(session-delete.cgi)


세션을 지우는 메서드는 다음과 같다.

delete()

 

#!/usr/bin/perl

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

# HTTP 헤더로부터 쿠키를 파싱하여 가져온다.
my %objCookies = fetch CGI::Cookie;
my $objCookie = undef;
my $objSession = undef;

if ($objCookies{'CGISESSID'} ne undef)
{
	# 쿠키로부터 전달된 'CGISESSID' 변수가 있는 경우
	# 유효기간이 과거로 설정된 새 쿠키로 덮어씀으로써 삭제한다.
	$objCookie = new CGI::Cookie(-name=>'CGISESSID', -value=>'', -expires=>'-24h');
	print "Set-Cookie: ", $objCookie->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>Delete Session</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'} = $ENV{'HTTP_COOKIE'}</code></pre>";
if ($objCookies{'CGISESSID'} eq undef)
{
	# 쿠키로부터 전달된 'CGISESSID' 변수가 없는 경우
	print "<pre><code>\$objCookies{'CGISESSID'} = <span style=\"color: red;\">undef</span></code></pre>";
}
else
{
	# 쿠키로부터 전달된 'CGISESSID' 변수가 있는 경우
	$objSession = new CGI::Session(undef, (scalar $objCookies{'CGISESSID'}->value), {Directory=>'/tmp'});

	if ($objSession->param('session_text1') eq undef)
	{
		# 첫 번째 세션 변수가 저장되어있지 않은 경우
		print "<p>세션변수 #1 : <code><span style=\"color: red;\">undef</span></code></p>";
	}
	else
	{
		# 첫 번째 세션 변수가 저장된 경우
		print "<p>세션변수 #1 : <code>", $objSession->param('session_text1'), "</code></p>";
	}

	if ($objSession->param('session_text2') eq undef)
	{
		# 두 번째 세션 변수가 저장되어있지 않은 경우
		print "<p>세션변수 #2 : <code><span style=\"color: red;\">undef</span></code></p>";
	}
	else
	{
		# 두 번째 세션 변수가 저장된 경우
		print "<p>세션변수 #2 : <code>", $objSession->param('session_text2'), "</code></p>";
	}

	# 세션 삭제
	$objSession->delete;
}
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>새로 작성할 쿠키 문자열</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<pre><code>", $objCookie->as_string, "</code></pre>";
print "</section>";
print "<p>&nbsp;</p>";
print "<section>";
print "<h2>4-3. 다음 작업</h2>";
print "<hr />";
print "<p>&nbsp;</p>";
print "<ul><li><a href=\"session-submit.cgi\">세션 작성</a></li><li><a href=\"session-import.cgi\">세션 전달</a></li></ul>";
print "</section>";
print "<p>&nbsp;</p>";
print "<footer>";
print "<p><a href=\"session-submit.cgi\">세션 작성</a> | <a href=\"session-export.cgi\">세션 생성</a> | <a href=\"session-import.cgi\">세션 전달</a> | <a href=\"session-delete.cgi\">세션 삭제</a></p>";
print "</footer>";
print "</article>";
print "</body>";
print "</html>";

 

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

 

이 페이지에서 새로고침을 하여 다시 열 경우 이미 세션과 쿠키 변수가 사라진 뒤이므로 다음과 같이 나타난다.

 

이 상태에서 이전 페이지로 돌아가 세션을 읽고자 하면 다음과 같이 나타난다.