🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Redis 핵심 개념 완벽 정리 - 슬라이드 1/13
A

AI Generated

2025. 11. 5. · 117 Views

Redis 핵심 개념 완벽 정리

Redis의 핵심 자료구조와 고급 기능을 실전 예제로 알아봅니다. 캐싱, Pub/Sub, 트랜잭션 등 실무에서 자주 사용하는 패턴을 다룹니다.


카테고리:Python
언어:Python
메인 태그:#Redis
서브 태그:
#Caching#PubSub#DataStructures#Performance

들어가며

이 글에서는 Redis 핵심 개념 완벽 정리에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. String_기본_연산과_원자적_증감
  2. Hash로_객체_데이터_저장
  3. List로_큐와_스택_구현
  4. Set으로_중복_제거와_집합_연산
  5. Sorted_Set으로_리더보드_구현
  6. 캐싱_패턴과_TTL_설정
  7. Pub_Sub로_실시간_메시징
  8. Pipeline으로_네트워크_왕복_최소화
  9. Transaction으로_원자적_연산_보장
  10. Lua_스크립트로_복잡한_로직_서버측_실행
  11. HyperLogLog로_대규모_집합_크기_추정
  12. 분산_락으로_동시성_제어

1. String 기본 연산과 원자적 증감

개요

Redis의 가장 기본적인 자료형인 String으로 값 저장, 조회, 원자적 증감 연산을 수행합니다. 카운터나 세션 저장에 자주 사용됩니다.

코드 예제

import redis
r = redis.Redis(host='localhost', port=6379, decode_responses=True)

r.set('user:1000:name', 'John')
r.set('page:views', 0)
r.incr('page:views')  # 원자적 증가
print(r.get('page:views'))  # "1"

설명

set으로 키-값을 저장하고, incr로 숫자를 원자적으로 증가시킵니다. 멀티스레드 환경에서도 안전하게 카운터를 관리할 수 있습니다.


2. Hash로 객체 데이터 저장

개요

Hash는 필드-값 쌍의 컬렉션으로, 객체의 속성을 개별적으로 접근하고 수정할 수 있습니다. 사용자 프로필이나 설정 데이터에 적합합니다.

코드 예제

r.hset('user:1000', mapping={
    'name': 'John',
    'email': 'john@example.com',
    'age': '30'
})

print(r.hget('user:1000', 'email'))  # john@example.com
print(r.hgetall('user:1000'))  # 전체 필드 조회

설명

hset으로 여러 필드를 한번에 저장하고, hget으로 특정 필드만 조회합니다. 객체 전체를 직렬화하지 않고도 부분 수정이 가능합니다.


3. List로 큐와 스택 구현

개요

List는 순서가 있는 문자열 컬렉션으로, 양쪽 끝에서 push/pop이 가능합니다. 작업 큐, 최근 활동 로그 등에 활용됩니다.

코드 예제

r.lpush('tasks', 'task1', 'task2', 'task3')  # 왼쪽 삽입
r.rpush('tasks', 'task4')  # 오른쪽 삽입

task = r.lpop('tasks')  # 왼쪽에서 꺼내기 (FIFO)
recent = r.lrange('tasks', 0, 2)  # 범위 조회
print(recent)  # ['task2', 'task1', 'task4']

설명

lpush/rpush로 양쪽에서 삽입하고, lpop/rpop으로 꺼냅니다. lrange로 범위 조회가 가능하여 최근 N개 항목을 쉽게 가져올 수 있습니다.


4. Set으로 중복 제거와 집합 연산

개요

Set은 중복되지 않는 문자열의 집합으로, 태그, 팔로워 목록 등에 사용됩니다. 교집합, 합집합 등의 집합 연산을 지원합니다.

코드 예제

r.sadd('user:1000:tags', 'python', 'redis', 'backend')
r.sadd('user:2000:tags', 'python', 'frontend', 'react')

common = r.sinter('user:1000:tags', 'user:2000:tags')
print(common)  # {'python'}
print(r.sismember('user:1000:tags', 'redis'))  # True

설명

sadd로 중복 없이 요소를 추가하고, sinter로 교집합을 구합니다. sismember로 O(1) 시간에 존재 여부를 확인할 수 있습니다.


5. Sorted Set으로 리더보드 구현

개요

Sorted Set은 각 요소에 점수를 부여하여 자동 정렬되는 집합입니다. 랭킹, 우선순위 큐, 시계열 데이터에 최적화되어 있습니다.

코드 예제

r.zadd('leaderboard', {'player1': 1500, 'player2': 2000, 'player3': 1800})
r.zincrby('leaderboard', 100, 'player1')  # 점수 증가

top3 = r.zrevrange('leaderboard', 0, 2, withscores=True)
print(top3)  # [('player2', 2000), ('player3', 1800), ('player1', 1600)]

설명

zadd로 점수와 함께 추가하고, zrevrange로 상위 N개를 조회합니다. 점수 변경 시 자동으로 정렬되어 실시간 랭킹 시스템에 이상적입니다.


6. 캐싱 패턴과 TTL 설정

개요

Redis의 가장 일반적인 사용 패턴으로, 데이터에 만료 시간(TTL)을 설정하여 자동으로 삭제되게 합니다. DB 부하를 줄이는 핵심 기법입니다.

