2022.01.17 TIL

듀듀·2023년 1월 17일
0

[ ServiceImpl을 사용해야 하는 이유 ]

스프링에서 Service를 두고 ServiceImpl 로 이를 구현하는 경우를 볼 수 있다.

1. Loose Coupling

객체 간의 결합도를 낮추어 변화에 유연한 개발을 하기 위해서이다. 하나의 인터페이스를 구현하는 여러 구현체가 있고 기능에 따라 적절한 구현체가 들어가서 다형성을 주기 위함이다. 또 하나의 인터페이스만 바라보니 의존관계도 줄일 수 있다.

2. Spring에서 JDK Dynamic Proxy를 사용하여 AOP Proxy를 만들기 위해

JDK Dynamic Proxy는 인터페이스 기반으로 프록시 객체를 만들게 되어 있다. 예를 들어, 인터페이스가 있어야지 @Transactional 어노테이션이 동작하게 된다.
하지만 특정 버전부터 CGLIB 라이브러리를 사용하여, 클래스 기반으로 AOP Proxy를 만들도록 지원을 하게 되었다. 그래서 개발자는 AOP Proxy를 만드는 방식을 선택할 수 있게 되었다.


// 비밀번호를 바꾸는 인터페이스
public interface ChangePasswordService {
    public void change(MemberId id, PasswordDto.ChangeRequest dto);
}

// 비밀번호 기반으로 비밀번호를 변경하는 기능
public class ByPasswordChangePasswordService implements ChangePasswordService {
    private MemberFindService memberFindService;
    @Override
    public void change(MemberId id, PasswordDto.ChangeRequest dto) {
        if (dto.getPassword().equals("비밀번호가 일치하는지 판단 로직...")) {
            final Member member = memberFindService.findById(id);
            final String newPassword = dto.getNewPassword().getValue();
            member.changePassword(newPassword);
        }
    }
}

// 비밀번호를 잃어버렸을 때 다른 인증 기반으로 비밀번호를 변경하는 기능
public class ByAuthChangePasswordService implements ChangePasswordService {
    private MemberFindService memberFindService;
    @Override
    public void change(MemberId id, PasswordDto.ChangeRequest dto) {
        if (dto.getAuthCode().equals("인증 코드가 적합한지 로직 추가...")) {
            final Member member = memberFindService.findById(id);
            final String newPassword = dto.getNewPassword().getValue();
            member.changePassword(newPassword);
            // 필요로직...
        }
    }
}

예를 들어 ChangePasswordService 인터페이스의 책임은 비밀번호를 변경하는 것이다. 해당 구현체들은 비밀번호 변경에 대한 다양한 로직을 구현하게 된다. 이것을 인터페이스로 둘 수 있는 이유는 인터페이스의 책임이 하나이기 때문이다.

profile
나는 내 의지대로 된다.

0개의 댓글