왜 다른 프레임워크 대신 스프링을 사용하는가?

스프링은 자바 프레임워크이다. 그러므로 자바를 빼먹을수가 없는데 이 자바덕분에 다형성이 가능하기때문에 스프링을 선택했다. 또한 이러한 다형성을 잘 사용하려면, 즉 스프링을 잘 활용하려면 SOLID원칙을 잘 지켜야한다

결론적으로 스프링의 가장 중요한 점은 다형성SOLID이다

1. 다형성

스프링은 자바 언어 기반의 프레임워크이다

자바의 가장 큰 특징은 객체 지향 언어이다

유연하고 변경이 용이

  • 객체지향에서 가장 중요한 점은 다형성이다
  • 이러한 다형성덕분에 프로그램을 유연하고 변경이 용이하게 될수 있다
  • 역할과 구현으로 나뉘는데 역할은 Interface(MemberRepository)이고 구현은 Interface(MemoryMemberRepository)의 구현체이다
  • 역할과 구현의 예시
    • 운전자 - 포르쉐, 아반떼..등등
    • 로미오 - 장동건, 류승범..등등
    • USB - 마우스, 키보드,, 등등
  • 하지만 다형성만으로는 DIP, OCP를 지킬수가없어 DI컨테이너가 탄생한다

클라이언트에게 영향을 주지 않는다

  • 클라이언트(MemberService)는 대상의 역할(인터페이스)만 알면 된다
  • 클라이언트(MemberService)는 구현 대상의 내부 구조를 몰라도 된다
  • 클라어인트(MemberService)는 구현 대상의 내부 구조가 변경되어도 영향 X
  • 클라이언트(MemberService)는 구현 대상 자체를 변경해도 영향 X ( MemoryMemberRepositoryJDBCtemplateMemberRepository )

오버라이딩

  • 오버라이딩이 있기 때문에 다형성이 가능하다

image

  • 이러한 객체 지향의 다형성 덕분에 클라이언트를 변경하지 않고, 서버의 구현기능을 유연하게 변경 가능

스프링에선?

  • 스프링에선 다형성을 활용한 제어의 역전(IoC), 의존관계 주입(DI)를 사용하여 구현을 편리하게 다룰수 있도록 지원한다.
  • 즉 레고 블럭 조립하듯이 구현을 편리하게 변경할 수 있다.

2. 좋은 객체 지향 설계의 5가지 원칙 : SOLID

기존

public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository = MemoryMemberRepository;
    private final DiscountPolicy discountPolicy = new RateDiscountPolicy;

    ...
}

AppConfig 적용

public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
		...
}
public class AppConfig {

    ...

    public OrderService orderService() {
        return new OrderServiceImpl(
                memberRepository(),
                discountPolicy());
    }

    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }

}

구성 클래스(AppConfig)

IoC

  • 프로그램에 대한 제어 흐름 및 인스턴스 생성에 대한 권한 즉, 설정 정보를 갖는 클래스
  • 이렇게 클라이언트 구현 객체가 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것이 Ioc(제어의 역전)

DI

  • AppConfig는 DI 컨테이너이다
  • DI(Dependency Injection)은 특정한 기능을 구현하는 객체가 다른 클래스와의 의존 관계를 인터페이스에만 의존하고, 실제 어떤 클래스 구현 객체가 사용될지 모른다는 것을 의미한다
  • 즉 클라이언트 코드를 변경하지않고, DI 컨테이너를 통해 클라이언트가 호출하는 대상의 타입 인스턴스를 변경할 수 있다

즉, 객체를 생성하고 관리하면서 의존관계를 연결해 주는 것을 DI 컨테이너라고한다

SRP

한 클래스는 하나의 책임만 가져야한다

  • 구현 객체를 생성하고 연결하는 책임, 즉 구성 단계는 AppConfig 클래스
  • 클라이언트 객체는 실행하는 책임만 담당

DIP

추상화에 의존해야지, 구체화에 의존하면 안된다

  • 클라이언트 코드는 인터페이스에만 의존해야한다
  • 하지만 클라이언트 코드는 인터페이스만으로는 아무것도 실행할 수 없다
  • Appconfig(어플리케이션 구성파일)을 구성하여 객체인스턴스를 직접 생성하고, 클라이언트 코드에 의존관계를 주입한다

OCP

소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다

  • AppConfig에서 FixDiscountPolicyRateDiscountPolicy 로 변경할때 클라이언트 코드를 건들지 않고(=변경에는 닫혀있음) 따로 구성 영역을 담당하는 설정 클래스를 만들어 소프트웨어 요소를 새롭게 확장할 수가 있다.
  • 소프트웨어 요소를 새롭게 확장하여도 사용 영역(클라이언트)는 변하지 않는다

댓글 쓰기