본문 바로가기

Architecture

개발팀장의 얽힌 실타래 (소프트웨어 복잡성)

소프트웨어 복잡성

개발을 시작한 지 2년이 넘어가고 개발 팀장이 되면서 소프트웨어 복잡성이라는 벽을 실감하기 시작했습니다. 작은 애플리케이션을 만들 때는 모든 게 단순해 보였지만, 시스템이 커져갈수록 보이지 않던 복잡성이 곳곳에서 드러났습니다.

재미있게도 이 복잡성은 단순히 코드 구조나 아키텍처 문제만이 아니였습니다. 조직 구조, 커뮤니케이션, 일정 압박, 우선순위 결정 등 비기술적인 요소들과 복잡하게 얽혀 있다는 것입니다.

 

한가지 예를 들어보겠습니다. 

어떤 서비스가 Web 서비스와 API 서비스를 모두 제공한다고 가정할 때, 사용자의 요청으로 ‘A’라는 기능을 개발하게 되었습니다. 처음엔 Web 서비스에만 우선적으로 기능을 추가하고, API 서비스는 나중에 개발하기로 계획했습니다.

 

그러나 시간이 흐르면서 API 서비스 쪽에 더 급하고 우선순위가 높은 요구사항들이 계속 들어오게 됩니다. 이로 인해 ‘A’ 기능의 API 개발은 일정상 계속 밀리고, 다른 팀과의 일정 조율이나 인프라 팀의 가이드라인 등을 맞추는 과정에서도 점점 더 늦어질 수밖에 없습니다. 심지어 사업 전략이 변경되면서 API 서비스 쪽에서 ‘A’ 기능 개발을 아예 포기하는 경우도 생길 수 있습니다.

 

이렇게 되면 결과적으로 Web 서비스와 API 서비스 사이에 기능 차이가 발생하게 되고, 사용자가 Web에서 ‘A’라는 기능을 사용할 때 API 서비스에서는 이를 처리하지 못해 예외가 발생합니다. 결국 처음에는 간단해 보였던 기능 추가가 Web과 API 간의 기능 차이를 만들어, 전체 시스템의 복잡성을 증가시키는 상황을 만들어내는 것입니다.

 

어느 순간부터 저는 "기술적 복잡성 뒤에는 언제나 조직과 사람의 이야기가 함께 있다고" 느끼게 되었습니다.

 

처음엔 이 문제를 나만 겪는 문제로 여겼지만, 시간이 지날수록 주위의 동료들도 비슷한 고민을 하고 있음을 알게 되었습니다. 다들 시스템이 복잡해져가는 것을 체감하고 있었지만, 정작 그 복잡성을 어떻게 다루어야 할지에 대해선 답을 내기 어려워했습니다.

제가 이 글을 쓰는 이유처럼 개발자로서 마주한 복잡성의 정체는 무엇이고, 왜 우리는 이에 무력감을 느끼는지, 또 뛰어난 조직들은 이 문제를 어떻게 풀어나가고 있는지 고민해보고자 합니다.

 

복잡성 앞에서 좌절했던 제 경험을 시작으로, 이 글은 기술과 현실 사이에서 균형을 찾으려는 개발자의 시각을 담아보려 합니다.

 

복잡성의 본질

소프트웨어를 개발하다 보면 Complexity(복잡성) 이라는 단어가 자주 등장합니다. 모든 복잡성이 똑같은 것은 아닙니다. IT 업계에서는 흔히 본질적인 복잡성(Essential Complexity)부수적인 복잡성(Accidental Complexity)으로 나누어 이야기합니다.

 

본질적 복잡성이란 우리가 해결하려는 문제 도메인 자체에서 나오는 타고난 복잡성을 말합니다. 반면 부수적 복잡성은 문제 해결을 위한 도구나 기술 선택으로 인해 추가로 발생하는 복잡성을 뜻합니다.(때로는 기술에 해단 Level로 발생하기도 합니다)

예를 들어 금융 거래 시스템의 업무 규칙이 복잡한 것은 본질적인 복잡성이지만, 이를 구현하면서 생기는 지나치게 복잡한 클래스 구조나 복잡한 배포 파이프라인의 어려움 등은 부수적인 복잡성이라고 볼 수 있습니다.

 

여기에 대해서 마이크로소프트 기술 책임자였던 Ray Ozzie는 2005년 사내에서 이런 말을 남겼습니다.

