현재 서비스 레이어에서 중복되는 코드가 있어서 고쳐보려고 한다.
고치는 김에 조금 불편함을 느꼈던 부분들도 같이 고쳐보고자 한다.
기존의 아키텍처는 다음과 같았다.
기존의 아키텍쳐는 TagService, MemberService 등 여러 서비스들이 Article을 조회하고자 할 때 ArticleRepository를 의존하는 경우도 있고, ArticleService를 의존하는 경우도 있었다.
그러다보니 아래 그림처럼 타 도메인의 Service를 의존하고 어떤 도메인은 Repository를 의존하는 등 의존성이 다소 꼬이는 상황이 발생했다.
이를 해결하기 위해 타 도메인 엔티티를 필요로할 때에는 서비스 레이어의 코드를 의존하는 것으로 통일하게 되었다.
의존성 통일
하지만 그런 과정에서 문제가 생겼는데, 코드의 중복이 생긴다는 것이었다.
중복되는 코드는 아래 두개이다.
예를 들어 컨트롤러에서 Article 엔티티 1개를 조회하는 기능을 필요로 하고, 타 서비스 레이어에서도 Article 엔티티를 조회하는 기능이 필요하다고 하자.
두 메소드 모두 id를 기준으로 Product를 찾아오는 기능을 한다. 다만 하나는 컨트롤러에서 호출하기 때문에 반환형이 DTO이고 하나는 다른 서비스에서 사용할 수 있도록 만든 메소드라 반환형이 엔티티이다.
컨트롤러를 최대한 얇게 만들고 싶어서 서비스 레이어에서 엔티티⇒DTO 변환을 거쳐서 컨트롤러에 보내고, 컨트롤러는 가능한 요청과 응답만을 수행하도록 하였는데,
그러다보니 완전히 동일한 기능을 하는 두 개의 메소드가 탄생해버렸다.
위의 메소드를 사용하는 컨트롤러 레이어 코드이다. 보다시피 정말 얇고, 클라이언트와의 소통 외에는 아무런 기능이 없다. 따라서 조금은 두께를 줘도 될 것 같다는 생각이 들었다.
아이디어는 다음과 같다. 서비스레이어에서 컨트롤러 레이어로 응답을 줄 때 DTO가 아니라 엔티티 형태로 주고, 컨트롤러에서 엔티티→DTO 형태로 변환해서 클라이언트에 반환하면 되지 않을까 싶었다.
클라이언트에만 엔티티로 반환하지 않으면 되는것이기 때문에 상관없을 것이라 생각되었다.
또한 서비스 레이어가 도메인에만 의존하고, 반환 DTO에 의존하지 않게 되어서 재사용성이 높아질 것이라 생각했다.
변경된 코드는 다음과 같다.
서비스 레이어에서 엔티티를 반환하고, 컨트롤러 레이어에서 그 엔티티를 dto로 변환해서 클라이언트에 반환하는 코드로 변경했다. dto로 변환하는 코드는 재사용될 여지가 충분하니 따로 메소드로 빼두었다.
이렇게 수정하니 컨트롤러 레이어 메소드가 그렇게 뚱뚱해지지도 않았고, 서비스 레이어에서 중복되는 메소드를 없애고자 했던 처음의 목적도 달성할 수 있었다.
수정된 코드가 반영된 아키텍처는 다음과 같다.
타 도메인이 필요한 경우의 의존성 방향이 통일되어서, 코드를 추가하거나 수정할 때 혼동이 없게 되었다.
다만 걱정되는 점은 컨트롤러 레이어가 이전과 다르게 엔티티에 의존하게 되므로, 엔티티의 변경 여부에 따라 컨트롤러 레이어도 변경될 여지가 생겼다는 것이다.
또한 현재 컨트롤러의 반환형이 Raw여서 개발자(나)의 실수로 엔티티 자체를 반환할 여지가 있다는 점이 문젠데, 추후 수정할 예정이다.
만약 서비스 레이어에서 엔티티만을 의존하게 해서 재사용성을 높이고, 컨트롤러 레이어에서도 dto를 의존하도록..만약 중간 다리를 놓을 수 있다면 좋지 않을까..하는 생각도 들었다.