현재 링크가 강조되는 네비게이션 메뉴

울티마 가이드 메뉴 구성

울티마 가이드 홈페이지의 네비게이션 메뉴는 왼쪽 이미지처럼 수평(horizontal) 주 메뉴와 수직(vertical) 보조 메뉴로 구성되어 있습니다. 그런데 주 메뉴의 ‘처음으로’ 항목은 오렌지색으로, 보조 메뉴의 ‘새 소식’은 밑줄로 강조된 것을 볼 수 있는데 이것은 페이지를 보는 사용자가 현재 위치를 쉽게 알 수 있도록 도와주는 역할을 하고 있습니다.

이런 기능은 강조할 현재 문서 링크에 CSS의 class 속성을 부여하는 것으로 간단히 구현할 수 있습니다. 하지만 각각의 페이지마다 링크 강조를 위한 마크업을 개별적으로 넣게 되면 전체적인 사이트 유지, 관리에 어려움이 생기게 됩니다.

일반적으로 다수의 페이지로 구성된 사이트의 경우 html 편집기(드림위버와 같은)가 지원하는 템플릿이나 PHP와 같은 스크립트 언어를 사용해서 페이지의 일부를 불러오는(include) 방식으로 관리를 하게 되는데 이런 방법으로는 메뉴에 개별적인 마크업을 넣기가 어렵습니다.

문제점을 해결하려면 강조를 담당하는 class가 자동으로 생성되도록 해야합니다. 방법은 여러 가지가 있는데 대표적인 것이 CSS 활용으로 유명한 A List Apart에 제시된 방법으로 PHP 언어로 각 페이지마다 변수를 만들고 이를 이용하는 것입니다. 하지만 이 방법 역시 개별적인 코드가 들어가는 단점이 있습니다.

다른 해결법으로는 모든 메뉴 링크에 id나 class를 미리 부여하는 방법이 있습니다. hicksdesign에서 제시한 방법으로 앞서 소개한 것과는 달리 개별적인 코드가 들어가지 않으므로 메뉴에 들어갈 항목 수가 적다면 이 방법이 가장 효율적일 수도 있습니다. 하지만 울티마 가이드의 일부 보조 메뉴처럼 스무 개 이상의 링크가 들어갈 경우에는 id나 class 부여하는 것도 상당히 번거롭더군요. ^^; 물론 이마저도 PHP 언어를 이용해서 자동으로 처리되도록 할 수 있습니다. 하지만 그보다 더 좋고 편한 방법이 있는데 지금부터 소개해보겠습니다.

요구 사항

일단 PHP 함수를 사용하기 때문에 당연히 PHP 언어가 지원되어야 합니다. 또한, 앞으로 들 예에서는 각각의 주 메뉴에 해당하는 디렉토리가 있고, 그 안에 보조 메뉴와 연결된 html 문서가 있다고 가정하겠습니다. 그런데 일반적으로 사이트의 인덱스 페이지는 웹 서버의 최상위 디렉토리(/)에 있으므로, 첫 번째 주 메뉴에 해당하는 문서들은 하위 디렉토리가 아닌 최상위 디렉토리에 있다고 생각해보지요.

예를 들어 위의 이미지에서 ‘처음으로’ 항목에 속하는 ‘새 소식(index.htm)’, ‘이용 안내(about.htm)’ 등의 문서는 최상위 디렉토리에 있고, ‘브리타니아 도서관’ 메뉴에 해당하는 모든 문서들은 하위 디렉토리인 /library에 있습니다.

PHP 코드

PHP에 익숙한 분들은 아래 코드만 봐도 어떻게 동작하는지 금방 아실겁니다. 일단 보도록 하지요.

<?php
define (INCPATH, '/path/to/include/dir');
function highlight_current($include_file, $target_str) {
	if ($target_str == 'index.htm') $target_str = './';
	$menu = file_get_contents($include_file);
	$menu = str_replace("\"" . $target_str . "\"", "\"" . $target_str . "\" class=\"current\"", $menu);
	echo $menu;
}
$target_file = basename($_SERVER['PHP_SELF']);
$target_dir = dirname($_SERVER['PHP_SELF']);
?>

처음 등장하는 define 문은 불러올(include) 메뉴 파일들이 있는 절대 경로를 선언합니다. 매번 경로 전체를 적어주기 보다 INCPATH 상수를 사용하기 위해서지요.

이어서 나오는 highlight_current 함수가 이 방법의 핵심입니다. 두 개의 인수를 필요한데 첫 번째 include_file은 불러올 메뉴 파일의 이름을, 두 번째 target_str은 현재 보고 있는 문서의 파일 이름이나 디렉토리 이름을 받습니다.

함수에 들어 있는 if 문은 현재 문서가 index.htm일 경우 이름을 ./로 바꿔주는데 각 디렉토리에 있는 인덱스 파일(index.htm)은 굳이 이름을 지정하지 않아도 다음과 같은 형식으로 링크를 만들 수 있기 때문입니다.

<a href="./">인덱스 페이지</a>

