In-Memory DB 구현 8편 - TTL과 만료 전략, 최소힙으로 데이터 수명 관리하기

들어가며 지금까지 구현한 데이터베이스에서 저장된 모든 데이터는 명시적으로 삭제하지 않는 한 영구적으로 존재한다. 하지만 세션 토큰, 캐시 데이터, 인증 코드 같은 것들은 일정 시간이 지나면 자동으로 사라져야 한다. 이번 포스팅에서는 키에 만료 시간(TTL)을 설정하고 만료된 키를 자동으로 삭제하는 두 가지 전략을 구현한다. 그 과정에서 최소 힙 자료구조를 직접 구현하고 백그라운드 고루틴의 라이프사이클도 관리해보는 과정을 다뤄보겠다. TTL TTL(Time To Live)은 데이터가 유효한 시간을 의미한다. 네트워크 패킷에서는 홉 수를 제한하고 DNS 캐시에서는 레코드의 유효 기간을 정하고, CDN에서는 캐시 갱신 주기를 결정한다. 컴퓨터 시스템 전반에서 “이 데이터가 얼마나 오래 살아야 하는가"를 제어하는 수단으로 널리 쓰인다. ...

2026년 2월 19일 PM08:28 · PolarBear

In-Memory DB 구현 7편 - 이중 연결 리스트로 List 명령어 구현하기

들어가며 이번 포스팅에서는 이중 연결 리스트를 직접 구현하고, 저장소를 다중 타입으로 확장하여 LPUSH, RPUSH, LPOP, RPOP, LRANGE 명령어를 추가한다. 배열과 연결 리스트의 근본적인 차이부터 시작해서 왜 이중 연결 리스트가 이 상황에 적합한지, 그리고 포인터로 노드 간 연결을 어떻게 구현하는지를 다룬다. 배열과 연결 리스트 데이터를 순차적으로 저장하는 가장 기본적인 두 자료구조가 배열과 연결 리스트이다. 이 둘의 핵심 차이는 메모리 배치에 있다. 배열은 연속된 메모리 공간에 요소를 나란히 저장한다. 컴파일러가 시작 주소 + (인덱스 × 요소 크기)로 바로 계산할 수 있기 때문에 인덱스 접근이 O(1)이다. 하지만 앞쪽에 요소를 삽입하거나 삭제하면 나머지 요소를 전부 한 칸씩 밀거나 당겨야 하므로 O(n)이 된다. go의 슬라이스([]string)가 내부적으로 배열 기반이다. ...

2026년 2월 11일 PM07:50 · PolarBear

In-Memory DB 구현 4편 - 저장소 구현 (해시 테이블/해시충돌/리팩터/리해싱)

들어가며 이전 포스팅에서 RESP 프로토콜을 구현해 클라이언트와 서버가 구조화된 형식으로 통신할 수 있게 되었다. 이번 포스팅에서는 Key-Value 저장소를 구현하고 SET/GET 명령어를 추가해보자. go의 map을 감싸는 단순한 구조체를 만드는 것이 전부지만, 그 뒤에 숨어있는 해시 테이블의 원리를 깊이 있게 다뤄보려 한다. 해시 함수가 갖춰야 할 조건, 충돌을 해결하는 전략, 로드 팩터와 리해싱까지 살펴보면 map[string]string 한 줄이 왜 O(1)인지 납득할 수 있을 것이다. Key-Value 저장 모델 가장 단순한 데이터 모델 Key-Value 모델은 데이터를 저장하는 가장 단순한 방식이다. key로 값을 저장하고 같은 키로 값을 조회한다. ...

2026년 2월 4일 PM04:58 · PolarBear