Service
와 ServiceImpl
구조에 대해처음 스프링 MVC 패턴을 배울 때 많은 참고 자료들은 비즈니스 레이어를 Service
와 ServiceImpl
로 나누어 구현하곤 했다. 대부분의 초심자들은 이 방식으로 Spring 예제를 만들었을 것이라고 생각한다.
그러나 실제로 프로젝트에 돌입하고 나서 느낀 점은, 많은 개발자들이 단일 Service
클래스 방식으로 만들고 있다는 것이었다. 나 또한 ServiceImpl
구현체 방식의 메리트를 느끼지 못해 현재는 Service
클래스 안에서 비즈니스 로직을 작성하고 있다.
그렇다면 Service
와 ServiceImpl
구조는 왜 사용하고, 왜 바뀌었을까?
💡
Service
와ServiceImpl
구조란?
- Service 인터페이스: 서비스가 제공해야 하는 기능을 정의한다.
- ServiceImpl 클래스: 인터페이스의 기능을 실제로 구현한다.
- 이 구조는 이렇게 인터페이스와 클래스로 분리되는데, 이때 인터페이스는 "무엇을" 해야 하는지에 초점을 맞추고, 구현체가 "어떻게" 해야 하는지에 집중함으로써 코드가 더 명확하고 관리하기 쉽게 만든다.
Service
와 ServiceImpl
구조는 주로 객체지향 프로그래밍(OOP)과 디자인 패턴, 특히 OCP 원칙을 준수하기 위해 개발된 설계 패턴이다.
Service
와 ServiceImpl
구조는 객체지향 프로그래밍(OOP)과 디자인 패턴의 영향을 크게 받았다. OOP의 핵심 개념인 추상화, 캡슐화, 상속, 다형성을 잘 활용하기 위해, 인터페이스와 구현체를 분리하는 디자인이 탄생했다.
이러한 패턴은 소프트웨어의 유연성과 유지보수성을 높일 수 있다.
이 구조는 OCP (Open/Closed Principle)
원칙을 준수하기 위해 만들어졌다. OCP란 소프트웨어 개체는 확장에는 열려 있고, 수정에는 닫혀 있어야 한다는 원칙이다.
이는 기존 코드를 수정하지 않고도 새로운 기능을 추가하는 것을 목표로 한다.
IoC(Inversion of Control)
: 객체의 생성, 초기화, 소멸 등의 제어권을 개발자가 아닌 컨테이너(스프링 프레임워크)가 담당한다.
DI(Dependency Injection)
: 객체가 필요로 하는 의존성을 외부에서 주입받는 방식이다. 주로 생성자 주입, 세터 주입, 필드 주입 방법이 있다.
Service
와 ServiceImpl
구조를 사용하면 Service
인터페이스를 빈으로 등록하고, 이를 ServiceImpl
에서 의존성 주입을 받아 사용하는 방식으로 구현할 수 있다.
이를 통해 의존성 주입을 스프링이 관리하도록 해 IoC/DI 방식을 구현할 수 있다.
이렇게 인터페이스와 클래스로 나누는 방식은 많은 장점을 가지고 있어 자주 쓰이곤 했었다. 그러나 최근에는 많은 개발자들이 단일 Service
클래스를 사용하는 경우가 많아졌다. 왜 바뀌었을까?
최근 소프트웨어 개발에서는 더 간결하고 신속한 개발이 요구된다. 특히 작은 규모의 프로젝트나 마이크로서비스 아키텍처에서는 단일 Service 클래스를 사용하는 경우가 많아졌다. 다음과 같은 이유 때문이다.
간소화: 작은 규모의 프로젝트에서는 인터페이스와 구현체를 분리하는 것이 오히려 불필요하게 복잡해질 수 있다.
신속한 개발: 빠른 프로토타이핑과 개발 속도가 중요한 환경에서는, 단일 클래스로 구현하면 코드 작성과 유지보수가 더 빨라진다.
과거 스프링 2.0 시절에는 AOP(Aspect-Oriented Programming) Proxy
를 구현할 때 주로 JDK Dynamic Proxy
를 사용했다. JDK Dynamic Proxy
는 인터페이스를 기반으로 동작하기 때문에, 인터페이스를 구현한 객체에 대해서만 AOP Proxy
를 생성할 수 있었습니다.
즉, 인터페이스가 없는 클래스에는 AOP
를 적용할 수 없었기 때문에 모든 서비스와 컴포넌트가 필수적으로 인터페이스를 구현했어야 했다.
그러나 시간이 지나면서 CGLIB(Code Generation Library)
가 도입되었고, 이를 통해 인터페이스를 구현하지 않은 클래스에도 AOP
를 적용할 수 있게 되었다.
💡
AOP Proxy
란?
- AOP(Aspect Oriented Programing)는 여러 비즈니스 로직에서 반복되는 부가 기능을 하나의 공통 로직으로 처리하도록 모듈화해 필요할 때 호출해서 사용하는 방식이다.
AOP
에 대한 내용은 1.1 스프링 프레임워크의 관점 지향 프로그래밍 (AOP) 목차에서 확인하면 된다.
Service
와 ServiceImpl
구조는 과거에 유연성과 확장성을 위해 널리 사용되었다. 또한 AOP
를 적용하기 위해서 반드시 사용해야 했다. 그러나 현대의 소프트웨어 개발 환경에서는 단일 Service 클래스 구조가 간소화된 코드와 빠른 개발 주기를 지원하는 데 더 적합한 경우가 많다.
이런 특징 때문에 개인이 진행하는 프로젝트나 포트폴리오용 미니 프로젝트에서는 단일 Service
구조를 더 자주 사용하게 되는 것 같다. 결국, 어떤 구조를 선택할지는 프로젝트의 규모와 복잡성, 팀의 경험과 선호도 등에 따라 달라질 것이다.
가장 좋은 방법은 두 접근 방식의 장단점을 이해하고, 상황에 맞게 적절히 선택하는 것이라고 할 수 있겠다.