본문 바로가기

Common Gateway Interface/Perl

[옛 강좌] 30. Perlprog - BBS 9

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

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

Perlprog - BBS 9

Description

게시판 만들기 9 - 검색


BBS 만들기 9

 게시판 만들기 아홉 번째 입니다. 휴... 어느덧 여기까지.... 이제 검색만 프로그램하면, 게시판의 모든 형태는 다 나오게 되네여... 그럼 검색에 대해 생각해 봐여. '이름', '제목', '본문' 이렇게 세 개의 조건으로 검색을 하겠습니다. 물론 동시 검색은 지금하지 않겠습니다. 그건 여러분들이 직접 해보시구여.... 우리가 지금까지 해온 것을 잠깐 보면.. board.idx파일이 있죠. 여기에 '이름'과 '제목'으로 검색을 할 수 있습니다. 그러니 위 두개의 조건이라면 idx파일만 열어서, 해당항목과 검색어를 비교하면 되구여.

 '본문'으로 검색을 한다면 각각의 파일을 열어야죠. 열어서 본문에 해당하는 데이터와 검색어를 비교를 합니다. 이 때, 해당 검색어와 조건이 일치하는 줄이 여러 줄에 걸쳐서 나올 수 있습니다. 그러므로, 한 번만 조건이 일치하면 루프를 바로 빠져나오도록 해야 됩니다. 또한 '이름', '제목'으로 검색을 했을 때, 해당 검색어를 빠알간색으로 처리하는 것도 괜찮겠죠. 물론 본문도 그렇게 할 수 있지만, 여기서는 하지 않겠습니다. 그럼 시작합니다.

 아.. 참고로, 함수 별로 살펴보겠습니다. 이 함수들을 합해서 하나의 프로그램으로 완성하는 것은 여러분의 몫으로 하겠습니다.(^^;)

board_search.cgi - 데이터 검색

SearchData()

