개발블로그

[Laravel 데이터 및 상태 관리] 성능 및 데이터 재사용 - Cache 본문

STUDY/Laravel

[Laravel 데이터 및 상태 관리] 성능 및 데이터 재사용 - Cache

devmel 2026. 8. 13. 23:38
Contents 접기
 

개념

개념

자주 사용하거나 조회 비용이 큰 데이터를 일정 시간 저장해두고 재사용하는 방식

 

Laravel은 여러 Cache 저장소를 같은 API로 다룰 수 있도록 통합된 Cache 기능을 제공함. 

 

사용목적

  • 반복적인 DB 조회 감소
  • 복잡한 연산 반복 방지
  • 외부 API 호출 감소
  • 응답 속도 개선
  • 서버 및 DB 부하 감소 

 

기본 구조

KEY - VALUE 

 


 

Cache Hit / Miss

 

개념

Cache를 사용할 때 요청한 데이터가 Cache에 존재하는지 여부에 따라 Hit/Miss

 

Cache Hit

요청한 데이터가 Cache에 존재하는 경우 

이미 Cache에 저장되어 있다면 DB를 다시 조회하지 않고 기존 데이터 반환 가능

요청
 ↓
Cache 조회
 ↓
데이터 존재
 ↓
Cache 데이터 반환

Cache Miss

요청한 데이터가 Cache에 존재하지 않는 경우

요청
 ↓
Cache 조회
 ↓
데이터 없음
 ↓
DB / API 등 원본 데이터 조회
 ↓
Cache 저장
 ↓
결과 반환

 


 

Cache 유효시간

 

TTL (Time to Live)

Cache에 저장한 데이터를 얼마 동안 유지할지 정하는 유효 시간

TTL이 지나면 해당 Cache는 만료되고, 이후 같은 데이터를 요청하면 다시 Cache Miss가 발생함

지정 기준

성능을 위해 Cache를 얼마나 오래 재사용할 것인지와 데이터 최신성을 어느 정도 유지할 것인지 결정하는 기준

TTL 짧음 → 최신성 ↑ / 재생성 빈도 ↑
TTL 김   → 재사용률 ↑ / 데이터 최신성 ↓

 


 

Cache 데이터 갱신과 삭제

 

Stale Data

원본 데이터는 변경됐지만 Cache에는 이전 값이 남아 있는 상태 

 

Cache Invalidation

더 이상 유효하지 않은 Cache를 제거하거나 갱신하는 처리 

 

방법

  • TTL에 의해 자동 만료
    Cache 저장 → TTL 경과 → Cache 만료
  • 원본 데이터 변경 시 Cache 제거
    DB 데이터 수정 → 관련 Cache 삭제 → 다음 조회에서 최신 데이터로 Cache 재생성 

 

언제 무효화해야 할까?

Cache가 만들어진 원본 데이터가 변경될 때.

 ex) 생성 | 수정 | 삭제 => 관련 Cache도 더 이상 최신 데이터 아닐 수 있음 => Cache 무효화 필요

 

중요한 건 변경된 데이터 하나만 보는 것이 아니라, 그 데이터에 의존하는 Cache까지 확인.

ex) 100번 게시글 수정 => 해당 게시글을 포함하는 popular_posts, latest_posts 등도 영향을 받을 수 있음

 


 

문법

 

Cache 저장

Cache::put(
    $key, // Cache Key
    $value // 저장할 값
    [, $ttl] //유지 시간 또는 만료 시점
);

// 캐시가 없을 때만 저장
$stored = Cache::add(
	$key,	// Cache Key
    $value,	// 저장할 값
    [, $ttl]	// 유지 시간 / 선택 
);

// 만료 없이 저장
$stored = Cache::forever(
    $key,
    $value
);

 

Cache 조회

$value = Cache::get(
    $key	// 조회할 Cache Key
    [, $default] // Cache가 없을 때 반환할 값/선택 
);

 

Cache 존재 여부 확인

$value = Cache::has(
    $key // 확인할 Cachey Key
);

 

조회와 저장 한 번에 처리

Cache::remember()
       ↓
Cache에 값 있음?
   ┌───────┴───────┐
  있음                                 없음
   ↓                                       ↓
값 반환                       Closure 실행
                                            ↓
                                결과 Cache 저장
                                            ↓
                                       값 반환

$value = Cache::remember(
    $key,	// Cache Key
    $ttl,	// Cache 유지 시간 또는 만료 시점
    $callback	// Cache가 없을 때 실행할 함수
); // return => 최종 반환값

