Redis의 새로운 Array 데이터 타입을 네 달에 걸쳐 설계하고 구현하며, AI를 활용해 명세 작성, 복잡한 자료구조 설계, 테스트, 정규식 검색 기능까지 발전시킨 과정을 돌아본다.
antirez 13시간 전. 조회수 66697. 나는 1월 초에 Redis의 새로운 Array 데이터 타입 작업을 시작했다. PR은 이제서야 저장소에 반영되었으니, 이 코드는 네 달 동안 다듬어진 셈이다. 구현 작업은 일종의 파트타임으로 진행했다. 그렇다고는 해도 실제로는 많은 주를 풀타임으로 보냈고, 때로는 키보드에서 떨어지는 것 자체가 쉽지 않았다. 그리고 LLM 이전 시대였다면 이 구현은 아마 내가 네 달 안에 해낼 수 있는 일 자체였을 것이다. 달라진 점은, 같은 시간 동안 훨씬 더 많은 일을 할 수 있었다는 것이다. 이것은 그 과정에서 무슨 일이 있었는지에 대한 짧은 이야기다.
첫 달에는 명세 문서만 작성했다. 새로운 데이터 타입의 근거, C 구조체, 사용된 희소 표현, 링 버퍼와 ARINSERT를 위한 배열 커서의 정확한 의미론까지 포함해서 말이다. 나는 며칠 동안 손수 긴 명세를 쓰기 시작했고, 처음에는 Opus와 함께 작업했다. 그러다가 GPT 5.3이 출시되었고, 이후 설계와 개발 전부를 Codex와 함께 진행하는 쪽으로 바꾸었다. 그때부터 시스템 프로그래밍 작업에는 GPT 5.x만 사용하고 있다. AI 덕분에 명세는 피드백을 주고받고, 무엇이 최선의 설계인지, 어떤 절충이 옳은지, 무엇이 과도한 설계이고 무엇은 아닌지에 대한 지적 도전을 거치며 크게 발전했다.
두 번째 달부터는 자동 프로그래밍을 사용해 구현을 시작했다. 원한다면 자동 코딩이라고 불러도 된다. 그러면서도 만들어진 코드를 끊임없이 검토했다. 그러다 내가 선택한 간접 계층 수준이 잘못되었다는 사실을 깨달았다. 나는 정말로 사람들이 ARSET myarray 293842948324 foo 같은 명령을 실행해도 거대한 할당 없이 모든 것이 계속 잘 동작할 수 있기를 바랐다. 내가 갖고 있던 두 단계 디렉터리 + 슬라이스 구조만으로는 충분하지 않았다. AI가 있었기 때문에 나는 타협하지 않았고, 한 걸음 더 나아가기로 했다. 특정 조건에 도달하면 자료구조는 내부적으로 형태를 바꾸어, 슬라이스된 조밀 디렉터리들의 슈퍼 디렉터리가 되고, 이 디렉터리들은 실제 배열 슬라이스도 가리키게 된다. 기본적으로 슬라이스당 4096개 요소다. 이 설계는 내가 원했던 내부적인 "실제로 배열인" 표현을 유지하면서도, 내가 원하던 메모리 특성을 제공했고, 동시에 ARSCAN과 ARPOP의 경우 존재하는 배열을 범위 전체에 비례하는 시간이 아니라 실제 존재하는 요소 수에 비례하는 시간으로 스캔할 수 있게 해주었다.
그다음에는 모든 코드를 한 줄씩 읽을 차례였다. 모든 것이 작동하고 있었고, 이 타입은 다시 한 번 AI 덕분에 방대한 테스트를 갖추고 있었다. 하지만 겉보기로 잘 동작한다고 해서 그것이 최적이라는 뜻은 아니다. 나는 원하지 않는 작은 비효율이나 설계 오류를 많이 발견했고, 그래서 많은 모듈을 수작업과 AI 보조를 섞어 다시 쓰는 과정을 시작했다. 이 단계가 끝났을 때, 세 번째 달 동안에는 구현을 여러 다른 방식으로 스트레스 테스트하기 시작했다. 그제야 이것이 정말로 견고하고, 유용하며, 잘 설계되었다는 확신이 들기 시작했다.
그러다… 일이 벌어졌다. 자료구조가 사용하기 편한지 보기 위해 여러 사용 사례를 모델링하던 중, 나는 마크다운 파일을 Redis 배열에 넣기 시작했다. 파일은 이것과 아주 잘 맞아떨어지기 때문이다. 이 시점에서, 에이전트로 다른 목표를 위해 작업하던 중이었는데, 내가 필요로 하던 skills 마크다운 파일 기반의 중앙집중식 지식 베이스를 만들 수 있겠다는 사실을 깨달았다. 그래서 내 필요에서 출발해 ARGREP를 구현하기로 결정했다. 하지만 정규식도 원했다. 어떤 라이브러리를 골라야 할까?
결국 TRE를 선택했다. 고맙다 Ville Laurikari! Redis에 정규식을 넣는다면, 시간이나 공간 면에서 병목을 일으키는 병리적인 패턴이 없어야 한다는 점을 확신하고 싶기 때문이다. 하지만 TRE는 구체적이면서도 극히 유용한 한 가지 경우, 즉 foo|bar|zap 같은 패턴 매칭에서 매우 비효율적이었다. 그래서 GPT의 도움을 받아 이를 최적화했고, 몇 가지 잠재적인 보안 문제도 수정했으며, 테스트도 확장했다. 필요한 것은 모두 갖추게 되었다.
이 모든 과정에서 가장 큰 깨달음이 무엇이었는지 아는가? 고품질 시스템 프로그래밍 작업에서는 여전히 완전히 깊이 관여해야 한다는 점이다. 하지만 나는 그렇지 않았다면 건너뛰었을 복잡성의 수준까지 나아갈 수 있었다. AI는 두 가지 면에서 안전망을 제공했다. 하나는 나중에 추가되고 테스트된 32비트 지원 같은, 매우 피곤한 대규모 작업들이다. 다른 하나는 복잡한 알고리즘에 명백한 버그가 없음을 확인하는 데 필요한 가상 노동력을 제공한다는 점이다. 처음의 거대한 명세를 작성한 것이 이후 작업의 핵심이었다. sparsearray.c와 t_array.c의 모든 줄을 검토하는 일 역시 핵심이었고, 모든 것을 수정하는 작업은 결코 잘 맞는 일은 아니었다.
사용 사례에 대해서는 여기서 굳이 길게 말하지 않았다. 그것들은 내가 PR 자체를 설명하면서 자세히 적어둔 메시지에 담겨 있기 때문이다.
https://github.com/redis/redis/pull/15162
그래서 여기서 같은 말을 반복하는 것은 별로 유용하지 않았다. 다만, 수치 인덱스가 의미론의 일부인 데이터 타입을 Redis가 가질 때가 정말 되었다고 나는 믿는다고 말하면 충분하다.
Array PR이 곧 받아들여지고, 그것이 열어줄 새로운 사용 사례의 혜택을 우리가 누릴 수 있기를 바란다. 물론 피드백도 환영한다. 고맙다.