웹모아
웹모아[손님] 검색   로그인 / 회원가입    


 
환경설정
 


세션을 DB로 관리하기 + 쪽지 확인하기
  2007-07-21 11:31:04 댓글:(1)   조회:1598



[1] 대개의 경우, 회원 로그인에 세션을 사용합니다. 즉 회원으로 로그인하지 않으면 세션을 사용할 일이 없는 경우가 많습니다. 따라서 여기서는 회원 전용 세션만 관리하도록 하겠습니다.

[2] 세션 테이블을 만들어서, 여기에 매번 insert, delete를 하는 것은 비록 테이블 크기가 작다고 하더라도 제법 부하를 줍니다. 따라서 여기서는 delete를 쓰지 않고 update만 사용하도록 하겠습니다. 회원이 몇만명이라고 할지라도 이게 더 나은 것 같더군요.

세션 테이블을 다음과 같이 만듭니다. 회원목록 테이블과 똑같은 rows를 갖게 되겠죠.
CREATE TABLE `user_sessions` (
`uid` int(10) unsigned NOT NULL default '0', /* 회원ID */
`sess_key` varchar(32) NOT NULL default '', /* 세션키 */
`last_log` int(11) unsigned NOT NULL default '0', /* 세션을 기록하는 시간 */
`last_ip` varchar(15) NOT NULL default '', /* 꼭 필요하지는 않지만, 추후 필요성을 느끼게 될 것임 ;-) */
`sess_value` text NOT NULL, /* 세션값 */
PRIMARY KEY (`uid`),
KEY `sess_key` (`sess_key`)
) TYPE=MyISAM;

세션을 처리하는 스크립트는 다음과 같습니다.
(편의상 DB 클래스를 사용했습니다만, 뭐하는건지는 다 아시겠죠? --;;)

session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
session_start();

function sess_open($save_path, $session_name) {
return 1;
}

function sess_read($key) {
$DB =& DB::getInstance();
$DB->query("SELECT sess_value FROM user_sessions WHERE sess_key = '$key' AND last_log > '".(time()-get_cfg_var("session.gc_maxlifetime"))."' ");
$row=$DB->get();
return $row[0];
}

function sess_write($key, $value) {
$DB =& DB::getInstance();
$DB->query("UPDATE user_sessions SET last_log='".time()."', last_ip='".$_SERVER["REMOTE_ADDR"]."', sess_value='$value' WHERE sess_key='$key' ");
return '';
}

function sess_close() {
return 1;
}

function sess_destroy($key) {
$DB =& DB::getInstance();
$DB->query("UPDATE user_sessions SET sess_key='', last_log='".time()."', last_ip='".$_SERVER["REMOTE_ADDR"]."' WHERE sess_key='$key' ");
}

function sess_gc($lifetime) {
return 1;
}

[3] 회원 로그인하는 부분에서 sess_key 값을 할당합니다. 그 다음부터 그 회원은 세션 테이블에서 데이타를 읽고 쓸 수 있습니다.
비회원인 경우는 session_start()를 하더라도 세션키값만 주어질 뿐, 여러가지 $_SESSION값을 사용할 수 없습니다. (물론 쿠키값을 이용해 비회원의 경우는 아예 session_start()를 실행하지 않는 방법도 있죠. ^^;;) 

[4] 이렇게 함으로써 굳이 가비지 콜렉션(update 혹은 delete)을 하지 않아도 됩니다. 또 회원의 마지막 접속시간이 최신으로 유지됩니다.

[5] 회원의 중복 로그인이 방지됩니다. 다만, 같은 위치에서 다른 세션을 다시 시작하는 경우인지, 이미 로그인된 상태인지 등의 예외적 상황을 처리하기 위해 로그인을 처리하는 부분을 보강해야겠죠. ;-)

------------------------------
자, 이쯤에서 한가지 욕심을 내어볼까요? 이른바, 쪽지 기능을 추가해보겠습니다. (실시간 쪽지 기능 아닙니다. --;;)
제로보드인가? 쪽지를 받으면 "딩동, 새로운 메시지가 도착했습니다" 하는 소리가 나쟎아요.
받은 쪽지 테이블을 따로 만들면, 매번 해당 테이블을 읽어야 하지 않습니까. 뭐 굳이 2번 작업을 하냐, 세션을 시작하면서 자동적으로 그 데이타를 읽어오자 하는거지요.

`user_sessions` 테이블에 chk_msg 라는 필드를 하나 추가합니다.
ALTER TABLE `user_sessions` ADD `chk_msg` TINYINT(2) UNSIGNED NOT NULL AFTER `last_ip` ;
다른 회원이 쪽지를 보낼때, chk_msg 값을 하나씩 증가시키고, 쪽지를 확인하면 chk_msg 값을 0로 update하려는 것입니다.

