Redis 주니어 CS 기초 기술면접
새 면접Q. Redis는 기본적으로 6379 포트를 사용합니다. 포트(Port)가 무엇인지 설명하고, 하나의 서버에서 여러 애플리케이션이 동시에 네트워크 통신을 할 수 있는 이유를 포트의 역할과 연관지어 설명해주세요.
포트는 네트워크 통신에서 프로세스를 구분하는 논리적인 번호입니다.
포트는 네트워크 통신에서 특정 프로세스나 서비스를 식별하기 위한 16비트 숫자(0~65535)입니다. IP 주소가 건물의 주소라면 포트는 건물 내 특정 방 번호에 해당합니다. 하나의 서버(IP 주소)에서 웹 서버는 80번, Redis는 6379번, MySQL은 3306번처럼 서로 다른 포트를 사용하여 여러 서비스가 동시에 통신할 수 있습니다. 운영체제의 TCP/IP 스택은 들어오는 패킷의 목적지 포트 번호를 확인하여 해당 포트를 리스닝하는 프로세스에게 데이터를 전달합니다. 이를 통해 포트 번호 기반의 멀티플렉싱이 가능해집니다.
- • 포트는 프로세스 식별을 위한 16비트 숫자
- • IP 주소와 포트 조합으로 특정 서비스 구분
- • 운영체제가 포트 번호로 패킷을 적절한 프로세스에 전달
마이크로서비스 아키텍처에서 하나의 서버에 여러 서비스를 배포할 때 포트 번호로 각 서비스를 구분합니다.
Well-Known 포트와 Ephemeral 포트의 차이는 무엇이며, Redis 클라이언트가 서버에 연결할 때 어떤 포트를 사용하나요?
Q. Redis의 Sorted Set은 내부적으로 Skip List를 사용합니다. Skip List의 기본 구조와 탐색 과정을 설명하고, 일반 Linked List와 비교했을 때 탐색 시간 복잡도가 어떻게 개선되는지 설명해주세요.
Skip List는 여러 레벨의 링크를 유지하여 탐색 시 일부 노드를 건너뛸 수 있는 구조입니다.
Skip List는 정렬된 링크드 리스트에 여러 레벨의 인덱스 레이어를 추가한 확률적 자료구조입니다. 최하위 레벨은 모든 노드를 포함하고, 상위 레벨로 갈수록 일부 노드만 포함하여 빠른 점프가 가능합니다. 탐색 시 최상위 레벨에서 시작해 목표값보다 큰 노드를 만나면 한 레벨 아래로 내려가는 방식으로 진행됩니다. 일반 Linked List의 탐색은 O(n)이지만, Skip List는 평균 O(log n)의 시간 복잡도를 가집니다. 이는 이진 탐색 트리와 유사한 성능을 보이면서도 구현이 더 간단하고 동시성 제어가 용이한 장점이 있습니다.
- • 여러 레벨의 인덱스 레이어로 구성된 확률적 자료구조
- • 상위 레벨에서 빠르게 점프하며 탐색
- • 평균 O(log n) 탐색 시간 복잡도 달성
- • 구현이 간단하고 동시성 제어 용이
대규모 게임 리더보드에서 수백만 명의 점수를 정렬하고 특정 사용자의 순위를 빠르게 조회할 때 사용됩니다.
Skip List에서 새로운 노드를 삽입할 때 어떤 레벨까지 인덱스를 만들지 어떻게 결정하나요?
Q. Redis는 싱글 스레드로 동작하지만 I/O Multiplexing을 사용하여 여러 클라이언트의 요청을 동시에 처리합니다. I/O Multiplexing이 무엇인지 설명하고, select, poll, epoll의 차이점과 Redis가 epoll을 선호하는 이유를 설명해주세요.
I/O Multiplexing은 하나의 스레드가 여러 소켓의 I/O 이벤트를 동시에 모니터링하는 기법입니다.
I/O Multiplexing은 하나의 프로세스나 스레드가 여러 파일 디스크립터(소켓)를 동시에 모니터링하여 읽기/쓰기 가능한 이벤트가 발생하면 처리하는 기법입니다. select는 최대 1024개의 파일 디스크립터를 모니터링할 수 있지만 매번 전체 집합을 커널에 복사해야 하고 선형 탐색으로 준비된 소켓을 찾아 O(n) 시간이 걸립니다. poll은 파일 디스크립터 개수 제한은 없지만 여전히 O(n) 탐색이 필요합니다. epoll은 커널이 준비된 소켓만 반환하여 O(1)에 가까운 성능을 보이며, 파일 디스크립터를 매번 복사하지 않아 대규모 연결 처리에 효율적입니다. Redis는 수만 개의 동시 연결을 처리해야 하므로 epoll을 사용하여 높은 성능을 달성합니다.
- • I/O Multiplexing으로 하나의 스레드가 여러 소켓 모니터링
- • select는 1024개 제한과 O(n) 탐색
- • epoll은 준비된 소켓만 반환하여 O(1) 성능
- • 대규모 동시 연결 처리에 epoll이 효율적
Node.js, Nginx 같은 고성능 서버도 이벤트 루프와 I/O Multiplexing을 사용하여 많은 동시 연결을 처리합니다.
Redis가 멀티 스레드 대신 싱글 스레드 + I/O Multiplexing 구조를 선택한 이유는 무엇인가요?
Q. Redis의 ZADD 명령어로 Sorted Set에 요소를 추가할 때 평균 시간 복잡도는 O(log n)입니다. 이 시간 복잡도가 나오는 이유를 내부 자료구조와 연관지어 설명하고, n이 100만일 때와 10만일 때 연산 횟수가 대략 몇 배 차이나는지 계산해주세요.
Sorted Set은 Skip List를 사용하며, log 함수의 특성을 생각해보세요.
Redis Sorted Set은 내부적으로 Skip List를 사용하여 정렬된 상태를 유지합니다. Skip List에서 삽입 위치를 찾는 과정은 이진 탐색 트리와 유사하게 레벨별로 탐색하므로 O(log n) 시간이 걸립니다. log2(1,000,000)은 약 20이고 log2(100,000)은 약 17이므로, n이 10배 증가해도 연산 횟수는 약 1.2배(20/17)만 증가합니다. 이는 로그 함수의 특성으로, 데이터가 기하급수적으로 증가해도 연산 시간은 선형적으로만 증가하여 대규모 데이터 처리에 효율적입니다. 만약 O(n) 알고리즘이었다면 10배의 시간이 걸렸을 것입니다.
- • Skip List의 레벨별 탐색으로 O(log n) 달성
- • log2(1,000,000) ≈ 20, log2(100,000) ≈ 17
- • 데이터 10배 증가 시 연산은 약 1.2배만 증가
- • 로그 시간 복잡도는 대규모 데이터에 효율적
실시간 순위표에서 100만 명의 사용자 중 새로운 점수를 빠르게 삽입하고 순위를 업데이트할 때 사용됩니다.
ZRANGE 명령어로 특정 범위의 요소를 조회할 때 시간 복잡도는 어떻게 되나요?
Q. 데이터베이스에서 ACID 속성이 무엇인지 각 항목을 설명하고, Redis의 MULTI/EXEC 트랜잭션이 전통적인 RDBMS의 트랜잭션과 비교했을 때 어떤 ACID 속성을 보장하지 못하는지 설명해주세요.
ACID는 Atomicity, Consistency, Isolation, Durability의 약자입니다.
ACID는 데이터베이스 트랜잭션의 안정성을 보장하는 네 가지 속성입니다. Atomicity(원자성)는 트랜잭션의 모든 연산이 완전히 실행되거나 전혀 실행되지 않음을 보장합니다. Consistency(일관성)는 트랜잭션 실행 후 데이터베이스가 일관된 상태를 유지함을 의미합니다. Isolation(격리성)은 동시 실행되는 트랜잭션들이 서로 영향을 주지 않음을 보장합니다. Durability(지속성)는 커밋된 트랜잭션의 결과가 영구적으로 저장됨을 의미합니다. Redis의 MULTI/EXEC는 Atomicity는 보장하지만, 중간에 조건부 롤백(Rollback)이 불가능하고, WATCH를 사용하지 않으면 다른 클라이언트의 변경을 감지하지 못해 완전한 Isolation을 제공하지 않습니다.
- • Atomicity: 모두 실행 또는 모두 취소
- • Consistency: 일관된 상태 유지
- • Isolation: 트랜잭션 간 독립성
- • Redis MULTI/EXEC는 완전한 Isolation과 조건부 Rollback 미지원
금융 시스템에서 계좌 이체 시 출금과 입금이 모두 성공하거나 모두 실패해야 하는 원자성이 중요합니다.
Redis에서 조건에 따라 트랜잭션을 중단해야 할 때 어떤 방법을 사용할 수 있나요?
Q. Redis 클라이언트와 서버 간 통신에서 RTT(Round Trip Time)가 무엇인지 설명하고, 지리적으로 멀리 떨어진 Redis 서버에 100개의 개별 명령을 순차적으로 실행할 때 RTT가 성능에 미치는 영향과 이를 개선할 수 있는 방법을 설명해주세요.
RTT는 요청을 보내고 응답을 받기까지의 왕복 시간이며, 파이프라인 기법을 고려해보세요.
RTT(Round Trip Time)는 클라이언트가 서버로 요청을 보내고 응답을 받기까지의 왕복 시간입니다. 네트워크 지연, 물리적 거리, 라우팅 경로 등에 영향을 받습니다. 서울-미국 간 RTT가 약 150ms라고 가정하면, 100개의 명령을 순차적으로 실행 시 최소 15초(150ms × 100)가 소요됩니다. 각 명령마다 네트워크 왕복이 발생하기 때문입니다. 이를 개선하기 위해 Redis Pipeline을 사용하면 여러 명령을 한 번에 전송하고 응답도 일괄 수신하여 RTT를 1회로 줄일 수 있습니다. 또는 MGET, MSET 같은 배치 명령어를 사용하거나, 지리적으로 가까운 Redis 인스턴스를 배치하는 방법도 있습니다.
- • RTT는 요청-응답 왕복 시간
- • 순차 실행 시 RTT × 명령 개수만큼 지연 발생
- • Pipeline으로 여러 명령을 묶어 RTT 횟수 감소
- • 배치 명령어 사용이나 지리적 근접 배치도 효과적
마이크로서비스 환경에서 API 서버와 Redis가 다른 리전에 있을 때 RTT로 인한 지연이 전체 응답 시간에 큰 영향을 미칩니다.
Redis Pipeline 사용 시 주의해야 할 점은 무엇이며, 너무 많은 명령을 한 번에 보내면 어떤 문제가 발생할 수 있나요?
Q. 해시 테이블(Hash Table)에서 해시 충돌(Hash Collision)이 발생하는 이유와 이를 해결하는 두 가지 방법인 Chaining과 Open Addressing의 차이점을 설명해주세요. 그리고 Redis의 Hash 자료구조가 내부적으로 어떤 방식을 사용하는지 설명해주세요.
해시 충돌은 서로 다른 키가 같은 해시값을 가질 때 발생하며, Redis는 상황에 따라 다른 구조를 사용합니다.
해시 충돌은 서로 다른 키가 해시 함수를 통해 같은 인덱스로 매핑될 때 발생합니다. 해시 함수의 출력 범위가 입력 범위보다 작기 때문에 비둘기집 원리에 의해 필연적으로 발생합니다. Chaining 방식은 같은 인덱스에 매핑된 요소들을 링크드 리스트로 연결하여 저장하며, 추가 메모리가 필요하지만 삭제가 용이합니다. Open Addressing은 충돌 시 다른 빈 슬롯을 탐색(Linear Probing, Quadratic Probing 등)하여 저장하며, 메모리 효율적이지만 클러스터링 문제가 발생할 수 있습니다. Redis의 Hash는 요소가 적을 때는 ziplist를 사용하고, 일정 크기를 넘으면 Chaining 방식의 해시 테이블로 전환하여 메모리와 성능을 최적화합니다.
- • 해시 충돌은 같은 해시값으로 매핑될 때 발생
- • Chaining은 링크드 리스트로 연결, 삭제 용이
- • Open Addressing은 다른 슬롯 탐색, 메모리 효율적
- • Redis는 ziplist와 hashtable(Chaining)을 상황에 따라 사용
대용량 캐시 시스템에서 수백만 개의 키-값을 빠르게 조회하기 위해 해시 테이블의 충돌 처리가 중요합니다.
해시 테이블의 Load Factor가 무엇이며, Load Factor가 높아지면 성능에 어떤 영향을 미치나요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!