10 KiB
10 KiB
Session 관리 가이드
개요
본 애플리케이션은 Redis를 기본 세션 저장소로 사용하며, Redis 장애 시 **Database(MariaDB)**로 자동 폴백하는 이중화 구조를 가지고 있습니다.
아키텍처
세션 저장소
| 우선순위 | 핸들러 | 설명 | 성능 |
|---|---|---|---|
| 1순위 | RedisHandler | 메모리 기반 고속 세션 | ~0.03초 |
| 2순위 | DatabaseHandler | DB 기반 안정적 세션 | ~0.05초 (수동 전환 시) |
구성 요소
┌─────────────────────────────────────────┐
│ 사용자 로그인 요청 │
└──────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Session.php 생성자 │
│ - Redis 연결 테스트 │
│ - SESSION_FORCE_DATABASE 확인 │
└──────────────┬──────────────────────────┘
│
┌──────┴──────┐
│ │
Redis 정상? Redis 장애?
│ │
▼ ▼
RedisHandler DatabaseHandler
(ci_sessions (ci_sessions
테이블) 테이블)
│ │
└──────┬──────┘
▼
세션 데이터 저장/조회
설정 파일
1. Session.php (src/app/Config/Session.php)
public string $driver = RedisHandler::class;
public function __construct()
{
// 환경변수로 강제 Database 모드 설정 가능
$forceDatabase = env('SESSION_FORCE_DATABASE', false);
if ($this->driver === RedisHandler::class && !$forceDatabase) {
try {
// Redis 연결 테스트 (타임아웃: 0.5초)
$testRedis = get_redis_connection('session');
if (!$testRedis) {
throw new \Exception('Redis connection failed');
}
// Redis 정상 - Redis 사용
$this->savePath = 'tcp://192.168.10.243:6379?database=0';
} catch (\Exception $e) {
// Redis 실패 - DatabaseHandler로 폴백
$this->driver = DatabaseHandler::class;
$this->savePath = 'ci_sessions';
}
} else {
// Database 모드
$this->savePath = 'ci_sessions';
}
}
2. 환경 설정 (.env)
# Redis 세션 설정
SESSION_REDIS_HOST = 192.168.10.243
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DATABASE = 0
#SESSION_REDIS_PASSWORD =
# 세션 강제 Database 모드 (Redis 장애 시 true로 변경)
SESSION_FORCE_DATABASE = false
3. Redis Helper (src/app/Helpers/redis_helper.php)
function get_redis_connection(string $type = 'worker')
{
$redis = new \Redis();
// 타임아웃 0.5초로 빠른 실패 감지
$timeout = 0.5;
$success = $redis->connect($host, $port, $timeout);
return $success ? $redis : false;
}
데이터베이스 테이블
ci_sessions 테이블 구조
CREATE TABLE `ci_sessions` (
`session_id` VARCHAR(40) NOT NULL DEFAULT '0',
`ip_address` VARCHAR(16) NOT NULL DEFAULT '0',
`user_agent` VARCHAR(120) NOT NULL,
`last_activity` INT UNSIGNED NOT NULL DEFAULT 0,
`user_data` VARCHAR(4000) NOT NULL,
PRIMARY KEY (`session_id`)
) ENGINE = MEMORY;
CREATE INDEX `last_activity_idx`
ON `ci_sessions` (`last_activity` ASC);
주요 특징:
- ENGINE = MEMORY: 메모리 기반 테이블로 매우 빠른 읽기/쓰기 성능
- 장점: Redis와 비슷한 속도 (디스크 I/O 없음)
- 단점: 서버 재시작 시 세션 데이터 소실 (일반적으로 문제없음 - 세션은 휘발성 데이터)
- 용량: VARCHAR(4000)으로 충분한 세션 데이터 저장 가능
운영 가이드
1. Redis 장애 발생 시
자동 폴백 (기본 동작)
- Redis 연결 실패 시 자동으로 DatabaseHandler로 전환
- 단점: 매 요청마다 Redis 연결 시도 → 타임아웃 대기 (약 0.5초 추가)
- 사용자는 약간 느린 응답 시간을 경험
수동 전환 (권장)
Redis 장애 감지 즉시 다음 조치:
# 1. .env 파일 수정
vi /path/to/src/.env
# SESSION_FORCE_DATABASE를 true로 변경
SESSION_FORCE_DATABASE = true
# 2. PHP-FPM 재시작 (선택사항, 다음 요청부터 자동 적용)
docker exec projects-admin_confirms kill -USR2 1
장점: Redis 연결 시도 없이 즉시 Database 사용 → 빠른 응답 (0.05초)
2. Redis 복구 후
# 1. .env 파일 원복
SESSION_FORCE_DATABASE = false
# 2. PHP-FPM 재시작
docker exec projects-admin_confirms kill -USR2 1
3. 모니터링
로그 확인
# 세션 관련 로그 확인
docker exec projects-admin_confirms tail -f /var/www/html/writable/logs/log-$(date +%Y-%m-%d).log | grep -i session
# Redis 폴백 경고 확인
docker exec projects-admin_confirms grep "Redis unavailable" /var/www/html/writable/logs/log-$(date +%Y-%m-%d).log
예상 로그 메시지
Redis 정상:
DEBUG - Session: Class initialized using 'CodeIgniter\Session\Handlers\RedisHandler' driver.
Redis 장애 (자동 폴백):
WARNING - Session: Redis unavailable (Redis connection failed), falling back to DatabaseHandler
DEBUG - Session: Class initialized using 'CodeIgniter\Session\Handlers\DatabaseHandler' driver.
Database 강제 모드:
INFO - Session: Forced to use DatabaseHandler (SESSION_FORCE_DATABASE=true)
DEBUG - Session: Class initialized using 'CodeIgniter\Session\Handlers\DatabaseHandler' driver.
4. 성능 모니터링
# 로그인 응답 시간 측정
for i in {1..5}; do
curl -X POST http://localtest2-admin.confirms.co.kr/login/chkLogin \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user_id=test&user_pw=test" \
-o /dev/null -s -w " Time: %{time_total}s\n"
done
기대 성능:
- Redis 정상: 0.03 ~ 0.05초
- Database (수동 전환): 0.05 ~ 0.08초
- 자동 폴백 (Redis 다운): 0.5 ~ 1.0초
사용자 알림
프론트엔드 경고 표시
Redis 장애 시 로그인 페이지에 자동으로 경고 배너가 표시됩니다:
// login.php의 JavaScript
function checkSystemStatus(responseData) {
if (responseData.system && responseData.system.redis_fallback) {
// 경고 메시지: "세션 서버(Redis) 장애로 임시 모드로 운영 중입니다."
showRedisWarning(responseData.system.warning_message);
}
}
API 응답 예시:
{
"code": "0",
"msg": "success",
"system": {
"redis_fallback": true,
"warning_message": "세션 서버(Redis) 장애로 임시 모드로 운영 중입니다. 시스템 관리자에게 문의하세요."
}
}
트러블슈팅
문제: 로그인이 느림 (2~3초)
원인: Redis 다운 상태에서 자동 폴백 모드 사용 중
해결:
# SESSION_FORCE_DATABASE=true로 수동 전환
echo "SESSION_FORCE_DATABASE = true" >> /path/to/src/.env
문제: 세션이 유지되지 않음
원인: ci_sessions 테이블이 없거나 권한 문제
해결:
-- 테이블 존재 확인
SHOW TABLES LIKE 'ci_sessions';
-- 권한 확인
SHOW GRANTS FOR 'confirms'@'%';
-- 테이블이 없는 경우 생성
CREATE TABLE `ci_sessions` (
`session_id` VARCHAR(40) NOT NULL DEFAULT '0',
`ip_address` VARCHAR(16) NOT NULL DEFAULT '0',
`user_agent` VARCHAR(120) NOT NULL,
`last_activity` INT UNSIGNED NOT NULL DEFAULT 0,
`user_data` VARCHAR(4000) NOT NULL,
PRIMARY KEY (`session_id`)
) ENGINE = MEMORY;
CREATE INDEX `last_activity_idx`
ON `ci_sessions` (`last_activity` ASC);
문제: 서버 재시작 후 모든 세션이 사라짐
원인: ci_sessions가 MEMORY 엔진을 사용 (정상 동작)
설명:
- MEMORY 엔진은 서버 재시작 시 데이터가 삭제됩니다
- 세션은 일시적 데이터이므로 일반적으로 문제가 되지 않습니다
- 사용자는 재로그인하면 됩니다
영구 저장이 필요한 경우:
-- InnoDB로 변경 (성능은 약간 느려짐)
ALTER TABLE ci_sessions ENGINE=InnoDB;
문제: Redis 연결 타임아웃이 너무 김
원인: redis_helper.php의 타임아웃 설정
해결:
// src/app/Helpers/redis_helper.php
$timeout = 0.5; // 0.1 ~ 1.0 사이 값으로 조정
$redis->connect($host, $port, $timeout);
관련 파일
| 파일 | 역할 |
|---|---|
src/app/Config/Session.php |
세션 설정 및 폴백 로직 |
src/app/Helpers/redis_helper.php |
Redis 연결 헬퍼 함수 |
src/app/Controllers/Login.php |
로그인 및 시스템 상태 체크 |
src/app/Views/pages/login.php |
프론트엔드 경고 표시 |
src/.env |
환경 설정 (Redis 연결 정보, 강제 모드) |
Worker 및 API (참고)
Worker (NaverWorker.php)
- Redis 큐 사용 (DB 9)
- Redis 장애 시 파일 기반 폴백 (
worker/fallback_queue/*.json)
API (api_receiver.php, KisoController.php)
- Redis 큐 사용 (DB 9)
- Redis 장애 시 파일 기반 폴백 (
worker/fallback_queue/*.json)
추가 개선 사항
고려 중인 기능
-
Redis Sentinel 도입 (고가용성)
- 자동 장애 조치
- 마스터/슬레이브 구조
-
APM 연동
- New Relic, DataDog 등
- 실시간 성능 모니터링
-
헬스체크 엔드포인트
// GET /health/session { "status": "ok", "driver": "RedisHandler", "redis_available": true, "response_time_ms": 12 }
문의
세션 관련 문제 발생 시:
- 로그 확인 (
/writable/logs/) - Redis 서버 상태 확인
- ci_sessions 테이블 상태 확인
- 필요 시 수동 전환 수행
Last Updated: 2026-03-25
Version: 1.0.0