사용자 프로필처럼 여러 속성을 가진 객체를 Redis에 저장해야 한다면 Hash가 적합합니다. 전체를 JSON 문자열로 묶지 않고 필드 하나씩 읽고 쓸 수 있어 훨씬 효율적입니다.
# 필드 설정 (여러 필드 한 번에 가능)
HSET user:1000 name "철수" email "cs@example.com" role "admin" age 30
# 단일 필드 읽기
HGET user:1000 name
# "철수"
# 여러 필드 읽기
HMGET user:1000 name email
# 1) "철수"
# 2) "cs@example.com"
# 전체 필드 읽기
HGETALL user:1000
# 1) "name"
# 2) "철수"
# 3) "email"
# 4) "cs@example.com"
# 5) "role"
# 6) "admin"
# 7) "age"
# 8) "30"
# 필드 존재 여부
HEXISTS user:1000 email
# 1 (있음)
# 필드 삭제
HDEL user:1000 role
# 전체 필드 목록 / 값 목록 / 개수
HKEYS user:1000 # ["name", "email", "age"]
HVALS user:1000 # ["철수", "cs@example.com", "30"]
HLEN user:1000 # 3
HSET product:500 stock 100 price 9900
# 재고 1 감소
HINCRBY product:500 stock -1
# 가격 조정
HINCRBYFLOAT product:500 price 500.0
# String(JSON) 방식: 이름 하나 수정에 전체 JSON 교체
SET user:1000 '{"name":"철수","email":"cs@example.com","role":"admin"}'
GET user:1000 # 역직렬화 필요
SET user:1000 '{"name":"영희","email":"cs@example.com","role":"admin"}'
# Hash 방식: 필드 하나만 수정
HSET user:1000 name "영희"
Hash가 유리한 경우:
JSON 직렬화가 유리한 경우:
직렬화(Serialization): 객체를 전송하거나 저장할 수 있는 형식(JSON, 바이너리 등)으로 변환하는 과정. Redis Hash는 직렬화 없이 개별 필드에 접근할 수 있습니다.
HSET session:abc123
user_id 1000
name "철수"
role "admin"
login_at "2026-06-18T09:00:00"
EXPIRE session:abc123 3600
# 세션에서 역할만 조회
HGET session:abc123 role
HSET product:500
name "무선 마우스"
price 29000
stock 150
category "전자기기"
# 구매 시 재고 감소
HINCRBY product:500 stock -1
HSET stats:2026-06-18
visits 0
signups 0
purchases 0
# 방문 시
HINCRBY stats:2026-06-18 visits 1
# 가입 시
HINCRBY stats:2026-06-18 signups 1
# 오늘 통계 조회
HGETALL stats:2026-06-18
Hash의 필드는 문자열만 저장됩니다. 중첩 객체나 배열은 직접 지원하지 않습니다.
# 불가: 중첩 객체
HSET user:1000 address '{"city":"서울","gu":"강남구"}'
# 가능하지만 address 필드 자체는 JSON 문자열이 됨
# 대안: 키 분리
HSET user:1000:address city "서울" gu "강남구"
또한 Hash 내 필드 개수가 수십만 개를 넘어가면 메모리 효율이 떨어집니다. 필드가 128개 이하이고 값이 64바이트 이하인 경우 내부적으로 더 효율적인 ziplist 인코딩을 사용합니다.
ziplist: Redis가 소용량 Hash/List/Set에 적용하는 내부 압축 인코딩. 포인터를 사용하지 않고 연속된 메모리 공간에 데이터를 저장해 메모리를 절약합니다.