“복잡성은 살인적이다. 개발자의 수명을 단축시킨다. 제품을 구상하고 제작하고 테스트하는 일을 어렵게 만든다. 보안 문제를 끌어들인다. 그리고 이용자와 관리자를 좌절시킨다.”

 

과거에는 하드웨어에 모놀리식 애플리케이션을 올려 구동하던 것을 이제는 수십 개의 마이크로 서비스로 쪼개어 컨테이너에 담고, 쿠버네티스로 오케스트레이션하여 분산 배포하는 시대이며, 클라우드 네이티브를 기본 전재로 생각하는 IT 환경이 되었습니다.

 

Amazon의 CTO인 Werner Vogels는 2019년 AWS 서밋 행사 중 "마이크로서비스가 보편화된 환경으로 이동하면 복잡성이 확연히 증가한다" 면서 "모든 것이 모놀리식 아키텍처였던 시절에는 더 단순했을까? 일정 부분에서는 분명이 그랬다"라고 말합니다. AWS의 Emily Freeman도  현대 소프트웨어에 대해서 "앤트로피의 연구와 같다. 갈수록 복잡해지고 있다."고 평하기도 했습니다.

 

물론 기능을 추가하고 시스템이 발전된다면 복잡성의 증가는 어느 정도 불가피한 측면이 있습니다. Vogels는 "소프트웨어는 진화하지 않으면 금방 relevance를 잃는다"고 말하면서, 새로운 기능을 덧붙일 때의도된 복잡성과 의도치 않은 복잡성이 함께 따라온다고 지적했습니다.

 

전자는 새로운 역량을 얻기 위해 기꺼이 받아들이는 복잡성이지만, 후자는 "기술 변화나 아키텍처 관리 소훌을 타고 들어 숨어드는 복잡성으로, 시스템을 느리게 하고 유지보수를 어렵게 만든다"는 것입니다. 

 

테슬러의 법칙 이라는 말도 있습니다. "복잡성은 새로 만들 수도 없고 없앨 수도 없으며 그저 다른 곳으로 옮길 수 있을 뿐이다."라는 법칙인데 복잡성을 완전히 제거하는 건 불가능하고 다만 어디에 그 복잡성을 둘 것인가를 선택할 뿐이라는 의미입니다.

다시 말해, 우리가 만든 시스템의 어느 계층 또는 어느 팀에서는 복잡성의 부담을 짊어져야 한다는 현실이죠.

 

중요한 것은 이 복잡성을 의식적으로 관리하느냐입니다. 본질적인 복잡성은 월급을 주는 뼈대이므로 피할 수 없지만, 부수적인 복잡성은 최소화 하도록 노력해야 합니다.

 

문제는 현실에서 이 노력이 말처럼 쉽지 않다는 데 있습니다. 복잡성이 쌓이고 있다는 것을 알면서도, 정작 손을 쓰지 못하고 속수무책으로 바라봐야 하는 상황이 자주 벌어집니다. 여기서 개발자들은 극심한 무력감을 느끼게 됩니다.

 

개발자의 무력감

개발자라면 누구나 한 번쯤 "이대로 두면 앞으로 발목을 잡을 텐데..." 라는 불안감을 느껴본적이 있을 것입니다.

예를 들어 어느 서비스의 코드베이스가 점점 난잡해지고 있다고 해봅시다.

 

모듈 간 결합도가 높아 중복 코드가 늘어나며, 새로운 기능을 추가할 때마다 예상치 못한 사이드 이펙트가 생깁니다. 개발 팀은 리팩토링이나 구조 개선으로 이 누적되는 복잡성을 줄이고 싶어하지만, 현실적으로는 그럴 시간과 자원을 얻기 어렵습니다. 사업 일정은 항상 촉박하고, 당장 눈에 보이는 새로운 기능 개발이 우선시되기 마련이니까요.

 

인프라나 배포 파이프라인을 개편하고 싶어도 "지금 잘 돌아가고 있는데 굳이 고쳐야 하나요?" 라는 질문이 돌아올 때가 많습니다. 때로는 "왜 우리가 그런대에 돈을 써야하죠?" 라는 말을 들으면 설득하려는 생각도 고이 접어 넣게됩니다.

 

