제공되는 세셔너 함수
세셔너 0.2.3부터는 PHP4에서 제공되는 모든 세션 함수를 제공합니다. 세셔너 함수의 사용방법은 PHP4 세션함수와 동일합니다. 그러니 자세한 내용은 PHP4 Manual을 참조하세요. 여기서는 PHP4 Manual에 없거나 차이나는 부분만 언급합니다.
세션함수 |
PHP4 |
세셔너 |
기능 |
session_start |
PHP 4 |
0.0.1 |
세션 데이터 초기화 |
session_destroy |
PHP 4 |
0.0.1 |
세션에 등록된 모든 데이터 제거 |
session_name |
PHP 4 |
0.2.0 |
세션명 획득/설정 |
session_module_name |
PHP 4 |
0.2.3 |
세션모듈명 획득/설정 |
session_save_path |
PHP 4 |
0.2.0 |
세션저장패스 획득/설정 |
session_id |
PHP 4 |
0.2.0 |
세션ID 획득/설정 |
session_register |
PHP 4 |
0.0.1 |
현세션에 변수 등록 |
session_unregister |
PHP 4 |
0.0.1 |
현세션에 등록된 변수 삭제 |
session_unset |
PHP 4.0b4 |
0.2.0 |
세션변수 해제 |
session_is_registered |
PHP 4 |
0.2.0 |
등록 여부 확인 |
session_get_cookie_params |
PHP 4.0RC2 |
0.2.2 |
세션 쿠키 매개변수 획득 |
session_set_cookie_params |
PHP 4.0b4 |
0.2.2 |
세션 쿠키 매개변수 설정 |
session_decode |
PHP 4 |
0.2.3 |
문자열을 세션변수화 |
session_encode |
PHP 4 |
0.2.3 |
세션데이터를 문자열화 |
session_set_save_handler |
PHP 4.0b4 |
0.2.3 |
사용자정의 세션저장함수 설정 |
session_cache_limiter |
PHP 4.0.3 |
0.2.2 |
캐시리미터 획득/설정 |
session_register()
PHP3에서는 가변길이 인수 리스트(variable_length argument list)를 지원하지 않기 때문에 session_register() 함수의 인수는 하나만 지정할 수 있습니다. 여러 개의 세션 변수를 지정하려면 session_register() 함수를 반복하여 사용하세요. 이 방법은 PHP4용 세션함수에서도 사용되는 방법입니다.
[code php;gutter:false]
session_register("a", "b");
[/code]
< PHP4용 세션함수만 가능한 방법 >
[code php;gutter:false]
session_register("a");
session_register("b");
[/code]
< 세셔너와 PHP4용 세션함수 모두 가능한 방법 >
세셔너 0.2.0 부터는 배열형식으로 여러 개의 세션변수를 등록할 수 있습니다. 이 방법은 PHP4용 세션함수에서도 사용되는 방법입니다.
[code php;gutter:false]
session_register(array("a","b"));
[/code]
< 세셔너와 PHP4용 세션함수 모두 가능한 방법 >
session_name()
세션명(session name)은 쿠키에 저장된 세션ID를 참조하기 위해 쿠키변수명으로 사용합니다. 세셔너에서는 기본적으로 세션명이 PHP4 세션과 마찬가지로 "PHPSESSID"로 설정되어 있습니다. 버전 0.2.3 이전에서는 세션명이 "PHPSES3ID"였습니다.
[code php;gutter:false]
//
// 클라이언트에서 전달해 온 세션ID를 참조하기 위해 세션명 사용
//
$session_id = $HTTP_COOKIE_VARS[$session_name];
//
// 클라이언트로 세션ID를 전달하기 위해 세션명 사용
//
SetCookie($session_name, $session_id, 0, "/");
[/code]
session_name() 함수는 현재 설정되어 있는 세션명을 얻거나 새로운 세션명을 설정할 때 사용할 수 있습니다. 공개된 세션명 "PHPSESSID" 등을 사용하는 것보다는 세션 정보를 조금 더 안전하게 보호할 수 있도록 하려면 세션명을 자신만이 알 수 있는 이름으로 변경하는 것이 바람직합니다. 그래야 세션정보를 훔치려는 장난꾼이 좀 더 고생하겠지요. 훔치려고 작정했으면 언젠가는 훔치기야 하겠지만......
session_name() 함수는 session_start() 또는 session_register() 함수보다 이전에 실행하여야 새로이 지정된 세션명으로 쿠키를 맛있게 굽거나 꺼내옵니다.
[code php;gutter:false]
$previous_name = session_name("%&%*)37#^%8Yd^&"); // 나만 아는 세션명으로 변경
$current_name = session_name();
session_start();
echo "The previous session name was $previous_name\n";
echo "The current session name is $current_name\n";
[/code]
session_save_path()
세셔너는 기본적으로 서버의 /tmp 디렉토리에 세션 파일을 저장합니다. 이 때 파일명은 접두어 "sess_"로 시작합니다. /tmp 디렉토리를 살펴보면 아시겠지만 PHP4용 세션함수에서 사용하는 세션 파일명도 "sess_"로 시작하지요. 세셔너 버전 0.2.3 이전에서는 "ses3_"로 시작하였습니다.
서버 디렉토리 /tmp는 서버에 계정을 가지고 있는 모든 회원이 공용으로 사용할 수 있는 임시 디렉토리로 전혀 보안이 되지 않습니다. 즉, 회원이면 누구든지 /tmp 디렉토리에 있는 세션 파일의 내용을 훔쳐볼 수 있습니다. 또한 서로 다른 웹사이트에서 개별적으로 사용하게 되는 세션파일이 뒤썩이게 되지요. 이와 같이 서버를 다수가 공유하여 사용하는 경우에는 세션 파일이 저장되는 디렉토리를 자신만 접근할 수 있는 곳으로 변경할 필요가 있습니다. 이럴 때 필요한 함수가 session_save_path()입니다. 이 함수는 session_start() 또는 session_register() 함수보다 이전에 실행하여야 새로운 저장장소에 세션파일이 저장됩니다.
[code php;gutter:false]
$previous_path = session_save_path("/home/hwooky/sessioner");
$current_path = session_save_path();
session_start();
echo "The previous session save path was $previous_path\n";
echo "The current session save path is $current_path\n";
[/code]
세션 파일의 저장장소를 변경할 때는 변경된 디렉토리의 소유자 또는 퍼미션을 재설정해 주셔야 합니다. chown 사용법 또는 chmod 사용법은 리눅스 쉘 Manual을 참조하세요.
session_id()
세셔너는 기본적으로 md5(uniqid(""))에 의해 생성된 32바이트의 세션ID를 이용합니다. 만약 쿠키에 저장하는 장바구니와 같은 정보의 ID를 간단하게 회원ID로 지정한다면 이같은 경우는 쿠키정보를 훔치려는 분들의 수고(?)을 상당히 덜어주게 됩니다. 될 수 있으면 이런 분들이 상상할 수도 없는, 실험해 볼 수도 없는 ID를 사용하는 것이 좋겠지요. md5(uniqid("")) 보다 더 나은 방법이 있다면 그 방법에 의해 세션ID를 지정할 수가 있습니다. 이것을 가능하게 하는 함수가 session_id()입니다.
session_id() 함수는 session_start() 또는 session_register() 함수보다 이전에 사용해도 되고 이 후에 사용해도 관계없습니다. 그러나 PHP4 세션함수의 경우를 보면 session_start() 또는 session_register() 함수보다 뒤에서 사용하게 되면 쓸모없는 세션파일이 또 하나 생겨서 session save path 디렉토리에 쓰레기가 쌓이게 됩니다. 그러니 가능하면 session_name()와 session_save_path() 함수와 같이 session_start() 또는 session_register() 함수 이전에 사용하는 것이 좋습니다.
[code php;gutter:false]
$previous_id = session_id("1234567890"); // 세션ID를 이렇게 지정하면 안되겠죠?
$current_id = session_id();
session_start();
echo "The previous session id was $previous_id\n";
echo "The current session id is $current_id\n";
[/code]
session_unset()
session_destroy() 함수를 사용하여 세션 데이터를 지워주더라도 전역변수로 저장되어 있는 세션변수는 계속 남아 있게 됩니다. 버전 0.0.3 이전에서는 이러한 세션변수를 없애기 위해서는 unset()을 이용하거나 아래와 같이 널문자로 지워주어야 합니다.
[code php;gutter:false]
session_destroy();
$bank = ""; // $bank가 현재 세션에 등록된 변수라고 가정하면
[/code]
그러나 버전 0.2.0에서는 session_unset() 함수를 이용하여 세션변수를 삭제할 수 있습니다. session_unset() 함수는 전역변수로 남아있는 세션변수를 깨끗이 없애주는 함수입니다. 주의할 것은 session_destroy() 함수를 사용하기 전에 지정해 주어야 한다는 것입니다. session_unset() 함수는 현재 세션에 등록된 정보를 이용하여 삭제하여야 하는데 session_destroy() 함수를 실행하면 현재 세션에 등록된 정보가 모두 삭제되어 버리기 때문에 session_unset() 함수가 정상적으로 동작하지 않습니다.
[code php;gutter:false]
session_unset(); // 우선 세션변수(전역변수)를 완전히 삭제
session_destroy();// $HTTP_SESSION_VARS[], 세션파일 등 세션데이터를 삭제
[/code]
session_set_save_handler()
세션데이터를 파일시스템이 아닌 데이터베이스와 같은 다른 저장 모듈을 이용하기 위해서는 사용자가 세션 핸들러 함수를 정의하고 이 함수들을 session_set_save_handler() 함수를 이용하여 등록하여야 합니다. 세셔너에서는 버전 0.2.3부터 session_module_name()와 session_set_save_handler()를 제공합니다.
PHP4 세션함수는 디폴트로 세션 데이터를 읽고 저장하기 위한 저장 매체로 파일시스템(모듈명="files")을 사용합니다. 파일시스템을 이용한 방법은 공유메모리를 이용한 방법(모듈명="mm")과 함께 PHP4에 내장하여 제공되고 있습니다. 공유메모리에 의한 세션 구현은 제가 공유메모리에 대한 경험이 없어 세셔너에서는 제공되지 않습니다. 향후 기회가 되면 세셔너에서도 공유메모리를 이용한 세션을 구현해 보고 싶습니다. PHP4에서 "mm" 모듈을 디폴트로 사용하시려면 PHP.INI 파일의 session.save_handler 지시자를 이용하여 "mm" 모듈로 변경해 보세요(저는 사용해 보지 못함).
"files"와 "mm" 모듈은 PHP4에 내장되어 제공되기 때문에 사용하기가 편하지만 나름대로 단점도 가지고 있어 보통 데이터베이스를 이용하여 세션을 구현하는 경우가 많습니다. PHP4에서 제공되지 않는 저장 매체를 이용하기 위해서는 session_set_save_handler() 함수를 이용하게 됩니다. session_set_save_handler() 함수는 새로운 저장매체로부터 세션 데이터를 읽고 저장하기 위한 사용자 정의 함수를 인자로 받게 됩니다. 이와 같이 사용자가 직접 정의하여 세션을 구현하는 방법(모듈명="user")을 이용하면 세션 데이터를 다양하게 활용할 수 있고, 다양한 정보를 end-user에게 제공할 수 있습니다.
session_set_save_handler() 함수를 이용하여 세션 데이터의 저장 매체(MySQL 등)를 확장하는 방법에 대하여는 관련 웹사이트를 검색하시면 부지기수로 얻을 수 있으니, 관심있는 분은 찾아보세요. 이러한 문서들을 참고하시거나 제가 제공하는 세셔너핸들러를 참조하시면 여러분도 그리 어렵지 않게 새로운 저장 매체로 변경할 수 있을 것입니다.
session_module_name()
현재의 세션모듈명을 얻거나 새로운 모듈로 설정할 수 있는 함수입니다. 내장모듈("files", "mm")로 변경할 때는 모듈명을 입력인자로 지정하면 되지만 외장모듈("user")로 변경할 때는 session_module_name() 함수를 사용할 필요가 없으며 session_set_save_handler() 함수를 이용하여 사용자정의 세션저장함수를 재설정하여 주세요. 그러면 현재 모듈명이 "user"로 자동 변경됩니다. 또한 session_destroy() 함수를 실행하면 이전에 사용되었던 사용자정의 세션저장함수에 대한 정보가 사라져 버리기 때문에 이때도 session_set_save_handler() 함수를 이용하여 사용자정의 세션저장함수를 재설정하여 주세요. 세셔너가 공유메모리를 이용한 "mm" 모듈을 제공하지 않기 때문에 session_module_name()을 이용하여 새로운 모듈로 설정할 일이 없을 것입니다. 사실 session_module_name()에 대한 메커니즘에 대하여는 저도 정확히 파악하고 있지 못하기 때문에 상황에 따라 문제가 발생할 수 있습니다.
[code php;gutter:false]
$mn1 = session_module_name();
session_set_save_handler("open", "clase", "read", "write", "destroy", "gc");
$mn2 = session_module_name();
session_start();
if ($init) {
session_unset();
session_destroy();
$mn3 = session_module_name();
session_set_save_handler("open", "clase", "read", "write", "destroy", "gc");
$mn4 = session_module_name();
}
[/code]
session_encode()와 session_decode()
인코딩은 현 세션에 등록되어 있는 세션 데이터(session_register 함수로 등록한 세션변수 및 세션변수에 할당된 값)를 세션파일(또는 세션디비 테이블)에 저장되는 형태의 문자열(예를 들어 access_userid|s:6:"sikkal";access_passwd|s:4:"1234";result_id|b:0;)로 변환시키는 함수입니다.
디코딩은 access_userid|s:6:"sikkal";access_passwd|s:4:"1234";result_id|b:0;와 같이 저장된 문자열을 가지고 세션 데이터(세션페이지에서 사용가능한 변수 형태)로 변환하는 함수입니다.
PHP4와 세셔너의 외부저장매체(파일 등)에 저장된 세션데이터는 하나의 문자열 구조이며, 반면에 메모리에 저장된 세션데이터는 각각의 변수마다 따로따로 저장됩니다. 이와 같이 세션데이터는 그 위치에 따라 서로 다른 구조를 가지고 있어서 상호간의 데이터를 변환할 필요가 있습니다. 이 역할을 하는 것이 session_encode()와 session_decode() 함수입니다. 이 함수들은 사용자가 외부저장매체에 저장되어 있는 문자열 구조의 세션데이터를 직접 다룰 필요가 있을 때에 요긴하게 사용할 수 있을 것입니다. 그런데 PHP4와 세셔너에서 외부저장매체(파일 등)에 저장된 세션데이터를 비교하면 양쪽의 구성 내용이 서로 상이하여 호환성이 없습니다. 사실 세션이라는 것이 각 사용자별, 사용시간별로 서로 독립적으로 작용하는 것이기 때문에 문자열 구조의 세션데이터를 동일한 구조로 설계할 필요가 없다고 보여집니다. 세셔너 자체에서도 ver 0.2.0부터 문자열 구성 내용이 이전 버전과 달리 변경되었습니다(버그때문에). 그러나 만약 문자열 구조의 세션데이터를 직접 다루어야 하는 경우라면 session_encode()와 session_decode() 함수를 이용하여야 하는데 세셔너 함수에서 이를 제공하게 되면 PHP4와 세셔너함수 사이에 호환성이 없어지기 때문에 세셔너를 제작하게 된 목적이 애매하게 되어 제공할 수가 없네요. 세셔너 0.2.3부터 제공되는 session_encode()와 session_decode() 함수는 제한적으로 PHP4 세션함수와의 호환성을 유지합니다. 저장모듈에 저장된 문자열 형태의 세션데이터를 직접 다루지 않고 세셔너함수를 통해서만 세션데이터를 다룬다면 호환성에 전혀 문제가 없습니다. 제가 Tip&Tech&Download 게시판에 공개한 "로그인 사용자 리스트 구하는 방법(세션함수 이용)"과 "동일ID로 다중접속하려는 것을 방지하는 방법(세션함수 이용)"을 보시면 PHP4와 호환성을 유지하면서 session_encode()와 session_decode() 함수를 어떻게 사용할 수 있는지 알 수 있습니다.
당장 세셔너를 PHP4와 동일한 구조로 설계하지 않았느냐고 궁금해 하실지도 모르겠으나 PHP4와 동일한 구조로 설계하는 것이 간단하게 몇 줄의 코딩으로 해결될 것이 아니기 때문이지요. 즉, 코드가 훨씬 복잡해집니다. 소스 코드를 가능하면 간결하게 하고자(사실은 제 실력이 딸려서) PHP4와는 다른 구조를 택하게 되었지요.
"http://www.codelib.co.kr"의 HOME 》Class & Func 》Session&Cookie 에 보면 "session var names (세션변수추출) 0.2" 라는 공개자료가 있는데 이를 이용하여 약간만 수정하면 session_decode() 함수를 구현할 수 있을 것입니다. 관심있는 분은 참조하시길......
session_encode()와 관련된 또 다른 문제는 메소드와 관련된 것입니다. 세션 변수값을 파일과 같은 저장 매체에 저장하려면 serialize() 함수로 직렬화시켜야만 합니다. PHP4용 세션함수도 내부적으로 이 함수를 사용하지요. 그런데 객체의 경우, 정확하게 이야기하면 메소드의 경우는 PHP4부터 지원됩니다. 따라서 PHP3에서는 메소드를 세션에서 사용할 수가 없습니다. 이 문제는 세셔너에서도 동일하게 적용됩니다. 즉, PHP3에서 동작되는 세셔너는 메소드를 세션 관리할 수 없습니다. serialize() 함수와 객체에 관련된 기술적인 정보는 "핍클래스 홈페이지 >> 객체에 관련된 정보 >> Serialize/Unserialize" 메뉴를 참조하세요.
session_get_cookie_params(), session_set_cookie_params()
(0.2.4 이하 버전에 버그 존재 -> 0.2.5에서 수정)세셔너가 세션ID를 전달하기 위해 쿠키를 이용하기 때문에 내부적으로 SetCookie() 함수를 사용하게 됩니다. 여러분이 아시다시피 SetCookie() 함수에 입력되는 매개변수로는 총 6개가 있습니다. 이 중에 첫번째 매개변수가 쿠키명이고, 두번째 매개변수가 쿠키값입니다. 나머지 4개가 쿠키와 관련된 정보들인데 마지막 매개변수인 보안 정보를 제외하고는 session_get_cookie_params()와 session_set_cookie_params() 함수를 통해 3가지 매개변수에 관련된 정보를 획득/설정할 수 있습니다. 이 정보는 쿠키의 만료 시간, 쿠키의 유효 디렉토리, 쿠키의 유효 도메인 정보입니다. SetCookie() 함수와 관련된 정보는 관련 웹사이트 또는 서적을 참조하시기 바랍니다.
[code c;gutter:false]
void session_set_cookie_params(int lifetime [, string path [, string domain]])
int setcookie(string name
, string value
, int expire
, string path
, string domain
, int secure)
[/code]
여기서 한가지 주의할 점이 있습니다. session_set_cookie_params() 함수의 첫번째 매개변수 lifetime과 setcookie() 함수의 세번째 매개변수 expire는 시간을 나타내는 것은 같지만 의미하는 바는 차이가 납니다. session_set_cookie_params() 함수의 첫번째 매개변수 lifetime은 쿠키의 생존시간을 초로 나타낸 것이며, 반면에 setcookie() 함수의 세번째 매개변수 expire는 타임스탬프로 지정한 것입니다. 예를 들어 현재시간을 기준으로 1시간 후까지 유효한 쿠키를 생성할 때 세션함수와 setcookie() 함수에 지정하여야 하는 값은 아래와 같습니다.
[code php;gutter:false]
session_set_cookie_params(3600);
setcookie("mycookie", "cookie_value", time()+3600);
[/code]
session_set_cookie_params() 함수에서는 위와 같이 현재시간을 기준으로 쿠키가 생존하는 시간을 초로 지정하게 됩니다. 그러면 세션함수 내부에서 쿠키를 생성할 때 setcookie("mycookie", "cookie_value", time()+$lifetime) 와 같이 현재시간을 첨부하여 setcookie() 함수로 넘기게 됩니다. 이러한 내용은 PHP4 소스코드 session.c에 정의된 php_session_send_cookie()를 살펴보면 알 수 있습니다. 세셔너 0.2.4 이하의 버전에서는 이 문제와 관련된 버그가 있었습니다.
참고로 setcookie() 함수에서 지정하여야 하는 타임스탬프는 1970년 1월 1일 이후 시간을 초로 표시한 시간입니다. 쿠키 매개변수와 관련하여 세셔너에서 기본으로 설정되어 있는 값은 아래와 같습니다.
매개변수명 |
기본값 |
동작 |
쿠키의 생존시간 |
0 |
사용자가 브라우저를 종료할 때 쿠키가 없어짐 |
쿠키의 유효 디렉토리 |
"/" |
서버상에 있는 모든 디렉토리 |
쿠키의 유효 도메인 |
"" |
쿠키를 설정한 서버의 도메인 |
위에서와 같이 세션 ID는 쿠키로 저장되는데 이 쿠키 변수명은 PHPSESSID입니다. 반면에 PHP4용 세션함수에서는 PHPSESSID입니다.
session_cache_limiter()
아마도 제일 머리 아픈 것 중에 하나가 캐시(cache) 문제일 것입니다. 다양한 사용 환경에서 다양하게 발생하는 캐시 문제는 해결하기도 쉽지 않습니다. 자신이 캐시에 대하여 완벽하게 대처했다고 생각했어도 막상 실험해보면 생각한대로 동작하지 않는 것이 바로 캐시이지요. 그래서 각종 Q&A 게시판에 단골로 등장하게 됩니다. session_cache_limiter() 함수를 구현하기 위해서는 header() 함수를 이용하면 되겠지만 캐시에 관련된 주제가 그리 간단한 것이 아니라서 접근하기가 매우 조심스럽습니다. 캐시 문제에 대하여는 앞으로 시간이 되면 하나의 주제(메뉴)로 다루어야 될 것 같습니다. 그 후에 이 함수 구현에 대하여 고려하는 것이 순서같네요. 제 Q&A 게시판에서도 캐시 문제로 올려진 자료가 있으니 관심있는 분은 검색하여 보시기 바랍니다.
(추가) 세셔너함수 0.2.2부터 session_cache_limiter() 함수를 제공합니다. 캐시리미터에 관한 기술적인 정보는 제 홈페이지 "후키라이브러리>>캐시리미터" 메뉴를 보시면 상세히 기술되어 있습니다.
예약어
예약된 클래스명
세셔너함수에서 클래스를 정의할 때 사용하고 클래스명들은 아래와 같습니다.
sessStaticAbstract : 추상화된 클래스 정의(최상위 클래스)
sessStaticVars : 세션ID 및 전역변수를 관리하기 위한 클래스
sessStatic : 모든 세셔너가 공용으로 사용된 클래스의 마지막 파생 클래스로
내장 모듈("files")이 정의되어 있는 클래스
위의 모든 클래스는 sessStaticAbstract를 최상위 클래스로 하여 순차적으로 상속받아 정의되어 있습니다.
예약된 전역변수
세셔너 내부에서 사용하기 위해 예약된 객체변수 $sessStatic는 아래와 같이 세셔너 파일 내에서 기본적으로 생성되어 있는 객체입니다.
[code php;gutter:false]
$sessStatic = new sessStatic;
[/code]
예약된 전역함수
세셔너 내부에서 정의되어 있는 클래스에서 소멸자를 사용할 수 있도록 sessDestructorExec()라는 함수가 아래와 같이 정의되어 있습니다.
[code php;gutter:false]
function sessDestructorExec() {
global $sessStatic;
$destructor = "_".$sessStatic->Classname;
$sessStatic->$destructor();
}
[/code]