# 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`) ```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`) ```bash # 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`) ```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 테이블 구조 ```sql 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 장애 감지 즉시 다음 조치: ```bash # 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 복구 후 ```bash # 1. .env 파일 원복 SESSION_FORCE_DATABASE = false # 2. PHP-FPM 재시작 docker exec projects-admin_confirms kill -USR2 1 ``` ### 3. 모니터링 #### 로그 확인 ```bash # 세션 관련 로그 확인 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. 성능 모니터링 ```bash # 로그인 응답 시간 측정 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 장애 시 로그인 페이지에 자동으로 경고 배너가 표시됩니다: ```javascript // login.php의 JavaScript function checkSystemStatus(responseData) { if (responseData.system && responseData.system.redis_fallback) { // 경고 메시지: "세션 서버(Redis) 장애로 임시 모드로 운영 중입니다." showRedisWarning(responseData.system.warning_message); } } ``` **API 응답 예시:** ```json { "code": "0", "msg": "success", "system": { "redis_fallback": true, "warning_message": "세션 서버(Redis) 장애로 임시 모드로 운영 중입니다. 시스템 관리자에게 문의하세요." } } ``` ## 트러블슈팅 ### 문제: 로그인이 느림 (2~3초) **원인**: Redis 다운 상태에서 자동 폴백 모드 사용 중 **해결**: ```bash # SESSION_FORCE_DATABASE=true로 수동 전환 echo "SESSION_FORCE_DATABASE = true" >> /path/to/src/.env ``` ### 문제: 세션이 유지되지 않음 **원인**: ci_sessions 테이블이 없거나 권한 문제 **해결**: ```sql -- 테이블 존재 확인 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 엔진은 서버 재시작 시 데이터가 삭제됩니다 - 세션은 일시적 데이터이므로 일반적으로 문제가 되지 않습니다 - 사용자는 재로그인하면 됩니다 **영구 저장이 필요한 경우**: ```sql -- InnoDB로 변경 (성능은 약간 느려짐) ALTER TABLE ci_sessions ENGINE=InnoDB; ``` ### 문제: Redis 연결 타임아웃이 너무 김 **원인**: redis_helper.php의 타임아웃 설정 **해결**: ```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`) ## 추가 개선 사항 ### 고려 중인 기능 1. **Redis Sentinel 도입** (고가용성) - 자동 장애 조치 - 마스터/슬레이브 구조 2. **APM 연동** - New Relic, DataDog 등 - 실시간 성능 모니터링 3. **헬스체크 엔드포인트** ```php // GET /health/session { "status": "ok", "driver": "RedisHandler", "redis_available": true, "response_time_ms": 12 } ``` ## 문의 세션 관련 문제 발생 시: 1. 로그 확인 (`/writable/logs/`) 2. Redis 서버 상태 확인 3. ci_sessions 테이블 상태 확인 4. 필요 시 수동 전환 수행 --- **Last Updated**: 2026-03-25 **Version**: 1.0.0