개발/REDIS

#12 🔐 보안·성능·관측: ACL·eviction·latency

cedis 2026. 3. 19. 11:47
빠른 Redis, 안전하게 운영하려면? ACL로 최소 권한을 설정하고, eviction으로 메모리를 관리하며, slowlog로 병목을 찾는 운영 필수 지식을 정리합니다.

⚡ "빠른 만큼 운영이 중요합니다"

Redis는 빠릅니다. 초당 수십만 건의 요청을 처리할 수 있죠. 하지만 빠른 만큼 잘못 사용하면 순식간에 메모리가 가득 차거나, 보안 허점이 생기거나, 갑자기 응답이 느려질 수 있습니다.

시리즈 마지막 편인 이번 12편에서는 Redis를 안전하고 효율적으로 운영하기 위한 세 가지 핵심 영역을 다룹니다. 첫째는 보안(ACL) — 최소 권한 원칙으로 위험을 줄이는 방법. 둘째는 성능(eviction + pipelining) — 메모리를 관리하고 RTT를 최소화하는 방법. 셋째는 관측(slowlog + latency + hotkeys) — 문제를 발견하고 조치하는 방법.

이 세 가지를 알면 "Redis가 왜 갑자기 느려졌지?", "누가 데이터를 조작했지?", "메모리가 왜 이렇게 많이 쓰이지?"라는 질문에 스스로 답할 수 있게 됩니다.

🔑 핵심 개념 1: ACL — 최소 권한 원칙

Redis 6.0부터 도입된 ACL(Access Control List)은 사용자별로 접근 가능한 키, 실행 가능한 명령을 세밀하게 제어합니다. 기본 사용자(default)는 모든 권한을 가지지만, 실제 운영에서는 서비스별로 최소한의 권한만 부여해야 합니다.

ACL 기본 규칙 문법

규칙 설명
on / off 계정 활성화/비활성화
>password 비밀번호 설정
~cache:* 접근 가능한 키 패턴 (cache:로 시작하는 키만)
+get / -set 허용(+) / 금지(-) 명령
+@read 읽기 명령 그룹 전체 허용
nopass 비밀번호 없이 허용 (개발 환경에서만)
redis-cli — ACL 실습
# Lab 11 — ACL 사용자 생성

# 1. 현재 사용자 목록 확인
ACL LIST
# → user default on nopass ~* &* +@all

# 2. 읽기 전용 사용자 생성
ACL SETUSER readonly on >readpass ~* +@read
ACL LIST  # readonly 사용자 확인

# 3. 캐시 전담 사용자 (cache: 키만, GET/SET만)
ACL SETUSER cache-svc on >CacheP@ss ~cache:* +get +set +del +expire +ttl
ACL LIST

# 4. 인증 테스트 (새 연결에서)
AUTH cache-svc CacheP@ss       # 인증

SET cache:user:1000 "kim"      # → OK (허용된 키/명령)
GET cache:user:1000            # → "kim"

SET session:abc "data"         # → NOPERM No permissions to access a key
SET other:key "data"           # → NOPERM 키 패턴 불일치

# 5. 사용자 삭제
ACL DELUSER readonly
💡 default 사용자 잠그기
운영 환경에서는 ACL SETUSER default off로 기본 사용자를 비활성화하거나 비밀번호를 설정해야 합니다. 기본 사용자가 nopass + 전체 권한이면 누구든 접근할 수 있어 매우 위험합니다.

🗑️ 핵심 개념 2: maxmemory + eviction 정책

Redis는 기본적으로 메모리 제한이 없습니다(64비트 시스템에서 maxmemory 0). 데이터가 계속 쌓이면 결국 서버의 전체 메모리를 다 쓸 수 있습니다. maxmemory를 설정하면 한도를 넘을 때 Redis가 오래된 데이터를 자동으로 삭제(evict)합니다.

eviction 정책 종류

정책 설명 추천 상황
noeviction 삭제 안 함 → 한도 초과 시 쓰기 오류 주요 데이터 보존 필수 시
allkeys-lru 전체 키 중 LRU로 삭제 캐시 용도 ⭐ 가장 많이 사용
volatile-lru TTL 있는 키 중 LRU로 삭제 TTL 있는 키만 삭제 허용 시
allkeys-random 전체 키 중 랜덤 삭제 모든 키 접근 빈도 균등 시
volatile-ttl TTL 짧은 키 우선 삭제 만료 예정 키 먼저 정리 시
allkeys-lfu 전체 키 중 접근 빈도 낮은 것 삭제 (Redis 4.0+) 핫/콜드 데이터 구분 명확 시
redis-cli — eviction 설정
# maxmemory 설정
CONFIG SET maxmemory 100mb
CONFIG SET maxmemory-policy allkeys-lru

