방문자공용변수 개요
MS의 ASP에서 사용되는 Application 객체에서와 같이 웹애플리케이션에서 모든 방문자가 데이터를 공유할 수 있는 변수를 등록하여 다룰 수 있도록 작성된 프로그램입니다.
웹애플리케이션?
웹애플리케이션은 웹 상에서 실행되는 파일들로 구성되며, 일반적으로 같은 디렉토리 상에 저장되어 있는 파일로 구성됩니다. 이러한 웹애플리케이션에서 동작되는 변수는 모든 사용자들이 공유하게 됩니다. 이와 같이 웹애플리케이션에서 동작되는 변수(이하 방문자공용변수)들은 여러 사람이 공유하다보니 단일 사용자만 사용하는 변수(정적변수, 전역변수, 세션변수 등)와는 다소 그 특성이 다르다고 할 수 있습니다.
방문자공용변수로 사용되는 가장 대표적인 경우가 카운터라고 할 수 있습니다. 현재 PHP에서 카운터를 구현할 때에 데이터베이스 테이블을 이용하거나 아니면 파일 액세스를 통해 그때그때 상황에 따라 개발하고 있어 다소 번거로운 면이 있다고 볼 수 있습니다. 만약 모든 사용자가 공유할 수 있는 방문자공용변수를 서버 사이드 스크립트인 PHP가 지원해 준다면 아주 간단히 카운터를 만들 수 있겠으나 그렇지 못한 것이 현실인 것 같습니다. 반면에 ASP에서는 Application 객체를 이용하면 카운터를 보다 간단히 구현할 수 있겠지요.
PHP에서도 모든 사람이 공유해야하는 데이터를 구현하기 위해 그때그때 번거롭게 데이터베이스나 파일을 다루기보다는 미리 방문자공용변수를 다룰 수 있는 라이브러리를 작성하여 이를 이용하면 어떨까 하는 생각에 방문자공용변수를 다룰 수 있는 함수를 클래스를 이용하여 만들어 보았습니다. 클래스 내부적으로는 방문자공용변수를 데이터베이스 테이블에 기록하고 필요에 따라 읽어들이고 있지요. 완벽한 기능을 가지지는 못했지만 좀 더 보완한다면 충분히 사용할 가치가 있다고 생각합니다.
방문자공용변수 충돌 회피의 필요성
방문자공용변수를 사용할 때는 한가지 주의할 점이 있는데, 방문자공용변수를 모든 방문자가 공유하다보니 이 변수를 한 방문자가 다루고 있는 순간에는 다른 방문자가 접근할 수 없도록 막아야 합니다. 그러지 않으면 방문자공용변수에 저장되는 데이터 결과를 전혀 신뢰할 수 없게 되지요.
카운터를 예를 들어보면, 이 카운터는 모든 방문자가 공유하게 됩니다. 한 방문자가 이 카운터를 읽어올 때 "100"이 저장되어 있었다면 이 값에 "1"을 더하여 카운터 값을 "101"로 수정하게 될 겁니다. 수정된 카운터 값을 저장하기 직전에 다른 방문자가 방문하여 카운터 값을 읽게 되면 아직 수정되기 전이기 때문에 "100"을 읽어들일 것이고 이 방문자도 "100"에 "1"을 더하여 카운터 값을 "101"로 수정하여 저장하려고 할 것입니다. 따라서 두 방문자가 모두 접근하더라도 카운터 값의 최종 결과는 "101"이 될 것이고 이 값은 실제 상황과 다른 신뢰할 수 없는 값이 되어 버릴 것입니다.
이런 현상을 방지하기 위해서는 방문자공용변수는 그 변수의 값을 다루기 전에 다른 방문자가 접근할 수 없도록 제한할 필요가 있고, 방문자공용변수를 더 이상 사용할 필요가 없을 때는 제한을 풀어주어 다른 사용자가 방문자공용변수를 사용할 수 있도록 할 필요가 있습니다. 이 역할을 수행하는 멤버함수가 uglobal_lock(), uglobal_unlock() 함수입니다.
[code php;gutter:false] .
.
.
$obj = new clsUserglobal($host, $user, $pass, $base);

$obj->uglobal_lock();

$all_page_hits = $obj->uglobal("pageglobal","all_page_hits")+1;
$obj->uglobal("pageglobal", "all_page_hits", $all_page_hits);

if (0 == ($all_page_hits % 10))
$history = "";
else
$history = $obj->uglobal("pageglobal", "history");

$history .= "[".$obj->webpage_static_id()
. "/히트수][a]=$all_page_hits";
$obj->uglobal("pageglobal", "history", $history);

$obj->uglobal_unlock();
.
.
. [/code]

Posted by 방글24