코드 예제

def get_user_cached(user_id):
    key = f'cache:user:{user_id}'
    cached = r.get(key)
    if cached:
        return cached
    user = fetch_from_db(user_id)  # DB 조회
    r.setex(key, 3600, user)  # 1시간 TTL
    return user

설명

setex로 값과 동시에 만료 시간을 설정합니다. 캐시가 있으면 즉시 반환하고, 없으면 DB에서 조회 후 캐싱하는 전형적인 Cache-Aside 패턴입니다.


7. Pub Sub로 실시간 메시징

개요

Pub/Sub은 메시지를 발행(publish)하고 구독(subscribe)하는 패턴으로, 실시간 알림, 채팅, 이벤트 브로드캐스팅에 사용됩니다.

코드 예제

# 구독자
pubsub = r.pubsub()
pubsub.subscribe('notifications')
for message in pubsub.listen():
    if message['type'] == 'message':
        print(f"Received: {message['data']}")

# 발행자 (다른 프로세스)
r.publish('notifications', 'New user registered!')

설명

subscribe로 채널을 구독하고 listen으로 메시지를 수신합니다. publish로 메시지를 보내면 모든 구독자가 실시간으로 받습니다.


8. Pipeline으로 네트워크 왕복 최소화

개요

Pipeline은 여러 명령을 묶어서 한 번에 전송하여 네트워크 왕복 시간을 줄입니다. 대량 작업 시 성능이 크게 향상됩니다.

코드 예제

pipe = r.pipeline()
for i in range(1000):
    pipe.set(f'key:{i}', f'value:{i}')
    pipe.expire(f'key:{i}', 3600)
pipe.execute()  # 한번에 실행

print("1000개 키 설정 완료")

설명

pipeline()으로 파이프라인을 생성하고 명령을 쌓은 후 execute()로 일괄 실행합니다. 네트워크 RTT가 줄어들어 처리 속도가 10-100배 빨라집니다.


9. Transaction으로 원자적 연산 보장

개요

MULTI/EXEC를 사용한 트랜잭션으로 여러 명령을 원자적으로 실행합니다. 계좌 이체, 재고 관리 등 일관성이 중요한 작업에 필수입니다.

코드 예제

with r.pipeline() as pipe:
    pipe.multi()
    pipe.decrby('product:100:stock', 1)
    pipe.incrby('user:1000:purchased', 1)
    pipe.sadd('orders', 'order:12345')
    result = pipe.execute()

print(f"재고 차감 및 주문 완료: {result}")

설명

multi()로 트랜잭션을 시작하고 execute()로 모든 명령을 원자적으로 실행합니다. 중간에 실패하면 모두 롤백되어 데이터 일관성을 보장합니다.


10. Lua 스크립트로 복잡한 로직 서버측 실행

개요

Lua 스크립트를 사용하면 복잡한 로직을 Redis 서버에서 원자적으로 실행할 수 있습니다. 네트워크 왕복 없이 조건부 연산이 가능합니다.

코드 예제

rate_limit_script = """
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local current = redis.call('incr', key)
if current == 1 then
    redis.call('expire', key, 60)
end
return current <= limit
"""
allowed = r.eval(rate_limit_script, 1, 'rate:user:1000', 10)
print(f"요청 허용: {allowed}")

설명

eval로 Lua 스크립트를 실행하여 rate limiting을 구현합니다. 증가와 만료 설정이 원자적으로 수행되며, 결과를 바로 반환받아 조건부 처리가 가능합니다.


11. HyperLogLog로 대규모 집합 크기 추정

개요

HyperLogLog는 매우 적은 메모리(12KB)로 수십억 개의 고유 원소 개수를 근사 계산합니다. 일일 방문자 수, 고유 IP 추적 등에 사용됩니다.

코드 예제

for user_id in range(1, 100000):
    r.pfadd('daily:visitors:2025-01-15', f'user:{user_id}')

unique_count = r.pfcount('daily:visitors:2025-01-15')
print(f"오늘 방문자 수: {unique_count}")  # ~100000 (오차 0.81%)

설명

pfadd로 요소를 추가하고 pfcount로 고유 개수를 조회합니다. 정확한 카운트 대신 확률적 추정을 사용하여 메모리를 극도로 절약합니다.


12. 분산 락으로 동시성 제어

개요

Redis의 SET NX EX를 활용한 분산 락으로 여러 서버 간 임계 영역을 보호합니다. 중복 작업 방지, 자원 경쟁 해결에 핵심적입니다.

코드 예제

import uuid
lock_key = 'lock:critical_section'
lock_value = str(uuid.uuid4())

acquired = r.set(lock_key, lock_value, nx=True, ex=10)
if acquired:
    try:
        # 크리티컬 섹션 작업
        print("작업 수행 중...")
    finally:
        r.delete(lock_key)

설명

nx=True로 키가 없을 때만 설정하고, ex=10으로 10초 후 자동 만료됩니다. UUID로 락 소유자를 식별하여 다른 프로세스의 락을 실수로 해제하는 것을 방지합니다.


마치며

이번 글에서는 Redis 핵심 개념 완벽 정리에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#Redis #Caching #PubSub #DataStructures #Performance

#Redis#Caching#PubSub#CS#Performance#Python

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스