
연결 리스트문제였는데, 연결 리스트를 직접 구현해서 해결해보기도 하고 새로운 아이디어도 배워볼 수 있었다. 그러나 문제에 투자한 대부분의 시간은 시간초과를 해결하기 위해 입출력기능을 최적화하는것이였다.
AI를 이용해 C로 바꾼다면 통과할 수 있었는데, 파이썬으로 푸니까 시간 제한에 굉장히 민감했다. 결국 pypy로 통과할 순 있었는데, 많은 시간을 입출력 최적화에 사용했고 돌아보면 시간대비 배운것이 별로 없는것 같다.
내가 시간을 투자해 많이 배울 수 있는지를 생각해보고, 아니다 싶으면 빠르게 넘기는 식으로 시간을 아낄 필요가 있어보인다.
구현까지 코드가 길었는데, 끝까지 마무리지을 수 있는지를 연습해보는 문제였던것 같다. 그리고 회전을 행렬연산을 이용해 구현했다는 얘기를 듣고, 고민해보았는데 어렵지 않게 구현해볼 수 있었다.
세수의 합이 집합에 포함되어있는지를 2수의 합과 나머지 수의 차로 바꿔 생각해보면 시간 복잡도가 줄어드는 경험이 신기했다. 문제 시간은 길지 않았지만, 좋은 아이디어를 배워갔다.
연결 리스트로 직접 구현하여 풀어보았는데, 스택 2개를 이용해 커서가 움직이는것처럼 구현한다는걸 보고 참신했다. 사고가 구현하는것에 묶여있는건지, 기존 데이터 구조를 활용할 생각이 잘 안났던것 같다.
호제법을 비롯해 저번주에 풀지 못하거나, 어려움을 겪었던 문제들을 다시 풀어보았는데 생각보다 시간이 오래 걸렸다. 그 만큼, 내가 제대로 이해하지 못했다는걸 반증한다고 본다. 그래서 다시 풀어보면서 전부보다 더 깊게 이해할 수 있었다. 새롭게 떠오르는 생각도 있었기에, 복습을 통해 성장을 느낄 수 있었다.
Mini Redis 구현을 주제로 여러 기능을 만들어보았다. 팀원들 각각이 구현하고 싶은 기능들이 있었고, 요구를 반영해 아키텍처를 만든 후 기능 분배가 수월했다.
RESP 프로토콜을 구현해 Redis cli와 호환이 된다는것도 인상적이였고, 개인적으로는 Redis 내부에 있는 개념들이 궁금해, 코테를 빨리 끝내고 Redis 조사를 빨리 시작했다.
incremetal rehashing, TTL, 캐시 무효화 등등 여러 개념들을 이해하고 AI를 이용해 직접 구현하고 확인해보면서 Redis 이해 수준이 깊어진것은 느낄 수 있었다.
아쉬운것은 문제풀이를 더 빨리 끝내고, 개념 공부에 들어갔으면 더 좋았을 것 같다. 개념은 알지만, 언제 사용해야하는지와 어떤 환경에서 쓰면 좋고 어떨때 쓰면 안되는지에 대해서는 제대로 대답할 수 없었다. 예를 들면, 로컬에서 redis를 만드는게 아닌 redis 서버를 만들어야하는 이유에 대해서 대답해볼 수 없었다. 또, 언제 redis가 오히려 해가 되는지도 몰랐다.

design
Storage Manager
TTL Manager
Test
지난주 수요코딩회 설계 미흡을 보완해, 충분한 시간을 설계에 투자했다. 3시간 정도 설계를 진행했고, 구체적으로는 아래 업무를 수행했다.
당시 수요 코딩회때 주제를 학습하여 구현한다는것이 무리한 요구로 느껴졌다. 사전준비를 가졌고, 미리 공부했던 내용을 팀원들에게 공유했다. 목표는 전반적으로 비슷한 지식 수준을 갖는 것이였다. 이후, 관심이 있는 것들을 조사해보기로 했고 당일에 설계부터 기능분배까지 매끄럽게 진행되었다.

