일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- JPA
- Singleton
- 싱글톤
- 프로토타입
- js
- HTTP
- Spring
- 로그인
- vuex
- VUE
- HTTP 메서드
- Kotlin
- thymeleaf
- vue-cli
- cache
- Repository
- Stateless
- Security
- di
- Vue.js
- Java
- BEAN
- 의존성 주입
- 캐시
- DB
- 라이프 사이클
- dependency injection
- Excel
- Setter
- javascript
- Today
- Total
jhhan의 블로그
스프링 코어(5) - 싱글톤(Singleton) 패턴 + 컨테이너 본문
이번 포스트에서는 싱글톤 패턴에 대해서 알아보겠습니다.
싱글톤 패턴은
- 클래스의 인스턴스가 1개만 생성되는 것을 보장하는 디자인 패턴
- 2개 이상의 객체가 만들어지지 않게 한다!
- 간단하게 생각하면 private을 이용해서 new로 생성하지 못하게 할 수 있다.
그러면 싱글톤 패턴을 간단하게 적용할 수 있게 해보겠습니다.
singleton 패키지 밑에 SingletonService 자바 파일을 만듭니다.
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance() {
return instance;
}
private SingletonService() {}
public void logic() {
System.out.println("싱글톤 객체 로직 호출");
}
}
이런 식으로 작성합니다.
- static 영역에 객체 인스턴스를 미리 생성하면
- 이 객체 인스턴스는 오직 getInstance()라는 메서드를 통해서만 접근이 가능하다.
- 딱 1개의 객체 인스턴스만 있어야 하기 때문에, 생성자를 private으로 설정
→외부에서 new를 사용해서 객체 생성이 되지 않음 - 참고) 객체 생성은 비용이 많이 들기 때문에, 이미 생성된 객체를 공유해서 사용하는 것이 훨씬 효율적이다.
외부에서 생성하면 에러가 뜨는 것을 확인할 수 있습니다.
그러면 이제 싱글톤 패턴을 사용하는 테스트 코드를 한번 작성해 보겠습니다.
public class SingletonTest {
...
@Test
@DisplayName("싱글톤 패턴을 적용한 객체 사용")
void singletonServiceTest() {
SingletonService singletonService1 = SingletonService.getInstance();
SingletonService singletonService2 = SingletonService.getInstance();
// 실행해보면 같은 인스턴스가 반환된 것을 알 수 있음
System.out.println("singletonService1 = " + singletonService1);
System.out.println("singletonService2 = " + singletonService2);
// isSameAs : 객체의 참조값이 같은지 비교
// isEqualTo : 자바에서의 Equals와 동일
assertThat(singletonService1).isSameAs(singletonService2);
}
}
호출할 때마다 같은 객체가 반환되는 것을 확인할 수 있습니다.
(싱글톤 패턴을 구현하는 방법은 여러가지라고 합니다. 그 중에서 가장 단순하게 구현할 수 있는 방법을 선택한 것입니다.)
이렇게 싱글톤 패턴을 적용하면
여러 요청이 들어오더라도, 이미 만들어진 객체를 공유해서 효율적인 사용이 가능합니다.
하지만 단점도 존재합니다.
- 싱글톤 패턴을 구현하는 코드가 많고 길다.
- 클라이언트가 구체 클래스에 의존함 → DIP 위반
- OCP 위반 가능성 큼
- 테스트 어려움
- private 생성자 → 자식 클래스 생성이 어려움
- 유연성 떨어짐
생각보다 단점이 많습니다.
하지만 괜찮습니다.
스프링 컨테이너가 이런 문제점을 해결해 줄 수 있기 때문입니다.
특히 스프링 컨테이너는 싱글톤 컨테이너의 역할을 하고
Spring Container == Singleton Container라고 봐도 무방하다고 합니다.
그래서 스프링 컨테이너는 싱글턴 패턴을 따로 적용을 안해도 객체 인스턴스가 싱글톤으로 관리됩니다.
즉, 스프링 컨테이너는 싱글턴 패턴의 단점을 해결해주면서 객체를 싱글톤으로 유지할 수 있게 합니다.
- 싱글톤 패턴을 위한 코드가 생략이 됨
- DIP, OCP, 테스트 코드, private 생성자 → 이것들에서 자유롭게 싱글톤 사용이 가능
테스트 코드를 한번 보겠습니다.
import static org.assertj.core.api.Assertions.*;
public class SingletonTest {
// Singleton 컨테이너 관련된 부분
@Test
@DisplayName("스프링 컨테이너와 싱글톤")
void springContainer() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService1 = ac.getBean("memberService", MemberService.class);
MemberService memberService2 = ac.getBean("memberService", MemberService.class);
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
// 실행하면 여기서 오류가 나는 것을 확인할 수 있음
// assertThat(memberService1).isNotSameAs(memberService2);
// 이렇게 실행해야 오류 안남
assertThat(memberService1).isSameAs(memberService2);
}
}
여기서 테스트를 할 때
- 생성된 2개의 객체를 다른 것으로 테스트를 하면 테스트 오류가 납니다.
- 생성된 2개의 객체를 같다고 테스트를 해야 테스트가 정상적으로 작동합니다.
결국 스프링 컨테이너가 있기 때문에
요청이 들어올 때마다 객체 생성이 아닌
이미 만들어진 객체를 공유하기 때문에 효율적인 사용이 가능합니다.
추가적으로 스프링의 빈 등록 방식은 기본적으로 싱글톤입니다.
하지만 싱글톤이 아닌 요청할 때마다 새로운 객체를 생성해서 반환하는 기능도 제공합니다.
대부분의 스프링의 빈 등록 방식이 싱글톤이기 때문에 다른 방식을 굳이 알려고 하지는 않아도 됩니다.
이상으로 싱글톤 패턴 + 컨테이너 에 대한 설명을 마칩니다.
출처: 인프런 - 스프링 핵심원리(기본편) by 김영한
'Spring' 카테고리의 다른 글
스프링 코어(7) - 싱글톤(singleton)과 Configuration (0) | 2021.04.27 |
---|---|
스프링 코어(6) - 싱글톤(Singleton) 주의점 (0) | 2021.04.27 |
스프링 코어(4) - 싱글톤(Singleton)에 대한 이해 (0) | 2021.04.26 |
스프링 코어(3) - 스프링 컨테이너 & 빈 (0) | 2021.01.24 |
스프링 코어(2) - 스프링 컨테이너 & 빈 (0) | 2021.01.23 |