비개발자 입장에서는 소프트웨어 내부의 복잡도가 체감되지 않기 때문에, 돌아가는 시스템을 뜯어고치는 일에 공감하기란 어렵습니다. 실제로 기능 요청을 받은 입장의 기획자나 사업 부서는 시스템 내부의 설계 부채보다는 겉으로 드러나는 제품의 변화에 관심이 크기 때문에, 개발자가 "지금 구조 개선이 필요합니다." 라고 호소해도 우선순위에서 밀리는 경우가 많습니다.

 

저 역시 "지금 빚을 쌓으면 나중에 더 큰 비용을 치를 텐데..." 라는 생각에 밤을 설친적도 있고 팀원들과 "어젠가 리팩토링을 하는 스프린트를 따로 잡자" 고 다집해보지만 그 "언젠가" 는 좀처럼 오지 않습니다. 이렇게 복잡성이라는 빚(기술 부채)은 계속 쌓여가고, 개발자는 속으로만 끙끙 앓으며 무력감을 느끼게 됩니다.

 

가끔은 개발자 스스로도 체념합니다. "어차피 지금은 시간도 없고, 이정도 복잡성은 그냥 안고 가자" 며 흐린눈을 하며 애써 외면하기도 합니다.

 

하지만 해결되지 않은 복잡성은 서서히 개발 생산성을 좀먹게 하고, 결국엔 모두가 체감하는 속도의 저하로 돌아옵니다.

아이러니하게도 처음에는 "빨리 가기 위해" 복잡성을 무시했지만, 나중에는 그 복잡성 때문에 "더 느려지는" 것이죠.

이 때 "아니 기능 하나 추가하는데 왜 이렇게 오래 걸려요?" 라는 말을 들으면 머리가 뜨거워지면서 개발에 대한 회의감까지 들기도 합니다.

 

한가지 더 흥미로운 점은, 때로는 개발자 자신들이 새로운 기술을 도입함으로써 복잡성을 증가시키기도 한다는 것입니다.

클라우드 시대의 풍부한 오픈 소스 툴과 서비스들은 개발자로 하여금 이것저것 써보고 싶은 유혹을 느끼게 합니다. 반면 관리자는 "너무 많은 툴을 쓰면 통제가 안된다"며 제동을 걸곤 합니다.

 

한 기사에서는 현대 개발 환경에서 개발자와 경영진 간의 충돌을 이렇게 묘사했습니다.

클라우드 네이티브 시대에는 부가적 복잡성이 과거 어느 때보다 증가했고, 개발자는 사용 가능한 모든 도구를 활용하고 싶어하지만 경영진은 고객 가치 전달에 집중하기를 원하기 때문에 서로 충돌하는 경우가 늘었다.

 

실제로 "왜 새로운 프레임워크를 쓰냐 vs 왜 최신 기술을 안쓰냐"를 두고 의견이 갈리기도 합니다. 뭐.. 누구 말이 맞다고는 못하지만 복잡성을 둘러싼 시각 차이가 개발자에게 좌절감을 안기는 셈입니다.

 

이러한 경험들은 개발자를 점점 현실적인 체념으로 이끌곤 합니다. 신입때 누구보다 열정적이던 사람이 1년 2년 해가 지나가면서 "완벽은 못 이루니, 돌아가기만 하면 됐지" 라는 식의 자조적인 농담이 팀 내에 퍼지기도 합니다.

하지만 속으로는 모두가 알고 있죠. 언젠가 그 복잡성의 대가를 치러야 할 순간이 올거라는 것을요.. 그 때 누군가는 이 사태에 대한 책임을 지어야겠죠.. (판단하는 사람에 따라 "책임" 이라는 단어가 맞는지는 모르지요)

 

중요한 것은 조직이 이 신호를 얼마나 진지하게 받아들이느냐입니다. 다행히도, 모든 조직이 복잡성을 방치하는 것은 아니고 일부 선도적인 기업은 일찍이 이 문제를 인식하고 복잡성을 다루는 고유한 문화와 도구를 만들어 왔습니다.

 

반대로 흔히 개발자의 무덤이라고 하는 SI/SM에서는 이러한 사태를 해결하기보단 일단 덮고 넘어가는 일이 반복됩니다. 단기적 일정 준수가 최우선이 되면서 결국 기술 부채는 쌓이고, 복잡성은 시간이 갈수록 눈덩이처럼 불어납니다.

 

