노트

스프링 빈과 IoC 컨테이너

Spring Bean and IoC Container

백엔드#spring · 연결된 개념 9개

쉽게 말하면

스프링 빈은 내가 직접 만들지 않고 컨테이너가 만들어 서로 이어 주는 객체예요. 무대감독이 소품을 준비해 배우 손에 쥐여 주듯, 객체는 필요한 걸 받아 쓰기만 하면 돼요.

비유가 깨지는 곳 무대감독은 배우가 몰래 가져온 소품은 몰라요. new로 만든 객체는 컨테이너가 모르니 주입도 프록시도 받지 못하고, 기본 싱글턴 빈은 앱 시작 때 미리 만들어져 설정 오류가 바로 드러나요.

스프링 빈은 스프링 IoC(Inversion of Control, 제어의 역전) 컨테이너가 만들고, 의존성을 연결하고, 생명주기(lifecycle)를 관리하는 평범한 자바 객체(POJO, Plain Old Java Object)다. 컨테이너(ApplicationContext)는 이 빈들을 담는 공간이고, 내가 new로 만든 객체는 컨테이너가 모른다.

빈을 등록하는 두 방법

@Component                     // 내가 만든 클래스: 붙이기만 하면 스캔 대상
public class OrderService { }
 
@Configuration
public class AppConfig {
    @Bean                       // 외부 라이브러리 객체 등: 메서드 반환값을 빈으로
    public ObjectMapper objectMapper() {
        return new ObjectMapper().findAndRegisterModules();
    }
}
@Component@Bean
붙이는 곳클래스@Configuration 클래스의 메서드
대상내가 작성한 클래스외부 라이브러리 클래스도 가능
생성 제어컨테이너가 알아서생성 코드를 내가 작성
같은 타입 여러 개어렵다메서드마다 하나씩
  • 스테레오타입(stereotype) 애너테이션 @Service, @Repository, @Controller는 모두 @Component의 특수화다. 역할을 드러내고, @Repository는 DB 예외를 스프링 예외로 바꿔 주는 등 부가 기능이 붙는다
  • @ComponentScan이 어느 패키지를 뒤질지 정한다. 스프링 부트는 메인 클래스 패키지 아래를 자동으로 스캔한다(스프링 부트 자동 설정)
  • 빈 이름은 기본적으로 메서드명·클래스명(첫 글자 소문자)이다

생명주기

  • 기본 싱글턴 빈은 앱 시작 때 미리 만들어진다(eager initialization). 설정 오류를 시작 시점에 잡을 수 있다. @Lazy를 붙이면 처음 쓸 때 만든다
  • @PostConstruct는 의존성 주입이 끝난 직후, @PreDestroy는 컨테이너 종료 직전에 호출된다. 연결 풀 정리 등에 쓴다(스프링 부트 3부터 jakarta.annotation 패키지)
  • 빈을 하나만 둘지 요청마다 만들지는 빈 스코프가 정한다
stateDiagram-v2
  state "생성 (앱 시작 때, @Lazy면 처음 쓸 때)" as New
  state "의존성 주입" as DI
  state "@PostConstruct" as Post
  state "사용" as Use
  state "@PreDestroy" as Pre
  [*] --> New
  New --> DI
  DI --> Post
  Post --> Use
  Use --> Pre: 컨테이너 종료
  Pre --> [*]

연결

빈끼리의 연결이 의존성 주입이다. 컨테이너는 원본 대신 프록시를 넣어 트랜잭션·AOP를 끼우기도 한다. "스프링 빈은 컨테이너가 관리하는 싱글턴"이라는 점에서 싱글턴 패턴과 비교해 보면, 클래스가 스스로 하나임을 강제하지 않는다는 점이 다르다. 생성 책임을 바깥으로 빼는 발상은 팩토리 메서드 패턴와도 닮았다.

책: 4장. 마법 걷어내기 — DI와 IoC

출처: Spring Framework 문서: IoC 컨테이너와 빈 소개 · 스테레오타입 애너테이션 · @Bean 애너테이션

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • Lombok

    Lombok은 게터·세터·생성자·toString 같은 반복 코드를 어노테이션으로 대신 생성해 주는 자바 라이브러리다. 컴파일할 때 어노테이션 처리기(annotation processor)가 바이트코드(bytecode)에 메서드를 넣는다. 스프링과는 별개 라이브러리라 따로 추가한다.

  • 스프링 설정 외부화와 프로파일

    스프링 부트는 설정값을 코드 밖(application.yml·환경변수·명령줄 인자 등)에 두고, 실행 환경에 따라 다른 값을 주입하게 해 준다. 같은 빌드 산출물을 개발·QA·운영에 그대로 쓰고 설정만 바꾸는 것이 목표다.

  • 스프링 AOP

    AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍)는 로깅·트랜잭션·보안·실행 시간 측정처럼 여러 클래스에 흩어져 반복되는 횡단 관심사(cross-cutting concern)를 한 곳에 모아, 비즈니스 코드를 건드리지 않고 메서드 호출 앞뒤에 끼워 넣는 방법이다. 스프링 AOP는 이를 프록시로 구현한다.

  • 스프링 REST 컨트롤러

    @RestController는 메서드의 반환값을 뷰 이름이 아니라 HTTP 응답 본문(보통 JSON)으로 쓰는 컨트롤러다. @Controller에 @ResponseBody를 합친 것으로, 직렬화(serialization)는 Jackson이 맡는다.

  • Spring Boot Actuator

    Spring Boot Actuator는 운영 중인 앱의 상태를 HTTP 엔드포인트로 보여주는 모듈이다. 헬스 체크, 지표, 설정값, 로그 레벨, 등록된 빈 같은 정보를 /actuator/* 아래에 노출한다.

보기 옵션