[개발 상식] BDD와 DDD

우아한 테크코스 프리코스 4주차를 시작하면서, “서비스의 핵심을 파악하고, 이를 우선 구현해 봐라”는 피드백을 받았습니다. 사실 지금까지 TDD에 대해서 배운바, 도메인 로직의 테스트 코드를 구성하고 나서, 실제 코드를 만드는 것에 익숙해져 있었습니다. 그런데 갑자기 “핵심 로직을 우선 구현하라”…?

 

사실 의아한 부분이 많았습니다. 지금까지 주구장창 도메인 로직의 구성부터 생각하며 빌드를 해왔는데… 음.. TDD와는 다른 어떠한 방법론에 대한 이야기라고 생각 들었습니다.

 

이게 단순히 ‘설계를 꼼꼼히 하라, 그리고 TDD 구현을 시작하라’ 라는 의미라면, 지금까지 잘 해왔다고 생각했지만, 분명 TDD의 단점은 원하는 서비스를 빠르게 만들진 못한다는 생산성의 문제가 있었기 때문에, 이를 개선해 나가야 할 방법을 생각해 보아야 했습니다.

 

그렇게 찾기 위한 노력으로 제가 접한 키워드는 BDD그리고 DDD라는 개념이었습니다.

❓BDD가 뭔가요?

BDD(Behavior Driven Development)는 행위 주도 개발로써 TDD에서 파생된 개념이라고 합니다. TDD와 유사하지만, 사용자의 행동과 시스템의 행위에 중점을 두는데요, 이 행위를 요구하는 사항 자체를 테스트 코드로 구현한 것이라고 생각하시면 됩니다.

사용자의 요구사항을 유저 스토리로 작성하고, 이를 Gherkin언어로 표현합니다. Gherkin언어란 Feature, Scenario, Given, When, Then구조를 사용하여 요구사항을 명확하게 이해하는 것입니다.

✨Gheerkin언어?

Gherkin 언어는 사용자와 개발자 간의 의사 소통을 용이하게 하며, 비즈니스 요구 사항을 이해하기 쉽도록 하는 것이 목표입니다. 다음과 같은 요소로 구성되어 있습니다.

  • Feature: 소프트웨어의 기능 또는 모듈을 정의합니다.
  • Scenario: 특정 상황에서의 기능 동작을 정의합니다.
  • Given: 시나리오의 시작 상태를 설정합니다.
  • When: 어떤 동작이 발생했을 때의 상태를 정의합니다.
  • Then: 동작 결과로 얻어야 하는 상태를 정의합니다.

즉 BDD는 TDD의 테스트 환경을 유저 스토리로 개선한 개발 방법론이라고 할 수 있겠네요.

❓DDD가 뭔가요?

DDD (Domain Driven Development)는 도메인 주도 개발로써 도메인에 중점을 두는 개발 방법론입니다. 도메인 주도를 통해 개발팀과 비즈니스 팀간의 소통을 강화하여 도메인을 공유된 언어로 표현합니다. 또한 복잡한 환경에서 마이크로 서비스 아키텍처를 통해 분산 시스템을 지원함으로써 유연하고 일관성있는 소프트웨어를 만들 수 있습니다.

여기서 복잡해진 비즈니스 도메인을 다루기 위한 도구로써 애그리게이트와 리포지터리의 개념이 등장합니다.

✨애그리게이트

애그리게이트는 관련된 객체들의 그룹입니다. 애그리게이트는 데이터 일관성을 유지하기 위한 경계를 정의하며, 이를 통해 도메인 모델을 단순화하고, 응집도를 높입니다. 애그리 게이트에는 하나의 루트 객체가 존재하고, 이를 애그리게이트 루트라고 표현합니다. 이는 애그리게이트를 대표하고 외부에서 애그리게이트 내의 객체에 접근하게 합니다.

class OrderItem {
  constructor(product, quantity) {
    this.product = product;
    this.quantity = quantity;
  }
}

class Order {
  constructor(orderId, customer) {
    this.orderId = orderId;
    this.customer = customer;
    this.items = [];
  }

  // 애그리게이트에 변경을 가하는 메서드
  addItem(product, quantity) {
    const orderItem = new OrderItem(product, quantity);
    this.items.push(orderItem);
  }
}

Order 클래스가 애그리게이트 루트이고, OderItem은 애그리게이트에 속하는 객체입니다. OderItem이 많아질 수록 복잡해지는 비즈니스 환경에서 애그리게이트를 통해 관리할 수 있게 되는것이죠!

✨리포지토리

리포지토리는 도메인 객체의 저장소를 추상화한 개념입니다. 이를 통해 도메인 객체를 저장, 검색, 삭제하는 작업을 추상화 함으로써 도메인 로직과 데이터 접근 로직을 분리하고 단순화 합니다. 이를 통해 비즈니스 복잡성을 해결하는 것이죠.

class OrderRepository {
  constructor() {
    this.orders = [];
  }

  // 주문을 저장
  save(order) {
    this.orders.push(order);
  }

  // 주문을 식별자로 검색
  findById(orderId) {
    return this.orders.find(order => order.orderId === orderId);
  }

  // 주문을 삭제
  delete(order) {
    const index = this.orders.findIndex(o => o.orderId === order.orderId);
    if (index !== -1) {
      this.orders.splice(index, 1);
    }
  }
}

이렇게 리포지토리를 이용해 검색을 하고 필요에 따라 변경, 삭제를 할 수 있다는 것이죠.

❗결론…!

처음 목표였던 생산성을 증가시키는 방법은 결국 알진 못했지만, “요구 사항”을 BDD를 통해 꼼꼼히 체크할 수 있다는 방법을 알게되었습니다.

BDD와 DDD를 통해, TDD와 마찬가지로 모든 것들은 “요구 사항”에 중점을 두고 있다는 것, 결국 “요구 사항”을 모두 충족하면서, 빠르게 만드는 것은 개인의 실력을 향상시키는 방법일 뿐인가.. 라는 생각으로 결론을 내려봅니다..🥲