logo Fonnpo

문의하기
2026년 5월 30일 1분 읽기 Fonnpo

Redis 완전 가이드

Redis는 String, Hash, List, Set, ZSet 등 풍부한 데이터 구조를 지원하는 고성능 인메모리 키-값 저장소입니다. 설치부터 시작해 모든 핵심 데이터 타입, 만료 시간, 영속성(RDB/AOF/하이브리드), Pub/Sub, 트랜잭션, Pipeline, 분산 잠금·리더보드 등 실용 시나리오, 그리고 캐시 침투·장애·사태의 해결책까지 Redis 실무에 필요한 모든 지식을 다룹니다.

#Redis#Database#Cache

Redis는 풍부한 데이터 구조를 지원하는 인메모리 키-값 저장소입니다. 캐싱, 메시지 큐, 분산 잠금, 리더보드 등 다양한 용도로 활용됩니다. 이 가이드는 설치부터 시작해 모든 핵심 데이터 타입과 실무 사용법을 다룹니다.

설치 및 연결

macOS

Bash
        brew install redis
brew services start redis   # 백그라운드에서 시작
redis-cli                   # 대화형 클라이언트 열기

    

Linux(Ubuntu / Debian)

Bash
        sudo apt update && sudo apt install redis-server
sudo systemctl start redis
redis-cli

    

Docker(권장 — 깔끔한 환경)

Bash
        # 컨테이너 실행
docker run -d --name redis -p 6379:6379 redis:7-alpine

# CLI 열기
docker exec -it redis redis-cli

    

기본 연결 및 확인

Bash
        redis-cli -h 127.0.0.1 -p 6379

# 연결 확인
PING              # PONG 반환

# 비밀번호가 설정된 경우
AUTH your_password

# 데이터베이스 선택(기본값 0, 총 16개)
SELECT 1

# 현재 데이터베이스의 키 개수 확인
DBSIZE

# 모든 키 조회(운영 환경에서는 피할 것)
KEYS *

# 패턴 스캔(운영 환경에서는 KEYS 대신 SCAN 권장)
SCAN 0 MATCH user:* COUNT 100

    

데이터 타입 개요

타입주요 사용 사례
String캐시, 카운터, 분산 잠금
Hash객체 저장(사용자 프로필, 상품 정보)
List메시지 큐, 활동 피드, 작업 로그
Set중복 제거, 공통 친구, 추첨
ZSet(정렬된 집합)리더보드, 가중치 큐
Stream영속 메시지 큐(경량 Kafka 대체)
Bitmap사용자 출석 체크, 블룸 필터
HyperLogLog대규모 UV 추정(근사값)

String(문자열)

String은 가장 기본적인 타입으로 텍스트, 숫자, 바이너리 데이터를 저장할 수 있습니다(최대 512 MB).

Bash
        # 저장 및 조회
SET name "Alice"
GET name              # "Alice"

# 만료 시간과 함께 저장(초 단위)
SET token "abc123" EX 3600

# 키가 존재하지 않을 때만 설정(분산 잠금의 기초)
SET lock "1" NX EX 10

# 일괄 작업
MSET k1 v1 k2 v2 k3 v3
MGET k1 k2 k3

# 값에 추가
APPEND name " Smith"  # "Alice Smith"

# 숫자 연산
SET counter 0
INCR counter          # 1
INCRBY counter 5      # 6
DECR counter          # 5
DECRBY counter 2      # 3

# 부동소수점 증가
SET price 9.99
INCRBYFLOAT price 0.5  # 10.49

# 문자열 길이 조회
STRLEN name

# 이전 값을 반환하고 새 값으로 설정
GETSET name "Bob"     # "Alice Smith" 반환, "Bob"으로 설정

    
접기

Hash(해시)

Hash는 구조화된 객체 저장에 적합하며 반복적인 직렬화/역직렬화를 피할 수 있습니다.

Bash
        # 필드 설정
