Files
confirms/SESSION_README.md

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)

추가 개선 사항

고려 중인 기능

  1. Redis Sentinel 도입 (고가용성)

    • 자동 장애 조치
    • 마스터/슬레이브 구조
  2. APM 연동

    • New Relic, DataDog 등
    • 실시간 성능 모니터링
  3. 헬스체크 엔드포인트

    // 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