6주라는 짧은 기간동안 서비스를 만들기 위한 좌충우돌의 개발이 끝나고,
계속해서 프로젝트를 빌드업시키려는 계획을 가지고 있었다.
또다시 새로운 기능을 만드는 기간도 잠시 있었지만,
이미 있는 기능들을 더 트렌디하게 만들어봐야겠다는 생각이 들었다.
마침 원티드에서 DDD와 이벤트 핸들링에 대해서 공부해본김에,
이를 활용한 프로젝트 리펙토링을 해봐야겠다는 생각이 들었다.
그래서 뭘 했을까?
곰터뷰는 객체간의 협력이 많고, 이로인해 직접참조시에 다른 도메인이 많이 호출된다.
이런식으로, Answer 도메인의 비즈니스로직을 서비스 레이어로 빼냈지만,
질문, 문제집 도메인의 리포지토리를 가져와 사용해야 하는 문제가 있었다.
기능을 새롭게 만드는 과정에서는 그냥 가져다 쓰지 뭐...하면서 썼다.
그런데, 이슈에 대응할 때 디버깅과 리펙토링과정에서 손이 너무 많이 갔다.
리펙토링이 너무 어려워 함수 자체를 지워버리고 새롭게 다시 만드는 경우도 많았다.
이에 대한 이유가 무엇일까? 생각해보았을 때,
Answer 도메인의 로직을 해결하기 위해 Question도메인의 리포지토리 로직을 건드리거나 하는 문제가 있다는 것을 생각했고,
이러한 문제를 해결하기 위해 모든 도메인이 더 책임을 제대로 지게 해야겠다는 생각이 들었다.
그래서 어떻게 했을까?
이를 해결하기 위한 나의 리펙토링 과정은 다음과 같았다.
- Entity의 직접참조를 간접참조로 바꾸기(필요에 따라 역정규화하기)
- Repository 로직 리펙토링
- 비즈니스 로직에서 다른 도메인의 리포지토리/엔티티 로직을 이벤트로 동작시키게 수정하기
- 테스트 재실행해보기
- 테스트 실패 케이스 고치기/부족한 테스트 더 넣기
이러한 과정을 통해 리펙토링을 진행했다.
좋았던 점?
가장 좋았던 점은, Module의 import나, 인스턴스등을 보면서 매우 만족했다.
다른 도메인을 불러와 사용하는 경우가 사라졌다.
이벤트 핸들러를 통해 다른 도메인의 일이 필요한 경우 시키게 하고, Answer 도메인의 로직들은 오직 Answer만을 위한 로직이 될 수 있었다.
이를 위해 트랜잭션, EventEmitter2(nestjs의 공식 홈페이지를 보고 공부했다)를 학습했다.
트랜잭션단위에서 이벤트를 통한 쿼리문들의 커밋/롤백또한 처리할 수 있고,
코드레벨에서는 이러한 부분들을 전부 해당 도메인 안에서 구현하면 되는 장점으로
코드리딩이 편하다는 장점이 컸던 것 같다.
또한, 이벤트로 인한 속도의 저하가 걱정되었지만,
사진으로 보는 것과 같이, 테스트상에서는 아무런 속도의 차이가 존재하지 않았다.
데이터베이스 서버에 슬로우 쿼리에 대한 로깅이 추가되어있어, 이를 검증하기위한 부하테스트등을 추가해야 할 것 같다는 생각이 든다.
아쉬운 점! 모든 코드에 대한 검증과 리펙토링을 또 해야했을까?
기획단계에 대한 스스로의 아쉬움이 있었다.
이번 기회로 이벤트와 도메인 주도 설계에 대해서 실습을 해볼 수 있는 기회가 있다는 것은 좋지만,
처음부터 도메인 주도 설계적으로 접근하고,
이벤트로 다른 도메인과의 협업을 구현했다면 더 좋지 않았을까?
물론 그 때는 이런 부분까지 접근할 여유나 지식이 없었다.
또한, 도메인 주도 설계의 단점중 하나로 언급되는 문제가 있다면,
빠른 시간의 구현이 어려울 수 있다는 부분이 있는데,
우리는 6주안에 프로젝트를 짜내야 하는 상황으로 적용하기 어려울 수 있었다.
부스트캠프를 들어가기 한 해 전,
스프링 스터디를 하면서 TDD라는 것을 해보았었다.
우리나라가 TDD가 핫할 그 시절이었다.
레딧같은 커뮤질을 하면서 찾아보았을 때,
TDD의 구현되지 않은 로직에 대한 테스트를 구상하며 만드는 것보다
DDD를 통해 설계시간이 오래걸리더라도 구현을 제대로 하는것이
부정확한 이슈에 대한 테스트를 만드는 것 보다 더 빠를 것이고
후에 더 구현하기 수월한 프로젝트가 될 것이라는 이야기를 봤었다.
그런 이야기를 들어놓고, 이제와서 DDD를 실제 프로젝트에 집어넣었다는 것이
스스로에 대한 아쉬움이다.
또한, EventEmitter2라는 provider를 모킹해서 테스트를 진행했는데,
이게 아닌 처음부터 eventHandler를 모킹해서 처리했다면 더 좋지 않았을까 라는 생각이 든다.
앞으로는 어떻게 할 것인가?
사실 DDD를 통한 프로젝트의 성능적인 향상은 크게 기대하기 힘들었다.
(오히려 이벤트로 호출했을 때 아주 미세한 딜레이라할지라도, 이로인한 성능의 감소를 걱정했지만, 이슈가 되지 못할정도의 현 상황이다)
어찌보면 내가 DDD를 넣은 것은 성능적인 향상보단,
개발자들의 수월함을 위해 프로젝트에 적용했다.
이제 정말 성능적인 향상이 존재할 수 있다는 부분들을 적용해봐야겠다.
DB Replication과 CQRS를 프로젝트에 적용시켜 이를 만들어볼 생각이다.
실제로 코드레벨에서만의 CQRS는 애플리케이션이 빨라진 경험이 없었다.
인프라적으로 DB Replication까지 적용해서 Master/Slave를 통한 속도의 향상을 만들어봐야겠다.
그럼...twenty thousand...🔥