Laravel에서 Redis 활용 가이드

환경 설정

Redis를 Laravel 프로젝트에 통합하려면 먼저 Predis 패키지를 설치합니다.

composer require predis/predis

설치 후 config/database.php에서 Redis 연결 정보를 구성합니다. 기본 설정은 다음과 같습니다:

'redis' => [
    'client' => 'predis',
    'cluster' => false,
    'default' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => 0,
    ],
],

Predis 클라이언트는 추가 연결 옵션도 지원하며, 필요한 경우 위 배열에 직접 확장할 수 있습니다.

기본 사용법

Redis 기능은 Illuminate\Support\Facades\Redis 파사드를 통해 접근합니다. 파사드는 동적 메서드를 지원하므로 모든 Redis 명령을 직접 호출할 수 있습니다.

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Redis;
use Illuminate\Http\Response;

class MemberController extends Controller
{
    public function fetchMember($memberId): Response
    {
        $cachedData = Redis::get("member:{$memberId}");
        
        return response()->view('member.detail', [
            'data' => $cachedData
        ]);
    }
}

데이터 타입별 조작

문자열(String) 처리

// 값 저장 및 만료 시간 설정
Redis::setex('session_token', 3600, 'abc123xyz');

// 단일 키 조작
Redis::set('username', 'honggildong');
$nickname = Redis::get('username');
Redis::del('username');

// 다중 키 일괄 처리
$userBatch = [
    'user:1001' => '김철수',
    'user:1002' => '이영희',
    'user:1003' => '박민수'
];
Redis::mset($userBatch);
$names = Redis::mget(['user:1001', 'user:1002', 'user:1003']);

// 문자열 속성 확인
$length = Redis::strlen('username');
$slice = Redis::substr('username', 0, 4);

// 메타데이터 조회
$matchedKeys = Redis::keys('user:*');
$remainingTime = Redis::ttl('session_token');
$exists = Redis::exists('username');

리스트(List) 구조

// 양방향 삽입
Redis::lpush('task_queue', 'job_alpha');
Redis::rpush('task_queue', 'job_beta');
Redis::rpushx('task_queue', 'job_gamma'); // 존재하는 경우만 추가

// 길이 및 범위 조회
$totalItems = Redis::llen('task_queue');
$items = Redis::lrange('task_queue', 0, -1);

// 인덱스 기반 접근 및 수정
$specificItem = Redis::lindex('task_queue', 1);
Redis::lset('task_queue', 1, 'job_modified');

// 요소 삭제 및 정리
Redis::lrem('task_queue', 1, 'job_alpha');
Redis::ltrim('task_queue', 0, 9);

// 위치 기반 삽입
Redis::linsert('task_queue', 'before', 'job_beta', 'job_new');

// 블로킹 팝
Redis::blpop('task_queue', 30); // 30초 타임아웃

집합(Set) 연산

// 기본 집합 조작
Redis::sadd('tags:php', 'laravel');
Redis::sadd('tags:php', 'symfony', 'codeigniter');
Redis::srem('tags:php', 'codeigniter');
$popped = Redis::spop('tags:php');

// 집합 간 연산
Redis::sadd('tags:frontend', 'react', 'vue');
Redis::smove('tags:php', 'tags:frontend', 'laravel');

// 집합 정보 조회
$count = Redis::scard('tags:php');
$isMember = Redis::sismember('tags:php', 'laravel');
$allMembers = Redis::smembers('tags:php');

// 집합 연산
Redis::sadd('group_a', 'a', 'b', 'c');
Redis::sadd('group_b', 'b', 'c', 'd');

$intersection = Redis::sinter('group_a', 'group_b');
$union = Redis::sunion('group_a', 'group_b');
$difference = Redis::sdiff('group_a', 'group_b');

// 결과 저장
Redis::sinterstore('common_items', 'group_a', 'group_b');

// 랜덤 추출
$randomPick = Redis::srandmember('group_a');

해시(Hash) 저장소

// 단일 필드 조작
Redis::hset('profile:1001', 'email', 'user@example.com');
Redis::hset('profile:1001', 'age', '28');
$emailValue = Redis::hget('profile:1001', 'email');

// 조건부 삽입
Redis::hsetnx('profile:1001', 'email', 'new@example.com'); // 실패, 이미 존재
Redis::hsetnx('profile:1001', 'phone', '010-1234-5678'); // 성공

