11P by GN⁺ 9시간전 | ★ favorite | 댓글 2개
  • 초기 스타트업에서 코드를 성급하게 마이크로서비스로 분리하면 팀의 생산성에 심각한 저하와 복잡성 증가를 초래함
  • 모놀리식(단일) 아키텍처는 단순한 배포와 빠른 신규 기능 출시, 효율적인 협업을 통한 생존 최적화를 제공함
  • 마이크로서비스는 대규모 확장성, 다양한 워크로드 또는 별도의 런타임 요구가 있을 때에만 분리의 이점을 제공함
  • 지나친 서비스 분리, 리포지터리 난립, 불안정한 로컬 개발환경, 기술 스택 불일치 등이 속도 저하와 팀 사기 저하로 연결됨
  • 스타트업은 모놀리스로 시작해 명확한 병목이 생길 때만 분리하는 신중한 접근이 최적임

서론 및 배경

  • 스타트업의 생존은 빠른 반복, 신규 기능 제공, 사용 가치 창출에 의해 결정됨임
  • 프로젝트의 기본 아키텍처, 기술 스택, 프로그래밍 언어 선택이 팀 속도에 영향 미침
  • 조기 마이크로서비스 도입은 공식적으로는 세련돼 보이나, 실제로는 생산성 저하, 미완성 서비스, 복잡성 과잉을 야기함
  • 데이터: 서비스 오케스트레이션, 도커/스크립트 문제, 중복된 CI/CD, 서비스 간 결합, 관측성 비용, 테스트 분산 등 다양한 개발 비용 발생임
  • 함부로 복잡한 아키텍처로 나아가는 대신, 실속형 아키텍처의 중요성 강조임

모놀리스의 강점

  • SaaS든 단순 데이터베이스 래퍼든, 시간이 흐르면 앱이 복잡해지지만 모놀리스 아키텍처는 단순하고 유연하게 유지되기 쉬움
  • 배포가 용이하고, 인기 프레임워크(Django, ASP.Net, Nest.js 등) 지원 및 오픈소스 커뮤니티 베네핏이 큼
  • 실제 사례: 한 부동산 스타트업에서 Laravel 모놀리스를 사용해 수많은 서드파티 통합 및 기능 확장을 수월하게 달성함
  • 복잡한 인프라 도입이나 마이크로서비스로 분리하지 않고, 비즈니스 요구와 기대치 충족에 집중할 수 있었음
  • 교훈: 아키텍처의 간결성이 팀이 배포에 집중하도록 도와주며, 내부 모듈화 실패만 조심하면 규모도 충분함

마이크로서비스가 항상 최선일까?

  • 많은 엔지니어가 마이크로서비스가 모범답안이라 생각하지만, 실제론 확장 등 특별한 이유가 있을 때만 진가를 발휘함
  • 적은 인원, 작은 규모, 빠른 변화 단계에선 오히려 중복 인프라, 느린 로컬 개발, 느린 반복주기로 역효과 남
  • Segment와 같은 회사도 비효율적 구조로 인한 전환을 겪었음
  • 교훈: 마이크로서비스는 병목구간 해결용 도구일 뿐, 초기 템플릿 아님

마이크로서비스가 특히 초기 단계에서 실패하는 이유

1. 임의적 서비스 경계

  • 도메인 중심 설계, 클린 아키텍처 이론 차용으로 비즈니스 로직별 서비스 분할 시도 → 실제 로직과 서비스 경계가 제대로 맞지 않음
  • 예시: 사용자, 인증, 권한 분리로 인해 배포 복잡성·API 개발 난도 상승임
  • 실제 병목이 발생하지 않은 단계에서의 분리는 시스템을 불안정하고 느리게 만듦
  • 내부 플래그나 토글로 미래 분리 시뮬레이션하며, 급한 인프라 작업 대신 유기적 경계 탐색이 효과적임
  • 교훈: 이론보다 실제 병목에 근거해 분리 결정할 것임

2. 리포지터리/인프라 과잉

  • 코드 스타일, 테스트, 환경설정, 문서, CI/CD 등 모든 요소가 서비스 수만큼 늘어남
  • 모노레포 구조를 사용하면 모든 구성을 한곳에서 관리해 코드 일관성과 협업 효율을 높일 수 있음
  • Node.js의 경우, nxturborepo 같은 도구로 내부 서비스 간 의존성 및 빌드 관리를 용이하게 함
  • 단점으로는 복잡한 의존관계, CI 성능 튜닝 필요, 더 빠른 빌드 도구 필요성 등이 있음
  • Go 생태계 역시 초기엔 단일 workspace로 관리하다가, 규모가 커지면 모듈 분리를 고민할 수 있음
  • 교훈: 작은 팀은 모노레포와 공유 인프라로 시간을 확보할 수 있음

