백엔드/Spring

[Spring] 스프링 빈의 동작원리 와 @Bean, @Configuration 어노테이션

happy_life 2022. 4. 30. 00:38

목차

  1. 스프링 정의
  2. 동작 원리
  3. 사용코드
  4. 어노테이션
  5. 장점
  6. 스프링 사용 이유

 

1. 스프링 정의

스프링은  IoC, DI 등을 통해 객체지향의 SOLID 원칙을 지키게 하고, 다양한 기능들을 할 수 있게 해주는 프레임워크이다. 

 

IoC란 제어의 역전이다. 제어의 주체가 개발자가 아닌 프레임 워크라는 뜻으로, 외부에서 제어한다는 의미이다.

DI는 의존관계 주입이라는 것이다. 프레임워크가 의존관계를 알아서 주입해준다. 

 

컨테이너란?

- 특정 객체의 생성과 관리를 담당하며 객체 운용에 필요한 다양한 기능을 제공하는 것. 애플리케이션 운용에 필요한 객체를 생성하고 의존관계를 관리한다는 점에서 스프링도 일종의 컨테이너라고 볼 수 있다.

 

2. 동작 원리

스프링 컨테이너는 @Configuration 어노테이션이 붙은 AppConfig.class(예시 클래스)를 설정 정보로 사용한다. 여기서 @Bean이라 적힌 메서드를 모두 호출해서 반환된 객체들을 컨테이너에 등록하는데, 이런 객체들을 빈이라고 한다.

/**
 * 기획자 의존관계 주입은 여기서 한다.
 **/

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService(){
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public OrderService orderService(){
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public DiscountPolicy discountPolicy(){
        return new RateDiscountPolicy();
    }
}

스프링 컨테이너에는 아래와 같이 빈 객체가 저장되며, 자동으로 의존관계를 주입하게 된다.

빈 이름 빈 객체
memberService MemberServiceImpl
orderService OrderServiceImpl
memberRepository MemoryMemberRepository
discountPolicy RateDiscountPolicy

 

의존관계주입

3. 사용코드

 

빈을 체크하기 위해선 아래와 같은 코드를 사용한다.

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

 

4. 어노테이션

 

1. @Configuration

 - 이 어노테이션을 단 클래스는 빈 설정을 담당하는 클래스가 된다.  이 클래스 안에서 @Bean 어노테이션으로 메소드를 선언하면, 그 메소드를 통해서 빈을 정의하게 됨.

 

2. @Bean

-@Configuration 선언한 빈 설정 클래스에 빈 선언을 담당하는 어노테이션으로 메소드에만 넣을 수 있음. 보통은 메소드 이름이 빈의 이름이지만, 수동으로 설정해줄 수 있음.

 

5. 장점

1. SRP 단일 책임 원칙을 만족시킨다.

 - 한 클래스는 하나의 책임만을 가진다는 것이 단일 책임 원칙이다. 구현 객체를 생성하고 연결하는 책임은 AppConfig가 담당한다. 클라이언트 객체는 실행하는 책임만 담당한다.

 

2. OCP 개방 폐쇄 원칙을 만족시킨다.

 - 클라이언트 코드를 수정하지 않고 AppConfig 클래스의 코드를 수정하여 의존관계를 변경할 수 있다.

 

3. DIP 의존관계 역전 원칙을 만족시킨다.

 - 클라이언트코드가 추상화 인터페이스에만 의존할 수 있도록 코드를 변경하였다. 

 

클라이언트코드

public class MemberServiceImpl implements MemberService{

    //추상화에만 의존하게됨
    private final MemberRepository memberRepository ;

    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Override
    public void join(Member member) {
        memberRepository.save(member);

    }
}

 

6. 스프링 사용 이유

보면 AppConfig를 활용한 java코드만으로도 위의 3가지 원칙을 만족할 수 있지만, 스프링은 이에 더해 싱글톤 패턴 보장 등 다양한 기능들이 있기때문에 사용한다.

 

 

* 참고 

 프레임 워크 vs 라이브러리

프레임 워크는 내가 작성한 코드를 제어하고 대신 실행한다.

라이브러리는 내가 직접 제어의 흐름을 담당한다.