// rememberForever() =>ttl 없이 동일한 동작을 수행, cache가 없을 때 callback 결과를 만료 시간 없이 저장
$value = Cache::rememberForever(
    $key,	// Cache Key
    $callback	// Cache가 없을 때 실행할 ㅏㅎ무
); // $value => 최종 반환값

 

ex)

// 원래는 아래와 같이 해야 하는 코드
$value = Cache::get($key);
if ($value === null) {
    $value = $callback();

    Cache::put(
        $key,
        $value,
        $ttl
    );
}

$posts = Cache::remember(
    'popular_posts',
    600,
    function () {
        return Post::orderByDesc('view_count')
            ->limit(10)
            ->get();
    }
);

Cache 삭제

Cache::forget(
    $key
);

// 전체 삭제 
Cache::flush();

// 조회 후 삭제
$value = Cache::pull(
    $key 	// Cache Key
    [, $default]	// 값이 없을 때 반환할 값
);

 

Cache 값 증/감

// 숫자 증가
$value = Cache::increment(
    $key	// Cache Key
    [, $amount]	// 증가량 (기본값 1)
); // 반환 : 변경 결과

// 숫자 감소
$value = Cache::decrement(
    $key
    [, $amount]
);

 

 


 

Cache Store / Driver

 

Cache API를 동일하게 사용하면서 실제 Cache 데이터를 저장할 저장소를 변경할 수 있음. 

 

정의하는 파일 : config/cache.php 

=> 여러 Store을 정의하고, 각 Store가 어떤 Driver를 사용할지 지정. 

ex) database, file, Redis, Memcached, DynamoDB, storage 등

 

Store와 Driver

Store => 캐시 설정 묶음의 이름 

 

Driver => 그 Store가 실제로 사용하는 저장 방식 

 

ex) 

'stores' => [

    'my_cache' => [ 
        'driver' => 'redis',
    ],

],

my_cache => Store 이름

redis => Driver 

 

Store과 Driver를 나누는 이유

같은 Driver를 사용하더라도 설정이 다른 Store를 만들 수 있기 때문.

ex) 

'stores' => [

    'cache_a' => [
        'driver' => 'redis',
        'connection' => 'cache',
    ],

    'cache_b' => [
        'driver' => 'redis',
        'connection' => 'default',
    ],

],

: 둘 다 Driver는 Redis지만 서로 다른 설정을 가진 Store가 될 수 있음. 

 

특정 Cache Store 사용

필요할 때 특정 Store를 직접 선택해서 사용 가능.

Cache::store()를 통해 config/cache.php에 정의된 Store중 하나를 선택할 수 있음.

 

문법

별도로 store()를 호출하지 않으면 Cache::get($key) 

라라벨은 설정된 기본 Store를 사용함.

Cache::store(
    $store // config/cache.php에 정의된 Store 이름
);

$value = Cache::store($store)
    ->get(
        $key
        [, $default]
);

 

의의

용도에 따라 저장소를 나눌 수 있음.

 

ex) 일반 Cache => file, 공유해야 하는 Cache => Redis 

 


 

Cache 사용 시 고려할 점

Cache Key 명명 규칙 

Key를 기준으로 데이터를 구분하므로 Key만 봐도 어떤 데이터인지 알 수 있게 설계하는 것이 좋음.

정해진 형식이 있는 것은 아니지만, 데이터의 범위와 식별 조건을 알 수 있도록 일관된 규칙으로 작성하는 것이 좋음.

 

Cache 결과를 달라지게 만드는 조건은 Key에도 포함

 

리소스:식별자:세부항목

 

조건이 더 붙으면 뒤에 계속 이어가는 식 

 ex)

post:100
post:100:comments

user:10:profile
user:10:settings

category:5:posts

posts:popular
posts:latest

 

Cache하기 적합한 데이터

반복해서 요청되지만 매번 원본에서 다시 조회하거나 계산할 필요가 없는 데이터

 

경우
조회 빈도가 높은 데이터 인기 게시글, 카테고리 목록
조회 비용이 큰 데이터 복잡한 JOIN·집계 결과
동일 결과가 반복되는 데이터 공통 설정값, 메뉴 목록
외부 요청 비용이 큰 데이터 외부 API 응답
약간의 지연이 허용되는 데이터 랭킹, 통계 데이터

 

Cache 적용을 신중하게 해야 하는 데이터

항상 최신 상태가 중요한 데이터는 신중하게 적용

ex) 재고, 결제 상태, 주문 상태, 잔액, 권한 정보