복잡성을 다룬 조직 사례

복잡성의 늪에 빠지지 않기 위해 궁여지책으로 대응을 하거나 선제적인 대응을 한 조직들의 이야기는 많은 시사점을 줍니다. 이들은 기술적 해법뿐 아니라 조직 문화와 프로세스 측면에서도 혁신을 도모하여 복잡성을 관리해왔습니다. 아래는 몇가지 사례입니다.

우아한형제들의 내부 플랫폼 구축 및 셀스서비스 도구

우아한형제들은 서비스 인프라 조직을 두어 개발팀에 공통 인프라 서비스를 제공합니다. 예를 들어 Service Infra 실에서 모니터링, 배포 등 다양한 도구를 마련해 두었고, 백엔드 개발자들은 이를 활용하여 자체적으로 개발과 모니터링을 수용할 수 있습니다.

실제 채용 공고에서도 "서비스인프라실에서 제공하는 다양한 서비스를 이용해서 개발하고 모니터링" 한다고 명시해 개발 편의를 강조하고 있습니다.

 

높은 복잡성으로 인한 장애를 어떤 식으로 해결했는지

monolitic으로 시작했던 배달의민족 서비스는 사업 성장과 함께 시스템이 비대해지면서 잦은 장애를 겪었습니다. 하나의 거대한 Rails 서버에서 모든 기능을 처리하다 보니, 리뷰 기능에 문제가 생겨도 주문 전체에 장애를 주는 등 단일 장애점 문제가 심각했죠. 이를 해결하기 위해 2016년부터 핵심 도메인을 MSA로 분리하기 시작했습니다.

 

우선 결제 서비스를 분리하면서 문제가 많던 데이터베이스를 신규 구축하고, 주문중계 서비스도 Node.js로 빠르게 떼어내는 등 단계적 분해를 진행했습니다. 2017년 급증한 트래픽으로 거의 매일 장애가 나자, 검색, 메뉴, 정산, 쿠폰, 주문, 포인트 등의 서비스를 차례로 독립시켰습니다. 이 과정에서 AWS 클라우드로 데이터베이스를 이전하고 (법적 제약으로 결제 DB는 온프레미스 유지) 인프라를 클라우드/컨테이너 환경에 맞게 재편했습니다. 남은 레거시 부분은 2018년 "프로젝트 먼데이"를 통해 3개월간 집중 개선하여 모놀리스를 완전히 해체했습니다.

 

또한 MSA 도입 후 늘어난 서비스 간 통신 복잡도를 해결하고자 이벤트 기반 아키텍처를 도입했습니다. REST API로 서비스가 촘촘히 연결되면 한 서비스 장애가 연쇄 영향을 줄 수 있어, 주문 -> 리뷰 알림 같은 연동은 메시지 큐로 비동기화하였죠. 이를 통해 서비스 간 느슨한 결합을 이루고 장애 전파를 차단했습니다.

이러한 MSA 전환과 인프라 자동화 결과, 일부 시스템 장애가 전체에 미치는 영향을 줄여 신뢰성이 높아졌고 트래픽 증가에 따라 개별 서비스만 손쉽게 스케일 아웃하는 유연성을 확보했습니다.

 

개발자 생산성 향상을 위한 문화 및 조직 변화

MSA 전환과 함계 조직 구조도 도메인 중심 스쿼드 체계로 변화했습니다. 배달의민족 팀들은 배달, 가게, 메뉴, 주문중계, 정산 등 각 도메인별로 나뉘어 있고, 각 팀에 기획자(PM), 백엔드 개발자, 프론트엔드, QA/운영 담당자가 모두 포함된 목적 조직으로 일합니다. 이러한 크로스 기능 팀 구조를 통해 개발 초기부터 다양한 역할이 긴밀히 협업함으로써 요구사항을 빠르게 조율하고 복잡성을 낮추었습니다.

 

개발자는 정해진 정책만 구현하는 것이 아니라 PM과 함께 정책을 논의하며 만들어가는 문화를 가지고 있어, 비즈니스와 기술 간의 애해 갭을 줄이고 더 나은 제품을 도출하는 것이 인상적입니다.

 

