Backend DEv/Spring

[Spring] 스프링 핵심 원리 - 기본편 정리

  • -
728x90

김영한 강사님의 스프링 핵심 원리 - 기본편을 완강 후 개념 위주로 재정리한 글이며 코드는 깃허브(링크) 에서 확인하실 수 있습니다.

인텔리제이 단축키 (복습)

커멘드+옵션+v
컨트롤+쉬프트+r : 테스트 실행
커멘드+o : 전체 검색
커멘드+e : 히스토리
커멘드+[ : 이전 파일
커멘드+/ : 해당 줄 주석처리
iter+tab 으로 for문 생성

배운내용

1. 객체 지향 설계와 스프링

: 스프링의 역사 그리고 스프링 프레임워크에 대해

객체 지향의 특징

  • 추상화
  • 캡슐화
  • 상속
  • 다형성(중요) - 역할구현으로 세상을 구분

2. 스프링 핵심 원리 이해1 - 예제 만들기

비즈니스 요구사항과 설계
: 회원 도메인의 설계 및 개발 / 주문과 할인 도메인 설계 및 개발

3. 스프링 핵심 원리 이해2 - 객체 지향 원리 적용 (단순 자바 코드에서 Spring으로 변경.)

할인 정책의 확장
: 할인 정책이 변경되었을 때 이를 구현하고, OCP와 DIP를 지킨 코드로 변경하기.

 

Appconfig를 통한 관심사의 분리
: 애플리케이션의 전체 동작 방식을 구성(config)하기 위해, 구현 객체를 생성하고, 연결하는 책임을 갖는 AppConfig의 등장.

 

AppConfig 리팩터링

  • 구성 정보에서 역할과 구현을 명확하게 분리
  • 역할이 잘 드러남
  • 중복 제거

좋은 객체 지향 설계의 5가지 원칙의 적용
: 5가지 중 SRP, DIP, OCP을 적용.

4. 스프링 컨테이너와 스프링 빈

스프링 컨테이너 생성
: 스프링 컨테이너를 생성하고, 스프링 빈을 등록하여 이에 대한 의존관계를 설정한다.

 

컨테이너에 등록된 모든 빈 조회
: 모든 빈 추력 및 애플리케이션 빈을 출력한다.

 

스프링 빈 조회
: 기본/동일한 타입이 둘 이상/상속 관계 의 세가지 경우에서 스프링 빈을 조회한다.

 

BeanFactory와 ApplicationContext

  • ApplicationContext는 BeanFactory의 기능을 상속받는다.
  • ApplicationContext는 빈 관리기능 + 편리한 부가 기능을 제공한다.
  • BeanFactory를 직접 사용할 일은 거의 없다. 부가기능이 포함된 ApplicationContext를 사용한다.
  • BeanFactory나 ApplicationContext를 스프링 컨테이너라 한다.

배운내용

5. 싱글톤 컨테이너

웹 애플리케이션과 싱글톤
: 스프링 없는 순수한 DI 컨테이너 테스트 → 메모리 낭비가 심하다.

싱글톤 패턴
: 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴
→ 객체 인스턴스를 2개 이상 생성하지 못하도록 한다. (private 생성자 사용)

문제점

  • 구현 코드 많음
  • DIP 위반(구체 클래스에 의존적)
  • OCP 원칙을 위반할 가능성 높음
  • 테스트 어려움
    등등..

해결법: 싱글톤 컨테이너 (싱글턴 패턴의 모든 단점을 해결하면서 객체를 싱글톤으로 유지할 수 있다.)
주의점: 무상태(stateless)로 설계해야 한다

 

@Configuration과 싱글톤

AppConfig에서 각각 다른 2개의 MemoryMemberRepository 가 생성되면서 싱글톤이 깨지는 것 처럼 보인다.

 

@Configuration과 바이트코드 조작의 마법

스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용한다. (@Configuration 을 적용한 AppConfig) → 스프링 설정 정보는 항상 @Configuration 을 사용.

6. 컴포넌트 스캔

컴포넌트 스캔과 의존관계 자동 주입 시작하기

스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔을 제공. & 의존관계도 자동으로 주입하는 @Autowired 라는 기능도 제공.

 

탐색 위치와 기본 스캔 대상

모든 자바 클래스를 다 컴포넌트 스캔하면 시간 ↑ => 꼭 필요한 위치부터 탐색하도록 시작 위치 지정 가능

  • 컴포넌트 스캔 기본 대상
    • @Component : 컴포넌트 스캔에서 사용
    • @Controlller : 스프링 MVC 컨트롤러에서 사용
    • @Service : 스프링 비즈니스 로직에서 사용
    • @Repository : 스프링 데이터 접근 계층에서 사용
    • @Configuration : 스프링 설정 정보에서 사용

필터

필터를 통해 컴포넌트 스탠 대상을 변경할 수 있다.

  • includeFilters : 컴포넌트 스캔 대상을 추가로 지정
  • excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정

중복 등록과 충돌

컴포넌트 스캔에서 같은 빈 이름을 등록할 때 해결법
자동 빈 등록 vs 자동 빈 등록

  • ConflictingBeanDefinitionException 예외 발생

수동 빈 등록 vs 자동 빈 등록

  • 수동 빈 등록이 우선권을 가진다.

7. 의존관계 자동 주입

의존관계 주입

  • 생성자 주입
  • 수정자 주입(setter 주입)
  • 필드 주입
  • 일반 메서드 주입

옵션 처리

스프링 빈이 없어도 동작해야 할 때 → 자동 주입 대상을 옵션으로 처리

생성자 주입을 선택해야 한다.

  • 불변 - 생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일이 없다.
  • 누락 - 주입 데이터를 누락 했을 때 컴파일 오류가 발생 (IDE에서 바로 어떤 값을 필수로 주입해야 하는지 알 수 있다.)
  • final 키워드 - 생성자에서 혹시라도 값이 설정되지 않는 오류를 컴파일 시점에 막아준다

롬복과 최신 트랜드

@RequiredArgsConstructor 기능을 사용하면 final이 붙은 필드를 모아서 생성자를 자동으로 만들어준다.

8. 빈 생명주기 콜백

빈 생명주기 콜백 시작

스프링을 통한 초기화/종료 작업의 진행

  • 스프링 빈의 이벤트 라이프사이클
    • 스프링 컨테이너 생성 → 스프링 빈 생성 → 의존관계 주입 → 초기화 콜백 → 사용 → 소멸전 콜백 → 스프링 종료
    • 초기화 콜백: 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출
    • 소멸전 콜백: 빈이 소멸되기 직전에 호출

스프링은 크게 3가지 방법으로 빈 생명주기 콜백을 지원한다.

  • 인터페이스(InitializingBean, DisposableBean)
  • 설정 정보에 초기화 메서드, 종료 메서드 지정
  • @PostConstruct, @PreDestroy 애노테이션 지원

9. 빈 스코프

스프링이 지원하는 스코프들
- 싱글톤: 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
- 프로토타입: 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프이다.
- 웹 관련 스코프
    - request: 웹 요청이 들어오고 나갈때 까지 유지되는 스코프이다.
    - session: 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프이다.
    - application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프이다.

빈 스코프: 빈이 존재할 수 있는 범위

프로토타입 스코프: 프로토타입 스코프를 스프링 컨테이너에 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다.

 

싱글톤 빈과 프로토타입 스코프를 함께 사용시 문제: 싱글톤 빈과 함께 사용할 때는 의도한 대로 잘 동작하지 않는다.

  • 해결1. 스프링 컨테이너에 프로토타입 빈 직접 요청
  • 해결2. 싱글톤 빈에서 프로토타입 빈 사용

→ 위 해결법들은 싱글톤 빈은 생성 시점에만 의존관계 주입을 받기 때문에, 프로토타입 빈이 새로 생성되기는 하지만, 싱글톤 빈과 함께 계속 유지되는 문제 발생.

 

따라서, Provider를 통해 싱글톤 빈이 프로토타입을 사용할 때 마다 스프링 컨테이너에 새로 요청하도록 한다.

  • ObjectProvider
    • ObjectFactory: 기능이 단순, 별도의 라이브러리 필요 없음, 스프링에 의존
    • ObjectProvider: ObjectFactory 상속, 옵션, 스트림 처리등 편의 기능이 많고, 별도의 라이브러리 필요 없음, 스프링에 의존
  • JSR330 Provider
    • get() 메서드 하나로 기능이 매우 단순하다.
    • 별도의 라이브러리가 필요하다.
    • 자바 표준이므로 스프링이 아닌 다른 컨테이너에서도 사용할 수 있다.
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.