
해당 글은 인프런의 김영한님의 강의인 '스프링 핵심 원리 - 기본편'을 공부하며 작성한 글입니다.
Section 1에서는 자바의 다형성 만으로는 SOLID 원칙의 DIP, OCP 원칙을 지킬 수 없다는 것을 알아보았다.
이번 섹션에서는 예제를 직접 만들어서 순수 자바 코드로는 어떻게 OCP, DIP 원칙을 지킬 수 있을지를 코드로 알아본다.
기존에는 공연 서비스 구체 클래스에서는 new 를 통하여 객체 주입을 하였다.
public class 공연서비스구현 implements 공연서비스 {
private final 남자주인공역할 남주 = new 이정재();
}
만약 남자 주인공 역할이 황정민으로 변경되었다면 공연 서비스 코드가 아래처럼 변경된다.
public class 공연서비스구현 implements 공연서비스 {
// private final 남자주인공역할 남주 = new 이정재();
private final 남자주인공역할 남주 = new 황정민();
}
위의 코드는 추상 인터페이스인 '남자주인공역할'과 구체 인터페이스인 '이정재'까지 모두 의존하는 코드였다.
이 공연의 남자 주인공 역할은 이정재이다 라고 공연이 정하고 있는 셈.
그래서 '공연 기획자'가 등장한다.
공연 서비스 구체 클래스에는 new 를 통한 객체 주입이 아닌 생성자 주입을 통하여 '남자주인공역할'을 넣어준다.
public class 공연서비스구현 implements 공연서비스 {
private final 남자주인공역할 남주;
private final 여자주인공역할 여주;
public 공연서비스구현(남주, 여주) {
this.남주 = 남주;
this.여주 = 여주;
}
public void 오프닝(남주, 여주) {
...
}
}
공연 기획자 클래스에서는 생성자를 통하여 공연서비스를 호출하면 구현 클래스 안에 남자주인공역할을 하게될 황정민 클래스를 넣어준다.
public class 공연기획자 {
public 공연서비스 공연서비스() {
return new 공연서비스구현(new 황정민(), 김혜수());
}
}
공연 서비스는 남자, 여자 주인공 역할 배우가 누가 될지 모르는 추상화에만 의존하면서 시나리오를 짤 수 있다.
그리고 공연 기획자는 생성자 주입을 통하여 배우 역할들의 캐스팅을 담당하게되며 DIP가 지켜지게된다.
공연 서비스는 공연에만 관심을 가질 수 있는 관심사의 분리가 완성되었다.
이후 메인 메서드에서는 new 확장자를 통하여 주입하는것이 아닌 공연 기획자를 통하여 공연 서비스를 가져온다.
한 클래스는 하나의 책임만 가져야 한다.
프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.” 의존성 주입은 이 원칙을 따르는 방법 중 하나다.
남자주인공역할 추상화 인터페이스에만 의존하도록 코드를 변경.황정민 객체 인스턴스를 클라이언트 코드 대신 생성해서 클라이언트 코드에 의존관계를 주입.소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
스프링을 활용해보자
AppConfig에는 구성 정보를 담고있다는 @Configuration 어노테이션을 달아준다.@Bean 을 달아주어 스프링이 관리할 수 있도록 한다.@Configuration이 달린 AppConfig를 보고 구성 정보로 활용하고, 스프링 컨테이너에 @Bean이 달린 메서드들을 모두 등록한다.기존에는 메인에서 AppConfig를 통하여 객체들을 조회했지만 이제는 스프링 컨테이너를 통해서 객체(스프링 빈)을 조회해야 한다.
그렇다면 굳이 왜 스프링 컨테이너를 왜 사용해야 할까?
객체가 한 개만 생성되고 공유하도록 설계하면 된다 > 싱글톤 패턴
싱글톤 패턴을 적용하면 고객의 요청이 올 때 마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유해서 효율
적으로 사용할 수 있다.
하지만 싱글톤 패턴은 다음과 같은 수 많은 문제점들을 가지고 있다.
하지만 스프링 컨테이너는 싱글턴 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리한다.
공유필드는 조심해야 한다! 스프링 빈은 항상 무상태(stateless)로 설계하자.
※ 싱글톤 패턴 추가 참고 : 싱글톤(Singleton) 패턴 - 꼼꼼하게 알아보자 - Inpa Dev