🌿SPRING/🍀공부 [SPRING]

[SPRING] Service 와 ServiceImpl

디카페인라떼 2022. 9. 14. 19:14

 처음 Spring을 배울때부터 채멘에게 배웠던 방식은 Service Interface를 두고 Service 구현체를 따로 두는 방식이었다.

그래서 팀과제를 할때에도 혼자서 꿋꿋이(?) 이 방식을 고수해오고 있었는데 최근 멘토링 중 매니저님께서 
' 이 방식을 사용할 때에 장점은?'
' 하나의 서비스 interface에서 2개 이상의 구현체가 필요할 경우 어떻게 할 것인가?'

하는 질문에서 제대로 대답을 하지 못하였다. 그리고 다른 팀원들도 '왜' 사용하는 지에 대해 물어보는데 그저 어렴풋이 대답할 뿐 확실한 답을 해내지 못하여서 이번 기회에 개념을 다 잡고자 한다.

 

 

관습적인 추상화
  • 왜 Service Interface 와 Service Impl Class를 따로 사용하는가?
    • 👀장점 
      • 인터페이스와 구현체의 분리를 통해 특정 기술이나 외부환경에 독립적으로 보다 자유로운 확장이 가능해짐.
      • 구현체 클래스를 변경하거나 확장해도 이를 사용하는 클라이언트의 코드에 영향을 주지 않도록 하기 위해서
      • 느슨한 결합을 유지하여 각 기능 간 의존관계를 최소화 가능
        • 의존관계 최소화로 인해 기능의 변화에도 최소한의 수정으로 개발할 수 있는 유연함을 가질 수 있음.
      • 모듈화를 통해 어디서든 사용할 수 있도록 하여 재사용성을 높임
      • 스프링의 IoC/DI기능을 이용한 빈 관리 기능을 사용할 수 있다.
      • 객체지향의 다섯 가지 원칙 중 하나인 OCP 원칙을 가장 잘 실현해주는 설계방식
        • OCP 원칙 (Open Closed Principle)
        • 개발, 폐쇄 원칙
        • 소프트웨어 개체 (클래스, 모듈, 함수 등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다.
    • 👀단점
      • 코드 구조가 복잡해지고, 복잡해진 구조만큼 코드를 분석하고 확인하는 과정에서 인터페이스를 거쳐 구현체들을 확인해야하는 번거로움 (= 설계 구조가 복잡해짐)
      • 실제로는 인터페이스와 구현체 클래스 사이의 관계가 1:1로 구성되어 실질적으로 인터페이스를 사용하는 것에대한 이점을 가지지 못함
      • 이러한 단점에도 불구하고 관습적으로 추상화를 적용하고 있음

 

왜 관습적인 추상화 방식을 해야하는 걸까?
  • 결국에는 프로젝트를 설계하는 사람의 마음...
  • 사용하든 사용하지 않든 이에대한 이유와 근거에 대해서 알고 있고, 설명할 수 있어야 한다
    • ⭕ 관습적인 추상화 방식을 적용해야한다는 의견 
    • 객체에 대한 설계와 이를 구현한 코드는 언제든지 변할 수 있습니다. 그렇기 때문에 개발자는 이를 대비해야 합니다. 지금 만들어서 사용중인 인터페이스와 구현체 클래스가 1:1 관계를 맺고 있을지 모르지만 서비스가 커지고 변화함에 따라서 얼마든지 구현체 클래스는 확장될 가능성을 가지고 있습니다. 그렇기 때문에 이러한 구조를 통해 미래의 변화에 유연하게 대처할 수 있도록 대비해야 합니다. (토비의 스프링 3.1 1장 중)
    • 이러한 구조는 협업에서 이점으로 작용될 수 있습니다.
      프로젝트를 시작할 때 설계자가 프로젝트의 큰 뼈대를 구성하고, 나머지 작업자들은 그에 맞는 실제 구현을 하게 되는 경우가 있습니다. 이때 함수명, 리턴, 파라미터 등을 설계자가 만들어놓은 인터페이스에 맞춰 코딩할 수 있습니다. 이처럼 인터페이스를 누군가 작성하고 실제 구현은 다른 사람이 할 수 있는 분할의 기능도 협업에서의 이점이 될 수 있습니다.

 

하나의 서비스 interface에서 2개 이상의 구현체가 필요할 경우 어떻게 할 것인가?
=> 추상화를 통한 설계 방식의 네이밍 컨벤션
  • 보통 인터페이스는 Service / 구현체의 경우 SerciveImpl을 사용함
    • 인터페이스와 구현체 사이의 관계가 1:1이기 때문에 인테페이스가 딱히 구현에 필요하진 않지만 설계 패턴을 만족시키기 위해 불필요한 네이밍이 반복됨
  • 1:N의 관계라면?
    • 이러한 확장에 있어선 고유한 특징을 구현체마다 가지고 있을 것이기 때문에 다음과 같이 변경 가능
Ex) 당근 마켓 이용시 일반 회원 사용자도 있지만 자영업자 사장님 회원도 있음
이런식으로 서비스가 확장됨에 따라서 사용자의 유형 또한 확장될 여지가 있음. 

MemberService : 회원 서비스 인터페이스
       - GeneralMemberService : 일반 회원 서비스 구현체 클래스
       - CeoMemberService : 사장님 회원 서비스 구현체 클래스
       - . .. .

 

MVC 패턴에서 Service Model의 역할
  • MVC 패턴에서 view는 자신이 요청할 Controller만 알고 있으면 되고, Controller는 화면에서 넘어오는 매개변수들을 이용해 Service객체를 호출하는 역할
  • Service는 불필요하게 Http 통신을 위한 HttpServlet을 상속받을 필요 없는 순수한 자바 객체로 구성
    • Service는 어떤 컨트롤러가 호출하든 상관없이 필요한 매개 변수만 준다면 자신의 비즈니스 로직을 처리
    • 모듈화를 통해 어디서든 재사용이 가능한 클래스 파일
  • 이렇게 제대로 구현된 Service라면 단순 Web 기반이 아니라 추후 native app으로 view단이 변경되더라도 Service는 view에 종속적인 코드가 없기 때문에 그대로 재사용할 수 있게 됨
  • 추가적인 요청 사항이 들어오면 기존의 소스를 수정하는 게 아니라 기존 Service 인터페이스를 구현하는 다른 클래스를 통해 그 객체를 사용하게 하는 것 (위에서 이야기한 OCP에 따른 변화에는 닫혀있고, 확장에는 열려있는 구조)