YouTubeVasilios Syrakis·2026년 9월 19일·0

Writing Redis in Rust

Quick Summary

Rust로 Redis를 직접 구현하며 인자 벡터 재사용은 테스트 통과까지 확인했지만, XADD 스트림 ID의 파싱·자동 생성·순서 검증은 후속 과제로 남았다.

영상 보기

클릭 전까지는 가벼운 미리보기만 먼저 불러옵니다.

원본 열기

🖼️ 인포그래픽

Writing Redis in Rust 내용을 설명하는 본문 이미지

🖼️ 4컷 인포그래픽

Writing Redis in Rust의 핵심 내용을 4단계로 요약한 인포그래픽
Writing Redis in Rust 핵심 내용을 4단계로 압축한 4컷 인포그래픽

💡 한 줄 결론

Rust로 Redis를 직접 구현하며 인자 벡터 재사용은 테스트 통과까지 확인했지만, XADD 스트림 ID의 파싱·자동 생성·순서 검증은 후속 과제로 남았다.

📌 핵심 요점

  1. 제로 카피와 무할당은 다르다. 문자열 페이로드를 복사하지 않아도 연결별 BytesMut 버퍼와 명령 처리용 벡터는 할당을 일으킨다. 유휴 연결 10,000개에서 버퍼가 약 80MB를 차지한다는 수치는 분석에 제시된 예시다.
  2. 우선 개선한 대상은 명령마다 생성하고 버리던 인자 범위 벡터다. 이를 코덱 필드로 옮겨 clear()하며 재사용하고, 생성자·참조 순회·역참조·가변성 관련 코드를 수정했다. 해당 변경은 컴파일과 테스트를 통과했으나 할당 감소량이나 처리 성능은 측정되지 않았다.
  3. XADD의 새 ID는 기존 ID와 중복되지 않는 것만으로 부족하다. 마지막 ID보다 엄격히 커야 하고 0-0도 허용되지 않아, 모든 엔트리를 순회하는 중복 검사만으로는 요구사항을 충족하지 못했다.
  4. ID를 밀리초와 시퀀스라는 두 정수로 저장하고 순서대로 비교하는 설계를 채택했다. 요청은 Auto, AutoSequence, Explicit으로 구분하는 방향이며, 원본 분석에서는 시간이 증가하지 않을 때 기존 밀리초를 유지하고 시퀀스를 높이는 자동 생성 규칙을 확인했다.
  5. 바이트 입력의 분리와 숫자 변환에서 타입 문제가 이어졌다. 하이픈 위치를 이용한 슬라이스 분리 코드는 컴파일됐지만, 전체 입력이 *인 경우를 분할 전에 처리해야 한다는 문제가 남아 최종 구현은 마무리하지 못했다.

🧩 배경과 문제 정의

  • Rust로 Redis를 구현하면서 TCP 스트림에서 명령 인자를 읽는 방식과 메모리 할당 비용을 점검한다. 비교 대상은 C Redis의 버퍼·인자 배열 재사용 구조다.
  • Gemini의 코드 분석은 Rust 구현이 문자열 데이터를 복사하지 않더라도 연결별 읽기 버퍼와 명령별 벡터 때문에 여러 힙 할당을 일으킨다고 지적한다. 이 비교는 분석 결과를 바탕으로 하며, 성능 측정 결과는 제시되지 않는다.
  • 우선 수정 대상은 명령마다 만들고 버리는 인자 범위 벡터다. 이를 코덱 내부에 보관하고 재사용하도록 바꾸면서 Rust의 소유권·참조·가변성 문제를 해결한다.

🕒 시간순 섹션별 상세정리

1. TCP 입력 처리와 Redis의 버퍼 재사용 구조

  • Gemini의 코드 탐색 결과에 따르면 이벤트 루프 알림이 네트워킹 읽기 핸들러를 호출하고, 핸들러는 메인 스레드 또는 지정된 I/O 스레드에서 클라이언트 입력을 읽는다 [01:14]
  • TCP 입력 바이트를 버퍼에 넣는 세부 동작에는 확신이 없지만, 분석에서 확인한 읽기 버퍼 크기는 16KB이며 스레드 로컬 버퍼를 재사용하는 구조다 [02:06]

