Service ServiceImpl

김도엽·2022년 8월 27일
0

Java Spring Boot

목록 보기
10/10

객체 지향 설계에 대해 공부하던 중 궁금한 점이 하나 생겼다.
지금까지 MVC 패턴으로 설계할때 Controller와 Service는 인터페이스 상속을 받지 않고 1:1 관계로 의존 관계를 맺어왔다.
하지만 레퍼런스를 참고하던 중 Service, Repository를 인터페이스화 하고 Serviceimpl, Repositoryimpl로 구현체를 만들어 사용하는 것을 보았고, 1:N관계라면 이해가 가지만 1:1관계에서 굳이 필요한가? 객체지향적 설계에 맞게하기위해 억지로 쓰는 것일까? 궁금증이 생겼다.

위 구조처럼 인터페이스를 상속받은 Service구현체가 따로 있다. 보통 인터페이스를 사용하는 이유는 객체지향 특징 중 하나인 다형성을 가지게 하기 위함으로 알고있다.

다형성 : 하나의 자료형에 여러가지 객체를 대입하여 다양한 결과를 얻어내는 성질

OCP 원칙에 맞는 설계이긴 하지만 굳이 관계를 하나 더 만들어서 사용해야할까?




이에 관련해서 구글링을 해봤고, 이해하기에 좋은 내용을 찾았다.

인터페이스
public interface IService {

    String test();

}
구현체
@Service
public class AServiceImpl implements IService {

    @Override
    public String test() {
        return "AServiceImpl";
    }

}
컨트롤러
// Controller 

@RequiredArgsConstructor
@RestController
public class SampleController {

    private final IService service;

    @GetMapping("/test")
    public String test(){
        return service.test();
    }

}

위 예시 코드를 보면 컨트롤러는 특정 구현체가 아닌 IService 타입을 의존 주입받고 있다. (물론 특정 구현체인 AServiceImpl 을 의존주입 받아도 괜찮다.)

이렇게 구현체가 아닌 인터페이스를 의존받으면 OCP 원칙을 지킬 수 있다. 무슨 뜻인지 잘 모르겠다면 임의로 BServiceImpl 구현체를 추가해보자.

또 다른 구현체(BServiceImpl)
public class BServiceImpl implements IService {

    @Override
    public String test() {
        return "BServiceImpl";
    }

}

AServiceImpl 와 마찬가지로 IService에 선언된 test() 메서드를 구현하고 있다. 이제 이 클래스에 @Service 어노테이션을 붙이면 스프링 컨테이너에 의해 SampleController 로 의존주입이 된다.
(AServiceImpl 의 @Service 어노테이션은 제거할 것)

결론

IService 라는 인터페이스를 구체화 하는 구현체간의(AServiceImpl, BServiceImpl) 차이만 있을 뿐, 클라이언트 코드(컨트롤러) 입장에서는 무엇이 변했는지 전혀 모르는 상태이다. 여기서 모르는 상태라는 것은, ServiceLayer 의 구현체가 변경되더라도 클라이언트 코드는 전혀 수정할 필요가 없다는 의미.
지금은 단순히 test() 라는 메서드에서 문자열을 출력하는 기능밖에 없어 감흥이 없을 수 있다. 유명한 예제인 정률 할일(%할인) 정액 할인(1000원 할인) 을 가정해보면, 만약 현재는 정률 할인을 진행하더라도, 갑자기 정액할인으로 정책이 변경된다면, 위의 예제처럼 서비스레이어의 어노테이션만 바꿔주면 간단하게 변경된 정책을 코드상 배포할 수 있게 된다.

기획 정책이 바뀌지 않는다는 보장이 없으니 구현체를 따로 두지 않는 방법이 더 좋은 방법으로 이해가 되지 않는 한 인터페이스를 사용해서 쓸 것 같다.





참고자료 출처 : https://junior-datalist.tistory.com/m/243
참고자료 : https://jeonyoungho.github.io/posts/spring%EC%97%90%EC%84%9C-Service-ServiceImpl%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC%ED%95%98%EB%82%98/
참고자료 : https://see-one.tistory.com/1
참고자료 : https://github.com/f-lab-edu/daangn-market-used-trading/blob/develop/src/main/java/com/ssibongee/daangnmarket/member/service/GeneralMemberService.java
profile
즐거운

1개의 댓글

comment-user-thumbnail
2023년 9월 1일

AServiceImpl 의 @Service 어노테이션을 제거하지 않고 BServiceImpl에도 @Service가 있으면 어떻게되는건가요?

답글 달기