기본 콘텐츠로 건너뛰기

Redis TTL 설정 완벽 정리: EXPIRE부터 SET EX, PERSIST까지

    목차

 

Redis를 캐시로 사용하다 보면 반드시 만나게 되는 개념이 TTL(Time To Live) 입니다.

TTL은 Redis에 저장된 Key가 얼마 동안 유지될지 지정하는 만료 시간입니다. 캐시 데이터, 인증 코드, 세션, 임시 데이터처럼 일정 시간이 지나면 자동으로 삭제되어야 하는 데이터에 특히 유용합니다.

이번 글에서는 Redis에서 TTL을 설정하고 확인하는 방법부터 실무에서 주의해야 할 부분까지 정리해보겠습니다.


1. Redis TTL이란?

Redis의 TTL(Time To Live)은 특정 Key가 만료되기까지 남은 시간을 의미합니다.

예를 들어 다음과 같은 데이터가 있다고 가정해보겠습니다.

SET user:1001 "Alice"

별도의 만료 시간을 설정하지 않았다면 이 Key는 직접 삭제하기 전까지 계속 유지됩니다.

하지만 캐시 데이터라면 일정 시간이 지난 후 자동으로 제거하고 싶을 수 있습니다.

이때 EXPIRE 명령어를 사용할 수 있습니다.

EXPIRE user:1001 60

위 명령은 user:1001 Key를 60초 후 만료하도록 설정합니다.


2. TTL 확인하기

Key의 남은 만료 시간은 TTL 명령어로 확인할 수 있습니다.

TTL user:1001

예를 들어 결과가 다음과 같다면,

(integer) 42

해당 Key는 약 42초 후 만료된다는 의미입니다.

TTL의 특수 반환값

TTL을 확인할 때는 -1-2 값을 알아두는 것이 좋습니다.

TTL key

결과의 의미는 다음과 같습니다.

반환값

의미

양수

Key가 만료되기까지 남은 시간(초)

-1

Key는 존재하지만 만료 시간이 설정되지 않음

-2

Key가 존재하지 않음

예를 들어,

SET test "hello"
TTL test

만료 시간을 설정하지 않았기 때문에 결과는 다음과 같습니다.

(integer) -1

3. SET과 동시에 TTL 설정하기

실무에서는 SET 이후 별도로 EXPIRE를 실행하기보다 데이터를 저장하면서 TTL을 함께 지정하는 방법을 자주 사용합니다.

SET auth:code:1001 "839201" EX 300

EX 300은 해당 Key를 300초 후 만료시키겠다는 의미입니다.

즉, 인증번호를 5분 동안만 저장하는 방식으로 사용할 수 있습니다.

SET verification:user@example.com "839201" EX 300

캐시 역시 동일합니다.

SET cache:product:1001 '{"id":1001,"name":"Keyboard"}' EX 600

이 경우 상품 캐시는 10분 동안 유지됩니다.

왜 SET + EX를 사용하는 것이 좋을까?

다음과 같이 두 개의 명령을 실행할 수도 있습니다.

SET cache:user:1001 "data"
EXPIRE cache:user:1001 600

하지만 애플리케이션에서 두 명령 사이에 장애가 발생한다면 SET은 성공하고 EXPIRE는 실행되지 않을 가능성이 있습니다.

그러면 의도와 달리 만료되지 않는 Key가 남을 수 있습니다.

반면,

SET cache:user:1001 "data" EX 600

처럼 하나의 SET 명령으로 값과 만료 시간을 함께 설정하면 이러한 문제를 피할 수 있습니다.

따라서 단순한 String 데이터를 저장하면서 TTL이 반드시 필요한 경우라면 SET ... EX 형태를 우선 고려하는 것이 좋습니다.


4. 초보다 정밀한 TTL이 필요하다면

Redis에서는 초 단위뿐 아니라 밀리초 단위의 만료 시간도 지정할 수 있습니다.

EXPIRE

초 단위입니다.

EXPIRE mykey 60

60초 후 만료됩니다.

PEXPIRE

밀리초 단위입니다.

PEXPIRE mykey 1500

1.5초 후 만료됩니다.

SET에서도 동일하게 EX와 PX를 사용할 수 있습니다.

SET mykey "value" EX 60
SET mykey "value" PX 1500

TTL 역시 밀리초 단위로 확인하고 싶다면 PTTL을 사용합니다.