2. 방송 장애 이후 전송 프로토콜 복구

  • 채팅 연동에는 방송을 시작할 때마다 새 영상 ID를 가져와 설정하는 작업이 필요했고, 이번에도 해당 설정을 수정한다 [04:10]
  • 화면이 깨진 문제는 RTMP에서 SRT로 전환한 뒤 발생했다. SRT 설정에 추가 디버깅이 필요할 가능성을 남겨 두고, 오래 사용되어 검증됐다고 판단한 RTMP로 되돌린다 [04:40]

3. 연결별 읽기 버퍼가 만드는 유휴 메모리 비용

  • Gemini 분석은 Rust 구현의 연결별 BytesMut 버퍼가 힙 할당을 일으키며, 용량이 부족하면 재할당도 발생한다고 지적한다. 페이로드 복사를 피하는 것만으로 전체 할당이 없어지지는 않는다 [05:43]
  • 연결마다 생성되는 태스크의 서버 객체가 전용 읽기 버퍼를 가진다. 분석에 제시된 예시는 유휴 연결 10,000개에서 버퍼만으로 약 80MB를 차지하는 경우다 [06:20]

4. 명령 처리 과정에 겹쳐 있는 벡터 할당

  • 디코더는 명령마다 벡터를 할당하고, BytesMut 분할은 참조 카운트 기반 공유 표현으로 전환되면서 추가 할당을 일으킬 가능성이 있다 [07:01]
  • 인자 범위를 mapcollect로 변환하는 과정에서 Bytes 벡터가 하나 더 만들어진다 [07:27]

5. 페이로드 복사 절감과 컨테이너 할당의 차이

  • 비교표상 유휴 연결 버퍼는 C Redis가 0바이트, 현재 Rust 구현이 8KB다. 명령 인자 컨테이너 역시 기존 배열 재사용과 명령별 새 벡터 할당이라는 차이가 있다 [09:17]
  • Rust 구현은 참조 카운트로 원본 바이트 메모리를 공유해, 읽기 버퍼의 문자열 페이로드를 새 문자열로 복사하는 비용을 피한다 [09:49]

6. 업무에서의 AI 사용과 버퍼 풀 제안

  • 현재 직장에서는 회사가 AI 도구 구독을 제공하고 AI 보조 작업을 기대하기 때문에 거의 모든 업무에 AI 도구를 사용한다. 다만 이를 최선의 작업 방식이라고 확신하지는 않는다 [10:56]
  • 바이트 버퍼에 객체 풀 크레이트를 적용하자는 제안이 나온다. 해당 크레이트는 익숙하지 않아 가능성만 검토하며, 이 시점에 도입하지는 않는다 [11:36]

7. 임시 인자 범위 벡터를 코덱 필드로 이동

  • argument_ranges는 용량을 확보해 할당한 뒤 슬라이스 생성 직후 버리는 중간 벡터다 [11:55]
  • 개선안은 인자 범위를 코덱의 필드로 유지하고 호출마다 clear()해 버퍼를 재사용하는 것이다 [12:31]

8. 상태를 가진 코덱의 생성 방식 수정

  • 인자 범위 필드가 추가되면서 기존 단위 구조체 형태의 Codec 생성 코드를 바꿔야 한다. 서버 쪽에서 빈 벡터를 넣어 직접 생성하려 하지만 필드 공개 범위에 막힌다 [14:04]
  • Codec::new() 생성자를 추가하고 호출부를 변경한다. 이어 생성자 자체의 비공개 접근 오류도 수정한다 [15:01]

9. 직장의 근무 기대와 개인적인 과로 성향

  • 현재 직장은 장시간 근무를 기대하지 않아 일과 삶의 균형이 괜찮다고 평가한다. 다만 본인은 과로하는 경향이 있어 스스로 균형을 잘 잡는 편은 아니라고 인정한다 [16:13]
  • 새 직장에서 근무한 기간은 약 3~4개월, 아마 4개월 정도라고 보여준다 [17:26]