또한 우아한형제들은 개발 문화로서 지속적인 개선과 공유를 중시합니다. 매달 한 번씩 백엔드 개발자 전원이 모여 지난달의 시스템 이슈를 회고/공유하는 자리를 갖고, 코드리뷰와 테스트 작성 습관을 장려하며 서로 성작하도록 합니다. 이러한 문화는 개발자 개인의 생산성을 높일뿐 아니라 문제를 조기에 발견하고 기술 품질을 담보하는 데 기여했습니다.

 

간혹 시스템 이슈가 발생했을 때, 원인을 파악하기보다는 누구의 잘못인지 추궁하거나 개인에게 책임을 묻는 조직 문화도 있습니다. 하지만 이는 결국 심리적 위축을 낳아 문제의 근본적인 해결을 어렵게 만듭니다. 좋은 문화란 문제가 발생했을 때 개인의 책임을 묻는 것이 아니라, 조직 전체가 이를 개선의 기회로 삼고 함께 배우는 것입니다. (물론 동일한 문제를 반복해서 발생시키는 경우는 여기에 해당되지 않습니다)

 

Spotify의 Golden Path

스포티파이는 애자일하고 자율적인 스쿼드 조직 문화로 유명합니다. 하지만 2010년대 중반, 이러한 자율성의 부작용으로 개발 도구와 방식이 파편화되는 문제가 나타났습니다. 팀마다 사용하는 기술 스택과 배포 방법이 달라서, 새로운 서비스를 만들 때 "어떻게 해야 하지?" 를 동료들에게 물어보는 수밖에 없었죠.

 

당시 내부에서는 이를 두고 rumour(소문) 주도 개발 이라 불렀다고 합니다. 잘못된 소문이 개발을 이끈다는 농담 섞인 표현이지만, 그만큼 표준화된 가이드가 없었다는 뜻입니다. 이런 상황에서 스포티파이 플랫폼 조직을 중심으로 개발 경험을 개선하기 위한 노력을 시작합니다.

그 결과로 나온 개념이 바로 Golden Path 입니다. 골든 패스란 스포티파이가 제공하는 공식적으로 권장되고 지원되는 개발 경로 를 뜻합니다.

 

예를 들어 백엔드 서비스 하나를 만들려면, 골든 패스 튜토리얼에 따라 스포티파이 표준 도구와 설정으로 시작하고 배포까지 진행할 수 있습니다. 이를 통해 개발자들은 일일이 최고의 방법을 찾아 헤맬 필요 없이, 검증된 길을 따라가는 것으로 빠르게 개발에 착수할 수 있게 됩니다.

골든 패스 중 일부를 보여주는 백스테이지 플랫폼(출처: Spotify)

"골든 패스의 취지는 엔지니어를 제한하려는 게 아니다. 오히려 툴을 재발명하지 않아도 되도록 해서 더 중요한 창의적 업무에 집중하고 다시 빠르게 움직일 수 있게 하는 데 있다" 라고 스포티파이 팀은 설명합니다.

 

골든 패스를 따르면 표준화된 도구와 문서, 지원 체계가 뒤따르기에 개발자는 인프라 세팅이나 관례 파악에 드는 정신적 에너지를 아낄 수 있습니다. 물론 원하는 경우 정석 경로를 벗어나 다른 도구도 쓸 수 있지만, 같은 수준의 지원을 받기 어렵다는 점을 명확히 했습니다.

 

이를 급성장으로 인해 느려지고 있던 개발 속도를 다시 끌어올릴 수 있었고, 현재는 대부분의 엔지니어가 골든 패스를 당연한 기반으로 여길 정도가 되었다고 합니다.

 

Internal Platform과 Self-Service

우아한형제들과 스포티파이 사례처럼 조직 내부에 개발자 경험을 전담하는 플랫폼 팀을 두고, 이들이 개발 환경을 표준화하고 "골든 패스"와 같은 포장된 길을 제공하는 전략이 점차 각광받고 있습니다. 이를 구현한 대표적인 예가 Amazon과 같은 빅테크 기업들입니다.

 

아마존은 일찍이 "Two pizza team"(두개의 피자를 나눠먹을 수 있는 팀의 크기) 이라는 소규모 자율 팀 구조를 도입하고, 각 팀의 서비스를 끝까지 책임지도록 하는 문화를 만들었습니다. 작은 팀이 독립적으로 서비스를 운영하려면 개발에서 배포까지 걸치는 많은 작업이 자동화되고 표준화되어야 했습니다. 그래서 아마존은 내부적으로 배포 시스템, 모니터링 툴, 통합 로그인 등 공유 플랫폼을 구축하여 각 팀의 공통 인프라를 재사용 하도록 했습니다.

 

