본문 바로가기

MY개발생각

[개발생각] DDD에서 ApplicationListener를 어떻게 설계해야 좋은가?

DDD에서는 크게 APPLICATION, DOMAIN, INFRA영역이 존재한다.

결국 모든 레이어는 DOMAIN을 바라보는 관계로 구현을 하게된다.

 

여기서 해당 영역은 사실 명확히 경계가 존재하기에 초기 배움에서는 크게 문제가 없다.

하지만, 조금만 더 프로젝트나, 개발을 진행하다보면,

 

찝찝한 부분이 생기는데,

이게 바로, APPLICATION_LISTERNER, KAFKA_LISTENER등의 비동기 이벤트에 따른 컨슘하는 리스너를 DDD에서 어떻게 깔끔하게 구현을 하는가 이다.

 

APPLICATION_LISTERNER, KAFKA_LISTENER는 인프라스트럭처 계층이기에 인프라스트럭처에 그 구현체가 존재하게 된다.

그런데 여기서, 결국은 해당 리스너에서는 Domain의 Service, Provider등을 실행하게 되는 방향으로 구현이 된다.

 

인프라스트럭처에서 도메인 레이어의 서비스를 사용하게 되는데,

이것은 엄밀히 보면, 크게 문제가 되지는 않는다.

위에서 이야기했듯, 인프라, 어플리케이션 레이어는 결국 도메인에 의존적인 동작을 하도록 하는게 DDD이기 때문이다.

 

하지만, 뭔가가 거슬리는 느낌이지 든다. ㅋㅋ

이런 구성은 상당히 거슬리는게 있는데, 바로 코드의 흐름, 비즈니스의 흐름이 끊긴다는 것이다.

 

어플리케이션 계층에서 시작한 구현 기능은 도메인 서비스의 구성으로 기능이 만들어지게 되는게,

인프라계층의 리스너에서 동작하는 도메인 서비스가 어떤방식으로 동작되는지가 어플리케이션, 도메인 레이어에서 바로 파악이 어렵고,

인프라계층까지 확인을 해야 파악이 되는 다소 모호한 상황이 발생할수있다. 

 

예를 들면)

 

1) 로그인 서비스 -> 2) 출석체크 서비스 (이벤트 발행) ,      3) 출석보상지급 서비스 (이벤트 컨슘)

 

이렇게 로그인이 되고, 출석체크를 했다는 흐름은 선형으로 이어지는 흐름이지만, 출석보상지급 서비스는 동떨어져있다. 

코드를 읽어서는 존재하지않는 동작이다. 리스너에서 불려지니,

도메인 서비스에는 해당 서비스가 리스너로 동작한다는 힌트를 알수가 없지..

 

이렇게 되면, 이벤트 드리븐, AOP(관점지향?)의 가장 단점인 흐름 파악이 어렵다는 문제가 나타나게된다.

 

따라서, 이런경우는, 도메인 서비스에 인터페이스를 DoneAttendence등으로 도메인의 행위를 인지할수있는 네이밍으로 정하는것이 먼저 중요하다. (공학보다 인문학이다!! ㅋ 우선 잘 네이밍을 짓는게 무엇보다 중요하다. 변수짓는거 아직도 어려워...)

 

그리고 해당 인터페이스는 도메인 클래스로 구현을 하고, 인프라스트럭처의 APPLICATION_LISTERNER, KAFKA_LISTENER에서는 해당 인터페이스의 구현체를 실행만 해주는 방법으로 구현을 하면, 좀더 비즈니스의 흐름을 파악하는데 도움이 되는 구조로 만들수있다.

 

예를 들면)

 

// 도메인

interface DoneAttendence {
    fun onAttendence(userId: UserId)
}

@Service
class UserDoneAttendenceService(
    private val userRepository: UserRepository
) : DoneAttendence {

    override fun onAttendence(userId: UserId) {
        // 출석 체크 비즈니스
    }
}



// 인프라

@Component
class AttendenceEventListener(
    private val doneAttendence: DoneAttendence
) {

    @EventListener
    fun handle(event: AttendenceEvent) {
        doneAttendence.onAttendence(event.userId)
    }
}

 

팀원끼리는 onXXXXX로 된 함수는 리스너를 통한 호출함수임을 미리 개발룰로써, 합의를 해두면 더욱더 코드읽기가 깔끔해진다.

 

코드를 통해 이해할수있게 만드는것 만큼,

미리 구성원간의 합의룰을 정하는 '최첨단 수동' 방식 또한 코드구현만큼이나 소중한 방식임을 알아야한다.

 

암튼, 이런식으로 도메인에 해당 리스너의 의도를 표현할수있는 방식으로 구현을 해준다면,

좀더 도메인 로직을 잘 확인할수있게 만들수있지 않을까 한다.

 

오늘 면접관으로 면접을 진행했는데... 내가 질문을 내용이다..

그런데 질문을 내가 면접자가 이해하지 못하게 모호하게 이야기를 한것같네...ㅋ