다음 등장하는 file_get_contents 함수를 사용하면 인수로 지정된 파일의 내용을 임의의 변수에 넣을 수 있습니다. 따라서 메뉴 링크만으로 구성된 html 파일의 내용을 임시로 보관할 수 있게 되지요.

그러면 str_replace 함수가 임시로 보관된 html 메뉴에서 target_str으로 지정된 문자열을 찾아서 current라는 class를 부여합니다. 예를 들어서 위의 링크가 다음과 같이 바뀌게 되지요.

<a href="./" class="current">인덱스 페이지</a>

마지막으로 class가 부여된 html 메뉴가 echo 명령으로 화면에 출력됩니다.

† 이 방법은 사실 제 독자적인 아이디어는 아닙니다. 예전에 어느 외국 포럼에서 봤는데 다시 찾으려니 안나오더군요. 참고했던 글에서는 정규 표현식(Regular Expression)을 사용했는데 단순한 문자열 치환을 사용하도록 수정했습니다. 그리고 위의 함수는 주 메뉴와 보조 메뉴에 동시에 적용시키려고 제가 만들었습니다.

이어서 두 개의 변수가 선언되는데 각각 현재 문서의 파일 이름과 속한 디렉토리 이름이 대입됩니다. 이 변수들을 상황에 따라서 highlight_current 함수의 두 번째 인수로 사용하게 되지요.

메뉴 불러오기

이제 실제 어떻게 사용되는지 알아보겠습니다. 먼저 울티마 가이드의 주 메뉴를 불러오는 예를 보여드리지요. 일단 주 메뉴는 menu-top.htm 파일에 아래 내용이 들어있습니다.

<div id="nav">
	<ul>
		<li><a href="/">처음으로</a></li>
		<li><a href="/library">브리타니아 도서관</a></li>
		<!-- 중간 생락 -->
	</ul>
</div>

이 메뉴를 다음 PHP 문으로 불러옵니다.

<?php highlight_current(INCPATH.'/menu-top.htm', $target_dir) ?>

현재 문서가 /library 디렉토리에 있다면 target_dir/library가 되므로 ‘브리타니아 도서관’ 메뉴에 자동적으로 current class가 부여됩니다.

그러면 이번에는 보조 메뉴를 불러와 볼까요? 불러올 보조 메뉴는 문서가 속한 디렉토리에 따라서 자동으로 정해집니다. 일단 코드를 보여드리지요.

<?php if ($target_dir == '/') $target_dir = '/root'; highlight_current(INCPATH.$target_dir.'-sm.htm', $target_file); ?>

이 코드에는 if 문이 들어가 있는데 웹 서버의 최상위 디렉토리(/)에 있는 문서일 경우 /root라는 디렉토리에 있다고 가정하게 됩니다. 위치한 디렉토리에 따라서 보조 메뉴를 불러오게 되는데 이 경우에는 root-sm.htm 파일이 그 대상이 됩니다. 하위 디렉토리에 있는 문서일 경우에는 디렉토리 이름 뒤에 -sm.htm이 붙은 파일을 불러오지요. 예를 들어서 /library 디렉토리에 있는 문서라면 library-sm.htm 파일에 메뉴가 들어있어야 합니다. 실제로 다음과 같은 메뉴가 들어 있습니다.

<div id="subnav">
	<h4>지식의 서</h4>
	<ul>
		<li><a href="./">머리말</a></li>
		<li><a href="folklore.htm">역사와 신화</a></li>
		<!-- 중간 생략 -->
	</ul>
</div>

그러면 highlight_current 함수가 현재 문서의 파일 이름을 바탕으로 현재 링크에 current class를 부여합니다.

CSS 작성

강조된 링크에 어떤 효과를 넣을지 지정하는 것은 간단한 CSS 규칙을 사용하면 됩니다. 예를 들어서 밑줄을 넣으려면 다음과 같이 작성하면 되겠지요.

a.current { text-decoration: underline; }

마치며

글이 무지 길어졌네요^^; 개인적으로 짧은 글을 선호하는데 쉽지가 않습니다. 이 방법을 잘 응용하면 블로그에도 적용할 수 있겠지만 메뉴나 최신 글 등에 속하지 않는 페이지에는 적용되지 않기 때문에 전체적인 메뉴의 일관성을 유지하기가 어려울 것 같아서 테스트만 해보고 실제로 적용하지는 않았습니다.

울티마 가이드는 앞서 소개했던 템플릿과 페이지 일부를 파일에서 불러오는(include) 방식을 함께 사용하는데 주 메뉴나 보조 메뉴는 파일 하나만 변경하면 모든 페이지에 적용되고, 레이아웃 역시 템플릿 파일 하나로 쉽게 관리됩니다.

그러나 결정적으로 내용을 업데이트 한한다는게 문제지요. ^^; 그래서 당분간 울티마 가이드를 우선적으로 업데이트 할 생각입니다. 결과는 알 수 없지만요~

태그: , ,

댓글이 닫혔습니다.