도메인이 아이디를 가져야 할까?

지하철 미션을 진행하면서 도메인이 ID를 갖지 않았습니다.

초반에 도메인이 ID를 갖지 않았던 이유는 다음과 같습니다.

  1. 도메인에서 ID를 사용하는 로직이 없다.

    중복된 역 이름이나 노선 이름을 등록할 수 없는 검증 로직이 존재했습니다.

    따라서 이름 에 해당하는 필드가 식별자 역할을 할 수 있었고, ID가 불필요했습니다.

  2. DB에 저장하면서 생기는 값인 ID를 도메인에서 사용했을 때 도메인 → DB로의 의존 관계가 생긴다.

    비즈니스 계층과 영속 계층을 나눈 만큼 각 계층간의 분리가 확실해야 한다고 생각했습니다.

    하지만 도메인에서 DB에서 생성된 데이터(ID)를 사용한다면 도메인이 영속 계층에 의존하게 됩니다.

객체를 식별하기 위한 방법으로는 객체의 고유한 속성으로 비교를 하거나, 객체의 모든 속성이 같은지를 비교했습니다. 속성이 고유한 값을 갖기 때문에 굳이 ID와 같은 식별자의 역할이 불필요했습니다. 하지만 이와 같은 방법으로 객체의 고유성을 보장할 수 있을까요?

도메인에 식별자가 필요한 이유

먼저 도메인이 ID를 갖지 않고 고유한 속성을 기준으로 객체를 식별하는 경우 다음과 같음 문제가 발생하는 것을 고려해볼 수 있습니다.

쉽게 변경되는 도메인 요구사항이 변경된 경우

지하철 미션에서는 역 이름이나 노선 이름과 같이 이름 속성이 유니크한 속성이기 때문에 식별자 역할을 할 수 있습니다. 하지만 요구사항이 변경되어 이름에 대한 중복이 허용된다면 이름 필드는 더이상 식별자의 역할을 할 수 없습니다. 이 경우 또 다른 식별자를 선정해야 합니다. 이처럼 도메인 요구사항이 변경될 때마다 새로운 식별자를 찾아야 한다면 리팩토링 하는 데에도 비용이 많이 들 것입니다.

이때 오히려 도메인과 관련이 없는 ID 값을 식별자로 두는 것이 객체의 고유성을 보장할 수 있으며, 변경되는 요구사항에도 객체의 고유성을 보장할 수 있는 좋은 방법이 될 수 있습니다.

모든 속성을 비교해야 하는 경우

특정한 식별자를 갖는 대신 모든 속성을 비교하는 방식을 사용할 수 있습니다. 하지만 프로그램의 규모가 커질수록 하나의 도메인이 갖는 속성의 개수가 늘어납니다. 그렇다면 DB에 쿼리를 날릴 때도 도메인에서 객체를 찾을 때도 모든 속성을 비교해야 한다는 점에서 굉장히 비효율적인 로직으로 이어지고, 객체를 식별하는 데 많은 비용이 들 수 있습니다.

상품 주문을 예로 들어보겠습니다.

주문자 정보 , 상품명 , 상품 가격, 상품 이미지 , 구입 개수 다섯 개의 속성을 갖는 Order 객체가 있다고 가정했을 때 모든 필드가 중복이 허용되기 때문에 특정한 속성을 기준으로 객체의 고유성을 보장할 수 없습니다. 따라서 두 번째 방법인 모든 속성을 비교하는 방법을 사용해야 합니다.

그러나 모든 속성을 비교하는 경우에도 객체의 고유성을 보장할 수 없습니다. 동일한 사용자가 동일한 상품을 동일한 개수만큼 구입할 가능성을 배재할 수 없기 때문입니다.

마찬가지로 지하철 노선을 구현한다고 가정해봅시다.

지하철 역 객체는 소속 노선, 역 이름 을 속성으로 가지고 있는 경우 2호선 잠실역과 8호선 잠실역은 다른 객체로 식별하게 됩니다. 이때 해당 역을 다른 역으로 취급할지에 대해서는 비즈니스 로직에 따라 다르게 정의될 수 있지만, 모든 속성을 기준으로 비교하게 될 경우 객체를 식별하는 로직이 복잡해질 것입니다.

즉, 모든 속성이 동일하다고 같은 객체로 취급할 수도 있고, 모든 속성이 같지 않더라도 같은 객체로 취급할 수도 있습니다. 이때 식별자인 ID를 사용하면 해당 문제를 쉽게 해소할 수 있습니다.

도메인 객체 간 관계가 복잡한 경우