MSA에서의 단위 테스트 작성하기

dasd412·2024년 7월 21일
0

실무 문제 해결

목록 보기
3/17

개선 이전

저번 달까지 내가 짯던 코드 형식이다. 참고로 기존 실무 코드는 헥사고날 아키텍처가 아니라 레이어드 아키텍처로 되어있다.

코드

type (
	someService struct {
		someGrpcHandler
        someMessageQueue
        someRepository
	}

	SomeService interface {
	}
)


func (s *someService) DoSomething() {
	someGrpcHandler.DoSomeGrpc()
	someMessageQueue.DoSomeMessageQueue()
	doSomethingImportant()//비즈니스 로직
    someRepository.DoSomeRepository()
}

문제점

이 코드의 문제는 서비스의 퍼블릭 메서드를 테스트하기 어렵다는 것에 있다.
모놀리식 아키텍처라면 딱히 겪지 않을 것 같은 문제다. 하지만 MSA는 서비스 간 통신이라는 복잡함이 있다.
위 서비스의 단위 테스트를 작성하고자 해도 매우 복잡한 코드가 나온다.
왜냐하면 grpc, mq, repo 단에서의 코드를 mocking해야하기 때문이다. 한 번 그렇게 짜보니까 매우 지저분하며, 유지보수하기 매우 어렵다는 것을 깨달았다.

근데 내가 테스트하고 싶은 것은 private method인 doSomethingImportant()라는 비즈니스 로직이다. 이것만 테스트하는 데 왜 다른 걸 모킹하고 있지라는 짜증남이 치솟았다. 그래서 private method에 관한 테스트 방법도 찾아봤다. 검색해보니 private method는 테스트를 해선 안되고, 그걸 테스트하고 앉아있는건 니 설계가 거지같다는 것을 알게 되었다.


개선 이후

또 검색하다보니 DDD layerd 아키텍처라는 것을 오랜만에 보게 됬는데, UI->Service->DataAccess의 3 계층 방식 말고 UI->Service->Domain->DataAccess의 4계층 방식도 있는 걸 알게 됬다.

UI,DataAccess는 뭐 똑같으니 냅두고, 검색 내용을 좀 참고해서 리팩토링했다. Service는 트랜잭션, 외부와의 통신(grpc, message queue), 로직 전체 흐름을 담당하도록 했다. 그리고 Domain은 그런거 다 신경 안쓰고 순수한 비즈니스 로직만 담당하게 코딩했다. 그리고 Domain은 Repository를 가질 수도 있고 아닐 수도 있게 했다. 이미지 좀 찾아보니, 엄격하게 UI->Service->Domain->DataAccess로 되어 있는 게 아니라 Service->DataAccessService->Domain->DataAccess 등의 경로들로 되어 있는 것 같다. 흠...

코드

type (
	someService struct {
		someGrpcHandler
        someMessageQueue
        someRepository1
        someDomain
	}

	SomeService interface {
	}
)


func (s *someService) DoSomething() {
	someGrpcHandler.DoSomeGrpc()
	someMessageQueue.DoSomeMessageQueue()
	someDomain.DoSomethingImportant()//비즈니스 로직
    someRepository1.DoSomeRepository()
}

type (
	someDomain struct {
      someRepository2
	}

	someDomain interface {
	}
)


func (s *someDomain) DoSomethingImportant() {
	//핵심 비즈니스 로직 수행! 
    ...
    someRepository2.DoSomeRepository()
}

효과

이렇게 하면서 좋은 거는 서비스의 private method가 아닌 도메인의 public method가 됨으로써 단위 테스트하기 쉬워졌다는 것이다.
솔직히 grpc, message queue 등 외부 요소는 단위 테스트하기도 어렵다. 이러한 요소는 통합 테스트에서 확인해야 할 일이다.
이렇게 도메인 로직만 단위 테스트를 하게 되면 핵심 비즈니스 로직은 좀 더 안전하게 지킬 수 있게 된다. 왜냐하면 뭔가 잘못 건드려도, 작성했던 도메인 단위테스트에서 문제에서 생기지만 않는다면 핵심 비즈니스 로직은 안전함이 꽤 보장되기 때문이다.
이는 리팩토링에 있어서 좀더 안정감을 준다. 그리고 기획 변경에 따른 추가 유지보수가 발생하더라도, 기존 비즈니스 로직이 동일하게 수행됨을 보장할 수 있기 때문에 테스트의 부담감과 시간도 덜해질거다.


참고 링크

1.

https://blog.kmong.com/private-%EB%A9%94%EC%84%9C%EB%93%9C%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%95%98%EB%82%98%EC%9A%94-2069f2e2216e

2.

https://dev-coco.tistory.com/166


나중에 DDD 책 좀 사서 읽어봐야겟넹

profile
시스템 아키텍쳐 설계에 관심이 많은 백엔드 개발자입니다. (Go/Python/MSA/graphql/Spring)

0개의 댓글