PTTL mykey

5. 특정 시각에 Key 만료시키기

“지금부터 1시간”이 아니라 특정 시각에 만료시키고 싶은 경우도 있습니다.

이때는 EXPIREAT을 사용할 수 있습니다.

EXPIREAT event:coupon 1798761600

EXPIREAT은 Unix timestamp를 기준으로 만료 시점을 지정합니다.

밀리초 단위의 Unix timestamp가 필요하다면 PEXPIREAT을 사용할 수 있습니다.

PEXPIREAT event:coupon 1798761600000

예를 들어 이벤트 종료 시점, 쿠폰 만료 시점처럼 절대적인 종료 시간이 존재하는 데이터에 활용할 수 있습니다.


6. 설정된 TTL 제거하기

이미 TTL이 설정되어 있지만 Key를 계속 유지해야 하는 상황도 있습니다.

이때 PERSIST를 사용합니다.

PERSIST user:1001

성공적으로 TTL이 제거되면 해당 Key는 자동으로 만료되지 않습니다.

확인해보겠습니다.

TTL user:1001

결과:

(integer) -1

Key는 존재하지만 TTL이 없는 상태입니다.


7. TTL을 다시 설정하면 어떻게 될까?

기존 Key에 다시 EXPIRE를 실행하면 TTL은 새 값으로 변경됩니다.

SET session:1001 "data" EX 300

5분이 설정되어 있다고 가정하겠습니다.

이후 다음 명령을 실행하면,

EXPIRE session:1001 1800

기존 TTL 대신 30분으로 다시 설정됩니다.

이 특징을 이용하면 사용자의 활동이 발생할 때마다 세션 만료 시간을 연장하는 방식도 구현할 수 있습니다.

사용자 요청
    ↓
세션 확인
    ↓
EXPIRE session:1001 1800
    ↓
30분으로 TTL 갱신

이러한 방식은 Sliding Expiration 형태의 세션 관리에 활용할 수 있습니다.


8. 주의: Redis TTL은 Key 단위다

Redis TTL을 사용할 때 매우 중요한 특징이 있습니다.

TTL은 Value 내부의 특정 데이터가 아니라 Key 전체에 적용됩니다.

예를 들어 Hash가 있다고 가정해보겠습니다.

HSET user:1001 name "Alice"
HSET user:1001 email "alice@example.com"

그리고,

EXPIRE user:1001 300

을 실행하면 name 필드만 삭제되는 것이 아니라 user:1001이라는 Key 전체가 만료됩니다.

따라서 서로 다른 만료 정책이 필요한 데이터라면 Key 구조 자체를 분리하는 것을 고려해야 합니다.

예를 들어,

user:1001:profile
user:1001:verification
user:1001:cache

처럼 데이터의 생명주기에 따라 Key를 설계할 수 있습니다.


9. TTL 설정 시 실무에서 주의할 점

TTL 없는 캐시 Key를 방치하지 않기

Redis를 캐시 용도로 사용하면서 TTL을 설정하지 않으면 Key가 계속 쌓일 수 있습니다.

SET cache:product:1001 "..."

보다는 캐시 정책에 따라,

SET cache:product:1001 "..." EX 600

처럼 만료 정책을 명시하는 것이 안전합니다.

물론 모든 Redis 데이터에 TTL이 필요한 것은 아닙니다. Redis를 영속 데이터나 별도의 자료구조 저장소로 사용하는 경우에는 서비스의 데이터 정책에 따라 판단해야 합니다.

모든 Key에 동일한 TTL을 적용하지 않기

데이터의 성격에 따라 적절한 TTL은 다릅니다.

예를 들면,

인증번호       → 3~5분
세션           → 서비스 정책에 따라 수십 분 이상
상품 캐시      → 수분~수십 분
변경이 적은 캐시 → 수시간 이상

처럼 데이터의 변경 빈도와 오래된 데이터가 사용자에게 미치는 영향을 기준으로 결정하는 것이 좋습니다.

캐시 만료가 한 시점에 몰리지 않도록 고려하기

많은 Key에 동일한 TTL을 동시에 설정하면 비슷한 시점에 대량으로 만료될 수 있습니다.

이후 애플리케이션 요청이 한꺼번에 DB로 향하면서 순간적으로 부하가 증가할 수 있습니다.

상황에 따라 기본 TTL에 작은 랜덤 값을 추가하는 방법을 고려할 수 있습니다.

