카카오 추천팀 러스트 도입
(tech.kakao.com)카카오 추천팀에서는 기존의 머신러닝 플랫폼을 대체할 새로운 플랫폼 개발을 진행.
팀 내 주력 언어인 파이썬으로 애플리케이션의 성능과 안전성을 모두 챙기기에는 조금 힘든 부분이 있음.
사용자 지표 애플리케이션에 러스트를 도입하여, 러스트로 애플리케이션을 구현하는 것이 적절한지 검증하는 절차를 진행.
- 러스트가 파이썬보다 작업을 1.9배 정도 빠르게 처리
- 메모리 사용량은 파이썬이 러스트 보다 4.5배 정도 더 사용
- 파이썬의 CPU 사용량은 러스트보다 최대 3배, 평균 2배 정도 높음
- 파이썬의 asyncio와 러스트의 tokio가 각 언어의 애플리케이션에 적용되어, 비동기 처리가 동일하게 구현된 단일 스레드 환경에서도, 러스트의 메시지 처리 속도가 파이썬 보다 10배 정도 빨랐음.
러스트의 큰 단점 중 하나는 학습 비용이 많이 들었음.
파이썬으로 개발할 때도 타입 어노테이션을 강제. 사용자 지표 애플리케이션을 두 가지 버전으로 구현하면서, 파이썬과 러스트 간의 개발 시간 차이를 크게 체감하지는 못함.
생산성 측면에서 체감되는 가장 큰 차이점은 컴파일 시간. (패키지 다운로드 도커 시간 포함)
- 러스트는 대략 340초 수준
- 파이썬의 경우 대략 100초 수준
파이썬을 쓸 때 타입 정보가 없는 라이브러리에서 만들어진 데이터는 타입 검사가 무시되는 Any 타입을 가짐. 전체 프로젝트의 타입 검사 정확도를 낮춤.
파이썬은 예외를 쓰고 러스트는 Result라는 enum 타입을 쓰는 등의 차이점도 있었음.
개발도구
러스트의 경우 cargo가 기본적으로 제공하는 기능이 많음.
파이썬 개발 도구가 고도화, 설치만 하면 비교적 쉬웠음.
파이썬과 러스트 모두 경험은 없지만, 글만 놓고 봤을 때.. 러스트 도입에 대한 큰 장점을 느끼지 못하겠어요.
러스트가 안좋다는게 아니라, 러스트 도입을 위해 진행했던 실험도 빈약하고
(고작 메시지 50건 처리결과만 놓고보면 몇배가 더 빠르니 몇배가 더 좋다고 주장하는건 너무 빈약한 전개인 듯 합니다..)
그리고 동일한 처리 로직(동기vs비동기)으로 비교한 것도 아니고요..
[비동기 메시지 처리를 지원하지만 레퍼런스가 많이 없는 파이썬 라이브러리] vs [학습비용이 높고 소수인원에 의한 유지보수risk 가 있는 러스트 언어]
위 두 상황을 놓고 봤을 때, 향후 지속가능성에 대한 부분도 진지하게 고민이 이루어진 것인지도 의문이고요 (적어도 글에서 느끼기엔 그랬습니다)
ETL 특성상 짧게 자주 테스트해야 하는 경우가 많을 것 같은데, 빌드타임 100초 vs 300초는 개발에 있어 큰 병목현상일 것 같은데 말이죠..
증분 빌드가 뛰어나다고 글에서 언급하고 있는데, 이에 대한 내용은 하이퍼링크로 대체하고...
실제로는 열심히 조사하고 검토했을텐데요, 적어도 글에서 느껴지는 바로는.. 진짜 러스트 도입으로 어떤 점이 좋아진건지 기대효과는 무엇이고 무엇을 해결해주었는지 알수도 없고 공감하기도 힘드네요..
개인적으로, '최근 핫한 기술' 내지는 커리어 한줄을 위해 기술을 선택하는 경우를 봐왔는데, 결과적으로 팀내 유지보수하지도 못하고 기술부채로 남았던 경우가 대부분이였습니다.
- 가령, 워크로드가 작고 순차처리 해도 전혀전혀 문제가 없음에도 kafka니 비동기 처리를 해야한다고 주장하는 경우
- (팀내 상황을 고려하지 않고) 비동기 처리에 무엇이 좋다고 하여 적용한 결과, 트러블슈팅도 매우 어렵고 결과적으로 또다른 레거시가 되는 경우....
- 최근 핫하다는 ooo을 도입하면 무엇이 좋다는 둥.. 하였지만 결국 또 다른 핫한 ooo이 나오니 또 그것이 좋다고 주장함..
물론 위 러스트 글이 그렇다는 건 아니고 그러지 않기를 바라겠지만..
진지하게 고민하지 않고 도입한 기술로 인한 피해는 팀원이 받는다는 사실을 여러 번 겪고나니 저러한 기술 프로모션 글을 읽을 때 더 신중해지는 것 같습니다.
기본적으로 ETL task처럼 보이는데, 이 도메인에서 Python과 함께 강점을 가지는 Java는 고려하지 않으셨는지, rust에 대비해서 배제한 이유가 있다면 알고 싶네요.
성능 테스트는 워크로드의 성격에 따라서 의미가 크게 달라지는데, 테스트 설계나 수치가 어떻게 얻어졌는지 설명 같은 것이 없어서 아쉽네요.
예를 들어서 500만건을 처리한 후에 50건 처리를 기준으로 산술 평균 등을 취했는지, 그렇다면 메모리 사용량은 어떻게 구하셨는지, CPU 사용량의 차이는 어떻게 측정되었는지 등이 궁금하네요. (시간은 아마 wall-clock time이겠죠?)
또한, 'CPU 사용량을 봤을 때 두 언어에서 성능 차이의 대부분은 입출력(Input Output. 이하, IO) 작업인 카프카 메시지 소비 작업과 몽고 DB 도큐먼트 저장 작업에서 비롯된 것'이라는 해석이 있는데, 결과에서는 wall-clock time은 rust가 1/2 정도였고, CPU 사용량 (CPU time?)은 1/4.5라고 하셨는데, I/O에 관한 구현 방식 차이라는 얘기인 것인지, 아니면 CPU-intensive한 I/O 대상 데이터를 다루는 과정의 차이라는 것인지, 논리가 약간 이해가 안되는 점이 있습니다. 사실 CPU-intensitve한 task에 대해서 rust가 이점을 가지는 부분은 잘 알려져있어서 후자라면 사실 라이브러리의 차이를 언급할 필요성도 없는 것 같아서요. 오히려 실험에서는 CPU-intensive한 작업이라면 글에서도 언급한 asyncio/tokio 구현 비교처럼 훨씬 큰 차이가 발생했어야 했는데, I/O 때문에 성능 차이가 덜 났다고 해석해야하는 것 아닌가 싶습니다.