싱글 스레드를 이용해 race condition이 생기지 않도록 설계했다. locking을 이용할 수 있었지만, 복잡도를 줄이는 방향을 선택했다. Redis역시 싱글 스레드를 지향하고 있었기에 이 선택에 힘이 더 실렸다. command queue를 명령어를 하나씩 순차적으로 처리하는 구조가 만들어졌다.
현재 구조가 단순하다는 장점이 있지만, 확장시 어떻게 해야할지 몰랐다. 요청은 application server를 수평확장하면 된다. 이때, command 큐에는 많은 명령어가 쌓이지만 단일 스레드라면 하나씩 처리가 되기 때문에 병목이 생긴다. Redis를 여러대로 늘려 각각이 명령어를 처리할수 있지만, 동기화 때문에 성능이 떨어질것이다.
대표적인 솔루션은 3가지가 있다.
1. Redis 성능 향상
2. 복제
3. sharding/cluster
1번은 Redis 서버 자체의 성능을 올리는것도 방법이다. 작은 규모에서는 충분히 사용할법하다. 이번 프로젝트는 작아 굳이 외부 서버로 두지 말고, 로컬 메모리를 사용하였다.
2번은 읽기 전용 redis와 쓰기 전용 redis를 별도 구분하는 방법이다. 작업 대부분이 읽기라면, 동기화할 일이 적다. 따라서 동일한 redis를 확장해볼 수 있다. 쓰기 전용 redis를 두고, 쓰기가 일어나면 쓰기 전용 redis를 읽기 전용 redis가 복제하여 동기화를 유지한다. 이 방법은 딜레이가 존재하므로 최신 정보에 민감할 경우에는 주의해야한다.
3번은 키에 따라 다른 redis 서버에 저장되는 방식이다. 읽기뿐만 아니라 쓰기 요청까지 분산할 수 있다. 그러나 여러 키를 조합하는 연산에 대해선 개별 redis 서버를 참조해야하므로 비용이 더 비싸진다는 단점이 있다.
느낀 설계의 장점은 다음과 같다.
지난주에 비해 충돌이 굉장히 줄었다. 충돌도 가볍기에 어렵지 않게 해결할 수 있었다. 본인이 관심있는것을 선택했기에 업무 집중도와 책임이 높았다.
그리고 테스트를 본인 혼자서 수행할 수 있다는것이 정말 큰 장점이였다. 독립적으로 기능을 분해하고 나니, 다른 사람의 작업을 기다리지 않고 스스로 완성도를 테스트해볼 수 있었다. 전주차 보이스 기능은 다른 사람과 서벌르 통해 음성이 인식되는지를 확인했어야 했는데, 충돌 때문에 어려움이 많았다. 이번에는 만들자마다 테스트해볼 수 있었기에 굉장히 편했다.
설계하고 나면, 조합을 위해 추가될 부분도 명확했다. 칠판을 보면 누구든 어떤 업무가 필요한지 알 수 있었다. 돌아보면, 누가 펑크나더라도 어떤 기능을 만들어야하는지를 알기 쉬웠던 것 같다.
현업을 제외하고, 처음으로 알아서 진행되는 팀을 만났다. 잠깐 쉬고 와도, 작업이 진행되어 놀랐다. 내가 빠져도 누군가 진행을 할 수 있었다. 지금까지 경험했던 팀 중에 가장 이상적이였다.
바이브코딩으로 진행되었는데 프로젝트를 다시 보았을 때, 커밋 메세지가 작성되어있지 않아 어떤 작업이였는지 확인하기 어려웠다.
개념을 공부하고 들어갔지만, 딱 공부용이라는 느낌이 들었다. 현업의 깊이만큼 들어가거나, 호환되도록 만들지는 못했다. 물론, 팀원중 한면이 실제 redis cli와 호환이 되도록 만들긴 했지만 난 그러지 못했다. 돌아보니 프로젝트 전체 완성도를 높이는게 어렵다면, 각자 기능을 현업 수준으로 끌어올리는게 좋겠다.
기능을 결합하여 쉽게 원하는 결과를 만들 순 있었다. 그러나 AI가 의도치 않은 기능까지 넣어두어, 완벽히 제어하진 못했다. 예를 들면, lazy expiration 기능을 넣었는데, 다른 팀원이 TTL 규칙을 추가해선지 접근하기도 전에 특정 데이터가 사라져버렸다.
알고리즘 문제풀이를 간소화하고, 대신 개념을 더 찾거나 직접 구현하는식으로 시간을 갖는게 더 많이 배울 것 같았다. 그래서 30분을 기준으로 진전이 없거나, 아이디어가 안떠오르면 답을 보고 해결한 뒤, 나중에 복습하는식으로 빠르게 넘기는 등 시간을 효율적으로 사용해야겠다.
다음 수요 코딩회 주제는 Virtual DOM, diff 알고리즘인데 실무에서 자주 사용하는 기능 내부 동작을 이해하는것이라 더 많이 공부해보고 싶다. 물론 이걸 위해서 기초가 되는 자료구조는 충분히 공부를 한 상태여야하지만, 다행히 사전에 학습이 어느정도 진행되었기 때문에 할만할 것으로 보인다.