Spring 탄생 전에는 EJB라는 기술을 사용했었다
EJB의 문제점
EJB를 사용하면 EJB에 의존적으로 코드를 작성해야 하기 때문에, POJO라는 개념이 등장
EJB를 대체하기 위해 Spring이 탄생
EJB 엔티티빈을 대체하기 위해 Hibernate가 탄생 (JPA 구현체가 Hibernate)
스프링을 편리하게 사용할 수 있도록 지원
스프링은 자바 언어 기반의 프레임워크이다.
자바의 가장 큰 특징은 객체지향 언어!
스프링은 객체 지향 언어가 가진 특징을 살려내는 프레임워크이고, 좋은 객체지향 어플리케이션을 개발할 수 있게 도와주는 프레임워크이다
기존에 EJB를 사용할 때는 EJB를 상속받는 등 EJB에 의존적으로 개발했었다.
이렇게 되면 객체지향의 장점을 잃어버리게 되고 EJB 종속되버리게 된다.
그래서 POJO라는 단어가 등장하고 예전의 자바 스타일로 돌아가자는 움직임이 생겼다.
핵심은 객체지향
프로그램을 유연하고 변경이 용이하게 만든다.
-> 다형성
클라이언트에 영향을 주지 않고 새로운 기능을 제공할 수 있다.
새로운 구현체가 나와도, 클라이언트에서 수정할 필요가 없다.
클라이언트는 대상의 역할(인터페이스)만 알면 된다. (내부 구조 몰라도 ok, 내부 구조 변경되어도 영향 x)
클라이언트는 구현 대상 자체가 변경되어도 영향을 받지 않는다.
자바의 다형성이 위의 개념을 구현했다.
역할 = 인터페이스
구현 = 인터페이스를 구현한 클래스
객체 설계 시, 역할과 구현을 정확히 분리해야 한다. -> 객체 간 협력 관계를 그대로 재사용할 수 있다!
인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경할 수 있다.
다형성의 본질을 이해하려면 협력이라는 객체사이의 관계에서 시작해야 한다
클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.
public class MemberService {
private MemberRepository memberRepository = new MemoryMemberRepository();
}
public class MemberService {
// private MemberRepository memberRepository = new MemoryMemberRepository();
private MemberRepository memberRepository = new JdbcMemberRepository();
}
한 클래스는 하나의 책임만 가져야 한다.
중요한 기준은 변경이며, 변경 시 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것
EX) 객체의 생성과 사용 분리
소프트웨어 요소는 확장에는 열려있으나, 변경에는 닫혀있어야 한다.
다형성을 활용해 준수할 수 있음
public class MemberService {
// private MemberRepository memberRepository = new MemoryMemberRepository();
private MemberRepository memberRepository = new JdbcMemberRepository();
}
이를 해결하기 위해 객체를 생성하고, 연관관계를 맺어주는 별도의 설정자가 필요하다
-> 스프링 컨테이너가 해줌 (DI)
상위 타입의 객체를 하위 타입의 객체로 치환해도 동작에 문제가 없어야 한다.
EX) 자동차 인터페이스의 엑셀을 앞으로 가라는 기능인데, 이를 하위에서 뒤로 가게 구현하면 LSP 위반
클라이언트 입장에서 사용하는 기능만 제공하도록 인터페이스를 분리해야 한다.
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
인터페이스를 분리하게 되면 인터페이스가 명확해진다
EX) 자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스로 분리
-> 정비 인터페이스에 변동이 있어도 운전자 클라이언트에 영향을 주지 않는다
구체화에 의존하지 말고 추상화에 의존해야 한다.
구현이 아닌 역할에 의존해야 한다.
구현(구현 클래스)에 의존하면 변경이 어려워지기 때문!
역할(인터페이스)에 의존해야 유연하게 변경할 수 있다.
public class MemberService {
// private MemberRepository memberRepository = new MemoryMemberRepository();
private MemberRepository memberRepository = new JdbcMemberRepository();
}
객체지향의 핵심은 다형성!
다형성만으로 유연하고 변경이 용이하게 개발할 수 없다.
구현 클래스를 변경할 때 클라이언트 코드 변경 (OCP 위반)
인터페이스에 의존하지만 구현 클래스에도 의존 (DIP 위반)
다형성만으로는 OCP, DIP를 준수할 수 없다
-> 이러한 문제를 스프링에서 해결했다. (DI 사용)
Spring은 DI(Dependency Injection)을 사용해 다형성 + OCP,DIP를 가능하게 지원한다.
DI를 통해 클라이언트 코드의 변경없이 기능을 확장하고, 부품을 교체하듯 쉽게 개발할 수 있도록 해준다.