올리브영 테크블로그 포스팅 10년 된 레거시를 현대화하다 - Part.1: 도메인 분리의 첫걸음
Tech

10년 된 레거시를 현대화하다 - Part.1: 도메인 분리의 첫걸음

오프라인 매장 서비스를 중심으로 본 DDD 전략적 설계 사례

2025.01.24

매장 도메인 분리의 첫걸음

안녕하세요! 올리브영에서 매장 도메인을 담당하고 있는 알렉스입니다 :)

2023년도 11월에 주니어 개발자의 우당탕탕 입사기로 첫 포스팅을 하고 벌써 1년이라는 시간이 흘렀는데요.
이전 글에서 마무리 멘트로 "다음 글에서는 O2O 서비스를 모듈화·모던화 하면서 직면하는 기술 문제들을 해결해 나가는 경험을 소개하겠다"고 했었습니다.
그 약속을 지키러 다시 돌아왔습니다 😄

저희 매장BO 스쿼드에서 지난 1년간 어떤 여정을 떠나왔는지 아래와 같은 시리즈로 소개해 보려고 하는데요!

  1. 10년 된 레거시를 현대화하다 - Part.1: 도메인 분리의 첫걸음
  2. 10년 된 레거시를 현대화하다 - Part.2: 매장 도메인의 구현 여정
  3. 10년 된 레거시를 현대화하다 - Part.3: 온라인 서비스로의 확장
  4. 10년 된 레거시를 현대화하다 - Part.4: 대고객 맞이 성능 테스트 전략 구축

이번 포스팅에서는 Part.1 도메인 분리의 첫걸음이라는 주제로 시작하겠습니다 🚀
(이 글에서는 "기술" 얘기가 많이 없으니 편하게 봐주세요 🙌)


목차

  1. 10년 된 레거시에는 어떤 문제들이 있었을까?
    • 레거시에 한 발짝 다가가기
    • 비즈니스 로직의 분산
  2. 매장 서비스의 시작
    • 도메인 경계 식별하기
    • 컨텍스트 매핑
  3. 다음 이야기

10년 된 레거시에는 어떤 문제들이 있었을까?

레거시에 한 발짝 다가가기

레거시를 모던화할 때의 첫 단추는 무엇일까요? 저는 그 레거시의 히스토리를 파헤치고, 이해하는 것이 가장 우선이라고 생각합니다.
10년 전으로 거슬러 올라가 보겠습니다.

올리브영은 초창기에 내부 개발자가 존재하지 않았습니다. 그때 당시 모든 CJ 계열사의 전반적인 IT 담당은 CJ올리브네트웍스가 맡았기 때문에, 올리브영의 개발·운영 관련 업무 역시 올리브네트웍스가 진행했었습니다.


이때 탄생한 백오피스 플랫폼이 바로 올리브원이라는 시스템입니다.
이 올리브원이라는 백오피스 플랫폼에는 매장, 발주/입고, 재고, 상품, 오프라인 쿠폰, 포인트 등 정말 다양한 도메인들이 한 통에 담겨있었습니다.

그러다 2021년도를 기점으로 올리브영에 뛰어난 개발자분들이 대거 합류하기 시작하면서, 7명에서 시작한 내부 개발 조직은 현재 20배 이상으로 급격하게 늘어났습니다.
이에 따라 발주/입고 등을 관리하는 SCM 스쿼드, 재고를 관리하는 인벤토리 스쿼드, 상품을 관리하는 상품 메타 스쿼드, 쿠폰/증정을 담당하는 쿠폰증정 스쿼드 등 정말 많은 스쿼드가 생겼는데요.
현재 각 스쿼드는 각자의 오너십 도메인을 올리브원으로부터 분리해나가고 있는 상태입니다.

하지만 여기서 애매한 도메인이 있습니다.
바로 매장이라는 도메인인데요. 올리브영의 모든 서비스는 항상 매장에서 시작되고 끝나기 때문에, 대부분의 스쿼드에서 이 매장에 대한 정보를 필요로 합니다.
하지만 이 매장에 대한 오너십을 가지고 API나 기타 방법으로 정보를 제공하는 스쿼드가 없었기 때문에, 각 스쿼드는 DB에서 매장 테이블을 직접 바라보는 사태가 벌어졌습니다.


비즈니스 로직의 분산

