본문 바로가기

Common Gateway Interface/Perl

[옛 강좌] 25. Perlprog - BBS 4

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

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

Perlprog - BBS 4

Description

게시판 만들기 4 - 선택된 데이터 보여주기


BBS 만들기 4

 게시판 만들기 네번째 입니다. 이번에 할 내용은 .... 지난번엔 저장된 데이터의 목록을 보여주는 부분이었죠... 그러니깐 이번엔 그 목록에서 원하는 제목을 클릭했을 때 그 데이터가 보여지는 부분을 프로그램 하겠습니다.

 여기서도 할 건 많죠.... 클릭된 거 불러들이는 건 어떻게 보면 일이 아닌데.. 다음글, 이전글 보여주기라든가... 또 한번 열렸으니 조회수를 올려야 겠죠. 여기서 조회수를 올리는 기준은 그 파일이 몇 번 열렸는가 하는거에 따르겠습니다. 그러니깐 한 번 열어놓고 reload를 마구마구 눌러대면, 조회수가 마구마구 올라가겠죠. 그렇지 않을려면 ip를 검색해서 하루에 한번만 하시던지, 아님, 서로 다른 ip만 조회수를 올리던지... 여러분 맴입니다.

 참고루여... 여기서 사용하는 소스는 여러 개의 파일로 나누었구여, 어떻게 하다보니, 앞으로 비슷한 부분을 계속해야 하는 경우가 생길 겁니다. 그건 여러분들의 이해를 돕기 위해, 그렇게 하는거니깐... '아니?? 이건 이렇게 해도 되는건데 왜 이렇게 하쥐?' 라고 의문이 생기시더라도, 기냥... 부드럽게... 스무스하게 넘어가 주셔여.... ^^;

 코드를 간결화하고, 구조화하는건 강좌가 진행하는 동안의 여러분들 각자의 몫에 맡기겠습니다.

 그럼 시작하겠습니다.

board_view.cgi - 선택된 데이타 출력

 우선 지난번 얘기를 떠올려 보죠... 목록에서 번호와 실제 참조되는 번호는 같을 수도 있고, 다를 수도 있어요. 삭제가 된다던가, 답변이 올라온다던가 하게 되면 그럴 수 있죠.

 그래서 지난 번에 해쉬를 이용해서 목록 번호와 실제 번호를 연결시켰었죠. 그래서 선택한 걸 읽게 해주는 board_view.cgi에 목록번호(글번호)와 실제 파일번호를 같이 넘긴 걸 기억하실 겁니다.

#! /usr/local/bin/perl

require "./board.conf";
require "./basic.pl";

&print_header;
$query_data = $ENV{'QUERY_STRING'};
&parse_data($query_data, *fields);
    
# 솔직히 위 두줄은 조금 불필요 하죠. 한줄로도 됩니다. parse_input(*fields); 이렇게요.
# 그냥 좀 더 명확히 할려구 이렇게 했어요. ^^;

$file_number = $fields{'real_number'};
$head_number = $fields{'virtual_number'};
$total_idx = &get_max_number($idx_file);
$now_num = $total_idx - $head_number;
$next_vir = $head_number + 1;
$prev_vir = $head_number - 1;

# 실제 파일번호, 보여지는 글번호, 그리고 다음글과 이전글을 추려내기 위한 전체 게시물, 실제 참조되는 현재의 번호, 다음번호, 이전번호를 설정해줍니다. 
# $now_num은 지난번에 얘기한 걸 생각하시면 되요. 우리는 아래서 부터 1,2,3.... 이렇게 나가지만, 배열에선 위에서부터 0,1,2... 이렇게 시작하기 때문에 역으로 계산을 해야 합니다. 

$file_name = "$data_dir/board".$file_number.".dat";
# 우리가 원하는 실제 파일명을 설정하구여, 

open (FILE, "$file_name") || die &error_message("$file_name을 열수 없습니다.");
@data = <FILE>;
close (FILE);  
# 그 파일을 열어서...

for $list(0..7)
{
	($key, $value) = split(/=/, $data[$list]);
	$file_data{$key} = $value;
}
# 본문 전까지 불러내서 분리하고, 