"자동으로 할 수 있는 일은 모두 자동화하라. 사람이 판단해야 할 곳에만 사람이 개입하도록 하라" 라는 Vogels의 말 은 이러한 철학을 잘 보여줍니다. 또한 AWS 클라우드를 통해서도 복잡성 대신 관리해주는 추상화 서비스들을 고객에게 제공하고 있는데, 예를 들어 초창기에는 AWS 사용자들이 데이터베이스를 직접 설치/운영해야 했지만 곧 RDS와 같은 관리형 DB 서비스가 나와 복잡한 운영 부담을 AWS가 대신 지도록 바뀌었습니다.

 

이는 결국 "복잡성을 완전히 제거할 수는 없지만, 어디선가 대신 처리해주면 사용자는 단순하게 쓸 수 있다"는 것을 의미합니다. 아마존 내부든 외부 서비스든 플랫폼화를 통해 복잡성을 숨기고 개발자가 비즈니스 로직에 집중할 수 있게 한 것이죠.

 

이 외에도 Netflix나 Google 같은 기업들은 일찍부터 내부에 강력한 플랫폼을 구축하여 개발자들이 대규모 분산 시스템을 비교적 일관된 방식으로 다룰 수 있게 했습니다. 그 결과 작은 스타트업이었다면 감당하기 어려웠을 엄청난 트래픽과 변화의 속도를 유지할 수 있었죠.

 

이러한 사례들이 공통적으로 알려주는 바는 분명합니다. 복잡성은 내버려두면 저절로 해결되는 법이 없으며, 오히려 적극적으로 다루어야 줄어든다는 것입니다. 그리고 복잡성을 다루는 일은 단지 좋은 프로그래머 몇 명의 역량으로 되는 것이 아니라, 조직적 합의와 문화가 뒷받침되어야 가능한 일입니다.

 

지나친 분리의 역설

복잡성을 줄이기 위해 시스템을 분리하고 추상화하는 노력이 때로는 역설적 결과를 낳기도 합니다. 앞서 우리는 모놀리스에서 마이크로서비스로 전환한 사례들은 봤지만, 모든 경우에 이 접근이 성공적인 것은 아닙니다. 처음부터 지나치게 세분화된 설계는 오히려 생산성과 속도를 떨어뜨릴 수 있습니다.

 

흔히 "조기 추상화(Early Abstraction)" 나 "조기 최적화" 를 경계하라는 이야기를 하곤 합니다. 문제를 충분히 이해하기도 전에 추상 계층을 만들고 구조를 복잡하게 설계하면, 정작 구현은 어려워지고 얻는 이득은 미미해지기 쉽습니다.

 

소프트웨어 아키텍처에서도 마찬가지로, 필요 이상으로 서비스를 잘게 나누는 것이 항상 좋은 결과를 보장하진 않습니다. 마이크로서비스의 장점으로 흔히 배포 독립성, 확장성, 팀의 자율설 등을 들지만, 그 이면에는 서비스 검색, 버전 관리, 분산 트랜잭션, 모니터링의 복잡도, 그리고 수많은 코드베이스를 이해해야 하는 kognitive load와 같은 큰 부담이 존재합니다.

 

작은 조직이나 초기 단계 스타트업이 이런 복잡한 분산 시스템을 도입하면 얻는 것보다 잃는 것이 많아질 수도 있습니다.  실제로 많은 성공한 기술 기업들도 초창기에는 단일 모놀리식으로 시작해서 충분히 성장한 뒤에야 상황에 맞춰 서비스를 분리해나갔습니다. 구글 아마존 넷플릭스 같은 회사들도 처음부터 마이크로서비스였던 게 아니라, 규모가 커지면서 점진적으로 아키텍처를 진화시켜 온 것입니다.

 

너무 빨리, 너무 많이 쪼개진 시스템은 일종의 "분산된 모놀리스(distributed monolith)" 가 될 수 있습니다. 겉보기에는 서비스가 나눠져 있지만 실제로는 서로 강하게 얽매여 있어 한 서비스를 바꾸려 해도 연쇄적인 수정이 필요하고, 배포도 한 덩어리처럼 움직이는 경우죠.