HSET user:1 name "Alice" age 25 email "alice@example.com"

# 단일 필드 조회
HGET user:1 name      # "Alice"

# 모든 필드와 값 조회
HGETALL user:1

# 모든 필드 이름 조회
HKEYS user:1

# 모든 값 조회
HVALS user:1

# 필드 개수
HLEN user:1

# 필드 존재 여부 확인
HEXISTS user:1 email   # 1(존재함)

# 필드 삭제
HDEL user:1 email

# 여러 필드 한 번에 조회
HMGET user:1 name age

# 숫자 필드 증가
HINCRBY user:1 age 1

# 필드가 없을 때만 설정
HSETNX user:1 role "admin"

    
접기

List(리스트)

List는 양방향 연결 리스트로 양쪽 끝에서 push/pop을 지원합니다. 큐와 스택에 적합합니다.

Bash
        # 왼쪽(헤드)에 추가
LPUSH logs "event1" "event2" "event3"

# 오른쪽(테일)에 추가
RPUSH queue "task1" "task2"

# 왼쪽에서 꺼내기
LPOP logs

# 오른쪽에서 꺼내기
RPOP queue

# 블로킹 꺼내기(0 = 무한 대기)
BLPOP queue 0
BRPOP queue 30     # 최대 30초 대기

# 범위 조회(0 -1 = 전체)
LRANGE logs 0 -1

# 인덱스로 조회
LINDEX logs 0

# 리스트 길이
LLEN logs

# 트림(앞 100개만 유지)
LTRIM logs 0 99

# 특정 요소 앞뒤에 삽입
LINSERT logs BEFORE "event2" "new-event"

# 일치하는 요소 삭제
LREM logs 2 "event1"  # "event1" 2개 삭제

    
접기

대표 활용: 메시지 큐

Bash
        # 프로듀서
RPUSH queue "msg1"

# 컨슈머(블로킹 — 메시지 도착 즉시 반환)
BLPOP queue 0

    

Set(집합)

Set은 순서 없는 고유한 멤버들의 집합으로 집합 연산을 지원합니다.

Bash
        # 멤버 추가
SADD tags "redis" "cache" "nosql"

# 멤버 존재 여부 확인
SISMEMBER tags "redis"   # 1

# 모든 멤버 조회
SMEMBERS tags

# 집합 크기
SCARD tags

# 멤버 삭제
SREM tags "nosql"

# 랜덤 조회(삭제 없음)
SRANDMEMBER tags 2

# 랜덤 꺼내기(삭제)
SPOP tags

# 집합 연산
SADD set1 "a" "b" "c"
SADD set2 "b" "c" "d"

SUNION set1 set2       # 합집합: a b c d
SINTER set1 set2       # 교집합: b c
SDIFF set1 set2        # 차집합: a(set1에 있고 set2에 없는 것)

# 결과를 새 키에 저장
SUNIONSTORE result set1 set2
SINTERSTORE result set1 set2

    
접기

ZSet(정렬된 집합)

ZSet의 각 멤버는 스코어를 가지며 스코어 순으로 정렬됩니다. 리더보드에 최적입니다.

Bash
        # 멤버 추가(스코어 멤버명)
ZADD leaderboard 1000 "Alice" 850 "Bob" 1200 "Charlie"

# 멤버 스코어 조회
ZSCORE leaderboard "Alice"   # 1000

# 스코어 오름차순 순위 조회(0 = 1위)
ZRANK leaderboard "Alice"    # 1(0-indexed)

# 스코어 내림차순 순위 조회
ZREVRANK leaderboard "Alice" # 1

# 순위 범위로 조회(오름차순)
ZRANGE leaderboard 0 -1 WITHSCORES

# 순위 범위로 조회(내림차순)
ZREVRANGE leaderboard 0 2 WITHSCORES

# 스코어 범위로 조회
ZRANGEBYSCORE leaderboard 800 1100 WITHSCORES

# 스코어 증가
ZINCRBY leaderboard 100 "Alice"   # 1100

