728x90
반응형
본 포스팅은 학습용으로, 김영한 님의 강의를 바탕으로 복습용도로 작성되었습니다.
웹 애플리케이션과 싱글톤
- 스프링은 태생이 기업용 온라인 서비스 기술을 지원하기 위해 탄생
- 대부분의 스프링 애플리케이션은 웹 애플리케이션 → 물론 웹 아닌 애플리케이션도 개발 가능
- 웹 애플리케이션은 보통 여러 고객이 동시에 요청
- 순수 DI 컨테이너 테스트
- SingletonTest
public class SingletonTest {
@Test
@DisplayName("스프링 없는 순수한 DI 컨테이너")
void pureContainer() {
AppConfig appConfig = new AppConfig();
//1. 조회 : 호출 할 때 마다 객체 생성
MemberService memberService1 = appConfig.memberService();
//2. 조회 : 호출할 때 마다 객체 생성
MemberService memberService2 = appConfig.memberService();
//참조값이 다른 것을 확인
System.out.println("memberService1 = " + memberService1);
//key = memberRepository1 values = hello.core.member.MemoryMemberRepository@a4add54
System.out.println("memberService2 = " + memberService2);
//key = memberRepository2 values = hello.core.member.MemoryMemberRepository@141e5bef
//웹 어플리케이션은 요청이 많다. 요청이 많으면 이런식이면, 객체가 계속 생성되면서 jvm에 메모리가 계속 쌓이게 된다.
// 메모리 낭비가 심한 해당 문제를 해결하기위해 객체를 딱 하나를 공유하게 만들면 된다 -> 싱글톤 객체
//memberService1 != memberService2
assertThat(memberService1).isNotSameAs(memberService2);
}
}
- 순수 DI 컨테이너인 AppConfig는 요청할 때마다, 객체를 새로 생성
- 고객 트래픽이 초당 100이 나오면 초당 100개 객체가 생성되고 소멸된다 → 메모리 낭비
해당 객체가 딱 1 개만 생성, 공유하도록 설계 ⇒ 싱글톤 패턴
싱글톤 패턴
- 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장.
- 객체 인스턴스를 2개 이상 생성하지 못하도록 제한
- private 생성자를 사용해 외부에서 임의로 new 키워드를 사용하지 못하도록 해야 함.
싱글톤 패턴 적용
package hello.core.singleton;
public class SingletonService {
//1. static 영역에 객체를 딱 1개만 생성된다.
private static final SingletonService instance = new SingletonService();
// 자바 기본의 static 영역에 메모리가 올라감.
//2. public으로 열어서 객체 인스턴스가 필요하면 이 static 메서드를 통해서만 조회하도록 허용한다.
public static SingletonService getInstance() {
return instance;
}
//3. 생성자를 private 를 생성자로 선언해서 외부에서 new 키워드로 사용한 객체 생성을 못하게 막는다.
private SingletonService(){
}
public void logic() {
System.out.println("싱글톤 객체 로직 호출");
}
}
- static 영역에 객체 instance를 미리 하나 생성해서 올려둠.
- 이 객체 인스턴스가 필요시, 오직 getInstance( ) 메서드를 통해서만 조회가능하고, 이 메서드를 호출하면 항상 같은 인스턴스를 반환
- 딱 1개의 객체 인스턴스만 존재해야 하므로, private 으로 막아서 혹시라도 외부에서 new 키워드로 객체 인스턴스가 생성되는 것을 방지
싱글톤 패턴 사용 테스트
@Test
@DisplayName("싱글톤 패턴을 적용한 객체 사용")
void singletonServiceTest() {
SingletonService instance1 = SingletonService.getInstance();
SingletonService instance2 = SingletonService.getInstance();
// 위에 인스턴스 2개 생성
System.out.println("instance1 = " + instance1);
System.out.println("instance2 = " + instance2);
// isSameAs 인스턴스 , isEqual 문자열
assertThat(instance1).isSameAs(instance2);
instance1.logic();
// same : ==
// equal : .equals()
}
[출력]
instance1 = hello.core.singleton.SingletonService@27c86f2d instance2 = hello.core.singleton.SingletonService@27c86f2d 싱글톤 객체 로직 호출
⇒ 싱글톤 패턴을 적용하면 고객의 요청이 올 때마다 객체를 생성하는 것이 아닌, 이미 만들어진 객체를 공유해서 효율적으로 사용할 수 있다.
싱글톤 패턴 문제점
- 싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다.
- 의존관계상 클라이언트가 구체 클래스에 의존 → DIP 위반
- 클라이언트가 구체 클래스(구현체)에 의존해서 OCP 위반할 가능성 높음
- 테스트의 어려움
- 내부 속성 변경 및 초기화 어려움
- private 생성자로 자식 클래스 만들기 어려움
- 유연성이 떨어지고, 안티패턴이라고 불린다.
싱글톤 컨테이너
스프링 컨테이너는 싱글톤 패턴의 문제점을 해결과 동시에 객체 인스턴스를 싱글톤으로 관리
- 싱글 턴 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리
- 싱글톤 객체를 생성하고 관리하는 기능 → 싱글톤 레지스트리
- 스프링 컨테이너의 기능 → 싱글턴 패턴의 단점 해결 및 객체를 싱글톤으로 유지
- 싱글톤 위한 지저분한 코드가 들어가지 않아도 됨.
- DIP, OCP , 테스트, private 생성자로 부터 자유롭게 싱글톤 사용 가능
스프링 컨테이너 사용 테스트
@Test
@DisplayName("스프링 컨테이너와 싱글톤")
void springContainer() {
AnnotationConfigApplicationContext 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);
//memberService1 = hello.core.member.MemberServiceImpl@1e461e41
System.out.println("memberService2 = " + memberService2);
//memberService2 = hello.core.member.MemberServiceImpl@1e461e41
//memberService1 == memberService2
assertThat(memberService1).isSameAs(memberService2);
}
싱글톤 컨테이너 동작 방식
- 이미 만들어진 객체를 공유해서 효율적으로 재사용가능
728x90
반응형
'Spring' 카테고리의 다른 글
[Spring] 컴포넌트 스캔 (0) | 2023.02.10 |
---|---|
[Spring] 싱글톤과 @Configuration (0) | 2023.02.08 |
[Spring] 컨테이너에 등록된 빈 조회 (0) | 2023.02.08 |
[Spring] 스프링 컨테이너 생성 (0) | 2023.02.08 |
[Spring] Spring의 핵심 및 목적 (0) | 2023.02.07 |