스타트업 개발팀은 언제나 많은 변화를 겪게 됩니다. 저희 블럭스 팀도 마찬가지로 기존에 ‘누구에게 무엇을 보여줄까?’라는 문제를 해결하며 ‘초개인화 상품 추천’ 제품을 개발할 때와는 달리, 이제는 ‘누구에게 무엇을, 언제, 어떻게 보여줄까?’라는 CRM(고객 관계 관리, Customer Relationship Management) 문제를 해결하는 새로운 환경에 직면하게 되었습니다.
이 복잡한 문제를 풀기 위해 저희는 기존에 사용하던 개발 언어를 바꾸는 중요한 결정을 내렸습니다. 오늘은 이러한 결정을 내리게 된 배경과 이유를 이야기하려고 합니다. 이 글이 비슷한 고민을 하는 다른 회사들에게도 도움이 되길 바랍니다.
▶ 블럭스가 해결하는 CRM 문제가 궁금하다면?
새로운 제품과 새로운 개발 언어의 필요성
블럭스 팀은 AI 마케팅 솔루션 ‘블럭스’를 통해 ‘개인화 상품 추천’과 ‘개인화 CRM’ 제품을 제공하고 있습니다. 엔지니어 관점에서 볼 때 개인화 상품 추천은 클라이언트 플랫폼으로부터 추천 요청을 받아 블럭스의 AI 모델이 학습한 결과를 전달하는 서비스입니다.
AI 모델링 과정은 전문성과 복잡성이 요구되지만, 그 외 비즈니스 로직은 상대적으로 단순한 편입니다. 그래서 이 제품은 기존의 파이썬 기반 프레임워크인 ‘장고(Django, 파이썬 기반의 자유-오픈 소스 웹 프레임워크)’ 대신, 더 가벼운 ‘FastAPI’를 사용해 개발되었습니다. FastAPI는 파이썬 3.8 이상에서 HTTP 기반 서비스 API를 구축하는 데 적합한 웹 프레임워크입니다.
가볍고 빠른 FastAPI 덕분에 블럭스 팀의 엔지니어들은 AI 모델의 성능을 개선하고, 다양한 클라이언트 요구사항을 반영한 전처리와 후처리 모듈을 개발하며, AI 모델과의 통신 속도를 높이기 위한 ‘gRPC(구글이 개발한 오픈 소스 원격 프로시저 호출 시스템)’ 엔지니어링에 집중할 수 있었습니다.
또한 AI 모델링에 사용하는 프레임워크인 ‘텐서플로우(TensorFlow, 다양한 작업에 대해 데이터 흐름 프로그래밍을 위한 오픈소스 소프트웨어 라이브러리)’나 ‘파이토치(PyTorch, 파이썬을 위한 오픈소스 머신러닝 라이브러리)’에서 파이썬 언어를 그대로 활용해 머신러닝과 서버 엔지니어링을 소규모 인력으로도 효율적으로 운영할 수 있었던 것도 큰 장점이었습니다.
블럭스 팀은 ‘쿠버네티스(Kubernetes, 컨테이너화된 애플리케이션의 배포, 관리, 확장을 자동화하는 오픈 소스 플랫폼)’, ‘아파치 에어플로우(Apache Airflow, 데이터 공학 파이프라인을 위한 오픈 소스 워크플로 관리 플랫폼)’, ‘Kinesis Data Stream(실시간 스트리밍 데이터를 저장하고 수집하는 서버리스 데이터 스트리밍 서비스)’ 등 다양한 인프라 스택을 도입하며 빠르게 성장해 왔습니다. 이를 통해 더 큰 규모의 클라이언트, 즉 수십만에서 수백만 건의 데이터를 보유한 기업들에게도 개인화 상품 추천 제품을 안정적으로 제공할 수 있게 되었습니다.
▶ 블럭스의 엔지니어링 시스템 구경하기
Kinesis Data Streams로 실시간 스트리밍 데이터 S3에 적재하기
그렇게 상품 추천 제품을 고도화하는 데 집중하던 중 많은 클라이언트로부터 CRM 시장의 문제에 대한 이야기를 자주 듣게 되었습니다. 비슷한 논의가 반복되면서, 블럭스가 상품 추천 시장에서 해결하려는 문제와 CRM에서 마주한 문제들이 본질적으로 크게 다르지 않다는 점을 깨달았습니다. 이에 저희 블럭스 엔지니어팀은 이 새로운 문제를 해결하기 위해 추가 제품을 개발하기로 결심했고, 그 결과가 바로 블럭스의 CRM 마케팅 제품인 ‘Blux Message’였습니다.
▶ 블럭스 CRM 마케팅 제품의 시작이 궁금하다면?
CRM 마케팅 솔루션 ‘Blux Message’ 탄생기: 1편
CRM 마케팅 솔루션 ‘Blux Message’ 탄생기: 2편
CRM 마케팅 솔루션 ‘Blux Message’ 탄생기: 3편
블럭스가 마주한 CRM 제품 개발의 주요 요구사항
‘개인화 상품 추천 제품’과 ‘CRM 마케팅 제품’은 비슷한 마케팅 업계에 속해 있지만, 서로 다른 특성이 많아 초기에는 다소 생소하게 느껴졌습니다. 저희 엔지니어팀이 CRM 마케팅 제품을 개발하며 마주한 주요 요구사항은 다음과 같았습니다.
첫째, 비즈니스 로직의 변화를 유연하게 받아들일 수 있어야 한다는 점입니다. 블럭스도 새로운 분야에 도전하는 만큼 도메인에 대한 완전한 이해가 부족하다는 사실을 인정해야 했고, 기획이 잦은 빈도로 바뀔 가능성을 항상 염두에 두어야 했습니다.
둘째, 여러 명의 엔지니어가 빠르면서도 안정적으로 협업할 수 있는 환경이 필요했습니다. 시장에 신속히 진입해야 했기 때문에 빠른 개발 속도가 중요했지만, 동시에 B2B 제품인 만큼 최소한의 안정성은 반드시 확보해야 했습니다.
셋째, 처음부터 ‘완성도 있게’ 만들어야 한다는 점입니다. 일반적으로 제품 생애 주기에서 초기 제품은 소수의 고객을 대상으로 출시되어, 비교적 적은 트래픽에서 제품의 컨셉과 유용성을 테스트하는 과정을 거칩니다. 하지만 블럭스의 CRM 마케팅 제품은 B2B 대상이기 때문에 클라이언트의 규모가 곧바로 제품에 큰 영향을 미칩니다.
예를 들어, 클라이언트가 100만 명의 고객에게 CRM 메시지를 보내려 한다면 저희는 그 즉시 100만 명에게 메시지를 발송할 수 있어야 했습니다. 그래서 최소 기능 제품(MVP, Minimum Viable Product)을 만들더라도, 시스템의 안정성이나 확장성에서 점진적으로 개선할 여유가 없었습니다.
넷째, 기존에 안정적으로 운영 중인 상품 추천 제품과는 다른 형태의 개발 운영 방식을 고려해야 했습니다. 앞서 언급한 것처럼 상품 추천 제품은 비즈니스 로직이 비교적 단순한 편입니다. 물론 성능 향상을 위한 모델링, 모델 학습 자동화 시스템, 데이터 파이프라인 등은 복잡하지만, <요청 - 고객 히스토리 조회 - 전처리 - 모델 추론 - 후처리 - 응답>으로 이어지는 흐름이 명확했기 때문에 단계별로 엔지니어 역할을 나누는 것이 용이했습니다. 특히 각 단계를 서로 다른 엔지니어들이 전담해도 시스템을 완성하는 데 큰 어려움이 없었습니다.
하지만 CRM 제품은 훨씬 더 복잡한 비즈니스 로직과 다양한 기능을 요구했습니다. CRM 시스템은 단순히 하나의 모델 추론으로 끝나는 것이 아니라, 이메일, 문자, 푸시 알림 등 여러 채널을 통해 고객에게 메시지를 발송하고, 발송 결과를 분석하며, 각 고객의 행동 데이터를 바탕으로 개인화된 마케팅을 실행하는 복잡한 과정을 포함합니다. 이처럼 각 기능이 서로 밀접하게 연관되어 있어, 상품 추천 제품보다 훨씬 더 복잡한 형태의 엔지니어링 협업이 필요했습니다.
블럭스가 타입스크립트를 선택한 배경
앞서 언급했듯이 블럭스 팀은 상품 추천 제품을 엔지니어링의 편의를 위해 파이썬을 기반한 ‘FastAPI’를 사용했습니다. FastAPI는 가벼운 구조로 초기 개발 속도가 매우 빠르고 비동기 처리를 기본으로 지원하여 높은 성능을 발휘하는 프레임워크입니다. 또한, 파이썬은 머신러닝(ML) 엔지니어링에서도 주로 사용되기 때문에 동일한 언어로 데이터 처리와 애플리케이션 개발을 통합할 수 있어 블럭스 팀에게 큰 장점이 있었습니다.
그러나 CRM 마케팅 제품 개발에 들어가면서 FastAPI의 몇 가지 단점이 드러났습니다. FastAPI는 구조적인 복잡성을 다루는 데 한계가 있었으며, 파이썬의 동적 타이핑으로 인해 복잡한 비즈니스 로직을 처리하는 과정에서 타입 안정성이 떨어지는 문제가 발생할 수 있었습니다. 또한, 더 큰 규모의 애플리케이션 개발을 위해선 코드 관리와 유지보수에 있어서 더욱 강력한 도구가 필요했습니다.
이와 함께 블럭스의 기술적 요구사항도 변하기 시작했습니다. 초기에는 머신러닝(ML) 엔지니어링과의 통합이 중요한 요소였지만, 제품이 발전함에 따라 복잡한 대시보드와 관리 콘솔이 추가되면서 프론트엔드와의 통합이 더 중요한 과제로 떠올랐습니다.
특히 CRM 마케팅 제품에는 사용자 인터페이스(UI)와 상호작용하는 요소가 많아지면서, 프론트엔드와 백엔드 간의 원활한 통신과 일관된 데이터 처리 흐름이 더욱 중요해졌습니다. 따라서 프론트엔드와 백엔드 모두에 대해서 타입 안정성과 개발 편의성을 제공하는 기술 스택이 필요하게 되었습니다.
블럭스 엔지니어팀이 새롭게 찾은 개발 언어는 ‘타입스크립트(TypeScript, 마이크로소프트에서 구현한 자바스크립트의 슈퍼셋 프로그래밍 언어)’였습니다. 파이썬과 달리 타입스크립트는 타입이 내장되어 있어 코드 작성 시에 변수와 함수에 타입을 명시할 수 있으며, 이를 통해 컴파일 단계에서 타입 오류를 사전에 검출할 수 있습니다. 이 기능은 개발 과정에서 버그를 줄이고 코드의 안정성을 높이는 데 매우 중요한 역할을 합니다.
파이썬에서도 타이핑이 가능하지만, ‘파이단틱(Pydantic, 데이터 유효성 검사 및 데이터 구조를 간편하게 정의하고, 검증할 수 있게 해주는 라이브러리)’이나 ‘Attrs(파이단틱과 유사한 데이터 검증 라이브러리)’ 또는 ‘데이터클래스(Dataclass, 데이터 구조를 간편하게 정의하게 해주는 라이브러리로 기능은 적지만, 내장 라이브러리라 가볍다)’와 같은 별도 라이브러리를 사용해야 합니다.
또한 정적타입 검사를 위해 ‘Mypy’라는 도구를 별도로 써야 했습니다. 정적 타이핑이 없으면 서버가 실제로 실행될 때 문제가 발생할 가능성이 커집니다. 만약 개발 단계에서 문제가 발견되지 않고, 실제 실행할 때 발견되면 클라이언트에게 치명적인 영향을 미칠 수 있기 때문에 미리 확인할 수 있어야 합니다.
당시 블러스 팀의 파이썬 스택들은 그런 정적타입 검사도구를 적용하지 않았습니다. 비즈니스 로직이 단순했고 서버가 하는 일이 적었기 때문에 굳이 정적타입 검사까지 해야할 정도로 코드 안정성이 위협받는 상황이 아니었기 때문입니다.
하지만 CRM 마케팅 제품은 단순 발송뿐만 아니라 예약 발송, 메일⋅문자⋅친구톡⋅알림톡⋅왓츠앱 등 다양한 채널별 발송을 지원해야 했고, 각 발송별로 과금을 위한 측정(Metering)과 성과를 보여드리기 위한 측정(Metric) 등 복잡한 로직도 함께 지원해야 했습니다. 그래서 안정성이 어느 정도 보장된 프로덕트 개발을 위해 정적 타이핑이 적용된 언어가 필요하다고 판단했습니다.
타입스크립트로 짜여진 서버코드는 ‘Node.js(크로스플랫폼 오픈소스 자바스크립트 런타임 환경)’에서 돌아가게 됩니다. Node.js는 비동기 I/O를 기본으로 채택하고 있습니다. 이는 외부 API와 네트워크 I/O가 많을 것으로 예상되는 CRM 마케팅 제품에 적합한 특성입니다.
복잡한 비동기 코드를 간편하게 지원할 수 있도록 도와주는 ‘async/await 구문’을 기본으로 지원하는 것도 그렇습니다. 물론 파이썬도 비동기 I/O를 지원하지만, 실제로 사용했을 때 Node.js만큼 자연스럽지 않아서 ‘asyncio’, ‘aiohttp’와 같은 비동기 내장 라이브러리를 사용해야 합니다.
무엇보다 타입스크립트는 ‘JSON(JavaScript Object Notation, 데이터를 쉽게 교환하고 저장하기 위한 텍스트 기반의 데이터 교환 표준)’을 활용하는 데 더 수월했습니다. JSON을 표현하는 데 사용되는 내장 Object 데이터 타입이 파이썬의 Dictionary보다 더 직관적이고, 타이핑하기 쉽기 때문입니다. 타입스크립트의 Object와 JSON 데이터 간의 변환 작업이 매우 간단하기 때문에 저희 팀은 타입스크립트의 타입추론 시스템을 십분 활용할 수 있었습니다.
물론 타입스크립트는 자바스크립트의 ‘슈퍼셋(Superset, 한 프로그래밍 언어가 다른 언어의 기능을 포함하면서 그 외에 더 많은 기능을 제공할 때 부르는 호칭)’에 불과하기 때문에 타이핑이 완벽하지 않은 부분도 있습니다. 자바, 러스트와 같은 다른 정적 타이핑 언어들에 비해 타이핑이 느슨한 것도 사실입니다. 하지만 오히려 그런 느슨함이 속도가 중요한 스타트업에는 장점으로 작용할 수 있다고 판단했습니다.
완벽하게 강력한 타입 시스템을 가진 언어들은 코드의 안전성을 높이지만, 동시에 코드 작성 시에 더 많은 제약을 요구하고 추가적인 타입 정의 작업이 필요합니다. 이는 개발 속도를 느리게 만들 수 있습니다. 반면, 타입스크립트의 느슨한 타입 시스템은 개발자에게 필요한 곳에만 타입을 엄격하게 정의하고, 필요하지 않은 곳에서는 유연하게 작성할 수 있도록 하여 빠른 프로토타이핑과 신속한 기능 구현이 가능하게 만듭니다.
결과적으로, 오랜 논의 끝에 1) 이미 구성원들이 기본 정보를 습득하고 있으며, 2) 기존과 다른 개발 체제에 빠르게 접목할 수 있고, 3) 다양한 CRM 문제를 해결할 수 있다고 판단해서 파이썬 대신 타입스크립트를 활용해 CRM 마케팅 제품 개발을 시작했습니다. 다행히 저희가 선택이 틀리지 않아서 2달도 안 되는 시간에 수십, 수백만 명의 고객 데이터에도 불구하고 대량 발송과 예약 발송 등을 안전하게 지원하는 시스템을 구현할 수 있었습니다.
그때는 맞고 지금은 틀리다
스타트업 엔지니어 팀은 기술적인 선택을 할 때 유행을 따르거나 팀 내 의견에 휘둘리기 쉽습니다. 하지만 가장 중요한 것은 ‘실용성’이라고 생각합니다. 기술 스택은 그 자체가 목적이 아니라 문제를 해결하는 수단이기 때문입니다. 따라서 어떤 기술을 선택할지 결정할 때 그 기술이 실제 문제 해결에 얼마나 유효한지, 그리고 상황에 맞는지 여부가 가장 중요한 기준이 되어야 합니다.
예를 들어, CRM 마케팅 제품을 개발할 때는 처음에 상품 추천 제품에서 사용하던 쿠버네티스 환경을 그대로 활용했습니다. 기존 서비스가 안정적으로 유지되고 있었기 때문에 자연스러운 선택이었죠. 그러나 쿠버네티스 환경은 도메인조차 명확하지 않은 초기 제품을 운영하는 데 지나치게 많은 유지보수 비용을 발생시켰습니다.
CRM 업계의 핵심 비즈니스 로직을 파악하고 구현하는 데에도 방대한 자원이 소모되었고, 이 상황에서 쿠버네티스 관리까지 겹치니 더욱 어려운 상황이었습니다.
결국 저희는 일부 로직을 서버를 직접 관리하지 않는 ‘서버리스(Serverless, 서버 또는 백엔드 인프라를 관리하지 않고도 애플리케이션을 설계하고 실행할 수 있는 클라우드 컴퓨팅 애플리케이션 개발 및 실행 모델)’로 전환해 운영하고 있습니다. 물론, 앞으로 더 큰 부하나 새로운 요구사항이 생기면 다시 쿠버네티스로 돌아갈 가능성도 열어두고 있습니다.
CRM 마케팅팀이 새롭게 구성되고, 개발 언어를 타입스크립트로 전환한 이후 최초의 프로토타입부터 Version 1, 그리고 현재의 Version 2에 이르기까지 매우 공격적인 ‘리팩토링(코드의 결과를 변경하지 않으면서 구조를 재정비하는 작업)’이 진행되었습니다. 이러한 과정을 통해 블럭스의 CRM 마케팅 제품은 꾸준히 발전하고 안정화되었으며, 기존 상품 추천 제품과의 호환성도 준비 중입니다.
‘그때는 맞고 지금은 틀리다’는 말처럼, 기술 스택의 선택도 시간과 상황에 따라 달라질 수 있습니다. 과거에는 최선의 선택이었더라도, 시간이 흐르면서 더 이상 맞지 않을 수 있죠. 그럴 때는 유연하게 판단하여 현재 상황에 맞는 선택을 해야 하고, 그 결정을 과감하게 실행할 수 있도록 리팩토링과 개발을 진행해야 합니다.
저희 블럭스는 앞으로도 속도와 정확성을 유지하면서, 담대하게 선택하고 필요한 수정을 이어가며, 기술을 통해 클라이언트의 비즈니스 성공을 지원하는 데 최선을 다하겠습니다.
글쓴이 엄의섭(Aesop) 블럭스 Software Engineer 비즈니스 이해를 바탕으로 기술적 해결책을 제시하며, 임팩트를 창출하는 데 집중하고 있습니다. 문제 해결 능력과 도전적인 과제를 통해 조직에 긍정적인 변화를 만들어내는 것을 목표로 하고 있으며, 실질적인 가치를 제공하는 소프트웨어 개발을 지향합니다. |