3. 불안정한 로컬 개발 환경

  • 로컬 실행에 과도한 시간, 복잡한 스크립트, 시스템별 의존성 등 온보딩 지연 및 생산성 감소 발생임
  • 문서화 부족, 호환성 문제, OS 특정 해킹(예: macOS 전용 스크립트) 등이 장애물임
  • 한 프로젝트에서는 Node.js 프록시로 Docker 복잡성 완화하며 개발자 온보딩 시간을 줄임
  • 교훈: 앱이 한 OS에서만 돌아가면, 팀 생산성은 결국 한 대의 랩탑 신뢰성에 달림

4. 기술 스택 불일치

  • Node.jsPython은 빠른 반복엔 좋지만, 마이크로서비스 환경에선 빌드/런타임 불일치 문제 자주 발생함
  • Go는 정적 바이너리, 빠른 빌드, 운용 단순성에서 장점임
  • 초기에 기술 스택 선택을 신중히 해야 하며, 필요하다면 gRPC 등 프로토콜로 언어 혼용 가능함
  • ML·ETL 등 특별한 요구가 없다면 스택 혼용은 오히려 복잡성만 증가시킴
  • 교훈: 꿈보다 팀 현실에 맞는 스택을 선택할 것임

5. 숨겨진 복잡성: 통신과 모니터링

  • 마이크로서비스에선 서비스 디스커버리, API 버저닝, 분산 트레이싱, 중앙 로그 관리 등이 필수적임
  • 버그·장애 추적이 모놀리스에선 스택트레이스 하나지만, 분산 환경에선 훨씬 복잡함
  • 제대로 하려면 OpenTelemetry 등 전문 도구 도입, 관측성 스택 구축 필요임
  • 분산시스템은 추가 엔지니어링 챌린지에 대한 의무투자임을 인식해야 함

마이크로서비스가 유효한 상황

  • 워크로드 격리: 이미지 처리, OCR 등 특정 비동기 작업을 분리하면 효율적임
  • 확장 필요성의 불균형: 웹 API와 ML 워크로드의 하드웨어·운영 요구가 달라질 경우 각기 별도 분리함
  • 다른 런타임 필요: 레거시 C++ 코드 등 주요 앱과 런타임 호환이 안 되는 구성요소는 분리 서비스로 유지함
  • 대형 엔지니어링 조직(예: Uber) 사례에서 볼 때, 명백한 조직적 필요와 성숙한 운영 능력이 있을 때만 적합함
  • 작은 팀에서도 드물게 외부 분석 서비스처럼 관리가 단순한 경우 분리가 실용적임
  • 교훈: 실질적으로 분리의 이점이 명확한 워크로드에서만 채택할 것임

스타트업 실전 가이드

  • 처음엔 모놀리스로 시작하고, 입증된 프레임워크로 작업에 몰입할 것임
  • 싱글 레포지터리가 운영 및 관리 효율·보안 관점에서 초기팀에 더 이익임
  • 로컬 개발환경 간소화가 중요하며, 어려울 땐 자세한 안내 문서·영상 제공 필수임
  • CI/CD에 조기 투자해 반복작업 자동화 및 팀 심적 부담 해소 필요함
  • 명확한 병목이 나타날 때만 선택적으로 분리하고, 그렇지 않을 땐 모놀리스 내 모듈화와 테스트 강화에 집중함
  • 최우선 목표는 개발 속도 유지
  • 교훈: 단순함에서 시작해, 분리의 필요성에 맞게 스케일할 것임

마이크로서비스를 꼭 써야 한다면

  • 기술 스택 평가 및 개발자 경험 도구 투자: 서비스별 자동화, 명확한 스크립트, 통합 배포 관리 도구 마련 필요성임
  • 신뢰성 있는 서비스 통신 프로토콜 및 표준화: 메시지 스키마 일관성, 문서화, 에러 처리 등 추가 구현 사항 파악 필요임
  • 테스트 인프라 안정화: 단위·통합·E2E 테스트가 서비스 분리에 맞게 확장되어야 함
  • 공통 라이브러리 고려: 관측성·통신 공통코드는 최소 범위로 유지, 잦은 전체 서비스 재빌드 방지함
  • 관측성은 조기 도입: 구조적 JSON 로그, 코릴레이션 아이디 등 기본 로깅 도구부터 마련할 것임
  • 결론적으로, 복잡성을 받아들일 땐 전력을 다해 관리 가능한 체계를 설계하는 게 중요