예를 들어 기본 TTL이 10분이라면,

600초 + random(0~60초)

와 같이 분산시키는 방식입니다.

이를 TTL jitter라고 부르기도 하며, 캐시 만료 시점을 분산하는 데 도움이 됩니다.


10. Redis TTL 명령어 정리

자주 사용하는 명령어를 정리하면 다음과 같습니다.

명령어

설명

EXPIRE key seconds

초 단위 TTL 설정

PEXPIRE key milliseconds

밀리초 단위 TTL 설정

EXPIREAT key timestamp

Unix timestamp 기준 만료

PEXPIREAT key timestamp

밀리초 Unix timestamp 기준 만료

TTL key

남은 TTL을 초 단위로 확인

PTTL key

남은 TTL을 밀리초 단위로 확인

PERSIST key

설정된 TTL 제거

SET key value EX seconds

값 저장과 동시에 초 단위 TTL 설정

SET key value PX milliseconds

값 저장과 동시에 밀리초 TTL 설정


마무리

Redis에서 TTL은 단순히 “Key를 몇 초 후 삭제한다”는 기능을 넘어 캐시와 임시 데이터의 생명주기를 관리하는 핵심 기능입니다.

기본적인 사용법은 매우 간단합니다.

SET cache:user:1001 "data" EX 600

남은 시간을 확인하려면,

TTL cache:user:1001

TTL을 제거하려면,

PERSIST cache:user:1001

을 사용하면 됩니다.

실무에서는 특히 다음 세 가지를 기억해두면 좋습니다.

  1. TTL이 필수인 String 데이터라면 가능하면 SET ... EX처럼 저장과 만료 설정을 하나의 명령으로 처리합니다.
  2. TTL은 필드가 아니라 Key 단위로 적용된다는 점을 고려해 Key 구조를 설계합니다.
  3. 대규모 캐시에서는 동일한 시점에 Key가 만료되지 않도록 TTL 분산 전략도 고려합니다.

Redis를 단순한 Key-Value 저장소가 아니라 캐시 시스템으로 제대로 활용하려면 Key 설계와 TTL 정책을 함께 설계하는 것이 중요합니다.

댓글

이 글도 관심 있으실 것 같아요!

놀이의 4대 요소 (Agon(아곤), Mimicry(미미크리), Ilinx(일링크스), Alea(알레아))

네덜란드의 고전 학자인 '요한 하위징아'의 저서인 「호모 루덴스 」에서 인간을 '유희의 인간'이라고 칭했습니다. 프랑스의 '로제 카유아'라는 학자는 「호모 루덴스 」의 이론을 발전시켜 그의 저서인 「놀이와 인간」 (원제 「 Man, plays and games 」) 에서 ‘놀이의 4대 요소’를 말했습니다. 저자는 그것을 아곤, 미미크리, 알레아, 일링크스로 소개했습니다. 이 네 가지 놀이의 요소는 인간의 모든 유희, 놀이에서 발전되어 현대의 비디오 게임에서도 매우 중요한 이론으로 알려져있습니다. 먼저, 아곤(Agon), 경쟁 아곤은 놀이의 주체와 객체간의 경쟁을 의미합니다. 사람들은 경쟁에서 승리함으로써 성취감을 얻고, 우월감을 느끼게 합니다. 이 아곤을 현대의 게임에 대입 시켜보면 경쟁은 최근 가장 많이 플레이 하는 게임 중 하나인 ‘배틀 그라운드’나 ‘리그 오브 레전드’같은 게임들도 경쟁에 기반이 되어있고, 혼자 플레이 하는 게임에서도 자기 자신과의 경쟁, AI와의 경쟁 등이 포함되어있습니다. 예를 들어, 슈퍼 마리오 같은 게임에서도 플레이어들은 어떻게 이 게임을 더 빨리 클리어하기 위해 경쟁하고, 더 많은 점수를 받기 위해 노력합니다. 또한 비교적 MMR시스템이 잘 짜여져있는 '리그 오브 레전드'같은 AOS게임에서도 플레이어의 등급을 결정하는 랭크 게임 시스템이 중점적으로 돌아가고 있고, '오버워치'의 경쟁전 등 많은 게임에서 이런 경쟁을 유도하는 시스템을 만들어 놓았습니다. 게임을 계속 플레이하게 만드는 가장 큰 요소가 아곤입니다. 많은 게임에서 플레이어의 경쟁을 어떻게 잘 이끌어 나갔느냐에 따라서 그 게임의 성공이 나뉠 수도 있습니다. 미미크리(Mimicry), 역할 미미크리는 역할을 의미합니다. 사람들은 실제 세계에서 하지 못하는 일들을 놀이에서 느끼면서 큰 기쁨을 느낄 수 있습니다. 이 역할은 롤플레...