# 전체 멤버 수
ZCARD leaderboard

# 스코어 범위 내 멤버 수
ZCOUNT leaderboard 900 1200

# 멤버 삭제
ZREM leaderboard "Bob"

# 순위 범위로 삭제
ZREMRANGEBYRANK leaderboard 0 1

# 스코어 범위로 삭제
ZREMRANGEBYSCORE leaderboard 0 800

    
접기

만료 시간

Bash
        # 초 단위로 만료 시간 설정
EXPIRE key 3600

# 밀리초 단위로 설정
PEXPIRE key 3600000

# Unix 타임스탬프(초)로 설정
EXPIREAT key 1893456000

# 남은 TTL 확인(초, -1=만료 없음, -2=키 없음)
TTL key

# 남은 TTL 확인(밀리초)
PTTL key

# 만료 시간 제거(영구 저장)
PERSIST key

    

영속성

Redis는 기본적으로 인메모리입니다. 재시작하면 데이터가 사라집니다. 두 가지 영속성 방법이 있습니다:

RDB(스냅샷)

주기적으로 메모리를 디스크에 덤프합니다. 기본 영속성 방식입니다.

Bash
        # redis.conf(60초마다 1개 이상 변경 시 저장)
save 60 1
save 300 10
save 900 1

# 수동으로 트리거
BGSAVE      # 비동기 백그라운드 저장
SAVE        # 동기(블로킹 — 운영 환경에서 피할 것)

    

장점: 파일이 컴팩트하고 복원 속도가 빠름.
단점: 두 스냅샷 사이의 데이터가 손실될 수 있음.

AOF(추가 전용 파일)

모든 쓰기 명령을 기록하고 재시작 시 재생하여 데이터를 복원합니다.

Bash
        # redis.conf
appendonly yes
appendfilename "appendonly.aof"

# 동기화 정책
appendfsync always    # 매번 동기화 — 가장 안전, 가장 느림
appendfsync everysec  # 초당 1회 동기화(권장 — 최대 1초 데이터 손실)
appendfsync no        # OS에 맡김 — 가장 빠르지만 위험

    

장점: 안전성이 높고 최대 1초의 데이터 손실.
단점: 파일이 크고 복원이 느림.

하이브리드 영속성(권장 — Redis 4.0+)

Bash
        # redis.conf
aof-use-rdb-preamble yes

    

AOF 파일 앞부분에 RDB 스냅샷을 포함하고 이후 증분 명령을 추가합니다. 속도와 안전성을 모두 확보합니다.

Pub/Sub

Bash
        # 채널 구독(메시지를 기다리며 블로킹)
SUBSCRIBE news sports

# 메시지 발행
PUBLISH news "Breaking: Redis 8.0 released"

# 패턴 구독
PSUBSCRIBE news.*

# 구독 정보 확인
PUBSUB CHANNELS        # 활성 채널 목록
PUBSUB NUMSUB news     # 채널의 구독자 수

    

주의: Pub/Sub은 전송 후 잊어버리는 방식으로 영속성이 없습니다. 신뢰할 수 있는 메시지 전달에는 Stream이나 외부 MQ를 권장합니다.

트랜잭션

Redis 트랜잭션은 MULTI / EXEC를 사용해 명령 배치를 원자적으로 실행합니다(단, 런타임 오류에 대한 롤백은 없음).

Bash
        MULTI          # 트랜잭션 시작
SET k1 "v1"   # 큐에 추가
SET k2 "v2"
INCR counter
EXEC           # 큐의 모든 명령 실행

# 트랜잭션 취소
DISCARD

    

WATCH(낙관적 잠금):

Bash
        WATCH balance         # 키 감시

MULTI
DECRBY balance 100
EXEC                  # WATCH 이후 balance가 변경되면 nil 반환

    

Pipeline(배치 요청)

Pipeline은 여러 명령을 한 번의 네트워크 왕복으로 묶어 처리량을 크게 향상시킵니다.

