본문으로 바로가기

[DDD] Entity란?

category Architecture/DDD 2024. 2. 22. 04:14
728x90
반응형

목차

     

     

    개요

    Domain Driven Design(이하 DDD)를 처음 접했을 때 참 매력적인 주제라 생각했다. 개발을 시작하고 2년 차에 접어든 무렵에 알게 된 주제였는데 "코드"를 어떤 관점에서 바라보고 작성해야 되는지의 시야를 넓혀주었기 때문이다. 이때 당시엔 DDD에서 말하는 개념들이 너무 생소한지라 그런가 보다라며 다른 주제에 관심을 돌렸었다.

     

    어느 정도의 시간이 지나고 Sping의 MVC의 패턴을 접하게 되었는데 역할에 따라 구성된 코드 구조를 보면서 이를 Python으로 옮긴다면 단순히 MVC 패턴이 아닌 "무엇"을 더해 코드를 구성하면 좋을까로 고민이 이어졌다. 그러던 와중 예전에 펼쳐서 읽어봤던 "DDD"에 관련한 책을 다시 읽으면서 Python으로 DDD 개념을 구현한 예제들을 찾아보게 되었다.

     

    그러나 Python으로 구현한 DDD에 관련된 자료는 너무 미미했고 이미 익숙해진 Django의 MVT와 회사 코드 구조에서 벗어나 생각하기가 쉽지 않았다. 개인적으로 잡다한 스크립트와 프로젝트를 만들면서 최근에 와서야 "DDD"의 개념들을 Python에서 어떤 식으로 다뤄야 할지가 어느 정도 가시권에 들어왔는데 그러한 맥락에서 "DDD"에 관련된 주제를 정리해보려 한다.

     

    사족이 길었지만 한 줄로 정리하자면 "DDD 내용 정리 + 개인적인 생각"이다. 

    그 첫 번째 글을 Entity로 시작해보고자 한다.

     

    1. Entity 란?

    DDD(Domain Driven Design)에서 정의하는 Entity란 "가변적", "식별성"의 성질을 만족하는 객체이다.

    1.1 Entity의 성질 - "가변성과 식별성"

    "가변적"이다의 의미는 Entity에 정의된 특정 속성이 어떤 Method에 의해 변경이 일어날 수 있음을 의미한다. 예를 들어 어떤 사람의 나이가 올해 19살이면 다음 연도에는 20살이 될 것이다. 다음 연도가 되어 "사람" 이란 Entity의 "나이"라는 속성이 20으로 변경이 일어난 것이다. 곧 후술 하겠지만 속성이 변경되지만 Entity 식별성이라는 성질을 가지기에 "가변성"을 지킬 수 있다.

     

    "식별성"의 의미는 하나의 Entity가 유일하게 구분될 수 있어야 함을 의미한다. 이는 "연속성"이라고도 표현할 수 있는데 앞선 예제에서 19살이던 사람이 20살이 된다고 전혀 다른 사람이 되는 게 아니듯 식별 가능한 identity를 정의하는 걸 의미한다. "식별성"에 관해서 "에릭 에반스"의 도메인 주도 설계에서는 다음과 같이 설명한다.

    ENTITY는 자신의 생명주기 동안 형태와 내용이 급격하게 바뀔 수도 있지만 연속성은 유지해야 한다. 또한 사실상 ENTITY를 추적하려면 ENTITY에 식별성이 정의돼있어야 한다. (93p)

    1.2 Entity의 성질 - "생애주기"

    Entity는 도메인 모델에서 Value Object라는 것과 비견되는데 Entity가 될 수 있으려면 앞서 언급한 "가변성", "식별성"외에도 특징에 "생애주기"가 존재하는지도 포함된다.

     

    앞서 언급한 "사람"이라는 Entity는 '살아있다/죽었다'로 구분 가능하다. 다르게 표현해 보자면 System 안에서 어떤 사람(사용자)은 회원가입을 통해 Entity가 생성되며 회원 탈퇴를 통해 해당 Entity를 삭제(soft or hard delete)할 수 있게 된다.

     

    그러니까 즉 "사람(사용자)"이라는 Entity는 "생애주기"를 가지기에 Entity가 되기 충분하다.

     

     

    2. Entity의 식별성은 어떻게 만드나?

    지금까지 Entity의 식별성을 정리하면서 이 식별성은 "유일"해야 함을 설명했다. 그렇다면 "식별성"을 달성하기 위해 "식별자"를 어떻게 만들 수 있을까?

     

    Entity의 식별자는 특정 규칙에 따라 생성할 수 있다. 그러나 규칙을 정의하기 힘들고 어느 환경에서나 고유해야 함을 감안하자면 UUID나 NanoID와 같은 기능을 이용해 식별자를 정의해 볼 수 있다.

     

    또한 DataBase의 AUTO_INCREMENT와 같은 일련번호를 통해 Entity에 식별성을 부여할 수도 있지만 Application에서 생성된 Entity를 DataBase에 넣기 전까지는 "식별자"를 사용할 수 없다는 단점이 존재한다.

     

    3. Entity의 책임

    Entity는 도메인 모델 중의 하나이다. 즉 도메인의 개념을 Entity라는 모델에 잘 정의해놓아야 하는데 이와 관련해서 에릭 에반스의 "도메인 주도 설계"에는 Entity의 기본 책임을 다음과 같이 설명했다.

    ENTITY의 가장 기본 책임은 객체의 행위가 명확하고 예측 가능해질 수 있게 연속성을 확립하는 것이다 (95p).

    이 설명은 선뜻 무엇을 말하려고 하는지 또한 어떻게 구현해야 하는지를 막연하게 만드는데 이어지는 내용에서 다음과 추가 설명이 존재한다.

    개념에 필수적인 행위만 추가하고 그 행위에 필요한 속성만 추가한다. (95p)

    즉 특정 Entity가 할 수 있는 행동이 무엇인지 그에 따른 속성이 무엇인지를 명확하게 해야 하므로 이해하자.

     

    4. Entity of Python Object

    "파이썬으로 살펴보는 아키텍처 패턴"이라는 책에는 다음과 같은 내용이 나온다.

    도메인 모델에는 그 어떤 의존성도 없기 바란다. 하부 구조와 관련된 문제가 도메인 모델에 지속적으로 영향을 끼쳐서 단위 테스트를 느리게 하고 도메인 모델을 변경할 능력이 감소되는 것을 원하지 않는다. (62p)

    위 정의에 따라 Python에서 Entity를 사용하기 위해 고려해 볼 수 있는 건 POPO와 dataclass로 두 가지 정도이다. 각각에 대해 어떤 방법인지 알아보자.

    4.1 Plain Old Python Object

    POJO에 대해 들어본 적 있는가? Java에서는 "Plain Old Java Object"라는 단어가 있는데 "객체지향 원리에 충실하면서 환경과 기술에 종속되지 않고, 필요에 따라 재활용될 수 있는 방식으로 설계된 객체"를 말하는 단어이다.

     

    이에 영향을 받은 것인지 Python은 이를 POPO라 부르는 듯하다. 따로 POPO라는 용어가 등장하는 공식적인 문서가 있는지 조사해 봤지만 찾을 순 없었다. POPO는 Plain Old Python Object의 약자로 순수 Python Class로 구현된 객체를 가리키는 말이다.

    다음 코드는 POPO에 대한 예시 코드이다.

    import uuid
    
    class Entity:
        def __init__(self):
            self.identity = uuid.uuid4()

    앞서 언급한 "도메인 모델에는 그 어떤 의존성도 없기 바란다"라는 측면에서 생각해 보면 POPO가 가장 잘 들어맞는다. 물론 외부 종속성을 가지지 않은 채로 구현된 POPO일 경우에 한해서이다.

    4.2 dataclass

    Python의 dataclass 또한 Python의 Class를 정의하기에 훌륭한 도구다. dataclass로 Entity를 작성한다면 다음과 같은 형태가 될 것이다.

    import dataclasses
    
    @dataclasses.dataclass
    class Entity:
        identity: str

    개인적으로 dataclass를 Entity로써 정의해서 사용해도 틀린 방법은 아니라 생각한다. 그러나 "파이썬으로 살펴보는 아키텍처 패턴"에서는 dataclass를 Value Object의 특성 중 하나인 "불변성"을 다루기에 적합한 도구이기에 Value Object를 정의할 때 사용하는 게 더 편리한 듯 보인다.

    4.3  __eq__와  __hash__ 구현하기 

    Entity의 식별성을 Python의 Class에 적용하기 위해서 "identity equality"라는 정의를 코드 내에 명시해야 한다. 

     

    Python에서는 __eq__와 __hash__라는 매직 메서드를 Override 해서 사용하면 된다. Entity의 식별자를 이용해 해당 기능을 구현하자.

    class Entity:
    
        def __eq__(self, other): ....
        
        def __hash__(self): ...

     

     

    5. Python Entity와 Table Mapping

    Application 내에서 Entity를 정의했으면 이를 영속화(persistent)시킬 무언가가 필요하다. 쉽게 말하자면 DB에 저장해야 한다 뜻이다.

    5.1 SQLAlchemy의 Classical Mapping

    앞선 설명에서는 POPO나 dataclass를 이용해 Entity를 정의했다. 그렇게 정의한 이유는 도메인 모델인 Entity가 어떠한 외부 종속성을 가져선 안된다는 의도를 반영한 것이다. 그러나 이렇게 정의한 Entity를 영속화(persistent)시키기 위해선 이 Class들이 DB와 연결되는 무언가가 필요한 것이다.

     

    앞선 목적을 달성하기 위해서는 SQLALchemy는 Python object를 DB Table과의 Mapping 할 수 있는 "Classical Mapping" 방식을 고려해 볼 수 있는데 "파이썬으로 살펴보는 아키텍처 패턴"이라는 책에서 도 추천하는 방식이기도 하다.

     

    이 방식의 특이점은 Application의 시작 시점에 Entity와 Table 간의 매핑을 선택적으로 활성화시킬 수 있는 코드를 작성할 수 있다는 점이다.

     

    이에 관련한 내용은 이미 포스팅했으므로 궁금하다면 "https://jakpentest.tistory.com/337"를 참고해 보자.

    5.2 declarative_base Model이 Entity가 되는 것은?

    SQLAlchemy에는 classical mapping 방식과는 반대인 declarative_base라는 방식이 존재한다. 이 방식은 Domain Model인 Entity가 SQLAlchemy에 종속되어 버린다. 앞서 언급한 "도메인 모델은 외부 종속성을 가져선 안돤다"라는 특징을 취하지 못하게 된다.

     

    마치며

    Entity 자체만으로는 아직 무언가 할 수 없어보인다. DDD의 이론적 측면에서 말하는 Entity에 대한 정보는 검색하면 쉽게 나오기 때문에 이를 따로 정리하는 것은 불필요해보인다.

     

    "개요"에서 언급한 "맥락"에 따라 좀 더 집중해야할 부분은 DDD의 내용을 어떤식으로 Python에 접목시킬 수 있는지에 관련된 부분인데 계속 조사하면서 정리해보도록 하자.

     

    참고

    https://m.yes24.com/Goods/Detail/101818336

     

    파이썬으로 살펴보는 아키텍처 패턴 - 예스24

    아키텍처 패턴의 기초부터 활용까지 다루는 실전 가이드파이썬을 활용한 프로젝트의 규모가 커지면서 육각형/클린 아키텍처, 이벤트 기반 아키텍처, 도메인 주도 설계 등 고수준 디자인 패턴에

    m.yes24.com

     

    https://m.yes24.com/Goods/Detail/93384475

     

    도메인 주도 설계 철저 입문 - 예스24

    이해하기 쉬운 패턴부터 학습하자! 도메인 주도 설계를 쉽게 이해할 수 있는 입문서!초심자라도 이해하기 쉽고 실천하기도 쉬운 패턴부터 시작해 구체적인 예제와 함께 도메인 주도 설계에서

    m.yes24.com

     

    https://product.kyobobook.co.kr/detail/S000001514402

     

    도메인 주도 설계 | 에릭 에반스 - 교보문고

    도메인 주도 설계 | 소프트웨어의 복잡성을 다루는 지혜『도메인 주도 설계』. 이 책은 독자에게 도메인 주도 설계에 대한 체계적인 접근법을 제공하고 폭넓은 우수 설계 실천법과 경험을 토대

    product.kyobobook.co.kr

     

    https://product.kyobobook.co.kr/detail/S000001810495

     

    도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지 | 최범균 - 교보문고

    도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지 | 가장 쉽게 배우는 도메인 주도 설계 입문서!이 책은 도메인 주도 설계(DDD)를 처음 배우는 개발자를 위한 책이다. 실제 업무에 DDD를

    product.kyobobook.co.kr

     

    728x90
    반응형