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



 
토막소스
 


[초보강좌] 세션을 DB로 관리하기 + 쪽지 확인하기
  2007-07-04 00:13:52 댓글:(0)   조회:793



아래에도 세션을 DB로 관리하는 법을 써주신 분이 계시지만, 대개 Zend에 나와있는 예제와 같은 기본구조를 사용하시는 것 같습니다. 그래서 이걸 한번 커스터마이징해보도록 하겠습니다.

------------------------------
[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"])를 해줘야하겠죠?



 댓글 (0)


토막소스
페이지: 2 / 4   


   php로 유저의 로그인,로그아웃 판별하기(홈마스타)936
   접속자 현황 - 깔끔치는 않음(홈마스타)586
   whois class(홈마스타)408
   whois 도메인,ip조회(홈마스타)129
     [RE] [Whois] IP 추적(홈마스타)47
   url 유효성 체크(홈마스타)6
   특정사이트 소스보기(홈마스타)13
   사이트 방문경로와 검색한 단어 알기(홈마스타)8
   "로딩중입니다" 표시하기(홈마스타)(1) 12
   홈페이지 페이지별 접속카운터(홈마스타)13
   텍스트로 워터마크 투명도 줘서 찍기(홈마스타)6
   게시판에서 php 실행가능할까요?(홈마스타)8
   네이버 방송편성표 긁어오자(홈마스타)(2) 16
   js 파일을 php로 불러오기(홈마스타)9
   서브도메인 세션공유(홈마스타)13
   제로보드 게시판 최적화 성인인증 코드 (세션이용)(홈마스타)10
   브라우저별 다운로드 팁(홈마스타)11
   아이디.도메인.com 이라도 집으로 고정적 포팅하고(홈마스타)8
   제목자르기(홈마스타)6
   이미지를 업로드할때 워터마크를 새겨보자~(홈마스타)8
     [RE] 자동 썸네일 이미지 만들기(홈마스타)10
       [RE] 썸네일 이미지 생성(홈마스타)10
         [RE] GD 그래픽라이브러리를 이용한 썸네일 (홈마스타)6
   날짜 선택 - 다이나믹 페이지 소스(홈마스타)10
   php 에러페이지 만들기(홈마스타)12
   fsockopen()을 이용한 리퍼러 속이기 및 파(홈마스타)6
   외부 이미지의 썸네일을 만드는 함수(홈마스타)6
   썸네일을 원본의 비율대로 생성하여 주는 함수 - n(홈마스타)8
   썸네일을 원본의 비율대로 생성하여 주는 함수 - g(홈마스타)8
   썸네일을 생성하고 액자를 쒸워주는 스크립트 - gd(홈마스타)14
  [1]  [2]  [3]  [4]  

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





최근 글
[손님]

인기 글
[손님]
[깊은연못] 24시간 Classical Radio