안녕하세요, 하원입니다.
오늘은 스프링 개발에 막 입문했을 때 고민했던 주제를 가지고 왔습니다.
하나의 서비스 단에서 다른 서비스 또는 레포지토리를 주입 받아도 되는지에 대해 알아보겠습니다.
문제 상황
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class PosterService {
private final PosterRepository posterRepository;
private final EventRepository eventRepository;
private final PosterLikeRepository posterLikeRepository;
private final MemberService memberService;
private final ImageUploadService imageUploadService;
}
위 코드와 같이 하나의 서비스 클래스에서 작업을 하다 보면 다른 서비스 또는 레포지토리의 주입이 필요한 순간이 찾아오게 됩니다.
현재 PosterService에서 처리하고 있는 기능
- 포스터 등록/수정/삭제
- 포스터 단건/전체/필터링 조회
- 내가 등록한 포스터 조회
- 내가 좋아요 누른 포스터 조회
- 포스터 승인/반려
- 포스터 검색
현재 제 프로젝트의 PosterService에서 위와 같은 기능들을 수행하고 있습니다. 세어보니 대략 10개 이상의 기능을 수행하고 있습니다.
Q1 : 다양하게 주입 받는 것이 문제가 되나요?
->
Service단에서는 여러 도메인 간 상호작용이 발생하면서 협업이 이루어지기 때문에, 관련된 의존성 주입은 자연스러운 현상입니다.
Q2 : 단일 책임 원칙 (SRP, Single Responsibility Principle) 위반 아닌가요?
- SRP란 "하나의 클래스는 하나의 역할만 가져야 한다"는 원칙입니다.
- 원칙상 하나의 역할을 가져야 한다고 하지만, 현실적인 관점으로 보면 해당 클래스의 관심도가 명확한지를 확인하면 됩니다.
- 즉, 의존성의 수가 많더라도 하나의 도메인을 위해 주입된 것이라면, SRP 위반보다는 현실적인 타협 또는 협력으로 볼 수 있다는 겁니다.
하나의 책임, 하나의 관심사
리팩토링의 신호
PosterService 클래스는 10개 이상의 기능을 수행하고 있지만, 전부 "포스터"라는 도메인에 집중하고 있습니다.만약..
- 포스터 등록/수정/삭제
- 포스터 단건/전체/필터링 조회
- 내가 등록한 포스터 조회
- 내가 좋아요 누른 포스터 조회
- 포스터 승인/반려
- 포스터 검색
- 포스터 내 결제
- 카테고리 내 포스터 관리
- 팝업 포스터 관리
-> 만약 위처럼 포스터 이외의 도메인들을 처리하고 있다면, PosterService의 리팩토링을 고려해야 하는 상황일 수도 있습니다.
리팩토링을 진행한다면..
- PosterService
- 포스터 등록/수정/삭제
- 포스터 단건/전체/필터링 조회
- 포스터 검색
- MyPosterService
- 내가 등록한 포스터 조회
- 내가 좋아요 누른 포스터 조회
- AdminPosterService
- 포스터 승인/반려
- 카테고리 내 포스터 관리
- 팝업 포스터 관리
- PaymentService
- 포스터 내 결제
-> 만약 리팩토링을 진행한다면, 위와 같이 관심사에 따라 분리해 주면 됩니다.
유연하게 적용할 것
-> 결론적으로, 의존성의 수가 많은 것보다 해당 클래스의 역할들이 하나의 관심사를 유지하고 있는지, 과도한 역할을 맡고 있지 않은지 등을 살펴보는 것이 더 중요하다는 것입니다.
마무리
프로젝트를 진행하다 보면 초반 설계의 중요성을 정말 뼈저리게 느끼게 된다. 특히, 도메인 설계에 대한 후회가 종종 드는데 리팩토링 하는 시간과 비용이 꽤 들어서 완벽한 리팩토링을 진행하지 못하고 있다.
프로젝트 내의 유일한 백엔드 개발자로서, 모든 도메인 설계를 혼자 진행했음에도 불구하고 리팩토링이 자주 발생했는데, 실무에서는 어떤 방식으로 협업을 진행할지 궁금하다.