[SpringBoot] 스프링의 특징(IoC, DI, bean)

주운·2024년 2월 21일

스프링의 주요 특징 중 제어의 역전(IoC), 의존성 주입(DI), bean에 대해 알아보자.

제어의 역전(IoC)

사용자가 아닌, 프레임워크가 주요 객체를 생성, 관리한다.

제어의 역전이란?

프레임워크의 도움을 받지 않는 일반적인 상황이라면, 사용자는 객체를 사용하기 위해 직접 객체를 생성하고 폐기한다.
직접 객체를 관리한다면 모든 객체가 지닌 생명주기를 고려하는 것 역시 개발자의 몫이다.

//일반적인 객체 생성의 예
public class A {
    B b = new B();
    
    b.method1();
}

제어의 역전은 객체 관리의 권한을 프레임워크에 넘기는 것이다.

프레임워크는 객체의 생성, 생명주기, 폐기와 같은 관리를 모두 담당하며 개발자가 객체를 요청하면 객체를 전달한다.

스프링에서는 객체를 관리하는 주체를 스프링 컨테이너라고 한다.

public class A {
//프레임워크에서 객체를 전달받는 예
    @Autowired
    B b;

    b.method1();
}

이로써 개발자는 객체 생성과 생명주기에 신경쓰지 않고 비즈니스 로직에만 신경쓸 수 있다.

스프링이 제어를 역전하는 방법

스프링은 제어의 역전을 구현하기 위해 객체를 bean으로 등록해 관리하고, 의존성을 주입해 개발자가 객체를 사용하게 한다.

스프링 컨테이너는 container, service와 같은 특정 객체를 관리할 수 있다. 관리하는 객체는 bean이라 한다.
객체를 bean으로 등록하면 개발자가 객체를 필요로 할 때 의존성 주입을 통해 간편하게 사용할 수 있다.

bean

스프링 컨테이너가 생성, 관리하는 객체

bean의 등록 방법

1. 어노테이션

@Component를 명시해 빈을 등록하는 방법이다.
@Controller, @Service, @Repository, @Configuration와 같이 @Component를 상속받는 어노테이션 역시 모두 빈이 등록된다.

  • @Controller
    • 스프링 MVC 컨트롤러로 인식된다.
  • @Repository
    • 스프링 데이터 접근 계층으로 인식한다.
    • 해당 계층에서 발생하는 예외는 DataAccessException으로 변환한다.
  • Service
    • 특별한 처리는 하지 않는다.
    • 개발자들의 핵심 비즈니스 계층 인식에 도움을 준다.
  • Configuration
    • 스프링 설정 정보로 인식한다.
    • 빈이 싱글톤을 유지하도록 한다.
@Controller
public class UserController {
...

2. java 코드

@Configuration이 붙은 설정 파일에 코드로 등록하는 방법이다.
인스턴스 생성 메소드에 @Bean 어노테이션을 명시한다.

@Configuration
public class SpringConfig {
    private EntityManager em;

    @Autowired
    public SpringConfig(EntityManager em){
        this.em=em;
    }
    
    @Bean
    public CategoryRepository categoryRepository(){return new CategoryRepositoryImp(em);
    }

의존성 주입(DI)

객체 의존관계를 외부(스프링 컨테이너)에서 넣어주는 것

의존성 주입 방법

생성자 주입

생성자에 @Autowired 어노테이션을 달아 생성자에 필요한 빈을 주입한다.

  • 생성자 호출 시점에 1번만 호출되는 것을 보장한다.
  • 생성자가 1개만 존재한다면 @Autowired를 생략할 수 있다.
  • NullPointerException을 방지할 수 있다.
  • 주입받은 필드를 final로 선언할 수 있다.

의존관계가 변하지 않는다면 생성자 주입을 권장한다.

@Service
public class BugService {

    private BugRepository bugRepository;

    public BugService(BugRepository bugRepository){
        this.bugRepository = bugRepository;
    }
}

수정자 주입

@Autowired가 붙은 setter 메소드를 통해 빈을 주입한다.

  • 선택과 변경 가능성이 있는 의존 관계에 사용한다.
@Component
public class CoffeeService {
    private final MemberRepository memberRepository;
    private final CoffeeRepository coffeeRepository;

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Autowired
    public void setCoffeeRepository(CoffeeRepository coffeeRepository) {
        this.coffeeRepository = coffeeRepository;
    }
}

필드 주입

필드에 @Autowired를 붙여 빈을 주입한다.

  • 코드가 간결해진다.
  • 외부에서 변경이 불가능하기 때문에 테스트가 어렵다.
  • DI 프레임웤크가 없으면 아무것도 할 수 없다.
@Component
public class CoffeeService {
    @Autowired
    private final MemberRepository memberRepository;
    @Autowired
    private final CoffeeRepository coffeeRepository;
}
출처: https://ittrue.tistory.com/227 [IT is True:티스토리]

https://steady-coding.tistory.com/594
https://velog.io/@falling_star3/Spring-Boot-%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B9%88bean%EA%B3%BC-%EC%9D%98%EC%A1%B4%EA%B4%80%EA%B3%84
https://jhyonhyon.tistory.com/31

0개의 댓글