sess_read 함수를 변형시켜서, chk_msg 필드값을 읽어오도록 합니다.
function sess_read($key) {
$DB =& DB::getInstance();
$DB->query("SELECT uid, chk_msg, sess_value FROM user_sessions WHERE sess_key = '$key' AND last_log > '".(time()-get_cfg_var("session.gc_maxlifetime"))."' ");
$row=$DB->get();
$GLOBALS["USER"]["id"]=$row[0];
$GLOBALS["USER"]["chk_msg"]=$row[1];
return $row[2];
}

여기서는 $USER라는 변수에 회원ID, 받은쪽지 갯수를 저장하도록 했습니다. 즉 회원ID를 알기 위해 $_SESSION["id"]를 쓰지 않고 $USER["id"]를 쓸 수 있다는 거지요. 받은 쪽지 갯수는 $USER["chk_msg"]에 들어가니까 매번 이 값을 검사해서 "딩동~ 메시지가 도착했습니다" 라고 알려주면 됩니다.

"뭐야, 난데없이 $USER 라는 글로벌 오브젝트라니.... 난 이런거 싫어" 하시는 분.
여기서 $USER와 같은 변수를 할당하지 않고, $_SESSION을 사용해도 됩니다. $USER["chk_msg"]="1" 대신에 $_SESSION["chk_msg"] = "1" 이라고 써도 된다는 겁니다. 세션함수 안에서 $_SESSION을 사용한다니, 황당한 트릭이죠? 번거롭게 세션값($row[2])을 직접 파싱할 필요가 없습니다.
다만, 이것은 맨처음 1번만 적용됩니다. 다음번에 $_SESSION["chk_msg"] = "2" 라고 하더라도, 이미 세션 데이타 안에 "chk_msg"값이 1로 들어있기 때문에, 결과는 "1"로 나옵니다. 따라서 $_SESSON["chk_msg"] 값을 확인해서 "딩동~" 하는 메시지를 보여주거나 말거나 한 후에, 매번 unset($_SESSION["chk_msg"])를 해줘야하겠죠?



 댓글 (1)


  •   홈마스타    2007-07-21 11:32:10
    다시 보니 빠뜨린 부분이 있었네요. UPDATE 하는 부분에서도 시간 체크를 해야 됩니다.
  • 



환경설정
페이지: 1 / 2   


   PHP.INI에서의 세션 관련 설정4305
   [PHP] $_SERVER3471
   php 에서 세션시간설정1343
   업로드 용량과 관련한 php.ini 파일 설정1294
   mbstring - PHP 확장모듈을 추가하는 방법1340
     [RE] mbstring - PHP 확장모듈을 추가1463
   타도메인간 쿠키 공유하기1714
   home 데이타 백업 스크립트1287
   cron 이용 일정시간마다 php문실행2106
   cron, crontab, PHP 소스 자동실행, 1575
   crontab 에서 php 파일 실행이 가능한지요?1406
   crontab php 스크립트 실행문제입니다.(1) 1292
   2차 도메인과의 세션고유1517
   POST로 값을 넘길때, 만료된 페이지입니다 문제의(홈마스타)3100
   세션(로그인)시간 무한대로 늘리기 초간단 초보용(홈마스타)(2) 1399
   php mysql 세션 관리(홈마스타)2648
세션을 DB로 관리하기 + 쪽지 확인하기(홈마스타)(1) 1599
   브라우져를 종료해도 세션이 그대로 살아있어요(홈마스타)2456
   PHP에서 세션 사용하기(홈마스타)1387
   [설치/설정] PHP 파일업로드시 일정용량 이상 업(홈마스타)1261
   php.ini 값 설정가능한 범위 알아보기(홈마스타)1529
   PHP 슈퍼전역변수 들의 종류(홈마스타)19431
   쿠키공유를 위한 헤드값(홈마스타)1403
   php.ini 설정하기(홈마스타)1414
   php.ini (V4.2.3) - III(홈마스타)1386
   php.ini (V4.2.3) - II(홈마스타)1427
   환경을 실행중에 임시로 바꾸기(홈마스타)1283
   php.ini (V4.2.3)(홈마스타)1479
   error_reporting(홈마스타)1782
   경과만료 페이지 없애기(홈마스타)1624
≪ [1]  [2]   ≫

복수단어 검색은 공백(space)로 구분해 주세요.



 
최근 글
[손님]
9
10
153
162
322
515
1287
468
541
298
459
4057
977
1082
1320
 
인기 글
[손님]
5270
7288
4860
[홈마스타] [RE] input type=\\
6798
5465
6018
4826
8499
5246
5156
[예진아씨] 자료없음
7768
[푸른산] 검색식
11565
7617
5247
19431