Search
Duplicate

[스프링 핵심원리 기본] 싱글톤 컨테이너 - 웹 애플리케이션을 싱글톤 방식으로 변경

상태
스프링 핵심원리 기본
담당자
속성 1
Spring
JAVA
속성
7
1) AppConfig의 문제점
현재 AppConfig는 사용하고 싶을 때마다 new 생성자를 통해서 메모리를 할당받고 있다.
이렇게 될 시 웹에서 사용자들이 많아질수록 메모리 부담이 심해진다.
이를 해결하고자 Singleton 방식을 사용하려고 한다. 아래 예제를 보자.
2) SingletonService 구현
package hello.core.singleton; public class SingletonService { //1. static 영억에서 객체를 딱 1개만 생성한다. private static final SingletonService instance = new SingletonService(); //2. public으로 열어 객체인스턴스가 필요히면 이 static 메서드를 통해 조회하도록 한다. public static SingletonService getInstance() { return instance; } //3. 생성자를 private으로 선언해서 외부에서 new 키워드를 사용한 객체 생성을 못하게 막는다. private SingletonService() {} public void logic() { System.out.println("싱글톤 객체 로직 호출"); } }
Java
복사
3) singletonServiceTest 구현
같이 메모리 주소 값인지 확인
두 개의 참조값이 같은지 확인
package hello.core.singleton; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; public class SingletonServiceTest { @Test public void singletonServiceTest() { //private으로 생성자를 막아두었다. 컴파일 오류가 발생한다.//new SingletonService();//1. 조회: 호출할 때 마다 같은 객체를 반환 SingletonService singletonService1 = SingletonService.getInstance(); //2. 조회: 호출할 때 마다 같은 객체를 반환 SingletonService singletonService2 = SingletonService.getInstance(); //참조값이 같은지 확인 System.out.println(singletonService1); System.out.println(singletonService2); // singletonService1 == singletonService2 Assertions.assertThat(singletonService1).isSameAs(singletonService2); } }
Java
복사
4) 싱글톤 방식의 문제점
싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다.
의존관계상 클라이언트가 구체 클래스에 의존한다.
DIP를 위반한다. 클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높다.
테스트하기 어렵다.
내부 속성을 변경하거나 초기화하기 어렵다.
private 생성자로 자식 클래스를 만들기 어렵다.
결론적으로 유연성이 떨어진다.
안티 패턴으로 불리기도 한다
5) SpringContainer
스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤으로 관리한다.
package hello.core.singleton; import hello.core.AppConfig; import hello.core.member.MemberService; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import static org.assertj.core.api.Assertions.*; public class SingletonServiceTest { ... @Test @DisplayName("스프링 컨테이너와 싱글톤") void springContainer() { ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); //1. 조회: 호출할 때 마다 같은 객체를 반환 MemberService memberService1 = ac.getBean("memberService", MemberService.class); //2. 조회: 호출할 때 마다 같은 객체를 반환 MemberService memberService2 = ac.getBean("memberService", MemberService.class); //참조값이 같은 것을 확인 System.out.println("memberService1 = " + memberService1); System.out.println("memberService2 = " + memberService2); //memberService1 == memberService2 assertThat(memberService1).isSameAs(memberService2); } }
Java
복사
6) 싱글톤 컨테이너 적용 후
스프링 컨테이너를 통해서 고객의 요청이 올 때마다 만들어진 객체를 공유해서 효율적으로 쓸 수 있다.
DIP, OCP, 테스트, pirvate 생성자로부터 자유롭게 싱글톤을 사용할 수 있다.
결론
기존에 자바로 AppConfig.java를 구성하여서 스프링 대신에 사용했는데, 해당하는 구성으로는 New생성자를 통해서 계속 생성함으로, 메모리 낭비가 되었었다. 이를 해결하기 위해서 Singleton패턴을 사용했지만, DIP, OCP, 중복 코드로 관리하는 부분에서 어려움이 느껴졋다.
때문에 우리는 SpringContaier를 통해서 DIP, OCP, 중복코드 관리뿐만 아니라 싱글톤 방식도 자유롭게 쓴다는 것을 알아 두자.
이 글은 인프런의
제목 : 스프링 핵심 원리 - 기본편
강사 : 김영한 님의 동영상을 참조해 만들었습니다.