10. 벡터 재사용 과정의 소유권과 참조 타입 문제

  • 지역 벡터 대신 self.arg_ranges에 범위를 추가하고 사용 후 비우도록 변경한다. 이 과정에서 필드에 into_iter()를 적용하는 부분이 막혀 참조를 통한 순회 방식으로 수정한다 [17:42]
  • 순회 방식 변경 뒤 시작 위치와 길이가 참조 타입이 되면서 덧셈과 슬라이스 범위 구성에서 타입 오류가 발생한다 [19:00]

11. 프로젝트의 점진적 구현과 납기 압박

  • Redis 구현은 한 번에 완성한 결과가 아니라 작은 부분을 하나씩 쌓아 만든 것이다 [23:57]
  • 직접 코드를 쓰고 싶어도 회사가 빠른 결과물 전달을 요구한다는 시청자의 고민에 동의한다. 업무에서 AI 사용을 밀어붙이는 배경으로 납기 압박이 연결된다 [24:11]

12. 디코더의 오류와 값 부재 처리 재검토

  • 디코더 반환형에서 Result 안에 Option이 필요한 이유를 검토하다가, 일부 경로가 오류 대신 Ok(None)을 반환하고 있음을 확인한다 [24:32]
  • 파싱 결과를 패턴 매칭하고 조건이 맞지 않으면 반환하는 현재 구조가 복잡하다고 판단한다. 결과 전파를 간단히 적용하려 하지만 Option 처리가 얽혀 바로 바꾸지 못한다 [25:23]

13. 코덱 호출부 수정 후 컴파일 확인

  • 남은 코덱 생성 위치도 Codec::new()로 바꾸고, 가변 참조로 빌릴 수 없다는 오류는 변수에 가변성을 부여해 해결한다 [26:49]
  • 명령·데이터베이스·서버 관련 코드를 확인한 뒤 컴파일이 성공한다 [27:25]

14. 할당 감소 변경 정리와 테스트 통과

  • 변경 사항을 XADD의 스트림 타입 import 수정과 인자 처리 시 할당을 줄이려는 수정으로 구분해 정리한다 [28:08]
  • 변경을 스쿼시하는 작업을 진행하면서 강제 푸시가 필요하다고 판단한다. 자막에는 강제 푸시 완료 여부가 명시되지 않는다 [28:51]

15. 목표 기업의 채용 공고를 기준으로 역량 개발

  • 기술 지원과 솔루션 컨설팅 경력에서 다른 역할로 전환하려는 질문에 대해, 역량 개발의 출발점으로 자신이 일하고 싶은 회사의 채용 공고를 살펴보는 방법을 제시한다. 공고에서 어떤 요건을 확인하는지에 대한 설명은 처리 구간 끝에서 이어지다 중단된다 [29:47]

16. 채용 요건 보완과 지원자 경쟁

  • 충족하지 못한 채용 요건은 보완하되, 관심 없는 분야까지 무리하게 따라가지는 않는다는 구직 기준을 둔다 [30:21]
  • 경력이 좋아도 거절되는 배경에는 기업이 선택할 수 있는 지원자가 너무 많아진 상황도 있을 수 있다 [30:42]

17. Redis의 실제 활용 범위와 저평가

  • 업무에서 Redis를 사용하지만, 많은 사용자는 클라이언트가 제공하는 일부 명령만 활용한다. Redis 자체에는 훨씬 많은 명령이 있어, 높은 인지도에 비해 기능은 충분히 평가받지 못한다는 견해다 [31:55]
  • 현재 업무 환경의 서비스는 ElastiCache인지 Memcache인지 정확히 기억하지 못해, 자체 호스팅 여부를 명확히 확정하지 못한다 [32:34]

18. 스트림 엔트리 ID의 기본 제약

  • XADD에 엔트리 ID 검증을 추가하는 단계다. ID는 하이픈으로 구분한 두 정수로 구성되며, 스트림 안에서 유일하고 증가하는 값이어야 한다 [32:54]

