세션 라이브러리
Session 클래스는 사용자가 사이트를 탐색하는 동안 “상태”를 유지하고 활동을 추적할 수 있게 해줍니다.
CodeIgniter에는 목차의 마지막 섹션에서 확인할 수 있는 몇 가지 세션 저장 드라이버가 포함되어 있습니다.
Session 클래스 사용하기
세션 초기화
세션은 일반적으로 페이지가 로드될 때마다 전역으로 실행되므로 Session 클래스는 자동으로 초기화됩니다.
세션에 접근하고 초기화하려면:
<?php
$session = service('session', $config);
$config 파라미터는 선택 사항으로 애플리케이션 설정입니다. 제공하지 않으면 서비스 레지스터가 기본값으로 인스턴스를 생성합니다.
로드되면 세션 라이브러리 객체를 $session으로 사용할 수 있습니다.
또는 기본 설정 옵션을 사용하는 헬퍼 함수를 사용할 수 있습니다. 이 방식은 읽기에 좀 더 편리하지만 설정 옵션을 받지 않습니다.
<?php
$session = session();
세션은 어떻게 작동하나요?
페이지가 로드될 때 세션 클래스는 사용자 브라우저에서 유효한 세션 쿠키가 전송되었는지 확인합니다. 세션 쿠키가 없거나 (또는 서버에 저장된 것과 일치하지 않거나 만료된 경우) 새 세션이 생성되어 저장됩니다.
유효한 세션이 존재하면 해당 정보가 업데이트됩니다. 업데이트할 때마다 설정에 따라 세션 ID가 재생성될 수 있습니다.
초기화된 이후에는 Session 클래스가 자동으로 실행된다는 점을 이해하는 것이 중요합니다. 위의 동작이 발생하도록 별도로 처리할 필요가 없습니다. 아래에서 보듯이 세션 데이터를 다룰 수 있지만, 세션을 읽고 쓰고 업데이트하는 과정은 자동으로 이루어집니다.
참고
CLI에서는 세션 라이브러리가 자동으로 중단됩니다. 세션은 HTTP 프로토콜을 기반으로 하는 개념이기 때문입니다.
동시성에 관한 참고 사항
AJAX를 많이 사용하는 웹사이트를 개발하지 않는다면 이 섹션은 건너뛰어도 됩니다. 하지만 그렇다면, 그리고 성능 문제를 겪고 있다면 이 내용이 바로 찾고 있던 것입니다.
CodeIgniter v2.x의 세션은 잠금(locking)을 구현하지 않았기 때문에, 동일한 세션을 사용하는 두 HTTP 요청이 정확히 동시에 실행될 수 있었습니다. 좀 더 적절한 기술 용어로 표현하면 요청이 논블로킹(non-blocking)이었습니다.
그러나 세션 맥락에서 논블로킹 요청은 안전하지 않음을 의미하기도 합니다. 한 요청에서의 세션 데이터 수정(또는 세션 ID 재생성)이 두 번째 동시 요청의 실행을 방해할 수 있기 때문입니다. 이 문제가 많은 이슈의 근본 원인이었으며, CodeIgniter 3에서 세션 라이브러리를 완전히 다시 작성한 주요 이유입니다.
왜 이것을 알려드리는 걸까요? 성능 문제의 원인을 찾다 보면 잠금이 문제라고 결론 내리고 잠금을 제거하는 방법을 찾아보게 될 수도 있기 때문입니다…
그렇게 하지 마세요! 잠금을 제거하는 것은 잘못된 것이며 더 많은 문제를 일으킬 것입니다!
잠금은 문제가 아니라 해결책입니다. 진짜 문제는 이미 처리가 완료되어 더 이상 필요하지 않은데도 세션을 계속 열어 두고 있다는 것입니다. 따라서 필요가 없어진 후에는 현재 요청에 대한 세션을 닫는 것이 필요합니다.
<?php
$session->close();
세션 데이터란 무엇인가요?
세션 데이터는 특정 세션 ID(쿠키)와 연결된 단순한 배열입니다.
PHP에서 세션을 사용해 본 적이 있다면 PHP의 $_SESSION 슈퍼글로벌에 익숙할 것입니다 (그렇지 않다면 해당 링크의 내용을 읽어보시기 바랍니다).
CodeIgniter는 PHP가 제공하는 세션 핸들러 메커니즘을 사용하므로 동일한 방식으로 세션 데이터에 접근할 수 있습니다. 세션 데이터 사용은 $_SESSION 배열을 조작(읽기, 설정, 해제)하는 것만큼 간단합니다.
참고
일반적으로 전역 변수를 사용하는 것은 좋지 않은 관행입니다. 따라서 슈퍼글로벌 $_SESSION을 직접 사용하는 것은 권장하지 않습니다.
또한 CodeIgniter는 아래에서 자세히 설명하는 2가지 특별한 유형의 세션 데이터를 제공합니다: Flashdata와 Tempdata.
참고
역사적인 이유로, 플래시 데이터와 임시 데이터를 제외한 세션 데이터를 “userdata”라고 부릅니다.
세션 데이터 조회
세션 배열의 모든 정보는 $_SESSION 슈퍼글로벌을 통해 접근할 수 있습니다. 예를 들어 이전에 저장한 name 항목을 $name 변수에 할당하려면 다음과 같이 합니다:
<?php
$name = $_SESSION['name'];
또는 일반적인 접근자 메서드를 사용합니다:
<?php
$name = $session->get('name');
또는 매직 getter를 사용합니다:
<?php
$name = $session->name;
또는 세션 헬퍼 메서드를 사용합니다:
<?php
$name = session('name');
참고
get() 메서드는 접근하려는 항목이 존재하지 않으면 null을 반환합니다.
기존 세션 데이터를 모두 조회하려면 항목 키를 생략하면 됩니다 (매직 getter는 단일 속성 값에만 작동합니다):
<?php
$userData = $_SESSION;
// or:
$userData = $session->get();
중요
get() 메서드는 키로 단일 항목을 조회할 때 플래시 데이터나 임시 데이터 항목도 반환합니다. 그러나 세션에서 모든 데이터를 가져올 때는 플래시 데이터나 임시 데이터를 반환하지 않습니다.
세션 데이터 추가
특정 사용자가 사이트에 로그인한다고 가정해 보겠습니다. 인증 후 사용자 이름과 이메일 주소를 세션에 추가하면 필요할 때마다 데이터베이스 쿼리 없이 전역적으로 해당 데이터를 사용할 수 있습니다.
다른 변수와 마찬가지로 $_SESSION 배열에 데이터를 간단히 할당할 수 있습니다. 또는 $session의 속성으로 할당할 수도 있습니다.
새 세션 데이터를 담은 배열을 set() 메서드에 전달할 수 있습니다:
<?php
$session->set($array);
여기서 $array는 새 데이터를 담은 연관 배열입니다. 예시는 다음과 같습니다:
<?php
$newdata = [
'username' => 'johndoe',
'email' => 'johndoe@some-site.com',
'logged_in' => true,
];
$session->set($newdata);
세션 데이터를 한 번에 하나씩 추가하려면 set()이 다음 구문도 지원합니다:
<?php
$session->set('some_name', 'some_value');
세션 값이 존재하는지 확인하려면 isset()으로 간단히 확인할 수 있습니다:
<?php
// returns false if the 'some_name' item doesn't exist or is null,
// true otherwise:
if (isset($_SESSION['some_name'])) {
// ...
}
또는 has()를 호출할 수 있습니다:
<?php
$session->has('some_name');
세션 데이터에 새 값 추가하기
push() 메서드는 배열인 세션 값에 새 값을 추가할 때 사용합니다. 예를 들어 hobbies 키에 취미 배열이 있다면 다음과 같이 새 값을 추가하거나 기존 값을 교체할 수 있습니다:
<?php
/**
* [hobbies] => Array
* (
* [music] => rock
* [sport] => running
* )
*/
$session->set('hobbies', [
'music' => 'rock',
'sport' => 'running',
]);
/**
* [hobbies] => Array
* (
* [food] => cooking
* [music] => rock
* [sport] => tennis
* )
*/
$session->push('hobbies', [
'food' => 'cooking',
'sport' => 'tennis',
]);
세션 데이터 삭제
다른 변수와 마찬가지로 $_SESSION의 값을 해제하려면 unset()을 사용할 수 있습니다:
<?php
unset($_SESSION['some_name']);
// or multiple values:
unset(
$_SESSION['some_name'],
$_SESSION['another_name']
);
또한 set()으로 세션에 정보를 추가할 수 있듯이, remove()에 세션 키를 전달하여 정보를 제거할 수 있습니다. 예를 들어 세션 데이터 배열에서 some_name을 제거하려면 다음과 같이 합니다:
<?php
$session->remove('some_name');
이 메서드는 해제할 항목 키 배열도 허용합니다:
<?php
$array_items = ['username', 'email'];
$session->remove($array_items);
플래시 데이터
CodeIgniter는 다음 요청에서만 사용 가능하고 이후 자동으로 삭제되는 세션 데이터인 “플래시 데이터”를 지원합니다.
이는 일회성 정보, 오류 또는 상태 메시지(예: “레코드 2가 삭제되었습니다”)에 특히 유용합니다.
플래시 데이터 변수는 CodeIgniter 세션 핸들러 내부에서 관리되는 일반 세션 변수라는 점에 유의해야 합니다.
기존 항목을 “플래시 데이터”로 표시하려면:
<?php
$session->markAsFlashdata('item');
여러 항목을 플래시 데이터로 표시하려면 키를 배열로 전달하면 됩니다:
<?php
$session->markAsFlashdata(['item', 'item2']);
플래시 데이터를 추가하려면:
<?php
$_SESSION['item'] = 'value';
$session->markAsFlashdata('item');
또는 setFlashdata() 메서드를 사용합니다:
<?php
$session->setFlashdata('item', 'value');
set()과 동일한 방식으로 setFlashdata()에 배열을 전달할 수도 있습니다.
플래시 데이터 변수를 읽는 것은 $_SESSION을 통해 일반 세션 데이터를 읽는 것과 동일합니다:
<?php
$item = $_SESSION['item'];
중요
get() 메서드는 키로 단일 항목을 조회할 때 플래시 데이터 항목도 반환합니다. 그러나 세션에서 모든 데이터를 가져올 때는 플래시 데이터를 반환하지 않습니다.
그러나 “플래시 데이터”를 읽고 있음을 확실히 하려면 (다른 종류가 아닌) getFlashdata() 메서드를 사용할 수도 있습니다:
<?php
$session->getFlashdata('item');
참고
getFlashdata() 메서드는 항목을 찾을 수 없으면 null을 반환합니다.
모든 플래시 데이터를 배열로 가져오려면 키 파라미터를 생략하면 됩니다:
<?php
$session->getFlashdata();
추가 요청을 통해 플래시 데이터 변수를 보존해야 하는 경우 keepFlashdata() 메서드를 사용할 수 있습니다. 유지할 단일 항목이나 플래시 데이터 항목 배열을 전달할 수 있습니다.
<?php
$session->keepFlashdata('item');
$session->keepFlashdata(['item1', 'item2', 'item3']);
임시 데이터
CodeIgniter는 특정 만료 시간이 있는 세션 데이터인 “임시 데이터”도 지원합니다. 값이 만료되거나 세션이 만료되거나 삭제되면 값이 자동으로 제거됩니다.
플래시 데이터와 마찬가지로 임시 데이터 변수는 CodeIgniter 세션 핸들러가 내부적으로 관리합니다.
기존 항목을 “임시 데이터”로 표시하려면 키와 만료 시간(초 단위!)을 markAsTempdata() 메서드에 전달하면 됩니다:
<?php
// 'item' will be erased after 300 seconds
$session->markAsTempdata('item', 300);
모든 항목에 동일한 만료 시간을 적용할지 여부에 따라 두 가지 방식으로 여러 항목을 임시 데이터로 표시할 수 있습니다:
<?php
// Both 'item' and 'item2' will expire after 300 seconds
$session->markAsTempdata(['item', 'item2'], 300);
// 'item' will be erased after 300 seconds, while 'item2'
// will do so after only 240 seconds
$session->markAsTempdata([
'item' => 300,
'item2' => 240,
]);
임시 데이터를 추가하려면:
<?php
$_SESSION['item'] = 'value';
$session->markAsTempdata('item', 300); // Expire in 5 minutes
또는 setTempdata() 메서드를 사용합니다:
<?php
$session->setTempdata('item', 'value', 300);
setTempdata()에 배열을 전달할 수도 있습니다:
<?php
$tempdata = ['newuser' => true, 'message' => 'Thanks for joining!'];
$session->setTempdata($tempdata, null, $expire);
참고
만료 시간을 생략하거나 0으로 설정하면 기본 유효 시간인 300초(5분)가 사용됩니다.
임시 데이터 변수를 읽으려면 $_SESSION 슈퍼글로벌 배열을 통해 접근하면 됩니다:
<?php
$item = $_SESSION['item'];
중요
get() 메서드는 키로 단일 항목을 조회할 때 임시 데이터 항목도 반환합니다. 그러나 세션에서 모든 데이터를 가져올 때는 임시 데이터를 반환하지 않습니다.
“임시 데이터”를 읽고 있음을 확실히 하려면 (다른 종류가 아닌) getTempdata() 메서드를 사용할 수도 있습니다:
<?php
$session->getTempdata('item');
참고
getTempdata() 메서드는 항목을 찾을 수 없으면 null을 반환합니다.
물론 기존 임시 데이터를 모두 조회하려면:
<?php
$session->getTempdata();
임시 데이터 값이 만료되기 전에 제거해야 하는 경우 $_SESSION 배열에서 직접 해제할 수 있습니다:
<?php
unset($_SESSION['item']);
그러나 이 방법은 해당 항목을 임시 데이터로 만드는 마커를 제거하지 않으므로 (다음 HTTP 요청 시 무효화됩니다), 동일한 요청에서 동일한 키를 재사용하려는 경우 removeTempdata()를 사용해야 합니다:
<?php
$session->removeTempdata('item');
세션 키 유형 변경
플래시 데이터와 임시 데이터 같은 세션 데이터 값은 내부 플래그로만 구분되므로 데이터를 다시 쓰지 않고도 값의 유형을 변경할 수 있습니다.
<?php
session()->setFlashdata('alerts', 'Operation successful!');
/*
* Get flash value 'Operation successful!' in another controller.
*
* echo session()->getFlashdata('alerts');
*/
// You can switch the session key type from Flashdata to Tempdata like this:
session()->markAsTempdata('alerts');
// Or simply rewrite it directly
session()->setTempdata('alerts', 'Operation successful!');
/*
* Get temp value 'Operation successful!' in another controller.
*
* echo session()->getTempdata('alerts');
*
* But flash value will be empty 'null'.
*
* echo session()->getFlashdata('alerts');
*/
세션 닫기
close()
Added in version 4.4.0.
더 이상 필요하지 않은 현재 세션을 수동으로 닫으려면 close() 메서드를 사용합니다:
<?php
$session->close();
세션을 수동으로 닫을 필요는 없습니다. PHP는 스크립트 종료 후 자동으로 닫습니다. 그러나 세션 데이터는 동시 쓰기를 방지하기 위해 잠기므로 한 번에 하나의 요청만 세션에서 작동할 수 있습니다. 세션 데이터에 대한 모든 변경이 완료되는 즉시 세션을 닫으면 사이트 성능을 향상시킬 수 있습니다.
이 메서드는 PHP의 session_write_close() 함수와 정확히 동일한 방식으로 작동합니다.
세션 삭제
destroy()
현재 세션을 초기화하려면 (예: 로그아웃 시) 라이브러리의 destroy() 메서드를 사용하면 됩니다:
<?php
$session->destroy();
이 메서드는 PHP의 session_destroy() 함수와 정확히 동일한 방식으로 작동합니다.
이것은 동일한 요청 중에 수행하는 마지막 세션 관련 작업이어야 합니다. 모든 세션 데이터(플래시 데이터 및 임시 데이터 포함)가 영구적으로 삭제됩니다.
참고
일반 코드에서 이 메서드를 호출할 필요는 없습니다. 세션을 파괴하는 대신 세션 데이터를 정리하세요.
세션 메타데이터 접근
CodeIgniter 2에서는 세션 데이터 배열에 기본적으로 ‘session_id’, ‘ip_address’, ‘user_agent’, ‘last_activity’의 4가지 항목이 포함되어 있었습니다.
이는 세션 작동 방식의 특성 때문이었지만 새로운 구현에서는 더 이상 필요하지 않습니다. 그러나 애플리케이션이 이 값에 의존하고 있을 수 있으므로 대안적인 접근 방법을 안내합니다:
session_id:
$session->session_id또는session_id()(PHP 내장 함수)ip_address:
$_SERVER['REMOTE_ADDR']user_agent:
$_SERVER['HTTP_USER_AGENT'](세션에서 사용하지 않음)last_activity: 저장 방식에 따라 다르며 간단한 방법이 없습니다. 죄송합니다!
세션 설정
CodeIgniter는 일반적으로 별도 설정 없이도 모든 것이 작동하도록 합니다. 그러나 세션은 모든 애플리케이션에서 매우 민감한 구성 요소이므로 신중한 설정이 필요합니다. 모든 옵션과 그 영향을 충분히 검토해 주세요.
참고
v4.3.0부터 새로운 app/Config/Session.php 파일이 추가되었습니다. 이전에는 세션 설정이 app/Config/App.php 파일에 있었습니다.
app/Config/Session.php 파일에서 다음 세션 관련 설정을 찾을 수 있습니다:
설정 항목 |
기본값 |
옵션 |
설명 |
|---|---|---|---|
driver |
CodeIgniter\Session\Handlers\FileHandler |
CodeIgniter\Session\Handlers\FileHandler CodeIgniter\Session\Handlers\DatabaseHandler CodeIgniter\Session\Handlers\MemcachedHandler CodeIgniter\Session\Handlers\RedisHandler CodeIgniter\Session\Handlers\ArrayHandler |
사용할 세션 저장 드라이버입니다. |
cookieName |
ci_session |
[A-Za-z_-] 문자만 허용 |
세션 쿠키에 사용되는 이름입니다. |
expiration |
7200 (2시간) |
초 단위 시간 (정수) |
세션을 유지할 시간(초)입니다. 만료되지 않는 세션(브라우저가 닫힐 때까지)을 원한다면 0으로 설정하세요. |
savePath |
WRITEPATH . ‘session’ |
없음 |
사용 중인 드라이버에 따라 저장 위치를 지정합니다. |
matchIP |
false |
true/false (불리언) |
세션 쿠키를 읽을 때 사용자의 IP 주소를 검증할지 여부입니다. 일부 ISP는 IP를 동적으로 변경하므로 만료되지 않는 세션을 원한다면 이 값을 false로 설정하는 것이 좋습니다. |
timeToUpdate |
300 |
초 단위 시간 (정수) |
이 옵션은 세션 클래스가 자체적으로 재생성하고 새 세션 ID를 생성하는 빈도를 제어합니다. 0으로 설정하면 세션 ID 재생성을 비활성화합니다. |
regenerateDestroy |
false |
true/false (불리언) |
세션 ID를 자동 재생성할 때 이전 세션 ID와 연결된 세션 데이터를 삭제할지 여부입니다. false로 설정하면 나중에 가비지 컬렉터가 데이터를 삭제합니다. |
참고
최후의 수단으로, 위의 항목이 설정되지 않은 경우 세션 라이브러리는 PHP의 세션 관련 INI 설정과 ‘sess_expire_on_close’ 같은 CodeIgniter 3 설정을 가져오려 시도합니다. 그러나 이 동작은 예상치 못한 결과를 초래하거나 향후 변경될 수 있으므로 절대 의존해서는 안 됩니다. 모든 항목을 올바르게 설정하세요.
참고
expiration이 0으로 설정된 경우 PHP의 세션 관리에서 설정한 session.gc_maxlifetime 값이 그대로 사용됩니다(기본값은 1440인 경우가 많습니다). 필요에 따라 php.ini 또는 ini_set()을 통해 변경해야 합니다.
위의 값 외에도 세션 쿠키는 app/Config/Cookie.php 파일의 다음 설정 값을 사용합니다:
설정 항목 |
기본값 |
설명 |
|---|---|---|
domain |
‘’ |
세션이 적용되는 도메인 |
path |
/ |
세션이 적용되는 경로 |
secure |
false |
암호화된(HTTPS) 연결에서만 세션 쿠키를 생성할지 여부 |
sameSite |
Lax |
세션 쿠키의 SameSite 설정 |
참고
httponly 설정(app/Config/Cookie.php)은 세션에 영향을 미치지 않습니다. 보안 상의 이유로 HttpOnly 파라미터는 항상 활성화됩니다. 또한 Config\Cookie::$prefix 설정은 완전히 무시됩니다.
세션 드라이버
앞서 언급했듯이 세션 라이브러리에는 사용할 수 있는 다섯 가지 핸들러 또는 저장 엔진이 포함되어 있습니다:
CodeIgniter\Session\Handlers\FileHandler
CodeIgniter\Session\Handlers\DatabaseHandler
CodeIgniter\Session\Handlers\MemcachedHandler
CodeIgniter\Session\Handlers\RedisHandler
CodeIgniter\Session\Handlers\ArrayHandler
기본적으로 세션이 초기화될 때 FileHandler가 사용됩니다. 이는 가장 안전한 선택이며 사실상 모든 환경에서 작동할 것으로 예상됩니다(거의 모든 환경에 파일 시스템이 있습니다).
그러나 원한다면 app/Config/Session.php 파일의 $driver 설정을 통해 다른 드라이버를 선택할 수 있습니다. 단, 각 드라이버마다 주의 사항이 다르므로 선택하기 전에 아래 내용을 잘 숙지하세요.
참고
ArrayHandler는 테스트 중에 사용되며 모든 데이터를 PHP 배열에 저장하면서 데이터가 영속화되는 것을 방지합니다. 세션 테스트를 참고하세요.
FileHandler 드라이버 (기본값)
‘FileHandler’ 드라이버는 세션 데이터를 저장하기 위해 파일 시스템을 사용합니다.
PHP의 기본 세션 구현과 정확히 동일하게 작동한다고 할 수 있지만, 이것이 중요한 세부 사항이라면 실제로는 동일한 코드가 아니며 몇 가지 제한(및 장점)이 있습니다.
더 구체적으로 말하면, session.save_path에 사용되는 PHP의 디렉터리 레벨 및 모드 형식을 지원하지 않으며, 보안을 위해 대부분의 옵션이 하드코딩되어 있습니다. 대신 $savePath 설정에는 절대 경로만 지원됩니다.
또 알아야 할 중요한 사항은 세션 파일을 저장하는 데 공개적으로 읽기 가능하거나 공유된 디렉터리를 사용하지 않는 것입니다. 선택한 savePath 디렉터리의 내용에는 오직 본인만 접근할 수 있어야 합니다. 그렇지 않으면 누구든 세션 데이터를 보거나 탈취할 수 있습니다(“세션 고정” 공격이라고도 합니다).
UNIX 계열 운영체제에서는 일반적으로 chmod 명령을 통해 해당 디렉터리에 0700 모드 권한을 설정하여 디렉터리 소유자만 읽기 및 쓰기 작업을 수행할 수 있도록 합니다. 그러나 스크립트를 실행하는 시스템 사용자는 보통 본인이 아니라 ‘www-data’와 같은 계정이므로, 해당 권한만 설정하면 애플리케이션이 작동하지 않을 수 있으니 주의하세요.
대신 환경에 따라 다음과 같이 해야 합니다:
mkdir /<path to your application directory>/writable/sessions/
chmod 0700 /<path to your application directory>/writable/sessions/
chown www-data /<path to your application directory>/writable/sessions/
만료된 세션을 자동으로 삭제하는 내장 메커니즘이 자주 실행되지 않을 수 있으며, saveDir 디렉터리가 파일로 가득 찰 수 있습니다. 이 문제를 해결하려면 cron 또는 작업 스케줄러를 설정하여 오래된 파일을 삭제해야 합니다.
보너스 팁
파일 저장이 일반적으로 느리다는 이유로 다른 세션 드라이버를 선택하는 분들도 있을 것입니다. 이는 절반만 사실입니다.
매우 기본적인 테스트는 SQL 데이터베이스가 더 빠르다고 착각하게 만들 수 있지만, 99%의 경우 이는 현재 세션 수가 적을 때만 해당됩니다. 세션 수와 서버 부하가 증가할수록 - 실제로 중요한 시점에서 - 파일 시스템은 거의 모든 관계형 데이터베이스 설정을 일관되게 능가합니다.
또한 성능만이 관심사라면 세션을 매우 빠르게 만들 수 있는 tmpfs를 사용하는 것을 고려해 볼 수 있습니다.
DatabaseHandler 드라이버
중요
다른 플랫폼에는 권고 잠금 메커니즘이 없기 때문에 MySQL과 PostgreSQL 데이터베이스만 공식적으로 지원됩니다. 잠금 없이 세션을 사용하면 특히 AJAX를 많이 사용할 때 모든 종류의 문제가 발생할 수 있습니다. 성능 문제가 있는 경우 세션 데이터 처리가 완료된 후 close() 메서드를 사용하세요.
‘DatabaseHandler’ 드라이버는 세션을 저장하기 위해 MySQL 또는 PostgreSQL과 같은 관계형 데이터베이스를 사용합니다. 많은 사용자 사이에서 인기 있는 선택입니다. 개발자가 애플리케이션 내에서 세션 데이터에 쉽게 접근할 수 있기 때문입니다 - 데이터베이스의 또 다른 테이블일 뿐입니다.
그러나 제한 사항이 있습니다: 영속 연결을 사용할 수 없습니다.
DatabaseHandler 설정
테이블 이름 설정
‘DatabaseHandler’ 세션 드라이버를 사용하려면 앞서 언급한 테이블을 생성하고 $savePath 값으로 설정해야 합니다. 예를 들어 테이블 이름으로 ‘ci_sessions’를 사용하려면 다음과 같이 합니다:
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\DatabaseHandler;
class Session extends BaseConfig
{
// ...
public string $driver = DatabaseHandler::class;
// ...
public string $savePath = 'ci_sessions';
// ...
}
데이터베이스 테이블 생성
그런 다음 당연히 데이터베이스 테이블을 생성합니다.
MySQL의 경우:
CREATE TABLE IF NOT EXISTS `ci_sessions` (
`id` varchar(128) NOT NULL,
`ip_address` varchar(45) NOT NULL,
`timestamp` timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
`data` blob NOT NULL,
KEY `ci_sessions_timestamp` (`timestamp`)
);
PostgreSQL의 경우:
CREATE TABLE "ci_sessions" (
"id" varchar(128) NOT NULL,
"ip_address" inet NOT NULL,
"timestamp" timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL,
"data" bytea DEFAULT '' NOT NULL
);
CREATE INDEX "ci_sessions_timestamp" ON "ci_sessions" ("timestamp");
참고
id 값은 세션 쿠키 이름(Config\Session::$cookieName)과 세션 ID 그리고 구분자를 포함합니다. 예를 들어 긴 세션 ID를 사용하는 경우 필요에 따라 늘려야 합니다.
기본 키 추가
$matchIP 설정에 따라 기본 키(PRIMARY KEY)도 추가해야 합니다. 아래 예시는 MySQL과 PostgreSQL 모두에서 작동합니다:
// When $matchIP = true
ALTER TABLE ci_sessions ADD PRIMARY KEY (id, ip_address);
// When $matchIP = false
ALTER TABLE ci_sessions ADD PRIMARY KEY (id);
// To drop a previously created primary key (use when changing the setting)
ALTER TABLE ci_sessions DROP PRIMARY KEY;
중요
올바른 기본 키를 추가하지 않으면 다음 오류가 발생할 수 있습니다:
Uncaught mysqli_sql_exception: Duplicate entry 'ci_session:***' for key 'ci_sessions.PRIMARY'
데이터베이스 그룹 변경
기본적으로 기본 데이터베이스 그룹이 사용됩니다. app/Config/Session.php 파일의 $DBGroup 속성을 사용할 그룹 이름으로 변경하여 데이터베이스 그룹을 변경할 수 있습니다:
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\DatabaseHandler;
class Session extends BaseConfig
{
// ...
public ?string $DBGroup = 'groupName';
}
명령어로 데이터베이스 테이블 설정
이 모든 것을 직접 하고 싶지 않다면 CLI에서 make:migration --session 명령을 사용하여 마이그레이션 파일을 생성할 수 있습니다:
php spark make:migration --session
php spark migrate
이 명령은 코드를 생성할 때 $savePath와 $matchIP 설정을 반영합니다.
RedisHandler 드라이버
참고
Redis는 잠금 메커니즘을 노출하지 않으므로 이 드라이버의 잠금은 최대 300초 동안 유지되는 별도의 값으로 에뮬레이션됩니다.
참고
v4.3.2부터 TLS 프로토콜로 Redis에 연결할 수 있습니다.
Redis는 캐싱에 일반적으로 사용되는 저장 엔진으로 높은 성능으로 유명합니다. 이것이 ‘RedisHandler’ 세션 드라이버를 사용하는 이유이기도 할 것입니다.
단점은 관계형 데이터베이스만큼 보편적이지 않으며 시스템에 phpredis PHP 확장이 설치되어야 한다는 점입니다. 이 확장은 PHP에 번들로 제공되지 않습니다. RedisHandler 드라이버는 이미 Redis에 익숙하고 다른 목적으로 사용 중인 경우에만 사용하는 것이 좋습니다.
RedisHandler 설정
‘FileHandler’ 및 ‘DatabaseHandler’ 드라이버와 마찬가지로 $savePath 설정을 통해 세션 저장 위치를 설정해야 합니다. 여기서 형식은 조금 다르고 복잡합니다. phpredis 확장의 README 파일에 가장 잘 설명되어 있으므로 링크를 제공합니다:
그러나 가장 일반적인 경우에는 간단한 host:port 쌍으로 충분합니다:
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\RedisHandler;
class Session extends BaseConfig
{
// ...
public string $driver = RedisHandler::class;
// ...
public string $savePath = 'tcp://localhost:6379';
// ...
}
v4.5.0부터 Redis ACL(사용자 이름 및 비밀번호)을 사용할 수 있습니다:
public string $savePath = 'tcp://localhost:6379?auth[user]=username&auth[pass]=password';
참고
v4.5.0부터 잠금 획득 간격($lockRetryInterval)과 재시도 횟수($lockMaxRetries)를 설정할 수 있습니다.
MemcachedHandler 드라이버
참고
Memcached는 잠금 메커니즘을 노출하지 않으므로 이 드라이버의 잠금은 최대 300초 동안 유지되는 별도의 값으로 에뮬레이션됩니다.
‘MemcachedHandler’ 드라이버는 가용성을 제외하고 모든 속성에서 ‘RedisHandler’와 매우 유사합니다. PHP의 Memcached 확장은 PECL을 통해 배포되며 일부 Linux 배포판에서는 쉽게 설치할 수 있는 패키지로 제공됩니다.
그 외에 Redis에 대한 편향 없이 Memcached에 대해 달리 말할 것이 많지 않습니다. Memcached도 캐싱에 일반적으로 사용되고 속도로 유명한 인기 제품입니다.
그러나 Memcached가 제공하는 유일한 보장은 X 값을 Y초 후에 만료되도록 설정하면 Y초가 지난 후 삭제된다는 것입니다(그 이전에 만료되지 않는다는 보장은 없습니다). 이는 매우 드물게 발생하지만 세션 손실로 이어질 수 있으므로 고려해야 합니다.
MemcachedHandler 설정
여기서 $savePath 형식은 단순히 host:port 쌍으로 매우 간단합니다:
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\MemcachedHandler;
class Session extends BaseConfig
{
// ...
public string $driver = MemcachedHandler::class;
// ...
public string $savePath = 'localhost:11211';
// ...
}
보너스 팁
세 번째 콜론 구분 값(:weight)으로 선택적 weight 파라미터를 사용하는 다중 서버 설정도 지원되지만, 이것이 안정적인지는 테스트하지 않았습니다.
이 기능을 (본인 책임하에) 실험해 보려면 여러 서버 경로를 쉼표로 구분하면 됩니다:
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\MemcachedHandler;
class Session extends BaseConfig
{
// ...
// localhost will be given higher priority (5) here,
// compared to 192.0.2.1 with a weight of 1.
public string $savePath = 'localhost:11211:5,192.0.2.1:11211:1';
// ...
}