Redis는 단순한 키-값 저장소를 넘어, 5가지 핵심 자료구조를 통해 복잡한 데이터 모델을 효율적으로 처리할 수 있게 합니다. 그중에서도 Hash(해시)와 Set(집합)은 단순 캐싱을 넘어 애플리케이션의 데이터 관리 효율을 극대화하는 숨겨진 보석 같은 존재입니다. 이 두 자료구조의 특징, 장점, 그리고 실전 활용 꿀팁을 자세히 알아보겠습니다.
1. Hash (해시): 객체 지향적 데이터 저장소 📦
Redis의 Hash는 하나의 키(Key) 아래에 여러 개의 필드(Field)와 값(Value) 쌍을 저장할 수 있는 자료구조입니다. 관계형 데이터베이스의 레코드나 JSON 객체와 유사하게, 관련된 여러 속성을 하나의 엔티티로 묶어 관리할 때 최적화되어 있습니다.
1.1. Hash의 특징 및 장점
- 메모리 효율성: 작은 객체들을 개별 String으로 저장하는 대신 Hash로 묶어 저장하면, Redis가 내부적으로 메모리 최적화(ziplist 또는 quicklist)를 수행하여 메모리 사용량을 크게 절약할 수 있습니다.
- 원자적 부분 업데이트: 객체 전체를 가져오지 않고도 특정 필드만 원자적으로(Atomic) 읽거나 쓸 수 있습니다. 이는 네트워크 부하를 줄이고 데이터 정합성을 유지하는 데 유리합니다.
- 구조화된 데이터 관리: 사용자 프로필, 상품 정보 등 여러 속성을 가진 엔티티를 구조적으로 저장하고 관리하기 편리합니다.
1.2. 실전 활용 예제: 사용자 프로필 관리
사용자 ID 'user:100'의 이름, 이메일, 마지막 로그인 시간을 저장한다고 가정해 보겠습니다.
| 명령어 | 설명 | 예시 (Redis CLI) |
| HSET | Hash에 필드-값 쌍을 설정합니다. | HSET user:100 name "Alice" email "a@exam.com" last_login 1678886400 |
| HGET | 특정 필드의 값을 가져옵니다. | HGET user:100 name |
| HMGET | 여러 필드의 값을 한 번에 가져옵니다. | HMGET user:100 name email |
| HGETALL | 해당 Hash의 모든 필드와 값을 가져옵니다. | HGETALL user:100 |
| HINCRBY | 특정 필드의 값을 원자적으로 증가시킵니다. | HINCRBY user:100 posts_count 1 |
⭐ 실전 꿀팁: Hash 사용 시 주의사항 하나의 Hash에 너무 많은 필드(수십만 개 이상)를 저장하는 것은 지양해야 합니다. HGETALL 등의 명령어를 사용할 때 성능 저하를 일으킬 수 있으며, Hash를 분할하거나 Sorted Set 등 다른 자료구조를 혼합 사용하는 것을 고려해야 합니다. Hash는 일반적으로 100~1000개 정도의 필드를 가질 때 가장 효율적입니다.
2. Set (집합): 중복 없는 데이터 관리와 집합 연산 👥
Redis의 Set은 중복되지 않는(Unique) 문자열의 컬렉션입니다. 순서가 중요하지 않으며, 특정 요소의 존재 유무를 확인하거나 두 집합 간의 관계(교집합, 합집합, 차집합)를 계산하는 데 특화되어 있습니다.
2.1. Set의 특징 및 장점
- 고속의 중복 관리: 요소 추가 시 중복 여부를 $\mathcal{O}(1)$의 상수 시간 복잡도로 빠르게 검사하고 처리합니다.
- 강력한 집합 연산: 서버 측에서 두 개 이상의 Set에 대한 교집합(SINTER), 합집합(SUNION), 차집합(SDIFF) 연산을 매우 빠르게 수행하여 네트워크 오버헤드를 줄입니다.
- 멤버 확인: 특정 요소가 Set에 존재하는지 (SISMEMBER) 확인하는 속도가 매우 빠릅니다.
2.2. 실전 활용 예제: 소셜 기능 및 사용자 활동 추적
Set은 소셜 네트워킹 기능(팔로우, 친구 목록)이나 데이터 분석(방문자 집계)에 필수적입니다.
| 명령어 | 설명 | 예시 (Redis CLI) |
| SADD | Set에 멤버를 추가합니다. 중복은 무시됩니다. | SADD followers:user:100 user:200 user:300 |
| SISMEMBER | 특정 멤버가 Set에 포함되어 있는지 확인합니다. | SISMEMBER followers:user:100 user:200 (결과: 1) |
| SMEMBERS | Set의 모든 멤버를 가져옵니다. | SMEMBERS followers:user:100 |
| SINTER | 두 Set의 교집합을 계산합니다 (공통 친구 찾기). | SINTER followers:user:100 following:user:200 |
| SCARD | Set의 멤버 수를 가져옵니다 (일일 고유 방문자 수). | SCARD daily:unique:users:20250928 |
💡 실전 꿀팁: 일일 고유 방문자 수 (UV) 카운트
웹 서비스에서 일일 고유 방문자 수(Unique Visitor)를 집계할 때 Set은 완벽한 솔루션입니다.
- 사용자가 웹사이트에 접속할 때마다 해당 사용자의 ID를 당일 날짜의 Set에 추가합니다.
SADD daily:unique:users:20250928 user:55 user:56 user:55 # user:55는 중복되어 한 번만 저장됨 - 집계 시 SCARD 명령어를 사용하면 하루 동안 중복 없이 방문한 사용자 수를 $\mathcal{O}(1)$에 가까운 속도로 얻을 수 있습니다.
3. Hash와 Set을 활용한 복합 캐싱 전략 융합 🔄
실제 서비스에서는 Hash와 Set을 단독으로 사용하기보다, 서로 보완하며 복잡한 문제를 해결하는 데 사용됩니다.
예시: 커뮤니티 게시물 관리
- 게시물 상세 정보 (Hash):
- Key: post:123
- Fields: title, content, author_id, created_at
- 활용: HGETALL post:123으로 상세 정보 한 번에 조회.
- 게시물 태그 목록 (Set):
- Key: post:123:tags
- Members: Redis, Caching, Database
- 활용: SISMEMBER post:123:tags Redis로 특정 태그 포함 여부 확인.
- 특정 태그가 달린 모든 게시물 ID 목록 (Set):
- Key: tag:Redis:post_ids
- Members: 123, 456, 789
- 활용: SMEMBERS tag:Redis:post_ids로 "Redis" 태그가 달린 모든 게시물 ID를 빠르게 조회합니다.
이처럼 Redis의 Hash와 Set을 전략적으로 조합하면, 데이터베이스를 사용하지 않고도 빠르고 효율적으로 구조화된 데이터 관리, 중복 없는 고유성 보장, 그리고 복잡한 집합 관계 연산을 수행할 수 있습니다. 이 강력한 자료구조들을 활용하여 여러분의 애플리케이션 성능을 한 단계 끌어올리세요!