해당 글은 인프런의 김영한님의 강의인 '스프링 핵심 원리 - 기본편'을 공부하며 작성한 글입니다.
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