우리는 대용량, 큰 아키택쳐에 대한 판타지가 있는 것 같습니다. 지금은 작지만, 나중에 커 질 꺼니까 큰 미래를 위해서 거대하고 멋진 아키텍쳐를 구축해야겠어..라는 판타지죠.
그저 작은 강을 건너가기 위한 배의 설계가 필요한데, 항공모함의 설계도를 가지고 오는 느낌입니다. 목적이 다른데 크다고 좋다고 숭배하는 모양새입니다.
MVP 단계에서는 굳이 분산 시스템의 복잡성을 감당해야 할 이유도, 여유도 없습니다. Minimal 이라는 단어가 나타내는 것처럼, 말 그대로 "최소한"입니다. 물 위에 떠 있을 수 있고 앞으로 가는 엔진 있고, 방향 틀 수 있는 핸들만 달려 있으면 됩니다.
그냥 프로젝트 하나 생성한 후에 모든 코드 베이스를 하나의 저장소로 관리하세요.
모든 어플리케이션은 용도별로만 분리합니다. API 서버의 모든 기능도 하나의 서브 프로젝트에, 배치도, 큐도, 데이터베이스도 다 마찬가지입니다.
대략 이런 식으로요.
Project Root
- API Server Project (ex. FastAPI)
- Batch (ex. Spring Batch)
- Queue (ex. Rabbit MQ)
- DB Schema
....
도메인 같은 거 신경쓰지 마세요. MVP 레벨에서 도메인이 나누어져봤자 얼마나 나누어지겠습니까? 어차피 "하나의 문제를 풀기 위한" MVP잖아요.
이런식으로 나누면 개발자 한 명이 모든 시스템의 구성을 한번에 이해할 수 있습니다. 반면 클라우드펑션, 마이크로서비스, 분산 DB.. 등을 사방에 흐트려놓으면 그 어떤 개발자도 문서 없이는 전체를 파악할 수 없게 됩니다.
단순함이 정교한 아키택쳐보다 더 큰 무기입니다.
수많은 개발자들은 바퀴를 재발명하고 싶어합니다. 이미 있는데, 내 스타일로 코드를 다시 짜고 싶다거나 하는 욕망에서요.
특히 라이브러리 API 가 쓰기 불편하다거나, 우리가 원하는 기능이 없다거나 하는 이유에서 처음부터 바퀴를 만들곤 하죠.
그래요. 이런 건 취미 개발자로써는 훌륭한 일입니다. 하지만 "돈"을 위한 작업으로서는 그다지 현명하지 못합니다. 왜냐면 오래 걸리고 버그도 많은 데다가 유지보수할 일이 늘어나거든요.
만약 정말정말 내가 원하는 기능이 없다면 그 때 만드세요. 그렇지 않고 그저 사용하기 불편할 뿐이라면 기존 기능을 확장하세요. 아주 간단한 래퍼만으로 충분합니다.
라이브러리 API가 쓰기 불편한가요? 그러면 그냥 라이브러리 API를 래핑하는 클래스나 함수를 하나 만들어서 호출하면 됩니다.
우리가 원하는 기능이 없거나, 구현하려면 기존 라이브러리에 코드를 많이 덧대야 하나요? 그냥 한번 덧대놓으면 나중에 그 라이브러리를 쓰면 됩니다.
우리가 많이 쓰는 ORM을 생각해보면, 사실 ORM은 그저 데이터베이스 Raw Query를 래핑해놓은 겁니다. Spring Data JPA는 그냥 JDBC를 래핑해 놓은 거에요. 하이버네이트, MyBatis도 똑같습니다. 그냥 이런 식으로 접근하면 나도 즐겁고 개발 속도도 빨라지며 유지보수할 꺼리도 줄어듭니다.
요새는 Saas가 많습니다. 이제는 흔한 소셜 로그인을 넘어서서, 백엔드 인프라까지 자동으로 관리해주는 supabase 같은 것들도 있죠. 이런 걸 쓰면 귀찮게 로그인 안만들어도 되고, 사용자 관리 안해도 됩니다.
사용자 입장에서도 듣도 보도 못한 서비스에 내 정보를 넘기는 것보다는 그냥 소셜 로그인하고, 필요없어지면 접근을 끊는 방식으로 하는 게 훨씬 편합니다.
아, 물론 일년에 몇 시간 정도 SaaS 서비스가 다운될 수도 있습니다. firebase social login도 가끔 멈추거든요. 너무 걱정 마세요. 우리 서비스가 멈추는 건 큰일이지만, 사실 전세계 서비스의 절반은 같이 멈추니까요.
다만, 뭐든지 SaaS는 생각은 위험합니다. 클라우드 펑션은 편리하지만 제어하기가 어려워요. 작은 규모의 SaaS의 경우 언젠든지 없어질 위험성도 있습니다. 어디서부터 어디까지 SaaS와 자체 서비스를 구분할 것인지 잘 판단해야 합니다.
이전에 스키마는 바꾸기 어려우니까 잘 설계하라고 했었는데, 지금은 정 반대의 말을 하려고 합니다. 그렇습니다. 저는 모순덩어리입니다.
데이터베이스 스키마는 사실 데이터가 쌓이면 바꾸기가 어려운 건 사실입니다. 릴레이션이 틀어지면 데이터를 마이그레이션해야 하는 최악의 상황도 올 수 있죠.
그럼에도 불구하고, 저는 스키마의 정규화나 완벽한 관계 설정에 그닥 집착하지 않아야 한다고 생각합니다.
저는 보통 MVP 스키마를 설계할 때 그닥 복잡하게 생각하지 않습니다. PK열 있고, insert_dt, update_dt 있고, 나머지는 그냥 대부분 varchar로 해결하는 편이에요. 반드시 필요하지 않다면 하위 테이블도 잘 안가져가려고 애씁니다. FK는 전혀 걸지 않아요.
네, 설계 면에서는 정신나간 짓일 수도 있습니다. 이렇게 하면 용량도 커지고 속도도 느려지며 정렬도 제대로 동작 안할꺼고 ERD도 그리기 힘들 겁니다. 저도 잘 압니다.
그렇지만 이렇게 "대충" 설계해서 얻는 이득은 생각보다 큽니다. 뭔가 변경이 필요하면 간단하게 바꿀 수 있어요. Join 을 잘 안하므로 오버헤드도 별로 없습니다. 무엇보다 중요한 건, 언제든지 내가 필요한 컬럼을 넣었다 뺐다 할 수 있다는 겁니다.
스키마가 고정되면 어플리케이션도 스키마에 따라 고정됩니다. 어플리케이션의 제약 대부분은 사실 스키마에서 나오거든요. 이걸 유연하게 바꿀 수 있다면 피봇 등의 대형 변경이 일어났을 때도 상대적으로 변경이 적어집니다.
초기 단계 배포는 간단해야 합니다. 복잡한 CI/CD 파이프라인, 쿠버네티스 클러스터링 등은 나중에 생각합시다. 심지어 저는 프로덕션 초기 단계에서는 젠킨스 구축도 반대하는 편입니다.
그냥 git에 push하고, 버튼 누르거나 커맨드 하나면 배포가 나갈 수 있게 쉘스크립트만 만들어둡니다. 인프라에 묻혀서 배포 자체가 하나의 일이 되는 것보다 개발자가 모든 과정을 제어할 수 있는 것이 더 중요합니다.
쉘스크립트 작성도 귀찮다면 AI에게 맡기거나, 혹은 PaaS를 이용해도 됩니다. Heroku, AWS Elastic Beanstalk, Vercel, CloudFlare 같은거요. 그렇지만 PaaS도 초기 설정에 시간과 열정을 쏟아야 하므로, 저는 그 시간에 그냥 다른 걸 만드는 게 낫다고 생각합니다.
큰 회사에서 일해 보면, 벽면에 60인치쯤 되는 모니터가 있고 거기서 복잡한 대시보드 시스템이 막대 그래프를 그리고 있는 모습이 보입니다. 멋져보이죠. 우리 회사도 하고 싶어요.
그렇지만 참으세요. 이런 대시보드는 여러 서비스가 서로 어울려 돌아갈 때 장애를 모니터링 할 때 쓰는 겁니다. 보통 제니퍼 같은 걸 많이 쓰는데 엄청 비싸기도 하고 오버 스펙입니다.
우리에게 필요한 알람은 굉장히 단순합니다. "오류가 났을 때", 혹은 그에 준하는 아주 중요한 이벤트 (뭐 첫결제가 일어났다거나 하는..)에만 이벤트 트리거를 걸고, 이메일로 보내면 아주 쉽죠.
카카오톡이나 SMS로 받을 수도 있습니다만 좀 비싸거든요. 건당 10원 남짓... 별 거 아닐 수도 있는데 이벤트 일어날때마다 받으면 하루에 몇천원은 우습습니다. 게다가 자다가 카톡 받으면 그닥 기분 좋지도 않아요.
이메일은 상대적으로 저렴합니다. AWS의 SES (Simple Email Service)는 1,000건당 0.1달러, 우리 돈으로 150원정도에요. 100건당 15원, 10건당 1.5원, 1건당 0.15원이죠.
극초기에는 그냥 gmail의 smtp를 이용할 수도 있습니다. 하루 최대 500건이 전부이므로 이 범위를 넘어가면 AWS로 넘어가도 괜찮아요.
어 글쎄요. 뭐였더라... MVP의 아키텍쳐는 정말 필요한 최소한의 것만 구성하세요. 큰 그림은 잠깐 접어두세요. 우리는 "돌아가는 것"에 집중합니다.