[회고록] 내 안의 흑염...ㄹ.... 아니, DDD가 깨어났다.
수백 개 컬럼, 이건 뭔가 잘못됐다.
예전에 회사에서 작업하다가 테이블 컬럼이 수백 개인 걸 봐버렸다. 도대체 왜 이렇게 많은 데이터가 한 테이블에 몰려 있는지 이해할 수 없었다. 이건 그냥 구조의 문제인가? 설계 미스인가? 아니면 내가 뭔가를 놓치고 있는 건가? 머릿속이 복잡해지면서 자연스럽게 '도메인', '엔티티', 'DDD' 같은 단어들이 떠올랐다. 사실 DDD는 몇 번 책도 보고 강의도 들어봤지만, 선뜻 와닿지 않았다. 그런데 이상하게 이 수많은 컬럼을 가진 테이블을 보고 나니까, 내가 그동안 이해하지 못했던 것들이 하나씩 연결되기 시작했다. 약 7개월 전의 일이지만, 이제서야 그때 느꼈던 생각들을 정리해보려 한다.
왜 개발자는 괴로운가?
테이블 컬럼이 100개인 거대한 역정규화 ‘Device Meta’ 테이블이 있다고 가정해보자. 성능면에서만 바라보면 DBA 입장에서는 나쁘지 않다. 한 번의 쿼리로 모든 데이터를 다 가져올 수 있다. 심지어 관리 포인트도 하나로 끝나니까 깔끔하다. 이건 역정규화의 끝판왕이고, 크게 문제만 없다면 굳이 위험을 무릅쓰고 손댈 이유가 없다. 하지만 서버 개발자 입장에서는 상황이 전혀 다르다. 관련 없는 필드 100개가 하나의 테이블에 묶여 있고, 그걸 엔티티로 그대로 매핑하자니 객체지향적인 설계는 기대할 수 없다. 코드 구조는 복잡해지고, 유지보수는 어려워진다.
“혹시 정규화 가능할까요?”
이로 인해, 개발자는 테이블을 쪼개보자는 아이디어를 떠올리고 DBA를 설득하려 한다. "혹시 테이블 정규화 가능할까요?" 그러나 DBA는 단호하다. “죄송해요. 이미 잘 돌아가고 있기도 하고.. 성능 저하 및 사이드 이펙트 우려가 큽니다.” 실제로 테이블을 나누려 하면 연관된 시스템, 쿼리, 서비스 전반에 걸쳐 부작용이 생긴다. 결국 개발자도 이 구조를 바꾸는 건 현실적으로 어렵다는 걸 받아들이게 된다. 하지만 그렇다고 100개 필드를 하나의 엔티티로 받아들이는 것도 용납할 수 없다. 그건 객체지향적으로 설계된 시스템이 아니라 단지 테이블에 끌려다니는 코드일 뿐이다.
테이블은 그대로, 도메인은 어떻게?
개발자는 결론을 내린다. “도메인 객체 단위로 분리하자”. 테이블이나 엔티티는 그대로 두고, 코드 상에서 100개 필드 중 관련 있는 필드끼리 묶어 DeviceConfig, NetworkSetting, FirmwareInfo 같은 도메인 객체로 나눈다. 이 객체들은 하나의 엔티티 내부에 포함되거나, 속성으로 조합되어 사용된다. 놀랍게도 이렇게 하니 테이블은 하나 그대로지만, 코드 구조는 도메인 단위로 명확하게 분리되고 객체지향적인 설계가 가능해졌다. 도메인은 테이블이나 엔티티와 1:1 이어야 할 필요가 없다. 도메인은 업무 개념의 경계이고, 그 안에 어떤 객체가 어떻게 존재하느냐는 전적으로 업무 규칙과 책임 분리에 따라 설계되어야 한다.
착각에서 벗어나기.
우리가 이전까지 도메인을 이해하지 못했던 이유는 단순하다. “도메인 엔티티 테이블”이라는 잘못된 등식에 빠져 있었기 때문이다. 테이블이 하나니까 도메인도 하나여야 하고, 객체도 그대로 따라가야 한다고 생각했다. 하지만 실제로는 테이블은 물리 저장소일 뿐이고, 도메인은 그 위에서 업무를 어떻게 표현하고 관리할지를 결정하는 추상화의 단위다.
항상 이상적일 수는 없다.
물론 원칙적으로는 도메인 하나 안에 여러 엔티티가 존재하는 구조가 일반적이다. 예를 들어 주문 도메인에는 Order, OrderItem, ShippingInfo, Payment 같은 각각의 역할과 생명주기를 가진 엔티티가 존재한다. 이게 객체지향적이고 DDD에 가까운 모델링으로 보인다. 그러나 지금처럼 레거시 시스템이나 DBA 주도의 물리 설계가 먼저 된 경우, 도메인을 먼저 고려한 구조가 불가능한 상태에서의 차선책이 필요한 것이다.
결국, 중요한 건 설계다.
결국 이 모든 경험이 말해주는 건 하나다. “첫 설계가 정말 중요하다.” 도메인을 먼저 이해하고, 그에 맞는 테이블과 엔티티 구조를 처음부터 설계할 수 있었다면 불필요한 설득과 타협 없이 더 이상적인 구조를 가질 수 있었을 것이다. 하지만 그렇지 못한 상황이라면, 도메인 개념을 코드에서라도 분리해서 표현하는 것이 현실적으로 객체지향을 회복하는 실마리가 되어줄지도 모른다.