19. 원격 해시맵을 넘어서는 Lua 스크립팅

  • Redis를 키의 조회·설정만 가능한 원격 해시맵으로 보는 인식은 전체 명령 범위를 담지 못한다. Redis에서는 저장 프로시저와 비슷한 방식으로 Lua 코드도 실행할 수 있다 [34:25]
  • Lua는 프로그램을 다시 컴파일하지 않고 기능을 확장하도록 내장하는 스크립트 언어다. Nginx가 활용 사례이며, Redis의 EVAL도 내장 Lua 인터프리터로 서버 측 스크립트를 실행한다 [36:38]

20. 중복 ID를 허용하는 기존 구현의 실패

  • 같은 ID를 반복해서 넣는 테스트에서 오류 대신 bulk string이 반환된다. 기존 엔트리에 동일한 ID가 있는지 검사하는 방안을 떠올리지만, 적절한 방식인지 의문을 둔다 [40:54]
  • 현재 코드는 스트림에 필드를 추가하고 ID를 반환한다. 키별로 모든 ID를 집합에 저장하는 대안도 검토하며, 클라이언트가 ID 자동 생성을 요청할 수 있다는 조건을 확인한다 [42:38]

21. 학습용 구현의 범위와 자료구조 선택

  • Redis 구현은 CodeCrafters 과제를 따라 진행하는 작업이며, 현재 다루는 부분은 기본적인 비동기 입출력 처리라는 인식이다 [44:26]
  • ID에는 하이픈이 들어가고 별표도 허용되므로, 숫자인지만 확인하는 방식으로는 입력 조건을 충분히 다룰 수 없다 [44:46]

22. 반복적인 개발 업무의 보수와 복수 취업

  • 반복적인 기본 C++ 업무의 급여로 제시된 50,000필리핀페소는 월급이라는 답변이 나온다. 이를 계기로 같은 종류의 일을 여러 개 병행할 수 있을지 가능성을 묻는다 [46:18]
  • 현재 여러 직장에 동시에 고용된 상태는 아니다. 복수 취업은 수입에 도움이 될 수 있지만 평판에는 나쁠 수 있다는 양면성을 언급한다 [47:10]

23. 고객 소유 인프라에 배포한 경험의 한계

  • 고객이 통제하는 VM과 네트워크에 소프트웨어를 배포한 경험은 거의 없다. 보통은 자신이 관리하는 환경에 배포해 왔다 [47:38]

24. 순회 기반 중복 검사와 오류 응답 추가

  • 스트림 엔트리를 순회하며 ID가 같은 항목이 있는지 찾는 단순한 구현을 시도한다. 존재 여부를 불리언으로 얻기 위해 반복자의 any를 사용한다 [50:19]
  • 동일한 ID가 존재하면 데이터베이스 오류로 거부하도록 하고, ID가 이미 존재한다는 오류를 추가한다. 다만 이 문구가 테스트에서 요구하는 메시지와 다를 가능성을 예상한다 [50:51]

25. 소규모 사업 수입과 해외 거주의 가능성

  • SaaS나 개인 사업으로 1,000~2,000달러를 벌 경우 필리핀에서 여유롭게 살 수 있을지 가정한다. 이는 현지 생활비가 낮다는 대화를 바탕으로 한 가능성 탐색이다 [52:24]
  • 현지 음식과 높은 습도도 생활 조건으로 고려하지만, 구체적인 거주 경험을 근거로 내린 판단은 아니다 [52:33]

26. 학위의 가치와 인턴십 지원 시점의 불확실성

  • 컴퓨터과학 석사의 가치에 대해서는 대학에 다닌 경험이 없어 판단하기 어렵다고 답한다 [52:41]
  • 인턴십 지원에 답이 없는 이유로 모집 시기가 맞지 않을 가능성을 제시한다. 해당 기업의 인턴 프로그램이 실제로 운영 중인지 확인할 필요가 있다 [52:58]

27. 테스트가 요구하는 오류 메시지 맞추기

  • 테스트를 통과하려면 반환해야 하는 특정 오류 메시지가 있음을 확인한다. 앞서 임의로 정한 중복 ID 오류 문구를 요구되는 응답에 맞추는 작업으로 계속된다 [53:56]