// 다중 필드 처리
Redis::hmset('profile:1002', [
    'name' => '홍길동',
    'city' => '서울',
    'score' => '85'
]);
$partialData = Redis::hmget('profile:1002', ['name', 'city']);

// 숫자 필드 증가
Redis::hincrby('profile:1001', 'login_count', 1);
Redis::hincrby('profile:1001', 'login_count', 5);

// 해시 메타데이터
$fieldExists = Redis::hexists('profile:1001', 'email');
Redis::hdel('profile:1001', 'temp_field');
$fieldCount = Redis::hlen('profile:1001');

// 전체 데이터 추출
$allFields = Redis::hkeys('profile:1001');
$allValues = Redis::hvals('profile:1001');
$entireHash = Redis::hgetall('profile:1001');

정렬된 집합(Sorted Set) 및 정렬

// 정렬된 데이터 삽입
Redis::zadd('leaderboard', 100, 'player1');
Redis::zadd('leaderboard', 250, 'player2', 80, 'player3');

// 범위 조회
$topPlayers = Redis::zrevrange('leaderboard', 0, 2);
$bottomPlayers = Redis::zrange('leaderboard', 0, 2);

// 순위 및 점수
$rank = Redis::zrevrank('leaderboard', 'player1');
$score = Redis::zscore('leaderboard', 'player1');

// 점수 범위 삭제 및 카운트
Redis::zremrangebyscore('leaderboard', 0, 50);
$countInRange = Redis::zcount('leaderboard', 100, 300);

정렬 명령

Redis::rpush('numbers', 5, 1, 9, 3);

// 기본 오름차순
$sorted = Redis::sort('numbers'); // [1, 3, 5, 9]

// 옵션 조합
Redis::sort('numbers', ['sort' => 'desc']); // [9, 5, 3, 1]
Redis::sort('numbers', ['limit' => [0, 2]]); // 처음 2개
Redis::sort('numbers', ['alpha' => true]); // 사전순

// 외부 키 참조
Redis::sort('numbers', ['get' => 'item:*']); // 관련 데이터 조회

서버 관리 명령

// 정보 조회
$serverInfo = Redis::info();

// 데이터베이스 선택 및 조작
Redis::select(2);
Redis::flushdb(); // 현재 DB 비우기

// 키 이동
Redis::set('temporary', 'data');
Redis::move('temporary', 3);

// 복제 설정
Redis::slaveof('192.168.1.100', 6379);
Redis::slaveof(); // 복제 해제

// 지속성
Redis::save();      // 동기 저장
Redis::bgsave();    // 비동기 저장
$lastSaveTime = Redis::lastsave();

파이프라인 처리

다수의 명령을 한 번의 네트워크 왕복으로 처리하여 성능을 향상시킵니다.

Redis::pipeline(function ($redis) {
    for ($idx = 0; $idx < 500; $idx++) {
        $redis->set("cache:item:{$idx}", "value_{$idx}");
        $redis->expire("cache:item:{$idx}", 600);
    }
});

Pub/Sub 메시징

채널 구독

구독 명령은 장기 실행 프로세스이므로 Artisan 커맨드로 구현합니다:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;

class NotificationListener extends Command
{
    protected $signature = 'notifications:listen';
    protected $description = '실시간 알림 채널 구독';

    public function handle(): void
    {
        Redis::subscribe(['alerts', 'updates'], function ($payload) {
            $decoded = json_decode($payload, true);
            $this->processNotification($decoded);
        });
    }
    
    private function processNotification(array $data): void
    {
        // 알림 처리 로직
    }
}

패턴 기반 구독

// 모든 채널 감시
Redis::psubscribe(['*'], function ($message, $channel) {
    logger()->info("{$channel}: {$message}");
});

// 특정 패턴 감시
Redis::psubscribe(['notifications.*'], function ($message, $channel) {
    // notifications.으로 시작하는 모든 채널
});

Redis::psubscribe(['users.*.events'], function ($message, $channel) {
    // users.{id}.events 형태의 채널
});

메시지 발행

// 컨트롤러나 서비스에서 발행
Redis::publish('notifications.123', json_encode([
    'type' => 'order_shipped',
    'order_id' => 'ORD-2024-001',
    'timestamp' => now()->toIso8601String()
]));

Redis 파사드의 모든 메서드는 기본 클라이언트의 명령을 직접 노출하므로, Redis 공식 문서의 명령어를 그대로 활용할 수 있습니다.

태그: Redis Laravel Predis Pub/Sub cache

6월 13일 16:28에 게시됨