# 현재 설정 확인
CONFIG GET maxmemory
CONFIG GET maxmemory-policy

# 메모리 및 eviction 상태 확인
INFO memory
# used_memory_human: 45.67M
# maxmemory_human: 100.00M
# maxmemory_policy: allkeys-lru

INFO stats | grep evicted
# evicted_keys: 1234  ← 삭제된 키 수 (증가하면 메모리 압박 상태)

⚡ 핵심 개념 3: 파이프라이닝 — RTT 최소화

Redis 명령 하나를 실행할 때마다 네트워크 왕복(Round-Trip Time, RTT)이 발생합니다. 1000개 명령을 개별 실행하면 RTT × 1000의 시간이 걸립니다. 파이프라이닝은 여러 명령을 묶어서 한 번에 보내고, 응답도 한 번에 받아 RTT를 1번으로 줄입니다.

Python — 파이프라이닝
# pip install redis
import redis
import time

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

# 비교 1: 개별 실행 (느림)
start = time.time()
for i in range(1000):
    r.set(f"seat:{i}", f"#{i}")
elapsed_individual = time.time() - start
print(f"개별 실행: {elapsed_individual:.3f}초")

# 비교 2: 파이프라인 (빠름)
start = time.time()
pipe = r.pipeline(transaction=False)  # transaction=False → 순수 파이프라인
for i in range(1000):
    pipe.set(f"seat:{i}", f"#{i}")
results = pipe.execute()  # 한 번에 실행
elapsed_pipeline = time.time() - start
print(f"파이프라인: {elapsed_pipeline:.3f}초")

print(f"속도 향상: {elapsed_individual / elapsed_pipeline:.1f}배")
Node.js — 자동 파이프라인
// npm install redis
import { createClient } from "redis";
const client = createClient();
await client.connect();

// Node-redis: 같은 tick에서 실행 → 자동 파이프라인
const results = await Promise.all([
  client.set("seat:0", "#0"),
  client.set("seat:1", "#1"),
  client.set("seat:2", "#2"),
]);
console.log(results); // ['OK', 'OK', 'OK']

await client.quit();

🔍 핵심 개념 4: 관측 — 문제 찾고 조치하기

Redis 성능 문제는 대부분 느린 명령, 메모리 부족, 핫키 집중 중 하나입니다. Redis 8.6에서는 이를 찾는 도구들이 더 강화되었습니다.

slowlog — 느린 명령 찾기

redis-cli
# slowlog 기준 설정 (마이크로초 단위, 10ms 이상인 명령 기록)
CONFIG SET slowlog-log-slower-than 10000
CONFIG SET slowlog-max-len 128

# 느린 명령 목록 조회
SLOWLOG GET 10
# 1) 1) (integer) 1       ← slowlog ID
#    2) (integer) 1710xxx ← 실행 시간 (Unix timestamp)
#    3) (integer) 52000   ← 실행 시간 (마이크로초)
#    4) 1) "KEYS"         ← 명령
#       2) "*"
# → KEYS * 가 52ms 걸린 것 발견!

SLOWLOG LEN    # 기록된 수
SLOWLOG RESET  # 초기화

latency — 지연 스파이크 감지

redis-cli
# latency 모니터링 활성화
CONFIG SET latency-monitor-threshold 10  # 10ms 이상 이벤트 기록

# 지연 이벤트 조회
LATENCY LATEST
LATENCY HISTORY event

# 실시간 지연 모니터링 (1초 간격)
redis-cli --latency -p 6379

hotkeys — 핫키 찾기 (Redis 8.6)

redis-cli
# 핫키 분석 (maxmemory-policy가 LFU 계열일 때 효과적)
# Redis 8.6.0에서 HOTKEYS 명령 추가
redis-cli --hotkeys -p 6379

# 큰 키 찾기 (메모리 많이 쓰는 키)
redis-cli --bigkeys -p 6379

# INFO 종합 상태 확인
INFO all          # 모든 섹션
INFO memory       # 메모리 사용량
INFO clients      # 클라이언트 연결 수
INFO stats        # 요청 수, eviction 수 등
INFO keyspace     # DB별 키 수

🔬 Lab 11: 통합 실습 — 문제 발견 → 측정 → 조치

redis-cli — 전체 흐름
# 1. ACL 사용자 생성
ACL SETUSER alice on >S3curePass ~cache:* +get +set +expire +ttl

# 2. maxmemory + eviction 설정
CONFIG SET maxmemory 50mb
CONFIG SET maxmemory-policy allkeys-lru

# 3. slowlog 활성화
CONFIG SET slowlog-log-slower-than 5000   # 5ms 이상