28. 클라우드 수요 전망과 인턴십의 지역 조건

  • 클라우드와 클라우드 보안 수요는 확신하기 어렵지만, 방향을 예상한다면 증가할 것 같다는 의견이다 [55:29]
  • 인턴십 무응답에는 거주지와 모집 지역의 불일치도 영향을 줄 수 있다. 인턴 프로그램은 대체로 사무실 출근을 요구한다는 점에서 지역 조건을 가능한 원인으로 본다 [55:54]

29. 중복 검사만으로는 충족되지 않는 ID 순서 조건

  • XADD 테스트에서 다시 오류 대신 bulk string이 반환된다. 요구사항을 재확인한 결과, 새 ID는 단순히 기존 ID와 달라야 하는 것이 아니라 마지막 엔트리 ID보다 반드시 커야 한다 [56:34]
  • 이 조건 때문에 동일 ID의 존재 여부만 검사하는 구현으로는 부족하다. 이후 이 처리 구간에서는 순서 검증 수정의 완료나 테스트 통과 결과가 확인되지 않는다 [56:42]

30. 초급 개발자 채용과 직접 구현하는 학습

  • 초급 개발자를 받아들이는지는 기업이 주니어 인력을 채용하려는지에 달려 있다. 입문자에게 좋은 특정 기업이 어디인지는 확답하지 못한다 [58:47]
  • Rust로 Redis를 만드는 이유에 대한 질문에는, Redis를 처음부터 만들어 보지 않고 소프트웨어 엔지니어라고 할 수 있겠느냐는 농담으로 답한다 [59:55]

31. 마지막 스트림 ID를 기준으로 유효성을 판단한다

  • 새 ID를 검증하려면 스트림의 마지막 항목 값을 가져와야 하므로 stream entrieslast 사용을 검토한다 [1:02:19]
  • 새 ID는 마지막 항목의 ID보다 엄격히 커야 하며, 0-0은 허용되지 않는다 [1:03:18]

32. 실제 XADD 실행으로 자동 생성과 오류 조건을 확인한다

  • 0-0 입력에는 그보다 큰 ID가 필요하다는 오류가 나오고, * 입력에는 현재 시각에 해당하는 값이 반환된다 [1:04:42]
  • 자동 생성 결과는 타임스탬프 뒤에 시퀀스 0이 붙는 형태로 관찰된다 [1:05:06]

33. Redis 원본에서 자동 ID의 단조 증가 규칙을 찾는다

  • ID 계산 방식을 이해하기 위해 Codex에 Redis 구현을 질의하고, XADD 관련 C 소스 위치를 찾는다 [1:07:59]
  • 자동 ID는 명령 시작 시점의 Unix 시간을 밀리초 단위로 사용한다. 같은 밀리초에 여러 번 추가하거나 시계가 뒤로 이동해 시간이 더 커지지 않으면, 기존 밀리초 값을 유지하고 시퀀스를 증가시켜 ID의 단조 증가를 보장한다 [1:09:45]

34. 시간 캐시의 갱신 방식을 추적한다

  • 시간값의 출처를 따라가며 실행 단위 진입 코드와 타이머를 살핀다. 매초 시간을 가져와 캐시하는 구조로 해석한다 [1:10:46]
  • 다만 이 해석은 “그렇게 동작하는 것 같다”는 수준으로 남아 있으며, 호출 위치를 추가로 확인한다 [1:11:16]

35. 명시적 ID는 마지막 ID보다 커야 삽입할 수 있다

  • 명시적으로 제공된 ID는 그대로 사용하되, 스트림의 마지막 ID보다 엄격히 크지 않으면 삽입을 거부한다 [1:11:29]
  • XADD 명령 진입부와 실제 항목 추가 로직의 위치가 다르므로, 검증 동작을 이해하려면 추가 로직까지 확인해야 한다 [1:11:44]

36. ID 분해와 저장 표현 변경을 구상한다

  • 입력 ID를 하이픈으로 나누고 두 부분을 비교하는 방식을 구상한다. 현재 하나의 Bytes로 다루는 ID를 두 부분으로 저장하면 처리가 쉬워질 것으로 예상한다 [1:15:38]
  • 명시적 ID 처리를 먼저 해결하면 별표를 사용하는 자동 생성도 쉽게 확장할 수 있을 것으로 본다 [1:15:57]

