해당 강의는 김영한 강사님의 유료 강의로, 아주 간략하게 배운 부분들을 짚고 넘어가는 식으로 작성하였습니다.
생략된 부분이 많습니다. 전체 소스코드 공개도 금지이므로 블로그에 부분적으로만 올릴 생각입니다.
강의를 보며 포스트잇을 붙이는 느낌으로 제가 보기 위해 작성하는 글이니
학습을 위해서라면 아래 링크의 강의를 직접 들으시는 것을 추천합니다!
스프링 핵심 원리 - 기본편 - 인프런 | 강의
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...
www.inflearn.com
싱글톤 컨테이너
스프링은 태생이 기업용 온라인 서비스 기술 지원을 위해 탄생했다.
대부분의 스프링 애플리케이션은 웹 애플리케이션이다.
웹 애플리케이션은 보통 여러 고객이 동시에 요청을 한다.
클라이언트 A, B, C가 memberService를 스프링한테 요청한다고 가정하자
만약 스프링 없는 순수한 DI 컨테이너라면
DI 컨테이너(AppConfig)가 new MemberService 해서 반환해준다.
요청이 올 때마다 이렇게 객체가 생성될 것이다.
이를 해결하기 위한 방안은 해당 객체가 딱 1개만 생성되고 공유하도록 설계하는 것이다.
이것이 싱글톤 패턴이다.
싱글톤 패턴
클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.
그래서 객체 인스턴스를 2개 이상 생성하지 못하게 막아야 한다.
-> private 생성자를 사용해 외부에서 임의로 new 키워드를 사용하지 못하게 막는다.
public class SingletonService {
// 자기 자신을 내부에 private static 으로 하나 가지고 있다.
private static final SingletonService instance = new SingletonService();
// 위의 instance 의 참조를 꺼낼 수 있는 방법은 얘밖에 없다.
public static SingletonService getInstance() {
return instance;
}
// 외부에서 new 키워드 사용한 객체 생성 막음
private SingletonService() {
}
public void logic() {
System.out.println("싱글톤 객체 로직 호출");
}
}
그런데 싱글톤 패턴은 많은 문제점들을 가지고 있다.
의존관계상 클라이언트가 구체 클래스에 의존해 DIP를 위반하고,
OOP 원칙 위반 가능성이 높고, 테스트하기 어렵고 등등..
따라서 스프링 컨테이너 사용으로 싱글톤 패턴의 문제점을 해결하면서,
객체 인스턴스를 싱글톤으로 관리한다.
지금까지 학습한 스프링 빈이 싱글톤으로 관리되는 빈이다.
싱글톤 방식의 주의점
싱글톤 객체는 상태를 유지하게 설계하면 안된다. 무상태로 설계해야 한다.
특정 클라이언트에 의존적인 필드 X
특정 클라이언트가 값을 변경할 수 있는 필드 X
가급적 읽기만 가능
필드 대신 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal 등 사용
이를 어길 시 정말 큰 오류가 발생할 수 있으니 주의해야 한다.
컴포넌트 스캔
스프링은 설정 정보 없어도 자동으로 스프링 빈 등록하는 컴포넌트 스캔이라는 기능을 제공한다.
또 의존관계도 자동으로 주입하는 @Autowired 라는 기능도 제공한다.
컴포넌트 스캔을 사용하려면 먼저 @ComponentScan을 설정 정보에 붙여준다.
컴포넌트 스캔은 @Component 애노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록한다.
- MemoryMemberRepository에 @Component 추가
- RateDiscountPolicy에 @Component 추가
- MemberServiceImpl에 @Component, @Autowired 추가
@Component
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
@Autowired는 의존관계를 자동으로 주입해준다.
생성자에 @Autowired를 지정하면, 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아 주입한다.
(memoryMemberRepository)
이때 기본 조회 전략은 타입이 같은 빈을 찾아 주입한다.
- OrderServiceImpl @Component, @Autowired 추가
스프링 빈의 이름은 클래스명을 사용하되 맨 앞글자만 소문자를 사용한다.
( MemberServiceImpl 클래스 -> memberServiceImpl )
스캔 권장 방법
패키지 위치를 지정하지 않고, 설정 정보 클래스 위치를 프로젝트 최상단에 둔다.
최근 스프링 부트도 이 방법을 기반으로 제공한다고 한다.
com.hello
com.hello.service
com.hello.repository가 있으면
com.hello (프로젝트 시작 루트) 에 AppConfig 같은 메인 설정 정보를 두고,
@ComponentScan 애노테이션을 붙인다. (basePackages 지정 생략)
이렇게하면 com.hello 포함한 하위는 모두 자동으로 컴포넌트 스캔의 대상이 된다.
스프링 부트 사용 시 스프링 부트 대표 시작 정보인 @SpringBootApplication을 이 프로젝트
시작 루트 위치에 두는 것이 관례이다. 이 설정 안에 바로 @ComponentScan이 들어있다.
컴포넌트 스캔은 @Component 뿐만 아니라 다음 애노테이션이 있으면 스프링은 부가 기능을 수행한다.
@Controller : 스프링 MVC 컨트롤러로 인식
@Repository : 스프링 데이터 접근 계층으로 인식하고, 데이터 계층의 예외를 스프링 예외로 변환
@Configuration : 앞서 보았듯이 스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤 유지하도록 추가 처리
@Service : 특별한 처리를 하지는 않는다. 다만 개발자들이 비즈니스 계층을 인식하는데 도움이 된다.
중복 등록과 충돌
자동 빈 등록 vs 자동 빈 등록
: 이름이 같은 경우 스프링은 오류를 발생시킨다.
수동 빈 등록 vs 자동 빈 등록
: 수동 빈 등록이 우선권을 가진다. (수동 빈이 자동 빈을 오버라이딩 해버린다.)
하지만 최근 스프링 부트에서는 수동 빈 등록과 자동 빈 등록 충돌시 오류 발생으로 기본 값을 바꾸었다.
'김영한님의 스프링 강의 학습 > 스프링 핵심 원리' 카테고리의 다른 글
#4 스프링 컨테이너와 스프링 빈 (0) | 2022.11.10 |
---|---|
#3 스프링 핵심 원리 이해2 - 객체지향 원리 적용2 (0) | 2022.10.01 |
#3 스프링 핵심 원리 이해2 - 객체지향 원리 적용1 (1) | 2022.09.30 |
#2 스프링 핵심 원리 이해 - 예제 만들기2 (0) | 2022.09.29 |
#2 스프링 핵심 원리 이해 - 예제 만들기1 (0) | 2022.09.28 |