# 4. 의도적 느린 명령 실행 (100만 키 환경에서 KEYS *)
# (실제 환경에서는 하지 마세요!)
# 대신 DEBUG SLEEP으로 지연 시뮬레이션
DEBUG SLEEP 0.1  # 100ms 지연

# 5. slowlog 확인
SLOWLOG GET 5

# 6. 메모리 상태 확인
INFO memory | grep -E "used_memory|evicted"

# 7. 운영 진단 명령
LATENCY LATEST
INFO clients

📋 운영 체크리스트 12개 (복사해서 사용하세요)

  1. ACL 설정: default 사용자에 비밀번호 설정 또는 off, 서비스별 최소 권한 계정 생성
  2. bind 설정: redis.conf에서 bind 127.0.0.1 (외부 노출 최소화)
  3. maxmemory 설정: 서버 RAM의 70~80% 이내로 maxmemory 지정
  4. eviction 정책: 캐시 용도 → allkeys-lru, 중요 데이터 → noeviction + 알림
  5. 퍼시스턴스 선택: 캐시만 → OFF, 세션/큐 → AOF everysec
  6. KEYS * 금지: SCAN 사용, slowlog로 KEYS 실행 여부 주기적 확인
  7. slowlog 설정: slowlog-log-slower-than 10000 (10ms), 주기적 SLOWLOG GET 확인
  8. TTL 습관: 모든 캐시 키에 TTL 설정, 만료 없는 키 정기 점검
  9. 파이프라이닝: 배치 쓰기/읽기 시 파이프라인 사용으로 RTT 최소화
  10. 핫키 모니터링: redis-cli --hotkeys, INFO stats의 keyspace_hits/misses 비율 확인
  11. 복제 지연 확인: INFO replication의 slave lag, repl_backlog_size 적절히 설정
  12. 보안 패치: Redis 최신 안정 버전 유지 (8.6.1에는 보안 수정 포함)

📌 12편 핵심 요약

  1. ACL: 서비스별 최소 권한 계정, ~키패턴 +명령으로 세밀 제어
  2. maxmemory + eviction: 메모리 한도 설정 필수, 캐시엔 allkeys-lru 권장
  3. 파이프라이닝: 배치 명령의 RTT를 1번으로 줄여 수배 속도 향상
  4. slowlog: 느린 명령 감지 → KEYS * 같은 위험 명령 발견
  5. hotkeys/bigkeys: Redis 8.6 HOTKEYS 명령으로 핫키 식별, 샤딩 전략 수립

✅ 12편 체크리스트

  • ACL SETUSER로 최소 권한 사용자를 만들고 인증 테스트를 했다
  • maxmemory와 maxmemory-policy를 설정했다
  • INFO stats에서 evicted_keys를 확인했다
  • Python 또는 Node.js로 파이프라이닝을 실행하고 속도 차이를 확인했다
  • slowlog로 느린 명령을 찾는 방법을 실습했다
  • 운영 체크리스트 12개를 북마크하거나 복사해 두었다

🧠 퀴즈 3문항

Q1. ACL SETUSER alice on >pass ~cache:* +get 에서 alice가 SET을 실행하면?
🚫 NOPERM 오류가 발생합니다. +get 만 허용했고 +set은 허용하지 않았기 때문입니다. 허용된 명령만 실행할 수 있습니다.
Q2. maxmemory-policy를 noeviction으로 설정했을 때 메모리 한도를 넘으면?
⛔ 쓰기 명령(SET, LPUSH 등)이 OOM command not allowed 오류를 반환합니다. 데이터가 삭제되지 않는 대신 새 데이터를 쓸 수 없게 됩니다.
Q3. 파이프라이닝이 성능을 높이는 이유는?
🚀 여러 명령을 묶어 RTT(네트워크 왕복 시간)를 1번으로 줄이기 때문입니다. 1000개 명령을 개별로 보내면 RTT×1000이지만, 파이프라인으로 묶으면 RTT×1이 됩니다.

📝 과제 3가지

  1. ACL 강화: default 사용자를 비활성화(off)하고, 관리자용 계정(admin)을 만들어 전체 권한을 부여하세요. 기존 연결에서 인증 없이 접근이 차단되는지 확인하세요.
  2. eviction 관찰: maxmemory를 10MB로 낮추고 데이터를 계속 추가하면서 INFO stats의 evicted_keys가 증가하는 것을 실시간으로 관찰하세요.
  3. 운영 체크리스트 적용: 위의 운영 체크리스트 12개 중 자신의 현재 Redis 설정에 빠진 항목을 찾아 적용해 보세요.
🎉

Redis 입문 시리즈 완주를 축하합니다!

설치부터 보안·운영까지, 12편의 여정을 끝까지 완주하셨습니다.

다음 단계: Redis University (university.redis.io) · Running Redis at Scale 코스