37. 두 정수의 순서 비교로 ID 검증을 단순화한다

  • 저장 ID를 두 개의 바이트 값이 아니라 두 정수로 구성하자는 제안을 채택한다. 순서 비교를 derive하면 밀리초를 먼저 비교하고 다음으로 시퀀스를 비교할 수 있다 [1:18:08]
  • 외부로 주고받는 ID 형식은 유지하면서 내부 표현을 바꾸는 방향이다 [1:18:32]

38. 입력 종류를 삽입 전에 enum으로 구분한다

  • 입력을 삽입 전에 enum으로 파싱하는 설계를 받아들인다. 자동 생성 여부와 명시적 ID를 구분하는 처리를 입력 단계에 두려는 방향이다 [1:19:30]
  • 제안된 설계는 아직 적용 전이며, 이어서 직접 구현할 예정이다 [1:19:35]

39. 원본 이식보다 과제에 맞춘 자체 구현을 진행한다

  • 작업은 Redis 소스를 일대일로 옮기는 방식이 아니라 CodeCrafters를 따라 자체 구현하는 방식이다 [1:19:49]
  • Redis 원본은 필요할 때 참고한다. C를 모르기 때문에 소스가 낯설고 이해하기 어렵다는 제약이 있다 [1:20:01]

40. 요청 ID와 저장 ID를 별도 타입으로 구성한다

  • 명령 입력에 사용할 enum은 전체 자동 생성인 Auto, 값을 동반하는 AutoSequence, 명시적 ID인 Explicit으로 구성하는 방향이다 [1:21:58]
  • 저장용 StreamId는 두 정수를 가진 구조체로 만들고, 첫 구성요소에는 밀리초라는 이름을 사용한다 [1:22:24]

41. 바이트 입력의 슬라이스와 분리 API를 탐색한다

  • 입력에 바로 match 분기를 구성하지 못해 슬라이스 변환을 시도한다. slice에는 범위가 필요하다는 점을 확인한 뒤 as_slice를 사용한다 [1:23:40]
  • ID를 나누기 위해 split_once, splitn, split 등의 API를 검토한다 [1:24:57]

42. 정수 변환 주변에서 타입을 확정하지 못한다

  • match 분기 자동 완성을 시도하지만 대상 타입이 unknown으로 나타난다 [1:27:37]
  • 해당 값은 바이트를 u64로 파싱하려는 부분이라고 파악하지만, 타입 문제가 해결된 결과는 나오지 않는다 [1:27:49]

43. 내부 컴파일러 오류로 작업이 미완성 상태에 머문다

  • 코드가 컴파일되지 않는 상황에서 내부 컴파일러 오류를 확인한다. 오류의 원인이나 해결책은 이 구간에서 밝혀지지 않는다 [1:28:46]
  • 피로와 아내·아기를 돌봐야 하는 사정으로 작업 종료를 고려하고, 몇 분만 더 살펴본 뒤 마칠 계획이다 [1:29:51]

44. split_n의 제한값과 반환 형태 확인

  • ID를 좌우로 나누려는 시도에서 split_n의 반환값을 바로 두 값으로 받거나 컬렉션으로 모으는 과정에 타입 문제가 발생한다 [1:30:57]
  • 문서상 n은 분할 횟수가 아니라 반환할 항목의 최대 개수다. 두 부분을 얻기 위해 제한값을 1에서 2로 수정한다 [1:32:01]

45. 바이트 단위 predicate와 숫자 변환의 혼동

  • 별도 Rust 실행 환경에서 재현하자 predicate가 받는 항목은 문자열이 아닌 바이트여서, 시도한 parse 호출이 성립하지 않는다 [1:33:37]
  • 문자와 10진수 변환을 시도하지만 predicate가 요구하는 불리언과 변환 결과인 Option 사이에 타입 불일치가 발생한다 [1:35:11]