여러 스쿼드가 매장 테이블을 직접 바라볼 경우 어떤 문제점들이 있을까요?
한가지 예시를 들어보겠습니다. Alex 손님은 오늘 올리브영N 성수점을 방문하고 싶습니다.
따라서 현재 영업 중인지, 아직 영업 전인지, 아니면 마감했는지 미리 확인하고 싶은 상황이라고 가정해 보겠습니다.

이때 판단 기준은 아래와 같습니다.

  • 해당 매장이 정상적으로 개점한 매장인지? 아니면 아직 공사 중인 매장이거나 폐점한 매장인지?
  • 오늘이 매장 휴무일인지?
  • 오늘의 영업시간은 몇 시부터 몇 시인지?
  • 현재 시간이 영업시간 안에 포함되어 있는지

여기서 한가지 정책이 추가됐다고 가정해 보겠습니다.

  • 기존 매장 영업시간은 월요일부터 일요일까지 각각의 오픈/마감 시간이 세팅되어 있습니다.
    • 수요일 영업시간은 10:00 ~ 22:00 라고 가정해 봅시다.
  • ※ 추가 정책 ※ : 설날, 추석 등의 공휴일일 때는 별도의 영업시간으로 관리해야 합니다.
    • 오늘은 설날(수요일)이고 설날 영업시간은 10:00 ~ 18:00 라고 가정해봅시다.

이 경우 어떤 일이 발생할까요?
모든 스쿼드가 이 정책을 잘 전달받아서 로직을 수정하면 다행이지만, 이 정책을 놓친 스쿼드가 있다고 해보겠습니다.

해당 스쿼드의 서비스에서는 분명 영업시간이 10:00 ~ 22:00 라고 표시됐기에, ALEX 손님은 19:00 쯤에 매장을 방문했지만 오늘은 설날이라 18:00까지 밖에 영업을 안 하니 이미 문을 닫은 상태일 겁니다.
이런 사례가 반복된다면 자연스럽게 사용자의 서비스 신뢰도는 하락하겠죠.
하지만 매장 정보를 한 곳에서 통합적으로 관리하고 제공한다면 이 문제는 쉽게 해결될 수 있을 것입니다.



매장 서비스의 시작

저희 매장 BO 스쿼드는 팀장님과 테크 리더의 지원 하에 매장 서비스를 구축하기로 결정했습니다.
매장 서비스는 매장 도메인에 대한 오너십을 맡고, 매장에 관련된 정책을 응집하여 관리하고 매장 정보를 제공하는 서비스입니다.
물론 올리브원이라는 레거시에서 매장 도메인을 떼어내는 것도 포함입니다.



도메인 경계 식별하기

특정 도메인을 추출하려고 할 때 우선으로 필요한 것이 무엇일까요? 먼저 매장 도메인과 다른 도메인 간의 관계를 대략적으로 파악해야 합니다.

이렇게 간략하게만 그려봐도 매장 정보들의 전체적인 흐름을 직관적으로 볼 수 있는데요.
매장 도메인은 POS, 매장 전시, 상품 등 여러 타 도메인과 협력하는 관계입니다.

하지만 더 중요한 것은 매장 도메인과 관련된 하위 도메인들을 식별하는 작업입니다.
이 매장 하위 도메인들이 특정 기준을 갖고 경계가 지어지는데, 이 경계를 바운디드 컨텍스트라고 부릅니다.
오랫동안 경계가 모호했던 영역이라서 명확하게 분리하기는 어려웠지만, 이 바운디드 컨텍스트를 기준으로 저희 스쿼드의 업무 범위가 결정될 예정이었으므로 최대한 이 경계를 식별할 필요가 있었습니다.

바운디드 컨텍스트를 최대한 식별해야 할 때 어떤 요소들이 필요할까요? 저는 아래 3가지의 요소가 필요하다고 생각합니다.


다행히 저희 스쿼드에는 매장에 대한 도메인을 누구보다 잘 알고, 실제로 CJ올리브네트웍스에서 올리브원을 개발하다 오신 PO와 개발자분들이 계셨습니다.
따라서 저희는 이분들과 함께 회사의 지원으로 AWS Korea에서 퍼실레이터의 가이드에 따라 이벤트 스토밍 워크숍을 진행하였습니다.



