내가 스프링 공부를 근본 원리 중심적으로 다시 공부하니까 느낀 것이 있다. 결국 사람들이 말하는 이상적인 스프링에서의 아키텍처는 스프링 삼각형 + 객체 지향 설계 5원칙으로 이루어져있다는 것이다.
아래의 사례를 보자.
DI의 가치는 관심, 책임, 성격이 다른 코드를 깔끔하게 분리하는데에 있다. 이러한 분리가 가져오는 특징은 객체 지향 5대 설계 원칙인 SOLID 중 SRP에서 찾아볼 수 있다.
즉, 사용자 관리 로직이 바뀌어도 UserService를 수정해야하고 서버 환경이 바뀌어도 UserService를 수정해야한다. → SRP를 위반한다.
DI를 통해 외부에서 제어하도록 만들기에 UserService가 변경될 이유는 사용자 관리 로직이 바뀌는 것 밖에 없다. → 모듈이 바뀌는 이유 1가지 UserDao 기술이 JDBC → JPA로 바뀌어도 코드는 단 한줄도 수정할 이유가 없다. → SRP를 충실히 지키고 있다.
결국 Ex)에 서비스 추상화를 사용하면 OCP와 SRP가 지켜지는 것이다. + DI
객체 지향 설계와 프로그래밍 원칙은 서로 긴밀한 관계가 있다. SRP를 잘지키는 코드를 짜려면 인터페이스를 도입하고 이를 DI로 변경해야 한다. 그 결과로 SRP 뿐만 아니라 OCP도 자연스럽게 잘 지켜지고 모듈간의 결합도가 낮아서 서로의 변경이 영향을 주지 않는다. 같은 이유로 변경이 SRP에 집중되는 응집도 높은 코드가 나온다.
그리고 이러한 과정에서 전략 패턴, 템플릿 콜백 패턴 등등 여러 디자인 패턴이 적용되기도 한다. 좋은 코드를 설계하고 만드려면 꾸준한 노력이 필요하다. 그저 기능이 동작하는 것에 만족하지 말고 계속 다듬고 개선하려는 자세가 필요하다.
패턴이나 설계 원칙을 공부하는 이유는 가오 ㅈ되는 용어를 외우고 기계적인 지식을 습득하려는게 아니라 개발자 스스로의 노력과 고민이 있을 때 비로소 빛이 나는 분야이기 때문이라고 생각한다.
다시 돌아와서 지금까지 코드를 발견시켜온 과정을 보면 DI가 빠질 수 없다. 스프링의 의존 관계 주입 기술인 DI는 모든 스프링 기술의 기반이 되는 핵심 엔진이자 원리이며, 스프링이 지지하고 지원하는 좋은 설계와 코드를 만드는 모든 과정에서 사용되는 가장 중요한 도구이다. 괜히 스프링 DI 프레임 워크라고 부르는게 아니다.
우선 우리가 흔히말하는 관습적인 추상화에 대해서 알아보자. 관습적이라고 나쁜것이 아니다. 오히려 좋은 설계 방법이지만 모르고 사용하는 개발자들이 많아서 이런 이름이 붙은 것 뿐이다. 앞으로 우리가 사용해야할 추상화도 관습에 따른 추상화이다.
기본적인 서비스 추상화가 적용되지 않은 애플리케이션에서의 작업 흐름도이다.
다음은 서비스 추상화가 적용된 애플리케이션이다.
차이점은 ServiceImpl이 생겨나고 Service가 interface가 된 것 정도만 알아보면 충분하다.
당연히 Service 계층은 인터페이스를 사용하였으니 추상화된 메서드를 작성해주어야한다. 물론 SRP(단일 책임의 원칙)을 잘 지켜서 말이다. 그 다음 ServiceImpl은 Service(interface)를 implements 받는 구현체이다.
Service의 추상화 메서드를 @Override 해서 구현하도록 하자
위에서 간략하게 설명하긴 했다만 정리하는 차원에서 장점과 알아가야 할 것을 한번 더 정리해보겠다.
장점 - 서버 또는 개발환경, 비즈니스 로직 변경이 클라이언트가 사용하는 코드는 바뀌지 않기에 개발 유지 보수성이 극대화된다. 작은 서비스의 경우 서비스를 2개의 계층으로 나누는것에 의미를 두나 마나라고 생각할 수 있지만, 서비스 추상화가 적용되지 않은 애플리케이션에서의 비즈니스 로직을 변경하면 관련된 모든 로직을 변경해야하는 대참사가 일어나기 때문에 서비스가 커지면 커질수록 서비스 추상화의 필요성은 극대화된다.