46. 반복자 결과를 다루는 과정에서 지속되는 막힘

  • 분할 결과를 원하는 컬렉션으로 만드는 데 실패하면서 반복자를 parts로 두고 next로 접근하는 방식을 시도한다 [1:36:24]
  • 단순한 문자열 분리를 의도했지만 바이트와 컬렉션 타입 문제를 해결하지 못한 상태가 이어지고, 피로도도 높아진다 [1:37:17]

47. 하이픈 위치 검색을 이용한 복사 없는 분리

  • position을 두 번 사용해 구분자를 확인하고, 바이트를 복사하지 않은 채 슬라이스로 나누는 대안이 등장한다 [1:38:16]
  • 첫 검색은 하이픈의 존재를 확인하고, 추가 검색은 하이픈이 하나뿐인지 확인하는 방식으로 이해한다 [1:38:54]

48. position의 반환값과 하이픈 누락 처리

  • position은 조건에 맞는 원소를 찾아 인덱스를 반환하는 메서드다. 이를 이용해 ID 안의 하이픈 위치를 구하는 방향으로 구현을 옮긴다 [100:48] [1:40:08]
  • 검색 결과가 Option이므로 ? 사용을 검토하지만, 하이픈이 없을 때는 오류를 반환해야 한다는 요구가 남는다 [101:47] [1:40:23]

49. * 예외와 메모리 할당 과제

  • *에는 하이픈이 없지만, 그 자체는 허용할 수 있는 경우로 취급한다 [102:50] [1:40:38]
  • 현재 구현에는 메모리 할당이 많이 발생하며, 이를 되돌아가 수정해야 한다는 후속 과제가 남아 있다 [103:22] [1:40:58]

50. 좌우 슬라이스 구성과 함수 분리

  • 하이픈 인덱스를 기준으로 ID 시작부터 인덱스 앞까지, 인덱스 다음부터 끝까지를 두 값으로 구성한다 [105:10] [1:41:13]
  • 해당 분리 코드는 컴파일되며, 이 처리를 unpack_stream_id라는 별도 함수로 옮기는 방안을 잡는다 [105:37] [1:44:01]

51. 숫자 파싱과 구체적인 오류 반환 요구

  • 분리한 값에 parse를 적용하는 과정에서 타입 문제를 조정하고, 파싱 호출이 가능한 상태까지 수정한다 [108:08] [1:44:06]
  • 파싱 실패 시 구체적인 오류를 반환해야 하므로 현재 처리를 다시 바꿀 필요가 있다. 이 시점의 ID는 여전히 두 u64로 구성된 튜플이다 [109:08] [1:44:21]

52. 별표 여부 판단을 숫자 파싱보다 앞세우기

  • 분리된 값이 *일 수 있으므로 이 단계에서 곧바로 숫자로 파싱해서는 안 된다는 문제를 발견한다 [109:59] [1:46:11]
  • 좌우 값을 우선 보존하고, 별표 여부에 따라 요청된 스트림 ID의 형태를 구분하는 방향으로 수정한다 [110:14] [1:47:13]

53. 자동 생성 유형과 단독 별표의 별도 처리

  • 기존 RequestedStreamIdAuto, AutoSequence 구분을 다시 연결하며 자동 생성 요청을 표현하려 한다 [110:55] [1:47:28]
  • 입력 전체가 *라면 애초에 분할할 필요가 없다. 따라서 하이픈으로 나누기 전에 이 경우를 별도로 처리해야 한다 [111:11] [1:49:18]

54. 미완성 구현의 후속 작업으로 이월

  • 단독 별표 처리 문제까지 드러난 상태에서 구현을 마무리하지 못하고, 작업을 이후에 이어가기로 한다 [111:40] [1:50:21]
  • 다음 작업 시점은 확정되지 않았다. 주말이므로 다음 날 시간이 날 가능성은 있지만, 실제 재개 여부는 불확실하다 [112:09] [1:51:23]