for $list(8..$#data)
{
	$data[$list] =~ s/\n/<br>/;
	$body .= $data[$list];
}

($key, $value) = split(/=/, $body);
$file_data{$key} = $value;
# ... 계속
					

 본문을 하나의 문자열로 만듭니다. 원래 이렇게 하지 않아도 되죠. BODY=...이렇게 했기 때문에 작업이 조금 길어 졌습니다. BODY분분을 BODY=이렇게 하지 않고, TITLE다음에 바로 본문 내용이 오게 한다면 이런 과정은 필요 없습니다. 그냥 출력하면 그만이죠...여러분들은 이렇게 해보세요.

 위 코드가 넘어온 변수를 사용해서 진짜 우리가 부르고자 하는 파일을 설정하고, 열어서, 각각의 데이터로 분류하는 과정입니다. 뭐... 이렇게 하면 우리가 하고자 하는 작업의 반은 끝난거지여....

print "
	<html>
		<head>
			<style type=\"text/css\">
				A:link          { color:#3542c4; text-decoration : none}
				A:visited       { color:#3542c4; text-decoration : none}
				A:hover         { color:red; text-decoration : underline }
			</style>
		</head>
		<body bgcolor=white>\n";
		
		&print_content;
		
print "
			<table border=0 width=550>
				<tr>
					<td bgcolor=white>
						<font size=2 color=#3542c4>
							<b>글번호 : </b>$head_number<br>
							<b>조회수 : </b>$file_data{'COUNT'}<br>
							<b>등록일 : </b>$file_data{'DATE'}<br>
							<b>홈페이지 : </b><a href=\"$file_data{'HOMEPAGE'}\">
							
							$file_data{'HOMEPAGE'}</a>
						</font>
					</td>
				</tr>
				<tr>
					<td bgcolor=white><font size=2 color=#3542c4><b>성&nbsp&nbsp&nbsp&nbsp&nbsp명 : 
						$file_data{'NAME'}</b> ($file_data{'IP'})</font><br>
						<font size=2 color=#3542c4><b>전자우편 : </b><a href=\"mailto:$file_data{EMAIL}\">
						$file_data{'EMAIL'}</font></a>
					</td>
				</tr>
			</table>
			<table border=0 width=550 bgcolor=white>
				<tr>
					<td bgcolor=#3542c4 height=23 align=center><font size=2 color=white><b>$file_data{'TITLE'}</b></font></td>
				</tr>
				<tr>
					<td align=left><br><font size=2 color=black>$file_data{'BODY'}</font><p></td>
				</tr>\n";
					

 이 부분은 특별한 설명이 없어도 잘 아시리라 믿습니다. 그냥 일정 형식에 맞춰 출력하는거죠. 전 디자인 감각이 없어서... 이렇게 하고 매우 만족했답니당....^^;;

이전글, 다음글, 조회수(next, prev, count)

$next_msg = &get_next_msg($now_num);
$prev_msg = &get_prev_msg($now_num);
&display_next_prev($next_msg, $prev_msg);

print "
<tr>
	<td align=right>
		<a href=$url onMouseOver=\"window.status=('Home'); return true;\">$HOME_IMAGE</a>
		<a href=./board_pwd.cgi?mode=delete&number=$file_number onMouseOver=\"window.status=('Delete data $head_number'); return true;\">$DELE_IMAGE</a>
		<a href=./board_pwd.cgi?mode=modify&number=$file_number onMouseOver=\"window.status=('Modify data $head_number'); return true;\">$MODI_IMAGE</a>
		<a href=\"./board_reply.cgi?num=$file_number&virtual=$head_number\" onMouseOver=\"window.status=('Reply data $head_number'); return true;\">$REPLAY_IMAGE</a>
		<a href=./board_write.cgi onMouseOver=\"window.status=('Write'); return true;\">$WRITE_IMAGE</a>
		<a href=./view_list.cgi?move=$head_number onMouseOver=\"window.status=('List'); return true;\">$LIST_IMAGE</a>
	</td>
</tr>\n";
&about_board;

print "</table></body></html>";
&count_up($file_number, $file_name);
					

 위의 코드를 더 추가하면 프로그램이 끝이나죠. 이전글과 다음글을 추가하고, 필요한 아이콘(홈, 삭제, 수정, 답변, 쓰기, 목록)을 출력하고 조회수를 하나씩 올리면 됩니다.

그럼 다음글, 이전글, 조회수에 대해 좀더 알아보죠.

get_next_msg()

sub get_next_msg
{
	my ($n_now_num) = @_;
	my (@next_data, $next_msg);
	
	if ($now_num == '0')
	{
		$next_msg = "";
		return $next_msg;
	}
	else
	{
		open (FILE, "$idx_file") || die &error_message("$idx_file을 열수 없습니다.");
		@next_data = <FILE>;
		$next_msg = $next_data[$n_now_num - 1];
		close (FILE);
		
		return $next_msg;
	}
}
						

 이 함수에 넘겨주는 값은 인덱스 파일에서 현재 우리가 보고 있는 인덱스번호의 배열번호죠. 근데 12개의 게시물중, 12번째를 클릭해서 보고 있다면(현재 배열번호는 0), 다음글이 없죠. 그렇지 않다면, 인덱스 파일을 열어서, 현재 배열에서 하나를 뺍니다. (다음글이라고 더하는게 아닙니다. 우리가 보는건 12, 11, 10 이고, 배열을 0, 1,2... 이렇게 됩니다.) 하나를 빼야 11번을 보고 있다면(현재 배열번호 1), 하나를 빼야 12번(다음 배열번호 0)이 되는 겁니다. 그래서 그 줄을 리턴합니다.

get_prev_msg()

sub get_prev_msg
{
	my ($p_now_num) = @_;
	my (@prev_data, $prev_msg);
	
	if ($head_number == '1')
	{
		$prev_msg = "";
		return $prev_msg;
	}
	else
	{
		open (FILE, "$idx_file") || die &error_message("$idx_file을 열수 없습니다.");;
		@prev_data = <FILE>;
		$prev_msg = $prev_data[$p_now_num + 1];
		close (FILE);
		
		return $prev_msg;
	}
}
						

이 함수는 get_next_msg() 함수와 같은 기능을 하죠. 그냥 이전글 목록을 리턴합니다. 단.. 현재 보고 있는 목록번호가 '1'이라면 이전글은 존재하지 않죠.

display_next_prev()

sub display_next_prev
{
	my ($dis_next) = $_[0];
	my ($dis_prev) = $_[1];
	my ($next_idx, $prev_idx, $name, $next_title, $prev_title, $count, $date);
	
	($next_idx, $name, $next_title, $count, $date) = split (/::/, $dis_next);
	($prev_idx, $name, $prev_title, $count, $date) = split (/::/, $dis_prev);
	
	print "
<tr>
	<td><br><font size=2><font color=green><b>☞ 다음글 :</b> <a href=./board_view.cgi?real_number=$next_idx&virtual_number=$next_vir onMouseOver=\"window.status=('Read next data'); return true;\">$next_title</a></font><p>
	<font size=2><font color=green><b>☞ 이전글 :</b> <a href=./board_view.cgi?real_number=$prev_idx&virtual_number=$prev_vir onMouseOver=\"window.status=('Read preview data'); return true;\">$prev_title</a></font>
	</td>
</tr>
<tr>
	<td align=center> <hr width=100% size=2 color=#3542c4> </td>
</tr>\n";
}
						

 이 함수는 위에서 설정된 $next_msg, $prev_msg를 인수로 받아서 타이틀을 분리해 낸 다음 다음글, 이전글의 제목을 표시하게 됩니다.

count_up()

sub count_up
{
	my ($index_number, $data_file) = @_;
	my (@count_data, @count, $now_count, @count_data_file, $i_count, $c_key, $c_value);
	$i_count = 0;
	
	open (FILE, "$idx_file") || die &error_message("$idx_file을 열수 없습니다.");
	@count_data = <FILE>;
	close (FILE);
	
	open (FILE, ">$idx_file") || die &error_message("$idx_file을 열수 없습니다.");
	foreach (@count_data)
	{
		@count = split(/::/, $_);
		if ($count[0] eq $index_number)
		{
			$count[3]++;
			print FILE "$count[0]::$count[1]::$count[2]::$count[3]::$count[4]";
		}
		else
		{
			print FILE $_;
		}
	}
	close (FILE);
	
	open (FILE, "$data_file") || die &error_message("$data_file을 열수 없습니다.");
	@count_data_file = <FILE>;
	close (FILE);
	
	open (FILE, ">$data_file") || die &error_message("$data_file을 열수 없습니다.");
	foreach (@count_data_file)
	{
		if ($i_count eq '1')
		{
			($c_key, $c_value) = split(/=/, $count_data_file[$i_count]);
			$c_value++;
			print FILE "COUNT=$c_value\n";
		}
		else
		{
			print FILE $_;
		}
		
		$i_count++;
	}
	
	close (FILE);
}
						

 이 함수가 마지막 함수네여... 조회수를 증가 시키는 함수죠. 넘어오는 인수로는 현재보고있는 실제 인덱스 번호하고, 실제 파일명이 넘어옵니다. 하게되는 작업은 인덱스 파일을 열어서, 인덱스번호를 비교해서 현재의 인덱스번호라면 조회수에 해당하는 숫자를 '1'증가시켜서 저장하구여,

 해당되는 파일을 열어서 조회수부분의 데이타를 '1'증가시켜서 다시 저장하는 작업이져.

NOTES

 여기까지라도 그나마 쓸만한 게시판(현재 제 홈에 사용된 -.-)정도로는 기능을 발휘할 수 있지 않을까 생각하는데여...... 쓰고, 목록도 보여주고, 목록중 선택한 데이터 읽고, 조회수도 증가하구.... 남은건.... 답변하고, 지우고, 수정하고, 검색하고, (관리자를 뺀다면...) 헐~~~ 생각해 보니 아직도 많이 남았군여..... 여러분들도 각자 생각해 보시구여, 그럼 다음에 뵙겠습니다. 의문사항이나 개선사항, 좋은 의견이 있으시면 멜을 보내주시거나, 게시판에 남겨주세요.


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

'Common Gateway Interface > Perl' 카테고리의 다른 글

[옛 강좌] 27. Perlprog - BBS 6  (0) 2015.04.29
[옛 강좌] 26. Perlprog - BBS 5  (0) 2015.04.29
[옛 강좌] 24. Perlprog - BBS 3  (0) 2015.04.29
[옛 강좌] 23. Perlprog - BBS 2  (0) 2015.04.29
[옛 강좌] 22. Perlprog - BBS 1  (0) 2015.04.29