sub SearchData
{
	### 먼저 검색어가 입력되지 않았을 경우를 처리합니다.
	if (!$input{'word'})
	{
		&error_message("입력된 검색어가 없습니다.");
		exit 0;
	}
	
	### 유효한 검색어인지 검사합니다.
	### 이 특수문자에 대해서는 디코딩과정없이, 바로 걸렀습니다.
	### 이 특수문자들로 검색을 해보세요. 아주 재밌는 현상이 생깁니다.
	### 꼭 해보세요.
	else
	{
		if(($input{'word'} =~ /^\./) || ($input{'word'} =~ /^\\/) || 
		($input{'word'} =~ /^\(/) || ($input{'word'} =~ /^\*/) || 
		($input{'word'} =~ /^\$/) || ($input{'word'} =~ /^\|/) || 
		($input{'word'} =~ /^\^/) || ($input{'word'} =~ /^\)/) || 
		($input{'word'} =~ /^\+/) || ($input{'word'} =~ /^\[/) || 
		($input{'word'} =~ /^\/) || 
		($input{'word'} =~ /^\?/)) 
		{
			### 위의 조건에 맞다면, 검색결과가 없다는 메세지를 출력합니다. $s_i변수는 검색결과의 개수입니다.
			$s_i = 0;
			
			&search_html($s_i);
			&search_bottom;
			exit 0;
		}
	}
	
	### 위의 조건을 모두 만족할 경우, 검색항목이 '이름', '제목', '본문'에 따라서
	### 검색을 수행할 'get_search_word()' 함수에 어떤 항목으로 검색하라는 걸 넘겨 줍니다.
	if ($input{'search_list'} eq 1)
	{
		$search_case = 1;
		&get_search_word($search_case);
	}
	elsif ($input{'search_list'} eq 2)
	{
		$search_case = 2;
		&get_search_word($search_case);
	}
	else
	{
		$search_case = 3;
		&get_search_word($search_case);
	}
}
						

get_search_word()

sub get_search_word
{
	## 위 함수(SearchData()) 함수에서 넘겨준 검색항목을 받습니다.
	local ($sr_case) = @_;
	
	## 검색결과의 개수를 초기화하고, 검색어를 받습니다.
	$s_i = 0;
	$sword = $input{'word'};
	
	## 검색항목이 '이름' 또는 '제목' 일 경우입니다.
	## board.idx 파일을 열어서 '::'로 분리를 한 다음, '이름'은 배열의 2번째,
	## '제목'은 배열의 3번째 값이므로, 그 값과 검색어를 비교합니다.
	## 조건이 일치하는 경우, %SearchResult 라는 해쉬에 검색결과에 해당하는
	## $s_i변수를 'key'로, 그리고 해당하는 'idx'번호를 'value'로 저장합니다.
	## 이렇게 저장을 해두면, 나중에 검색결과에 일치하는 항목은 해쉬배열에 해당하는 값을 불러오면 됩니다.
	## $s_i 변수가 처음엔 '0'이지만, 조건이 일치할때 마다, 하나씩 증가 시킵니다.
	if (($sr_case eq 1) || ($sr_case eq 3))
	{
		open (FILE, "$DB_idx") || die &error_message("$DB_idx을 열수 없습니다.");
		@SearchData = ;
		close (FILE);
		
		foreach (@SearchData)
		{
			($sidx, $sname, $stitle, $scount, $sdate) = split(/::/, $_);
			
			if ($sr_case eq 1)
			{
				if ($stitle =~ /$sword/i)
				{
					$SearchResult{$s_i} = $sidx;
					$s_i++;
				}
			}
			elsif ($sr_case eq 3)
			{
				if ($sname =~ /$sword/i)
				{
					$SearchResult{$s_i} = $sidx;
					$s_i++;
				}
			}
		}
	}
	
	## 검색항목이 '본문'일 경우입니다.
	## idx 파일을 열고, 인덱스 번호에 맞게, 데이터 파일을 엽니다.
	## 데이터 파일에서 본문에 해당하는 데이터에서만 검색작업을 하고,
	## 위에서 말씀드린 것처럼, 해당하는 항목이 한 번 나타나면 바로 루프를 빠져 나옵니다.
	## 검색결과의 저장방식은 위와 같습니다.
	else
	{
		open (FILE, "$DB_idx") || die &error_message("$DB_idx을 열수 없습니다.");
		@s_idx = ;
		close (FILE);
		
		foreach(@s_idx)
		{
			@s_idx_number = split(/::/, $_);
			
			$search_file = "$DB_data_dir/"."board".$s_idx_number[0].".dat";
			
			open (FILE, "$search_file") || die &error_message("$search_file을 열 수 없습니다.");
			@s_body = ;
			close (FILE);
			
			($sidx_temp, $sidx) = split(/=/, $s_body[0]);
			chomp($sidx);
			
			for (8..$#s_body)
			{
				if ($s_body[$_] =~ /$sword/i)
				{
					$SearchResult{$s_i} = $sidx;
					$s_i++;
					last;
				}
			}
		}
	}
	## 위의 루프에서 검색결과개수와 조건에 일치하는 데이터가 저장되었습니다. 출력만 하면 됩니다.
	## 먼저 머리부분을 출력합니다. 모두 몇개의 검색결과가 있다는 메세지를 보여 줍니다.
	&search_html($s_i);
	
	## 그리고 가상번호를 정합니다. 그리고 해쉬배열의 0번부터 불러와야 하니깐,
	## $s_i변수를 '0'으로 합니다.
	$s_count_number = $s_i;
	$s_i = 0;
	
	## 인덱스 파일을 열어서, 해쉬배열에 저장된 인덱스번호와 일치하는 항목을
	## 화면에 뿌려줍니다. 이 일을 맏는건 'build_table()'함수가 맡게 됩니다.
	## 가상번호를 하나씩 줄이면서 1이되면, 작업을 마칩니다.
	open (FILE, "$DB_idx") || die &error_message("$DB_idx을 열 수 없습니다.");
	@SearchData = ;
	close (FILE);
	
	foreach (@SearchData)
	{
		($sidx, $sname, $stitle, $scount, $sdate) = split(/::/, $_);
		
		if ($sidx eq $SearchResult{$s_i})
		{
			&build_table;
			$s_i++;
			last if ($s_count_number == '1');
			$s_count_number--;
		}
	}
	## 마지막부분의 HTML을 출력합니다. 이러면 모든 작업이 끝나게 됩니다.
	&search_bottom;
}
						

build_table()

 build_table() 함수는 view_list.cgi에서 각각의 테이블 모냥으로, 데이터를 출력만 하면 됩니다.

search_html()

 search_html() 함수는 검색 결과 개수를 받아서 전체 폼의 머리 부분의 출력을 담당합니다. 검색결과가 몇 개이고, 테이블의 번호, 이름 등... 을 출력합니다.

search_bottom()

 search_bottom() 함수는 우리가 게시판을 처음 눌렀을 때 나타나는 그 폼 그대로죠. view_list.cgi의 아래 부분 출력과 같습니다.

NOTES

 여기까지입니다. 위의 각 함수들을 하나의 프로그램으로 묶는 작업이 여러분이 해야될 일이고, 숙제가 되겠져?(^^;) 여기까지 오셨으면... 충분히 하실 수 있으실 겁니다.


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