이는 최악의 상황인데, 마이크로서비스의 복잡성과 모놀리식의 경직성을 모두 갖게 되는 셈이니까요.

 

이런 사례를 겪은 일부 조직은 다시 모놀리스로 회귀하거나 서비스 통합을 모색하기도 합니다. 물론 그렇다고 해서 큰 시스템을 영원히 하나로만 유지할 수는 없습니다. 핵심은 시기와 방법입니다. 마틴 파울러(Martin Fowler)는 "Monolith First" 라는 지침에서, 모놀리스로 먼저 만들어서 성공을 검증하고 필요할 때 서비스 분리를 고려하라고 조언했습니다. 섣부르게 분산 시스템의 복잡성을 도입하지 말라는 뜻이죠.

 

플랫폼 없는 분산화의 위험도 짚고 넘어가야 합니다. 앞 사례에서 보았듯이, 스포티파이나 아마존은 마이크로서비스로 인한 복잡성을 감당하기 위해 내부 플랫폼과 표준화에 상당한 투자를 했습니다. 만약 이런 플랫폼 없이 각 팀이 자체적으로 모든 것을 해결해야 했다면 스포티파이의 "소문 주도 개발" 상태에서 헤어나오기 어려웠을 것입니다. 너무 많은 선택지는 개발자에게 자유와 동시에 혼란을 줍니다.

 

레드몽크(Redmonk)의 애널리스트인 Stephen O'Grady는 서비스 카탈로그가 방대해질수록 그 복잡성 자체가 생산성을 갉아먹어 강점이 아닌 부담으로 작용할 수 있다고 지적했습니다. 켈시 하이 Tower(Kelsey Hightower)역시 "현대 개발자에게 주어진 선택지의 풍요로움은 선문이자 저주"라고 표현했습니다. 선물이라 함은 거의 무제한에 가까운 기술을 활용할 수 있지만 본래 업무 외의 복잡한 인프라 영역까지 클려 들어가야 한다는 점입니다.

 

그는 "결국 한동안 이어졌던 큰 분산의 흐름이 다시 통합의 방향으로 움직이고 있다" 고 말하는데 이는 업계가 복잡성의 균형점을 다시 찾아가고 있다는 의미로 들립니다. 실제로 쿠버네티스와 클라우드가 유행을 지나 안정기에 접어들면서, 초기의 혼돈을 정리하고 보다 관리하기 쉬운 형태통합 플랫폼을 도입하는 기업들이 늘고 있습니다. 한동안 모두가 자체적으로 구축하던 CI/CD 파이프라인, 서비스 메시, 인증 시스템 등을 이제는 전문 벤더나 오픈소스 플랫폼에 맡기는 추세가 그 예입니다.


궁극적으로 복잡성을 다루는 일은 균형의 예술 인 것 같습니다.

너무 느슨하면 무질서가 발생하고, 너무 엄격하면 속도가 떨어집니다.

너무 이르게 쪼개면 산만해지고, 너무 늦게 쪼개면 거대 괴물이 되어버리죠.

중요한 것은 우리 조직과 제품의 맥락에 맞는 적절한 수준의 추상화와 분리를 찾아내는 것입니다.

 

결국 아키텍처에 정답은 없다는 말이 여기에 적용됩니다. 다만 나쁜 아키텍처의 징후는 비교적 분명합니다.

  • 구성원의 변경이 없으나, 팀의 생산성이 눈에 띄게 떨어진다.
  • 디버깅에 드는 시간이 폭증한다.
  • 신규 입사자가 시스템을 이해하는데 몇 달씩 걸린다.

그럴 때 우리는 한 발 물러서서 "무엇이 우리를 느리게 만드는가?" 를 자문해볼 필요가 있습니다. 너무 많이 나누었기 때문일 수도 있고, 반대로 더 나누지 않아서 모든 것이 엉켜있기 때문일 수도 있습니다. 결국 답은 조직이 스스로 찾아내야 하나, 중요한건 복잡성에 대한 인식 자체를 공유하고 논의하는 일입니다.

 

결론

