1. "이거 하나 고치려면 몇 군데를 봐야 하죠?" - 비즈니스 코드를 UI에서 구출하기
"새로운 할인 정책이 추가됐는데, 어디어디 수정해야 할지 모르겠어요."
"분명 같은 로직인데, 왜 여기저기 복사-붙여넣기 되어 있죠?"
"이 if문은 대체 어떤 비즈니스 규칙을 나타내는 건가요?"
만약 이런 고민을 해봤다면, 당신의 코드는 여러 비즈니스 규칙과 책임들이 한곳에 뒤엉켜 있을 가능성이 높습니다. 하나의 기능을 수정하기 위해 여러 파일을 넘나들어야 하고, 변경의 영향 범위를 예측하기 어려운 상태. 이것이 바로 '도메인 분리'가 필요한 명확한 신호(Trigger)입니다.
트리거 체크리스트:
•
•
•
2. 구출 작전: 뒤엉킨 코드에서 비즈니스 규칙 분리해내기
이 문제를 해결하는 핵심은 각자의 역할과 책임을 명확히 나누는 것입니다. 아래 두 가지 사례를 통해, 뒤엉킨 코드에서 어떻게 비즈니스 규칙(도메인)을 구출해내는지 보겠습니다.
3. 원칙: '도메인'이란 무엇이고, 왜 분리해야 하는가?
지금까지 예시를 통해 우리가 분리해낸 것, 그것이 바로 도메인(Domain)입니다.
도메인이란 간단히 말해 '우리가 해결하려는 비즈니스 문제의 영역과 그 규칙들'을 의미합니다. '할인 정책', '배송비 계산', '회원 등급 시스템' 등이 모두 하나의 도메인이 될 수 있습니다.
🏢 회사 = 여러 도메인의 집합
├── 📦 상품 도메인 (상품팀이 관심)
├── 👥 회원 도메인 (CRM팀이 관심)
├── 💳 결제 도메인 (정산팀이 관심)
└── 🚚 배송 도메인 (물류팀이 관심)
Plain Text
복사
도메인 분리란, 이렇게 각기 다른 비즈니스 관심사를 코드 레벨에서도 독립적인 모듈로 분리하여, 서로의 영역을 침범하지 않도록 경계를 명확히 긋는 설계 패턴입니다.
도메인을 잘 분리하면 코드가 비즈니스 문서의 역할을 하게 됩니다.
기획자나 다른 팀 동료가 "우리 서비스의 할인 정책이 궁금해요"라고 물으면, 복잡한 문서를 찾는 대신 domain/discount.ts 파일을 보여주며 함께 이야기할 수 있게 됩니다.
도메인 로직 vs 일반 로직
// 🏪 도메인 로직: "회사의 돈이 되는 규칙"
const calculateVIPDiscount = (amount) => amount * 0.15
const isEligibleForFreeShipping = (amount) => amount >= 50000
const getReturnPeriod = (category) => category === 'food' ? 3 : 14
const calculate배송비 = () => { ... } // "배송비를 어떻게 책정할까?"
const check재고 = () => { ... } // "재고가 충분한가?"
const apply할인 = () => { ... } // "얼마나 할인해줄까?"
// 🔧 일반 로직: "기술적인 구현"
const formatPrice = (price) => price.toLocaleString()
const debounce = (fn, delay) => { ... }
const parseQueryString = (url) => { ... }
const useWebSocket = () => { ... }
const implementCache = () => { ... }
TypeScript
복사
더 깊이 알아보기: 도메인과 애그리게이트
•
도메인(Domain): ‘우리가 해결하려는 실제 비즈니스 문제의 영역’입니다. "회사의 돈이 되는 규칙"(calculateVIPDiscount)은 도메인 로직, "기술적인 구현"(formatPrice)은 일반 로직으로 구분할 수 있습니다.
•
애그리게이트(Aggregate): 여러 도메인이 모여 하나의 의미 있는 단위를 만드는 것입니다. 예를 들어 '주문'이라는 하나의 개념을 완성하려면 '누가(User)', '무엇을(Product)', '어떻게(Payment)' 등의 여러 도메인 정보가 필요합니다.
◦
배달앱을 만든다고 생각해볼까요? 단순히 "음식 주문하고 배달하기"라고 생각하기 쉽지만, 실제로는 여러 도메인이 복잡하게 얽혀있어요.
🍕 배달앱의 도메인 (상호 연결된 전체)
├── 주문 도메인 (Aggregate Root)
│ ├── 👤 User: 누가 주문하는가
│ ├── 📦 Product: 무엇을 주문하는가
│ ├── 💳 Payment: 어떻게 결제하는가
│ └── 📍 Address: 어디로 배달하는가
│
├── 배달 도메인 (Aggregate)
│ ├── 📦 Order: 무엇을 배달하는가 (주문 참조)
│ ├── 🏃 Rider: 누가 배달하는가
│ ├── 🏪 Store: 어디서 픽업하는가
│ └── 📍 Route: 어떤 경로로 가는가
│
└── 🔗 도메인 간 관계
└── 주문 생성 → 배달 요청 → 라이더 배정 → 리뷰 생성
Plain Text
복사
◦
보시다시피 '배달'이라는 도메인은 독립적으로 존재할 수 없어요. 반드시 '주문'이 있어야 하고, 그 주문을 처리할 '라이더'와 '가게'가 필요하죠. 각 도메인은 자신만의 규칙과 책임을 가지면서도, 다른 도메인과 협력하여 전체 시스템을 구성합니다.
•
도메인 찾기 팁: "누가 이 규칙을 바꿀까?"를 질문해보세요. 마케팅팀이 바꾸면 '프로모션' 도메인, 정산팀이 바꾸면 '결제' 도메인일 가능성이 높습니다.
