Redis, Kafka
✅ 고민해볼만한 POINT
1) Remote Cache를 위한 다양한 라이브러리(Memcached 등) 중에서 Redis를 선택한 이유는 무엇일까?
항목 | Redis 선택 이유 |
기능 | Redis는 단순한 key-value 저장뿐 아니라 List, Set, Hash, ZSet(정렬된 집합) 등 다양한 자료구조를 지원함. 반면 Memcached는 오직 key-value 저장만 가능. |
지속성 | Redis는 메모리 기반이지만 데이터를 디스크에 백업(AOF, RDB) 가능. Memcached는 비휘발성 저장 불가 (재시작 시 모두 사라짐). |
성능 | Redis는 단일 스레드지만 I/O 멀티플렉싱으로 매우 빠르고, latency도 낮음. |
운영 편의성 | Redis는 CLI 도구, 모니터링 툴, Pub/Sub, Lua 스크립트 등 운영 도구가 풍부함. |
Spring 통합 | @Cacheable, Spring Cache 추상화, RedisTemplate 등 Spring과의 통합 지원이 강력함. |
커뮤니티/문서 | 스타 수, 자료 수, 문제 해결 커뮤니티가 월등히 많음. |
➡️ 결론: Redis는 기능, 성능, 유연성, 안정성, 생태계 모두에서 Memcached보다 우수해서 선택.
🔹 Q1. Memcached? 로컬 메모리 캐시 말하는 건가?
❌ Memcached는 “로컬 캐시”가 아니라 분산형 리모트 캐시 서버.
항목 | 설명 |
이름 | Memcached (Memory + Cache + Daemon) |
역할 | 네트워크를 통해 접근하는 메모리 기반의 Key-Value 저장소 |
특징 | - 아주 단순한 구조 - 문자열 기반 Key-Value만 저장 가능 - 정렬, TTL 제어, 자료구조 없음 |
비교 | 로컬 캐시는 JVM 내에서 동작 (ConcurrentHashMap, Caffeine 등) Memcached는 별도의 서버로 동작, Redis처럼 Remote Cache 역할 |
🔁 비유: 로컬 캐시는 “네가 주머니에 넣어 둔 메모장”, Memcached/Redis는 “네트워크로 연결된 공유 저장소”.
🔹 Q2. Redis는 디스크 백업 가능(AOF, RDB)?
1) RDB (Redis Database File)
항목 | 설명 |
형식 | .rdb 파일 |
방식 | 특정 주기마다 전체 데이터를 스냅샷처럼 저장 |
장점 | 파일이 작고 로딩이 빠름 |
단점 | 마지막 저장 시점 이후의 변경은 유실될 수 있음 |
🔁 비유: “정기적으로 사진 찍어서 앨범에 저장”하는 느낌.
2) AOF (Append Only File)
항목 | 설명 |
형식 | .aof 파일 |
방식 | 모든 write 명령을 순서대로 로그에 추가 |
장점 | 더 안전하고 거의 유실 없음 |
단점 | 파일이 점점 커질 수 있음 (압축 필요) |
🔁 비유: “매번 일기장에 한 줄씩 쓰는 방식”.
✅ Redis는 보통 RDB + AOF를 함께 사용해서 안전성과 성능을 모두 챙김.
🔹 Q3. I/O 멀티플렉싱?
한 줄 요약: 하나의 스레드로 여러 I/O를 동시에 처리하는 기술.
항목 | 설명 |
기존 방식 | 요청마다 스레드 생성 (비효율적, 자원 낭비) |
멀티플렉싱 | 커널의 epoll, select 등을 활용해 하나의 루프에서 수백~수천 개의 I/O 이벤트 처리 |
Redis 적용 | Redis는 단일 스레드지만 I/O 멀티플렉싱으로 빠르게 수많은 클라이언트와 통신 가능 |
🔁 비유: 기존 방식은 “주문 받을 때마다 직원 1명 붙임”, 멀티플렉싱은 “직원 1명이 동시에 100명 주문을 관리하는 시스템”.
🔹 Q4. Redis 운영 도구들 간단 설명
도구 | 설명 |
CLI (redis-cli) | Redis와 대화하는 명령줄 도구 → get, set, zadd, flushdb 같은 명령어 사용 |
모니터링 툴 | - MONITOR 명령: 모든 요청 실시간 보기 - INFO: 메모리, 키 수, 히트율 등 상태 정보 조회 |
Pub/Sub | Publisher/Subscriber 시스템 → 하나의 채널에 메시지를 보내면 구독자들이 동시에 수신 |
Lua 스크립트 | Redis 안에서 실행되는 작은 코드 블록 → 트랜잭션처럼 여러 명령을 원자적으로 실행 가능 |
🔁 비유:
- CLI: Redis랑 대화하는 전화기
- Pub/Sub: 방송국이 보내고 청취자가 듣는 라디오
- Lua: Redis 안에서 실행되는 미니 프로그램
✅ Pub/Sub 활용 사례
Pub/Sub(Publish/Subscribe)는 발행자(Publisher)와 구독자(Subscriber)가 메시지를 주고받는 비동기 메시징 시스템입니다.
예시:
- 채팅 시스템: A 유저가 채팅방에 메시지를 보내면, 그 채팅방을 구독하고 있는 B, C 유저들이 메시지를 실시간으로 받음.
- 실시간 알림: 서버에서 중요한 알림을 발행하면, 해당 알림을 구독 중인 앱 사용자들이 실시간으로 알림 받음.
✅ AOF vs Kafka
항목 | AOF (Append Only File) | Kafka |
소속 | Redis | Apache Kafka (독립 메시지 큐 시스템) |
목적 | Redis의 데이터를 디스크에 영구 저장 | 대용량 메시지를 분산 처리하고 비동기로 전달 |
특징 | Redis 명령어를 로그 형식으로 계속 기록 | 메시지를 토픽 기반으로 나누고 각 소비자가 읽음 |
활용 | Redis 복구용, 장애 복구 | 로그 수집, 이벤트 스트리밍, 실시간 데이터 파이프라인 |
✅ Redis 클러스터링
Redis Cluster는 데이터를 여러 노드에 분산 저장하여 대용량 트래픽을 처리하는 구조예요.
- 각 노드는 일부 키 범위만 담당.
- 요청을 받은 노드는, 필요 시 다른 노드로 요청을 자동 라우팅해줌.
- 수평 확장이 가능해서 서비스 규모가 커져도 감당할 수 있어요.
✅ Kafka란?
Apache Kafka는 고성능의 분산 메시지 스트리밍 플랫폼이에요.
- 실시간으로 많은 데이터를 수집, 저장, 분산, 전달할 수 있음.
- 예를 들어, 네이버 뉴스 댓글 실시간 처리나, 로그 수집 시스템 등에 사용됨.
Kafka는 “로그 저장소 + 실시간 알림 시스템 + 이벤트 버스” 역할을 다 해주는 범용 메시징 시스템이에요.
✅ I/O란?
I/O(Input/Output)는 컴퓨터가 외부 세계와 데이터를 주고받는 모든 행위입니다.
- Input: 마우스, 키보드 입력
- Output: 화면 출력, 네트워크 전송 등
✅ I/O 멀티플렉싱이란?
서버가 수천 개의 네트워크 요청을 동시에 처리할 수 있게 하는 기술.
한마디로 “한 스레드로 수천 개 연결을 효율적으로 관리하는 방식”.
관련 기술:
- select: 오래된 방식. 느림.
- poll: select보다 낫지만 비슷함.
- epoll (Linux): 최신 방식. 이벤트가 생긴 소켓만 처리해서 성능이 뛰어남.
✅ 커널이란?
커널(Kernel)은 OS의 핵심.
하드웨어(CPU, 메모리, 디스크)와 프로그램 사이를 중재하는 “운영체제의 심장”이에요.
- epoll 같은 기술은 커널 내부에서 작동해요.
- 유저는 커널에게 “이 소켓에 데이터 오면 알려줘”라고 요청하면,
- 커널이 대신 감시하다가 알려주는 거죠.
🧩 1. 노드란?
❓ 노드(Node) = 컴퓨터 1대 (서버 1대)
Redis 클러스터에서는 여러 대의 컴퓨터(노드)가 함께 역할을 나눠서 데이터를 저장해요.
예시:
[노드1] 0 ~ 5번 키 담당
[노드2] 6 ~ 10번 키 담당
[노드3] 11 ~ 15번 키 담당
🧩 2. 라우팅이란?
❓ 라우팅(Routing) = 길 안내, 어디로 갈지 알려주는 일
Redis 클러스터에서는 사용자가 아무 노드에게 요청을 해도,
그 노드가 알아서 “이건 내 담당 아님, 다른 노드로 전달할게”라고 요청을 자동으로 돌려줍니다.
네가 A마트 갔는데, “이건 B마트 담당이네요. 제가 알아서 연결해드릴게요~” 하는 느낌.
🧩 3. 수평 확장이란?
❓ 수평 확장(Scale-out) = 서버 대수를 늘려서 처리량 늘리기
- 수직 확장: 컴퓨터 성능을 높이는 것 (CPU, RAM 올리기)
- 수평 확장: 컴퓨터를 여러 대로 늘리는 것
Redis 클러스터는 수평 확장이 가능하니까,
서버를 여러 대로 나눠서 더 많은 데이터를 빠르게 처리할 수 있어요.
🧠 4. Redis 클러스터 구조 예시
┌───────────────┐
│ Client │
└──────┬────────┘
│
▼
┌─────────────┐ ┌─────────────┐ ┌────────────┐
│ Redis 노드1 │<----->│ Redis 노드2 │<----->│ Redis 노드3 │
└─────▲───────┘ └─────▲───────┘ └─────▲──────┘
담당: 키 0~5 담당: 6~10 담당: 11~15
노드끼리는 서로 연결돼 있고,
Client는 아무 노드에나 요청하면 됩니다. 노드가 알아서 처리하거나 다른 노드에 전달합니다.
⚙️ 5. 커널이란?
❓ 커널(Kernel) = 운영체제(OS)의 심장, 하드웨어와 소프트웨어를 연결해주는 핵심 소프트웨어
우리가 “파일 저장해줘”, “키보드 입력 받아줘” 같은 요청을 하면,
커널이 그걸 진짜 하드웨어에 전달해서 처리해줍니다.
- 메모리 관리
- 프로세스 스케줄링
- 디바이스 I/O 등 다 커널이 해요.
커널은 우리가 건드릴 일은 없고, 우리가 짠 프로그램이 OS와 대화할 때 거쳐 가는 중간 관리자입니다.
⚙️ 6. epoll 방식 (I/O 멀티플렉싱)
🧶 전통적인 방식: select()
- 수백 개 연결을 한 번에 감시하는데, 하나하나 다 체크함 → 비효율적
🧶 최신 방식: epoll()
- OS(커널)에 “얘네 중 누가 이벤트 생기면 알려줘” 하고 등록만 해둠
- 이벤트가 생긴 애들만 딱! 알려줌
📌 즉, epoll은 “필요한 일만 해주는 알림 시스템”
→ 수천 개 연결이 있어도, 효율적으로 처리 가능
→ 그래서 Redis, Nginx, Kafka 같은 고성능 시스템들이 다 epoll을 씀
🔄 7. AOF vs Kafka 완전 정리
항목 | AOF (Append Only File) | Kafka |
어디 소속? | Redis 내부 기능 | 별도 메시지 시스템 (Apache Kafka) |
하는 일 | Redis 데이터를 파일로 저장하여 복구 가능하게 함 | 대규모 메시지 전달, 이벤트 처리, 로그 수집 등 |
사용 목적 | Redis가 꺼져도 다시 살아날 수 있도록 하는 용도 | 수많은 사용자에게 메시지를 실시간 분산 처리 |
메시지 전송 | ❌(전송 X), 오직 복구용 | ✅(다수의 소비자에게 메시지 전송) |
구조 | 단일 프로세스에 종속 | 분산 메시지 큐 시스템 (브로커/프로듀서/컨슈머 구조) |
💬 예시: 일반 채팅 vs 오픈채팅
항목 | 일반 채팅 (1:1, 소규모) | 오픈 채팅 (수천 명) |
시스템 예시 | Redis Pub/Sub 사용 가능 | Kafka 사용 권장 |
이유 | 단순 메시지 전달이면 충분 | 수많은 사용자에게 메시지 전달 필요 |
특징 | 빠르고 가벼움 | 안정적이고 확장 가능 |
✅ 정리
항목 | Redis | Kafka |
핵심 정체 | 인메모리 저장소 (Data Store) | 분산 메시지 브로커 (Message Broker) |
목적 | 데이터를 빠르게 저장/조회 | 데이터를 안정적으로 전달/스트리밍 |
비유 | 📦 “빠른 창고” | 📮 “대용량 우체국” |
🔎 구체적으로
🔴 Redis는?
- 메모리에 올려서 빠르게 저장하고, 필요 시 디스크에도 백업하는 저장소예요.
- 캐시처럼 쓰거나, 순위표, 세션, 검색 기록 저장 등에 사용해요.
- 클라이언트가 GET, SET 등으로 즉시 접근할 수 있어요.
📦 “지금 바로 꺼내 쓸 수 있는 저장소”
🟠 Kafka는?
- 메시지를 여러 시스템에 전달하거나 방송해주는 역할.
- 프로듀서가 메시지를 Kafka에 보내고, 컨슈머가 그걸 구독해서 가져감.
- 디스크 기반으로 데이터를 저장하지만 중간 전달자 역할에 초점이 있음.
[유저 A] --(WebSocket)--> [Spring 서버] --(KafkaProducer)--> [Kafka]
[Kafka] --(KafkaConsumer)--> [Spring 서버] --(WebSocket)--> [유저 B]
📮 “수많은 구독자들에게 메시지를 방송해주는 대규모 우체국”
📌 요약 비교
항목 | Redis | Kafka |
주 용도 | 빠른 데이터 저장/조회 | 안정적인 메시지 전달 및 스트리밍 |
데이터 위치 | 메모리 (디스크 백업 가능) | 디스크 기반 로그 저장 |
특징 | 빠름, 간단함 | 내구성, 분산 처리, 순서 보장 |
쓰임새 | 캐시, 세션, 순위표, 실시간 처리 | 로그 수집, 이벤트 스트리밍, 비동기 처리, ETL 등 |
✅ 1:1 채팅에 Kafka를 쓸 수 있을까?
Yes. 가능은 하지만 “Overkill”일 수 있음.
상황 | 적합한 방식 | 설명 |
✅ 실시간, 단순한 1:1 채팅 | Redis | 빠르고 구현이 간단함. 적은 오버헤드 |
✅ 대규모, 로그 저장, 메시지 재처리 필요 | Kafka | 내구성 좋고, 메시지 유실 위험 거의 없음 |
❌ 100명도 안 되는 서비스에 Kafka | 비추천 | 복잡도와 비용이 불필요하게 커짐 |
🔹 1:1 채팅이 단순하고 실시간이면 Redis가 더 적합
🔹 Kafka는 보낸 메시지를 저장하고 나중에 다시 처리하거나, 통계를 분석할 필요가 있을 때 적합
✅ Redis vs Kafka 1:1 채팅용 비교
항목 | Redis 채팅 | Kafka 채팅 |
속도 | 🟢 매우 빠름 (메모리 기반) | 🟠 빠르지만 디스크 기반 저장 |
메시지 유실 위험 | 🟠 서버 재시작 시 유실 가능 (AOF 설정 필요) | 🟢 유실 거의 없음 (디스크 저장 + ack 처리) |
사용 목적 | 단순 메시지 송수신, 실시간 기능 | 메시지 보관, 재처리, 분석, 다중 시스템 연동 |
유지 관리 | 매우 단순 | 운영 복잡도 큼 (브로커, 토픽, 파티션 관리 등) |
확장성 | 수동 클러스터 필요 | 수평 확장 쉽게 가능 (브로커 추가) |
🔀 Redis + Kafka 함께 쓰는 아키텍처 예시
[Client] ⇄ WebSocket API
|
▼
[Redis Pub/Sub]
|
┌─────────┴──────────┐
▼ ▼
[실시간 메시지 송수신] [Kafka Producer]
|
▼
[Kafka Topic]
|
┌──────────────┴────────────┐
▼ ▼
[로그 저장 시스템] [추천 시스템 / 알림 시스템]
✔ 설명
- 클라이언트 간 채팅은 Redis Pub/Sub으로 빠르게 실시간 처리
- 동시에 Kafka에 메시지를 비동기로 적재하여 나중에 분석, 검색, 추천, 로그 저장 등으로 활용
✅ 결론
- 단순한 채팅 → Redis
- 신뢰성, 로그 저장, 확장성, 통계 필요 → Kafka
- 둘 다 필요 → Redis + Kafka 혼합
WebSocket, 웹 소캣이란?
🔌 WebSocket이 뭐야?
WebSocket은 “양방향 통신”을 위한 기술이에요.
구분 | 설명 |
일반 HTTP | 요청(Request)을 보내야만 응답(Response)이 옴 → 단방향 |
WebSocket | 서버와 클라이언트가 서로 실시간으로 주고받을 수 있음 → 양방향 |
💬 왜 채팅에 WebSocket이 필요할까?
HTTP 기반 채팅이라면:
- 유저 B가 메시지를 받으려면 계속 서버에 “새 메시지 있나요?” 하고 물어봐야 함 (Polling)
- 비효율적이고 서버에 부담 큼
WebSocket은 한 번 연결되면, 서버가 바로 유저 B에게 메시지를 push할 수 있어요.
→ 카카오톡, 인스타 DM, 게임 알림 등 실시간 서비스에 WebSocket이 꼭 쓰이는 이유!
🔁 다시 구조를 보면
[유저 A] --(WebSocket)--> [Spring 서버] --(KafkaProducer)--> [Kafka]
[Kafka] --(KafkaConsumer)--> [Spring 서버] --(WebSocket)--> [유저 B]
흐름을 설명하면:
- 유저 A가 채팅 메시지를 WebSocket으로 Spring 서버에 보냄
- 서버는 Redis Pub/Sub으로 실시간 중계하거나, Kafka에 저장
- 유저 B가 같은 방에 접속 중이면 WebSocket 세션을 통해 실시간 전달
- 접속 안 돼 있다면, Kafka에 저장된 메시지를 나중에 꺼내서 보여줄 수 있음
📦 정리하자면
구성 요소 | 역할 |
WebSocket | 유저 ↔ 서버 간 실시간 메시지 송수신 |
Redis Pub/Sub | 서버 ↔ 서버 간 실시간 메시지 중계 (빠르게!) |
Kafka | 메시지 로그 저장, 장애 시 재처리, 추천/검색용 데이터 적재 |
🔥 혼합 구조 요약도
[유저 A] ⇄ (WebSocket) ⇄ [Spring 서버 A]
│
┌────────────────┴──────────────┐
↓ ↓
[Redis Pub/Sub] [Kafka - 적재용 로그]
↑ ↑
[Spring 서버 B] ⇄ (WebSocket) ⇄ [유저 B]
💡 실전에서 이런 식으로도 씀
- Redis Pub/Sub → 서버 간 broadcast 용
- Kafka → 메시지 영속화 및 이탈 유저 처리용
- WebSocket → 유저와 서버 간 실시간 인터페이스
2) Redis Cache에 데이터를 저장할 때 사용한 자료구조는 무엇이고, 왜 그것을 선택했을까?
-> 이건 이렇게 작업했다가 나중에 구조를 바꾸긴 했는데... 그냥 ZSet 부연 설명
항목 | 내용 |
사용 자료구조 | ZSet (Sorted Set, 정렬된 집합) |
ZSet 특징 | - 각 원소가 score(숫자)와 함께 저장됨 - 자동 정렬 지원 (reverseRangeWithScores로 역순 top-N 조회 가능) - incrementScore(key, value, score) 메서드로 조회 수 증가 가능 |
사용 이유 | - 인기 검색어 순위(=점수 기반 정렬) 구현에 최적 - Hash나 List보다 정렬성과 빠른 검색에 특화되어 있음 - Redis가 내부적으로 skip list를 사용해 효율적 정렬 가능 |
예시 상황 | 사용자가 “자바” 검색 → ZSet의 “자바” score 1 증가 → reverseRangeWithScores로 top 10 검색어 추출 |
➡️ 결론: 인기 검색어처럼 순위가 중요한 기능에는 ZSet이 가장 적합하기 때문에 선택.
📚 가로 학습 POINT
RDBMS(SQL) vs NoSQL(Redis)의 차이점은?
구분 | RDBMS (SQL 기반) | NoSQL (Redis 등) |
데이터 모델 | 테이블 기반 (행/열 구조, 스키마 고정) | Key-Value, 문서, 컬럼, 그래프 등 다양 |
스키마 | 엄격함. 변경 시 마이그레이션 필요 | 유연함. 구조 없이 자유롭게 저장 가능 |
트랜잭션 | ACID 보장. 강력한 일관성 유지 | BASE 지향. 가용성/확장성 중시 |
확장성 | 수직 확장 중심 (서버 업그레이드) | 수평 확장 중심 (서버 추가) |
속도 | 디스크 기반. 복잡한 연산에 강함 | 메모리 기반. 매우 빠른 읽기/쓰기 가능 |
적합한 상황 | 관계형 데이터, 복잡한 JOIN, 트랜잭션 중심 앱 | 실시간 캐싱, 세션 저장, 순위 집계 등 |
➡️ 결론: 정형 데이터 + 복잡한 쿼리 → RDBMS / 빠른 응답 + 유연한 구조 → NoSQL(Redis)