바보야, 그걸 왜 나눠? 아니 그건 왜 합쳐?
복잡해 보이지만 본질은 간단하다. 소프트웨어의 '내부 구조 설계' 어떻게 할 것인가? 질문에 답하는 것이다.
겉으로는 같은 건물처럼 보여도 그 안에 어떤 자재와 구조를 사용했느냐에 따라 내구성과 유지보수 비용이 달라진다.
소프트웨어도 마찬가지다. 이커머스 플랫폼이 서로 비슷해 보여도, 설계가 엉망이면 리펙터링과 유지보수 비용이 눈덩이처럼 불어나고,
결국 오래 버티지 못하는 코드베이스가 된다.
지금 내가 속한 서비스도 실제 상황도 크게 다르지 않다.
1. 과거의 잘못된 선택이 지금까지 발목을 잡고 있다. 처음부터 탄탄한 설계를 하지 못한 탓에, 비즈니스 요구사항이 생길 때마다 하드 코딩으로 임시방편을 반복했다.
2. 결과는 참혹했다. 코드는 점점 난잡해졌고, 새로운 기능을 추가할수록 가치전달 속도는 느려지고, 버그는 늘어났다. 개발자 한 명이 코드를 이해하는 데만 기존보다 5배 이상의 시간이 걸린다.
3. 이커머스의 기본 기능(상품 주문, 회원관리, 결제, 환불)조차도 각 모듈이 어디서 어떻게 동작하는지 찾기가 어렵다. 하나의 로직을 수정하면 예상치 못한 문제가 연쇄적으로 터지고, 유지보수를 하다가 결국 포기하고 싶어질 정도다.
4. 그리고 이 모든 결과가 테스트 코드 포기라는 최악의 상황으로 이어졌다. 단위 테스트가 가능하려면 로직이 일정한 규칙을 가져야 하는데, 현재 시스템은 변수도 많고 구조도 엉망이라 테스트 자체가 어려워졌다. 결국 QA에 의존하는 상황이 반복되고 있다.
그래서 우리는 어떻게 했을까?
"처음부터 다시 설계한다"
극단적인 선택처럼 보이지만, 현실적으로 다른 방법이 없었다.
2024년 하반기부터 우리는 이 문제를 해결하기 위해 움직였고, 현재(2025년) 가장 중요한 프로젝트로 진행 중이다.
이번 리팩토링의 핵심은 복잡한 비즈니스 로직을 체계적으로 정리하고, 이해하기 쉬운 방식으로 모듈화 하는 것.
그리고 이 과정에서 개발팀과 비즈니스팀 간의 의사소통을 원활하게 만드는 것이다.
우리가 선택한 접근법은 Domain-Driven Design(DDD). 이 방법론을 적용하면, 현재 하나로 보이는 서비스 안에서도 각 기능을 독립적인 서비스로 분리할 수 있다. 특히 모놀리식 아키텍처를 의도적으로 추구할 때 데이터 공유와 호출의 용이함을 얻을 수 있다
이 과정에서 가장 중점을 둔 것은 불필요한 복잡성을 제거하면서도 UX를 유지하는 것.
도메인을 MECE 원칙((Mutually Exclusive + Collectively Sxhaustive) )에 따라 나누고, 기존 시스템을 무너뜨리지 않으면서도 새로운 구조를 적용할 방법을 고민했다.
특히, 비즈니스와 개발 환경에서 용어 정리를 체계화하는 작업이 필수적이었다.
예를 들어, "이벤트(Event)"라는 단어가 개발팀에게는 프로그래밍 이벤트를 의미하지만, 커머스팀에게는 특정 기간 동안 진행되는 할인 프로모션을 뜻했다.
같은 단어가 서로 다른 의미로 쓰이면, 시스템과 비즈니스의 괴리가 커질 수밖에 없다.
(DDD에서는 Bounded Context 개념으로 설명한다. 하나의 도메인 내 의미가 일관되는 논리적 결계를 뜻한다. 예를 들어 Order라는 개념은 고객 컨텍스트에서는 '주문상태' 지만 물류 컨텍스트에서는 '배송경로'이며, 재고 컨텍스트에서는 '재고 감소'를 의미할 수 있다)
이 과정에서 중요한 깨달음이 있었다.
'상품을 판매한다'라는 이커머스 본연의 core domain을 기획(설계)할 때 '상품을 N개 등록할 수 있다'라는 단순한 하부 도메인 (Supprting subdmain) 내용이 특정 부서로부터는 한정된 맥락(Bounded context)으로 받아들여질 수 있다는 사실이다.
실제 예시로
"상품을 N개 등록가능하도록 설계하겠습니다" -라고 공유하자 한 팀에서 피드백이 왔다
'우리 부서는 단일 상품 등록만 허용하고 싶습니다. 전체 적용 되면 운영 리소스가 부담되니, 커스텀할 수 있으면 좋겠어요'
이때, 아차차! 싶었다. 내가 알고 있는 것이 상대도 당연히 알겠지 생각하고 '너무 쉽게' 간단하게 설명했고, 오해가 생겼던 것이다. (Curse of Knowledge)
하부 도메인은 코어기능이 잘 동작하도록 '보편적으로 설계'된 것이다. 이를 한정된 맥락처럼 따로 운영하게 된다면 불필요한 개발 비용이 증가하고, 사용자 경험이 복잡해진다. 이 사실을 해당 팀에 친절하고 자세하게 설명했어야 하는데 이를 놓쳤고, 불필요한 오해가 생긴 것이다.
요약하면, 고객입장에서는 상품 업로드 방식이 1개든 10개든 간에 이 서비스를 사용하는 차별화 포인트는 아니다. 핵심 기능을 운영하는데 필요한 '당연하고 보편적인' 영역일 뿐이다.
반대로, 운영팀과 개발팀, 전략팀은 서로 다른 주문 데이터를 봐야 할 필요가 있다.
예를 들어, Order data 내 상품 상세페이지의 로딩속도는 개발팀에 필요할 것이고, 상품 카테고리 별 구매전환 비율은 전략팀에 좀 더 필요할 것이고, 해당 상품의 CS 비율은 운영팀에 더 필요한 정보다.
이런 특수성을 무시하고, 모두 같은 주문 데이터만 보게 강요한다면 각 팀의 요구사항을 고려하지 않아 데이터 분석에 상당한 비용이 발생하게 된다.
--------------------------------------------------------------
#결론
이번 프로젝트를 진행하며 DDD의 중요성을 실전에서 체감하고 있다.
머리로는 알고 있었지만, 실제 프로젝트에서 하부 도메인과 한정된 맥락을 구분하는 것이 얼마나 중요한지 몸소 깨닫는 중이다.
✅ "모든 기능을 다르게 만들면 비효율적이다."
✅ "하지만 같은 기능이라도 다르게 보여줘야 할 때를 놓치면, 사용자는 불편해진다."
이것이 바로 소프트웨어 아키텍처가 중요한 이유이고, 동시에 어렵다고 느껴지는 이유다.
혹시 이 글을 읽는 당신도 나와 비슷한 고민을 하고 있다면,
우리 시스템의 각 부분이 어디까지 독립적이고, 어디까지 공통적으로 운영되어야 하는지 고민해 보자.
이 차이를 명확하게 이해하는 것이, 더 나은 소프트웨어를 만드는 첫걸음이 될 것이다.
끝