기존에 나는 user와 관련된 비즈니스로직의 인터페이스를 한 곳에서 관리하며 readonly와, tranjaction이 적용되어야 할 service코드를 분리시켜 구현했었다.
단기 프로젝트이긴 하나 실제로 사용되어야 할 웹 사이트라고 가정한다면 지금과 같은 코드는 유지보수나 기능확장면에서 효율이 떨어질 것 같아 인터페이스를 분리하고 DIP원칙을 적용시켜 controller가 구현클래스가 아닌 추상화에 의존성을 갖도록 코드를 수정하였다.
먼저 하나의 인터페이스에 정의된 메서드들을 로그인, 회원가입, 회원정보CRUD, 서비스클래스를 보조하는 readOnly로 나누었다.
처음에는 단순히 CRUD와 CRUD가 아닌 것으로 나눌 생각이었지만 좀 더 세분화하는게 예상치 못한 문제에 대응할 수 있을 것 같아 아래의 그림과 같이 작은단위로 나누었다.
가장 기본이 되는 SOLID원칙에 따라 인터페이스를 분리하였다.
1. 단일 책임의 원칙(SRP)에 따라 회원가입, 로그인과 관련된 기능은 별도의 인터페이스로 분리하였다.
2. 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다. 따라서 인터페이스를 작은 단위로 분리하여 클라이언트가 필요로 하는 기능에만 의존하도록 해야한다. 따라서 인터페이스 분리 원칙(ISP)에 의해 기능별로 세부화 시켰다.
3. 사용자 서비스에서 의존성 주입 사용자 서비스에서 이메일 서비스를 사용해야 할 경우, 의존성 주입(Dependency Injection)을 통해 이메일 서비스를 주입받아 사용하게된다. 이를 통해 사용자 서비스는 이메일 서비스의 구현에 의존하지 않고, 인터페이스를 통해 추상화된 기능에만 의존하게 되어 의존 역전 원칙(DIP)을 따를 수 있게 되었다.
public class UserController {
private final UserInfoServiceInterface infoService;
private final UserLoginServiceInterface loginService;
private final UserServiceUtilsInterface serviceUtils;
private final UserSignupServiceInterface signupService;
기존에는 UserService의 구현클래스를 DI하였으나, 코드 리팩토링 후 구현클래스가 아닌 추상화에 의존하고 있는 것을 볼 수 있다.