FastAPI 실시간 영상 스트리밍 OpenCV

  FastAPI와 OpenCV를 활용한 실시간 영상 스트리밍 Permalink 실시간 영상을 스트리밍 하는 방법을 찾던 중 파이썬 FastAPI를 활용한 방법을 시도 해보았다. 필수 라이브러리 Permalink 필요한 것은 Python3.9버전 (애플 M1칩셋 맥북에어에서 3.8 버전으로 시도 해보니 OpenCV라이브러리 설치에서 문제가 발생했었다) FastAPI uvicorn OpenCV 정도면 될 것 같다. 라이브러리들은 모두 설치 되었다고 가정 하고, 예제 코드 Permalink # main.py # 라이브러리 import # StreamingResponse를 가져와야함 from fastapi import FastAPI from fastapi.responses import StreamingResponse # cv2 모듈 import from cv2 import get_stream_video # FastAPI객체 생성 app = FastAPI () # openCV에서 이미지 불러오는 함수 def video_streaming (): return get_stream_video () # 스트리밍 경로를 /video 경로로 설정. @ app . get ( "/video" ) def main (): # StringResponse함수를 return하고, # 인자로 OpenCV에서 가져온 "바이트"이미지와 type을 명시 return StreamingResponse ( video_streaming (), media_type = "multipart/x-mixed-replace; boundary=frame" ) # cv2.py import cv2 def get_stream_video (): # camera 정의 cam = cv2 . VideoCapture ( 0 ) while True : ...

게임의 수학, 스탯과 대미지 계산 시스템을 효과적으로 재미있게 만드는 방법

대부분의 게임들은 스탯이라는 시스템을 가지고 있습니다. 이 스탯이라는 시스템은 대부분의 게임에서 캐릭터가 레벨업을 하거나, 스탯을 추가 시켜주는 아이템을 장착하거나, 스킬을 사용해서 올릴 수 있게 되어 있습니다. 하지만 많은 플레이어들은 이런 스탯을 그저 숫자 쪼가리 이상에 의미를 두려고 하지 않습니다. 그저 자신의 직업에 필요한 스탯의 숫자가 크면 좋다고 느끼는 것입니다. 예를 들어, 메이플 스토리의 스탯은 아예 자동 배분이라는 시스템을 도입하여, 대부분의 플레이어들이 같은 스탯으로 배분되게 되어, 스탯을 찍는다는 행위 자체가 없어졌습니다. 또한, 코어 플레이어가 아닌 일반적인 유저들은 자신의 스탯이 얼마인지, 어떤 방식으로 대미지 계산이 들어가는 지 모르고, 알려고 하지도 않습니다. 이는 메이플 스토리의 스탯과 대미지 계산 시스템이 지나치게 복잡해졌기 때문입니다. 이것은 메이플 스토리의 스트라이커라는 직업이 레벨 10에 배울 수 있는 매우 초반에 활용되는 스킬입니다. 하지만 그럼에도 '90초 동안', '1%확률', '30초 동안', '방어력을 1% 무시', '뇌전 버프', '최대 1회 누적 가능' 이라는 많은 효과와 조건들이 붙어 있습니다. 메이플 스토리의 대미지 계산식을 분석한 한 유저가 적은 대미지 계산식은 아래와 같습니다. 대 미지 = [ (주스탯 * 4 + 부스탯) * 총 공격력 * 무기상수 * 직업보정상수 / 100 ] * (스킬 퍼뎀 / 100) * (크리티컬 발동시) 크리티컬  대 미지 보정 * [ (100 + 공격력%) / 100 ] * [ (100 +  대 미지% + 보공%) / 100 ] * 방어율 무시 보정 * 렙차 보정 * 속성 보정 * (아케인포스 필요 적의 경우) 아케인포스 보정 * 숙련도 보정 * [ (모든 최종 대 미지 계산값% + 100) / 100 ]      (1.1) ...