결론

  • 성급한 마이크로서비스 도입은 부담만 남기므로 단순성을 최우선으로 택할 것임
  • 뚜렷한 고통 포인트 없이 분리하지 말고, 살아남고 성장하는 데 필요한 최소 복잡성만 추가하는 관점이 중요함
  • 살아남는 게 먼저, 확장은 그 이후임

팀을 마구 나누면 모여서 의견 나누는 것조차도 엄청난 업무가 되죠.

Hacker News 의견
  • 진짜로 확장 문제나 대규모 팀, 독립적으로 발전해야 하는 도메인이 없으면 마이크로서비스는 비용만 들고 이득은 얻지 못함을 깨달음, 실제로 Segment도 이런 이유로 마이크로서비스 분리를 되돌렸음, 기술이 아니라 조직 패턴이라는 점, 보통은 단일 모놀리스를 운영하다가 프론트, 백엔드, 오래 걸리는 작업(예: PDF 생성)만 별도 서비스로 뺌, 이후 서비스가 늘어나면 표준화, 아키텍처 고민 시작, 200명 미만 엔지니어에서는 오히려 생산성 손실이 큼, 마이크로서비스 때문에 살아남는 게 아니라, 그럼에도 불구하고 살아남는 것이라 봄
    • 일부 개발자들이 미래 대기업 이력용으로 마이크로서비스를 도입하려 하는 경향이 있음, 실제 스타트업에는 별로 도움이 안 됨, 이런 걸 막으려면 정말 현명한 기술 리더십이 필요함
    • 엔지니어 50명 규모 스타트업에서 수십 개 서비스 쪼갠 사례를 목격함, 신규 참가자가 시스템을 파악하는 데 최소 6개월, 사용자는 수백 명에 불과했으나 엄청난 복잡성, VC 자금 $5천만을 태우고 결국 망함, 제품은 혁신적이고 잘 설계됐으나 의미 없음
    • 서비스 쪼개기 시 코드는 나누지 않고, 일반적인 모놀리스를 역할 플래그로만 분리 배포하는 방법도 존재함, 백그라운드 워커도 웹서버와 같이 운영하면서 헬스체크, 메트릭 활용, 로드 밸런서가 역할별 트래픽 분배함
    • Khan Academy가 겪었던 사례처럼, 모놀리스를 충분히 확장한 후에는 경험을 바탕으로 서비스 경계 판단이 가능해짐, 그 때는 마이크로서비스 도입이 적합함
    • 기술적으로 분리해야 하는 이유를 들고는 있지만, 서비스란 원래 어려운 일임, 하지만 필요하다면 숙련도를 높이려는 자세가 중요함, 무조건 유행을 탔다고 거부하지 말고, 트레이드오프를 따져야 함
    • 단지 "여러 팀"이라고 해서 조직을 쪼갤 필요가 없는데, 실제로 소규모 Squad 두 개가 생겼다고 바로 모놀리스를 분리하려는 디렉터들이 있음, 팀이 자주 개편(9개월 마다)되어 아키텍처 경계를 일찍 잡았다면 오히려 재앙, 최소 18개월 정도 안정적으로 한 팀으로 운영해볼 가치가 있는지 확인해야만 아키텍처 경계로 삼을만함
    • 마이크로서비스 정의가 원래 "독립적으로 발전할 수 있는 도메인"에 대한 것이라서 새로울 게 없다고 느껴짐
    • 아주 특수한 URL 하나만 트래픽/메모리 요구가 차이나서, PHP 서버에서는 적합하지 않아 다른 언어의 서버 하나만 추가함, 1000배 성능·비용 개선 효과 경험함, Java/Spring/Guava식으로 서비스 개념을 "프로세스 밖" 구현이나 "안" 구현으로 바꿔 볼 필요도 있음, 기술 스택/버전·시리얼라이제이션 표준화를 잘 하면 생산성이 오히려 올라갈 수도 있으나, 표준화 결여 시 커뮤니케이션 오류·호환성 문제 등 혼란 야기됨
    • Conway's law(코드 구조가 조직 구조를 반영한다)는 실제로 맞는 이야기임
    • 서비스란 사람이 제공하는 것, 마이크로서비스는 기업 내 경제에서의 서비스임을 강조함
    • 15년 전 경험담, 작은 팀 단일 솔루션을 쉽게 운영하다가 마이크로서비스 도입 후 각 서비스 기동·조율까지 해야 해서 고생, YAGNI(필요할 때까지 만들지 않기) 실천의 중요성을 체득함
    • 트래픽이 높거나 중요한 경로만 분리하는 등, 기술적으로 분리해야 할 이유는 많음, 작은 조직에선 보통 바람직하지는 않지만, 고부하 경로만 잘라내면 스타트업에서도 큰 효과가 있을 수 있음
    • 실제로 마이크로서비스의 주요 이점은 작은 그룹이 서로 간섭 없이 독립적으로 일하게 해주는 데 있음, 하지만 여러 팀이 각자 마이크로서비스를 소유하다 보니 표준화 회의가 끝없이 이어지고, 외부 서비스에 딴지 걸려 협력보다 "넘의 일엔 신경 끄라"는 외교술이 더 중요함
  • 개발자 2-3명 팀에서 멋있어 보여 마이크로서비스 도입을 조언함에도 불구하고 시행, 2년 후에야 기존 코드를 재구축, 3년이 지난 지금도 배포와 기타 문제를 해결하지 못함, 초기에 조언을 무시하지 않고 모듈러 모놀리스를 선택했다면 이런 문제 없었을 것, 이 글에 공감함
    • 화려한 기술/프로젝트 이력만 남기고 곧 이직해버리면, 후폭풍이 남이 됨
    • 마이크로서비스는 각 서비스마다 팀 하나씩 맡을 때만 진짜 쓸 만함, 한 팀이 여러 서비스 돌보는 건 좋은 사례를 본 적 없음
    • 문제의 상당수는 팀원들이 마이크로서비스를 하나의 시스템(모놀리스)처럼 계속 생각하는 데서 비롯됨, 설계~배포까지 모든 과정에서 마찰 생김, 전체 조직이 충분히 공감해야만 성공할 수 있음, 기존 시스템을 마이크로서비스화하면 내부 저항이 많음
    • 결국 스타트업에서는 다들 비슷한 고생길을 간다는 느낌임
    • 8-12개의 마이크로서비스로 이뤄진 내부 UI 프로젝트에서도 실제 사용자 5-10명, 불필요하게 복잡함만 커짐, 이유를 알 수 없음
    • Thoughtworks 컨설팅 덕분에 마이크로서비스+Java 도입한 경험, 컨설팅 업체는 돈만 벌고 떠났으나 정작 조직은 기능 많은 모놀리스를 분산 마이크로서비스로 재구현하느라 헤맴, 프로젝트는 결국 실패, 회사도 사라짐, 이후로는 대형 컨설팅사를 불신
  • grug 뇌 스타일로, 왜 일부러 시스템을 쪼개서 네트워크 호출까지 추가하는 어려운 방식을 택하는지 의문임
    • 마치 파이썬처럼 언어에 "몽키패치" 기능이 없는 곳에 그걸 추가하는 것과 같다고 느낌
    • 네트워크 호출이 규칙(rule)을 법(law)으로 바꾸는 역할을 한다는 의견임
    • grug 유머로, grug 뇌를 가진 grug들이 많아져서 오버그룹이 9명의 grug로 1개월 만에 아기 grug 만들 수 있을 거라는 착각에 빠진다는 의견
  • 마이크로서비스는 대규모 조직에서 인적 문제 해결, 관료주의적 허들 제거, 개발자 자율성 부여에 효과적임, 소규모 스타트업에서는 실제 이익이 크지 않음, 다만 특정 도메인에서 기술 스택이 섞이면(예: Elixir와 Python/Go), 이런 분리가 필요할 수 있음
    • 앱에 서로 다른 부하나 리소스 요구가 있으면 작은 스타트업에서도 별도 서비스를 만드는 게 이점임, 대부분의 비즈니스 로직은 모놀리프로 두고, GPU처럼 특별한 작업만 분리, 다만 이런 패턴이 100개 서비스 유지로 번지는 것은 지양, 기본적으로는 모놀리스 선호, 필요한 순간에만 분리
    • 마이크로서비스는 오히려 조직적 의존성과 조율 필요성이 새로 생김, 예를 들어 "아무 서비스나 가져다 쓰기" 정책은 유지보수를 크게 늘리고, 누구든 모든 걸 배워야 돌아가게 됨, 결국 인력 찾기에 시간 쏟게 됨
    • 서로 갈등하거나 중복되는 팀이 있으면 비효율이 커짐
  • 마이크로서비스는 소프트웨어 아키텍처에서 Conway's Law(조직 구조가 코드 구조에 영향을 줌)와 비슷함, 팀 경계마다 건너야 하는 경계가 생기고, 내부적으로 큰 아키텍처 경계를 인위적으로 만드는 건 대부분 비생산적임, 대신 의존성 주입과 모듈 경계 설계, 액터 모델 활용 등 모듈러 모놀리스로 관리, 나중에 진짜 필요하면 서비스 분리도 쉬워짐, 이 방식이 비용 대비 효과가 좋았음, 직접 모놀리스를 3~4회 잘라내 본 경험 있음
    • Conway's Law는 소통, 즉 커뮤니케이션의 경계에 대한 법칙임, 팀 경계마다 건드릴 필요까지는 없음, 오히려 조직을 소프트웨어에 맞추는 재편이 필수, 즉 아키텍처 바꿀 때마다 회사 리오그 필요함, 이런 식은 팀-비즈니스 목표 단절 심화, 괜히 Amazon식 방식을 맹신하지 말라는 의견임
  • 기술적으로 스타트업에서 마이크로서비스가 적합한 경우는 (1) 코어 앱과 다른 언어가 필수일 때(예: Rails+R), (2) 일부 서비스만 엄청난 스케일 차이가 있을 때, (3) 특정 데이터만 다른 보안/수명 요구가 있을 때(의료정보 등), 그 외에는 세분화할 이유가 거의 없음, 작은 조직은 오히려 손해임
    • 몇 개 서비스 신규 분할은 진짜 마이크로서비스와는 다름, 실제 마이크로서비스는 일반 앱에서 모듈로 둘 만한 것도 전부 나눔
    • 스케일 뿐 아니라 신뢰성·가용성 요구가 극단적으로 다르면 별도 서비스 분리가 합리적, SLA 유지를 위한 관심사 분리를 통해 위험 감소·배포 속도 향상 기대
    • 이런 경우조차 DB서버만 별도로 운영하는 것과 크게 다르지 않다고 봄
  • 마이크로서비스의 진짜 성과는 조직 측면임, 문제를 쪼개서 각 팀이 한 조각을 완전 소유, 엔드 투 엔드 배달까지 책임지므로 전문화 가능, 변화가 기본적으로 점진적으로 이루어지고, API가 유일한 상호작용 경로임, 단일 DB/파일 시스템/API 공유 없음, 대신 표준화와 관리툴링(모니터링, 테스트, CI/CD 포함)이 중요, 모놀리스든 뭐든 어느 정도는 갖춰야 하는 부분임
    • 인프라, 로깅, 인증 등은 패키지화 하거나 gRPC·메시지 큐 등으로 관리, 서비스 신규 생성이 빠르고, 팀 내부 머지 리퀘스트도 작아져서 충돌 줄고 생산성 향상, 5~10명 규모일 땐 모놀리스를 쓸 때 충돌, 배포, 릴리즈 이슈가 잦았으나 마이크로서비스 전환 후 생산성·협업 리드미 증가, 다만 테스트/문서화/엔드포인트 등 규칙이 중요했음
    • DB 분리 등 퍼포먼스 측면에서 기술적으로 분리해야 하는 경우도 있으나, 일반 스타트업에선 드물 수 있음
  • BEAM/OTP(Erlang, Elixir) 생태계의 강점은, 모놀리스를 유지하면서 "마이크로서비스적" 설계를 연습하고, 진짜 분리가 필요할 때 쉽게 전환 가능, 규모가 작을 땐 모놀리스의 이점, 커지면 동시에 스케일링·독립성 확보 가능, 다만 불변 객체·동시성 커뮤니케이션·고장 관리 등 학습 필요, 직원 채용도 어려울 수 있음
  • 대부분 동의함, 스타트업 환경에선 서비스 경계 잡기가 거의 불가능함, 단 작은 팀에서 외부 API나 복잡한 종속성 문제 때문에 마이크로서비스화가 이득일 때가 있음, 이 경우 네트워크 경계가 필수라서 별도 서비스로 만드는 게 복잡도 증가가 크지 않음, 혹은 빌드/배포 복잡성이 있을 때도 분리하면 모놀리스를 단순화하는 효과 있음
  • 마이크로서비스는 대규모 확장이나 팀 마이크로매니지먼트 필요 시만 적합함, 명확한 모듈 경계는 포기하지 않아야 함, 메시지 패싱 스타일의 객체지향으로 모놀리스 내에서 마이크로서비스 장점 활용 가능, DB를 직접 건드리지 않는 훈련 필요, Java 같은 언어에서 모듈화·DB 스키마 네임스페이스·최소한의 인터페이스만 공개, 독립적 테스트/모니터링 가능, 여러 서비스 동시에 배포도 쉬움
    • 논리적 경계를 충분히 이해하면 ArchUnit 같은 툴로 강제하는 방법도 있음