하루 종일 진행한 이벤트 스토밍에서는 다양한 커뮤니케이션을 통해 정말 많은 정보가 도출되었습니다.
아래는 이벤트 스토밍의 흔적인데요.



해당 워크숍을 통해 저희는 저희 스쿼드가 관리해야 할 바운디드 컨텍스트를 식별하고 각각의 도메인 모델을 도출하였습니다.



컨텍스트 매핑

여기서 한가지 고려해야 할 것이 있습니다. 바로 하나의 하위 도메인이 여러 개의 컨텍스트로 분리되는 경우인데요.
예시를 위해 위의 바운디드 컨텍스트 안에 있는 상품 정보들을 가져와 보겠습니다.

우선 상품 도메인이 상품 컨텍스트에 있을 경우 상품 메타 정보를 의미합니다.

하지만 상품 도메인이 매장 바운디드 컨텍스트에 있다면, 매장에서 관리하는 상품을 의미할 겁니다.
즉 해당 매장이 판매하고 있는 상품을 의미하는 매장 취급상품으로 정의할 수 있죠.

상품 도메인이 진열 바운디드 컨텍스트에 있다면, 해당 상품의 위치로 정의할 수 있습니다.
더 나아가 매장 내 상품의 위치·배열·진열 방식을 시각적으로 나타냄으로써, 매대별로 상품을 효과적으로 배치·관리하기 위한 전략적 도구를 의미하는 POG로 정의할 수도 있을 겁니다.


이렇듯 같은 상품이라는 도메인도 어느 컨텍스트에 있고, 어느 관점에서 바라보는지에 따라 의미가 달라질 수 있습니다.


이때 매장 컨텍스트의 매장 취급상품 정보에 추가로 상품 컨텍스트의 상품 메타 정보가 필요하다고 가정하겠습니다.
이 경우 각 컨텍스트 간의 협력이 필요할 겁니다.
컨텍스트 간의 상호 협력, 즉 컨텍스트 매핑 종류는 여러 개가 존재합니다.

  • 소비자와 공급자(Customer-Supplier)
  • 공유 커널(Shared Kernel)
  • 준수자(Confirmist)
  • 충돌 방지 계층(ACL-Anti-Corruption Layer)
  • 공개 호스트 서비스(OHS-Open Host Service)
  • 발행된 언어(PL - Published Language)



저희의 경우 매장 바운디드 컨텍스트와 상품 바운디드 컨텍스트의 관계를 충돌 방지 계층(ACL)으로 정의하였습니다.
즉 Anticorruption Layer를 통해 상품 서비스의 도메인 모델을 매장 도메인 모델에 맞게 변환하여, 외부 도메인 모델이 매장 도메인 모델을 침범하지 않도록 막는 형태입니다.


하지만 사실 두 개의 컨텍스트가 어떤 관계인지 정의하는 것은 크게 중요하지 않습니다.
컨텍스트 매핑 종류를 참고해서 컨텍스트 간의 협력 방법을 정하고, 각각의 경계를 유지하면서도 각 경계 간의 도메인 모델을 적절히 변환·연계하여 비즈니스 요구 사항을 만족시키는 것이 더욱 중요할 겁니다.



다음 이야기

이번 포스팅에서는 도메인 주도 설계에서의 전략적 설계를 중점으로 소개하였습니다.
보시다시피 저희는 매장 도메인을 구현하기에 앞서 많은 준비와 과정을 거쳤는데요.

설계와 구현의 과정 속에서, 구현을 들어갔을 때 설계에 대한 변경이 잦을 경우 많은 비용이 발생합니다.
하지만 설계 단계에서 탄탄하고 좋은 설계를 한다면, 구현 단계에서는 구현에만 집중할 수 있어 비용을 크게 절약할 수 있습니다.

저희 또한 많은 준비를 한 덕에 구현에 드는 비용을 많이 줄일 수 있었습니다.
다음 포스팅에서는 실제 매장 도메인을 어떻게 구현해 나갔는지에 대해서 소개해 드리겠습니다.

긴 글 읽어주셔서 감사합니다 🙂

DDD전략적 설계LegacyModernization
올리브영 테크 블로그 작성 10년 된 레거시를 현대화하다 - Part.1: 도메인 분리의 첫걸음
🐯
알렉스(범) |
Back-end Engineer
소통을 좋아하고 꾸준함의 가치를 향해 달려가는 프로그래머 알렉스입니다