Bash
        # redis-cli 예시
redis-cli --pipe << EOF
SET k1 v1
SET k2 v2
INCR counter
EOF

    

주요 클라이언트 라이브러리는 모두 Pipeline을 지원합니다. Node.js(ioredis)예시:

Javascript
        const pipeline = redis.pipeline()
pipeline.set('k1', 'v1')
pipeline.set('k2', 'v2')
pipeline.incr('counter')
await pipeline.exec()

    

주요 사용 시나리오

캐싱

Bash
        # Cache-Aside 패턴:
# 읽기: Redis 확인 → 미스 시 DB 조회 후 Redis에 저장
# 쓰기: DB 업데이트 후 Redis 캐시 삭제(일관성 보장)

SET user:1:profile "{...}" EX 300

    

분산 잠금

Bash
        # 잠금 획득: NX로 단일 클라이언트만 성공 보장, EX로 데드락 방지
SET lock:order:123 "client-uuid" NX EX 30

# 잠금 해제: 내 잠금인지 확인 후 삭제(Lua 스크립트로 원자성 보장)
EVAL "
  if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
  else
    return 0
  end
" 1 lock:order:123 client-uuid

    

레이트 리미팅

Bash
        # 사용자당 1분에 100회 요청 제한
INCR rate:user:123
EXPIRE rate:user:123 60

# 원자적 초기화
SET rate:user:123 0 EX 60 NX   # 첫 요청 시 초기화
INCR rate:user:123              # 요청마다 증가

    

리더보드

Bash
        # 스코어 업데이트
ZINCRBY leaderboard 10 "user:123"

# Top 10 조회
ZREVRANGE leaderboard 0 9 WITHSCORES

# 사용자 순위 확인
ZREVRANK leaderboard "user:123"

    

세션 저장

Bash
        SET session:abc123 "{userId: 1, role: admin}" EX 86400
GET session:abc123
EXPIRE session:abc123 86400   # 세션 갱신

    

캐시 3대 장애

캐시 침투(Cache Penetration)

증상: 캐시에도 DB에도 존재하지 않는 키에 대한 요청이 항상 DB를 직접 조회합니다.

해결책:

  1. null 값 캐싱: DB에 존재하지 않아도 짧은 TTL로 빈 값을 Redis에 저장
  2. 블룸 필터: 존재하지 않는 키에 대한 요청을 Redis 도달 전에 차단

캐시 장애(Cache Breakdown)

증상: 핫 키가 만료되는 순간 대량의 동시 요청이 일제히 DB를 조회합니다.

해결책:

  1. 핫 키를 영구적으로 유지(만료 없음 또는 논리적 만료 + 비동기 갱신)
  2. 뮤텍스 잠금: 첫 번째 요청만 캐시를 재구성하고 나머지는 대기

캐시 사태(Cache Avalanche)

증상: 대량의 키가 동시에 만료되어 DB가 순식간에 과부하 상태가 됩니다.

해결책:

  1. TTL에 랜덤 지터를 추가해 만료 시간을 분산
  2. 중요 데이터는 영구적으로 유지하고 비동기 백그라운드 갱신
  3. 서킷 브레이커와 그레이스풀 디그레이데이션으로 DB 보호

유용한 관리 명령

Bash
        # Redis 정보 확인(메모리, 연결, 영속성 등)
INFO
INFO memory
INFO server

# 슬로우 쿼리 로그 확인
SLOWLOG GET 10

# 현재 데이터베이스 초기화(주의해서 사용)
FLUSHDB

# 모든 데이터베이스 초기화(주의해서 사용)
FLUSHALL

# 키 타입 확인
TYPE key

# 키 삭제
DEL key1 key2

# 비동기 삭제(큰 키에 권장, 논블로킹)
UNLINK key

# 키 이름 변경
RENAME old-key new-key

# 키 메모리 사용량 확인
MEMORY USAGE key

    
Fonnpo