🧾 결론

  • 이번 작업은 CodeCrafters 과제를 따라 Redis를 점진적으로 자체 구현하는 과정이다. Redis 원본은 필요한 동작을 확인하는 참고 자료로 사용했다.
  • 벡터 재사용 변경의 테스트 통과와 XADD 구현의 미완성 상태를 구분해야 한다. 앞선 테스트 성공이 이후 변경까지 검증한 것은 아니다.
  • 메모리 최적화는 페이로드 복사, 연결 버퍼, 인자 컨테이너를 나누어 살펴봐야 한다. 이번에 확인된 수정은 그중 인자 범위 벡터의 재사용이다.
  • 스트림 ID 처리는 입력 형태의 구분, 숫자 파싱, 저장 표현, 마지막 ID와의 비교를 연결해야 완성된다. 단독 별표와 부분 자동 생성도 이 흐름에 포함된다.

📈 투자·시사 포인트

  • 인프라 효율을 평가할 때 언어 선택이나 제로 카피 여부만으로 비용 절감을 판단하기 어렵다. 이 사례에서는 연결별 버퍼와 명령별 할당 구조가 별도의 점검 대상으로 드러났다.
  • AI 코드 분석은 할당 지점과 원본 구현을 찾는 데 활용됐지만, 분석 결과를 실제 성능 개선으로 판단하려면 측정이 필요하다.
  • Redis를 단순한 원격 키·값 저장소로만 보면 스트림과 Lua 실행 같은 기능을 놓칠 수 있다는 관점이 제시됐다. 활용 중인 명령 범위를 점검할 계기가 된다.
  • 클라우드·클라우드 보안 수요가 늘 것이라는 발언은 확신이 없는 전망이다. 이 자료에는 기업 가치나 투자 수익을 판단할 정량 근거가 없다.

⚠️ 불확실하거나 확인이 필요한 부분

  • C Redis와 Rust 구현의 버퍼·할당 비교는 주로 Gemini 분석에 근거한다. 유휴 연결 메모리 예시와 비교표를 실측 결과나 모든 Redis 환경의 특성으로 일반화할 수 없다.
  • 인자 벡터 재사용 이후 테스트 통과는 확인됐지만, 할당 횟수·메모리 사용량·처리량의 전후 측정치는 없다.
  • XADD의 최종 ID 파싱·검증·자동 생성 구현과 전체 테스트 성공은 확인되지 않는다. 중간의 내부 컴파일러 오류도 원인과 해결 여부가 명확하지 않다.
  • 자막 기반 정리: 타임스탬프가 있는 자막을 기준으로 정리했으며, 고유명사·수치·인용은 원문 확인 필요 시 별도 검증한다.
  • 영상 속 주장: 발표자의 해석·전망·비교는 확인된 외부 사실이 아니라 영상 속 주장으로 분리해 읽는다.
  • 검증 필요: 수치, 기업 실적, 정책·시장 전망은 발행 전 최신 자료로 별도 검증이 필요하다.

✅ 액션 아이템

  • 동일한 연결 수와 명령 조건에서 벡터 재사용 전후의 할당 횟수, 메모리 사용량, 처리 성능을 측정한다.
  • 전체 입력 *를 먼저 구분하고, 밀리초-*와 명시적 ID를 각각 요청 타입으로 파싱하는 흐름을 완성한다.
  • 0-0, 동일 ID, 마지막 ID보다 작은 값, 같은 밀리초에서 더 큰 시퀀스를 포함해 순서 검증 테스트를 구성한다.
  • 같은 밀리초의 연속 입력과 시계가 뒤로 이동하는 경우에도 자동 ID가 증가하는지 검증한다.

❓ 열린 질문

  • 코덱의 인자 범위 벡터 재사용은 전체 할당 비용 중 어느 정도를 줄이며, 연결별 읽기 버퍼 비용은 얼마나 남는가?
  • 요청 ID와 저장 ID를 분리한 설계로 자동 생성과 명시적 ID 검증을 얼마나 단순하게 구성할 수 있는가?
  • 원본 Redis의 시간값 갱신 경로는 정확히 무엇이며, 학습용 구현에도 별도의 시간 캐시가 필요한가?

관련 문서

공통 태그와 주제 흐름을 기준으로 같이 보면 좋은 문서를 이어서 제안합니다.