Redis array type: short story of a long development

Salvatore Sanfilippo

Redis 배열 타입: 긴 개발의 짧은 이야기

1월 초부터 Redis의 새로운 Array 자료형 작업을 시작했다. PR이 저장소에 반영된 건 이제야 이뤄졌으니, 이 코드는 4개월 동안 숙성된 셈이다. 구현은 어떻게 보면 파트타임으로 진행했는데(어떻게 보면이라고 한 건, 여러 주는 사실상 풀타임으로 일했기 때문이다. 가끔은 키보드에서 손을 떼는 게 어렵다), LLM이 없던 시절에도 4개월이면 구현 자체는 충분히 할 수 있었을 것이다. 달라진 점이 있다면 같은 기간 동안 훨씬 더 많은 일을 해낼 수 있었다는 것이다. 이것이 그간 있었던 일에 대한 짧은 이야기다.

첫 달에는 명세 문서를 작성하는 데만 집중했다. 새로운 자료형의 도입 취지, C 구조체, 사용된 희소(sparse) 표현, 링 버퍼와 ARINSERT를 위한 배열 커서의 정확한 의미론까지. 며칠 동안 긴 명세를 손으로 직접 쓰기 시작했고, 이후에는 Opus와 페어 프로그래밍을 하다가 GPT 5.3이 출시된 뒤로는 설계와 개발 전 과정을 Codex로 옮겼다. 그 이후로는 시스템 프로그래밍 작업에 GPT 5.x만 사용하고 있다. AI 덕분에 명세는 많은 피드백의 왕래와, 무엇이 최선의 설계인지, 어떤 타협이 옳은지, 무엇이 과한 엔지니어링이고 무엇이 아닌지에 대한 지적인 도전을 거치며 크게 발전했다.

두 번째 달부터는 자동 프로그래밍(자동 코딩이라고 해도 좋다)을 이용해 구현을 시작했고, 생성된 코드를 끊임없이 검토했다. 그러다 내가 선택한 간접화 단계가 잘못됐음을 깨달았다. ARSET myarray 293842948324 foo 같은 명령을 실행해도 거대한 메모리 할당 없이 모든 것이 그대로 동작하기를 정말 원했기 때문이다. 내가 갖고 있던 디렉터리와 슬라이스(희소 및 밀집)라는 2단계 구조로는 충분하지 않았다. AI가 있었기에 타협하지 않고 한 걸음 더 나아가기로 했다. 특정 조건에 도달하면 자료구조가 내부적으로 형태를 바꾸어, 실제 배열 슬라이스(기본값은 슬라이스당 4096개 요소)를 가리키는 잘게 쪼개진 밀집 디렉터리들의 슈퍼 디렉터리가 된다. 이 설계 덕분에 내가 원했던 내부적인 “실은 배열이다”라는 표현과 원하는 메모리 특성을 유지하면서도, ARSCAN이나 ARPOP 같은 명령에서 범위 전체가 아니라 존재하는 요소 수에 비례하는 시간으로 배열을 스캔할 수 있게 됐다.

그다음은 모든 코드를 한 줄 한 줄 읽어볼 차례였다. 모든 것이 동작하고 있었고, 역시 AI 덕분에 이 타입은 방대한 테스트를 갖추고 있었지만, 겉보기에 동작한다고 해서 최적이라는 뜻은 아니다. 원치 않던 사소한 비효율이나 설계 오류를 많이 발견했고, 그래서 여러 모듈을 직접 손으로 그리고 AI의 도움을 받아 다시 쓰는 과정을 시작했다. 이 단계가 끝나자 세 번째 달에는 다양한 방식으로 구현을 스트레스 테스트하기 시작했다. 이제는 정말 견고하고 유용하며 잘 설계되었다는 확신이 들기 시작했다.

그러다… 일이 벌어졌다. 자료구조가 쓰기 편한지 확인하려고 다양한 사용 사례를 모델링하던 중, 마크다운 파일들을 Redis 배열에 넣기 시작했다. 파일이야말로 이 자료구조와 아주 잘 어울리기 때문이다. 이때 다른 목표를 위해 에이전트들과 작업하고 있던 중에, 내가 필요로 하던 스킬 마크다운 파일들의 중앙 집중식 지식 베이스를 만들 수 있겠다는 생각이 들었고, 그래서 나의 필요에서 출발해 ARGREP을 구현하기로 했다. 하지만 정규표현식도 필요했다. 어떤 라이브러리를 고를까?

결국 TRE를 선택했다(Ville Laurikari에게 감사 인사를 전한다!). Redis에서 정규표현식을 쓴다면 시간이나 공간 면에서 병목이 되는 패턴이 없다는 확신이 필요하기 때문이다. 하지만 TRE는 foo|bar|zap 같은 매칭처럼 매우 유용한 특정 사례에서 몹시 비효율적이었다. 그래서 GPT의 도움으로 이를 최적화하고, 몇 가지 잠재적인 보안 문제를 수정했으며, 테스트도 확장했다. 이제 모든 준비가 갖춰졌다.

이 모든 과정에서 가장 크게 깨달은 점이 무엇인지 아는가? 고품질의 시스템 프로그래밍 작업을 하려면 여전히 온전히 몰입해야 하지만, 나는 AI 덕분에 그렇지 않았다면 건너뛰었을 복잡도 수준까지 나아갔다는 것이다. AI는 두 가지에 대한 안전망이 되어 주었다. 하나는 몹시 지치는 방대한 작업(나중에 추가되어 테스트된 32비트 지원 같은)과, 동시에 복잡한 알고리즘에 명백한 버그가 없는지 확인하는 데 필요한 가상의 인력이다. 초기에 그 방대한 명세를 작성한 것이 이후 작업의 핵심이었고, sparsearray.c와 t_array.c의 모든 줄을 하나하나 검토하며 맞지 않는 부분은 전부 고친 것 역시 핵심이었다.

사용 사례에 대해서는 따로 언급하지 않겠다. PR 자체에 메시지로 자세히 문서화해 두었기 때문이다:

https://github.com/redis/redis/pull/15162

그래서 여기서 같은 내용을 반복할 필요는 없을 것 같다. Redis에도 숫자 인덱스가 의미 체계의 일부가 되는 자료형이 생길 때가 되었다고 진심으로 믿는다는 말로 충분할 것 같다.

Array PR이 곧 받아들여져, 그것이 열어줄 새로운 사용 사례들의 혜택을 함께 누릴 수 있기를 바란다. 물론 피드백은 언제나 환영한다. 감사하다.

원문은 Salvatore Sanfilippo님이 에 게재했습니다.

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.