소프트웨어 개발에서 복잡성은 피할 수 없는 동반자입니다. 완전히 없앨 수 있다면 가장 좋겠지만, 현실적으로 복잡성을 없앤다기보다는 다른 형태로 관리 하는 것이 우리의 과제입니다. 좋은 개발 조직은 끝없는 새로운 기능 요구와 시장의 압박 속에서도 기술 부채와 복잡성의 위험을 외면하지 않고 직시합니다.

 

개발자들고 비개발자 모두가 복잡성의 존재와 비용을 이해하고, 이를 줄이기 위해 같은 언어로 대화할 수 있어야 합니다. "복잡성 때문에 속도가 느려지고 있다"는 개발자의 호소에 공감하지 못하는 조직이라면, 이미 위험 신호가 켜진 것일지도 모릅니다. 반면에 "지금 당장은 돌아가지만, 앞으로를 위해 구조를 개선하자"는 결정을 내릴 수 있는 조직이라면 장기적으로 큰 이익을 볼 가능성이 큽니다.

 

하지만 현실을 무시한 이상론만을 펼칠 수는 없습니다. 결국 개발은 비즈니스를 돕기 위해 존재하고, 때로는 기술적 아름다움보다 현실적인 타협이 필요하기 마련입니다. 개발자는 완벽한 시스템과 현실적인 일정 사이에서 매일 줄타기를 하는 사람들입니다. 그런 점에서 개발자는 단순히 키보드를 두드리는 기계가 아니라, 시스템과 현실 사이의 균형점을 찾는 엔지니어라고 할 수 있습니다. 좋은 개발 조직은 이 균형을 잘 설계해놓은 조직입니다. 필요한 복잡성과 불필요한 복잡성을 구분하고 후자를 줄이기 위한 투자를 아끼지 않는 조직이 결국 지속적인 속도와 품질을 얻습니다.

 

마지막으로, 복잡성에 대한 공감과 소통의 중요성을 강조하고 싶고 "우리 이렇게하면 힘들지 않나요?" 라는 공감의 시작이 복잡성을 낮출 수 있는 확실한 출발 신호라고 생각합니다. 우리가 처한 복잡성을 누구 탓으로 돌리기보다 함께 짊어져야 할 도전으로 인식할 때, 해결의 실마리가 보이기 시작할 것 입니다.

 

시스템을 단순하게 유지하는 것, 사람들이 복잡성으로 지쳐가지 않도록 배려하는 것 이것이 업계가 추구해야 할 방향이라고 생각합니다.

오늘도 복잡성과 씨름하고 있을 수 있는 수많은 개발자들에게 공감이 되었으면 좋겠고, 우리 모두 같은 목표를 가지고 있음을 기억했으면 합니다.

 


[참고자료]

https://www.infoworld.com/article/2270714/complexity-is-killing-software-developers.html#:~:text=%E2%80%9CComplexity%20kills%2C%E2%80%9D%20Lotus%20Notes%20creator,%E2%80%9D

 

Complexity is killing software developers

The growing complexity of modern software systems is slowly killing software developers. How can you regain control, without losing out on the best these technologies have to offer?

www.infoworld.com

https://www.runtime.news/werner-vogels-complexity-is-inevitable/#:~:text=a%20lack%20of%20architectural%20oversight%2C,can%20only%20move%20somewhere%20else

 

Werner Vogels: "Complexity is inevitable"

Today: Amazon CTO Werner Vogels closes AWS re:Invent 2024 with advice on how to make complex things simple, OpenAI unveils an absurdly expensive subscription plan for its latest model, and the latest enterprise moves.

www.runtime.news

https://woowahan.oopy.io/fbb1a960-8a4c-4d8e-9e7a-4c4946c975a0

 

[배민플랫폼실] 서버 개발자

업무 내용

woowahan.oopy.io

https://sihyung92.oopy.io/architecture/woowa-msa-travel

 

MSA, 배달의 민족 마이크로서비스 여행기 정리

우아콘 2020 - 배달의 민족 마이크로서비스를 제 글로 정리한 내용입니다.

sihyung92.oopy.io

https://toss.tech/article/22563

 

은행 최초 코어뱅킹 MSA 전환기 (feat. 지금 이자 받기)

수십 년간 정체되어 있던 전통적인 은행 시스템의 모놀리식 소프트웨어 아키텍처를 MSA로 전환할 수 있을까요? 토스뱅크의 ‘코어뱅킹 MSA 전환’ 사례를 통해 향후 은행 시스템이 나아가야 할

toss.tech