[Web] Spring Bean 선언, 오토와이어링(Autowired)

2022. 11. 3. 04:07·Programming/Web
728x90

스프링 빈(Spring Bean)은 스프링 컨테이너에 의해 관리되는 자바 객체로 빈 등록은 설정 xml, 어너테이션, 설정 클래스를 이용해 등록할 수 있다. 그리고 이렇게 등록한 스프링 빈은 오토와이어링을 통해 공급된다. 이 두 가지 개념은 스프링 프레임워크로 개발하기 위해서는 꼭 알아야 한다.

스프링 빈

스프링 부트의 경우 어너테이션을 통한 빈 등록을 기본으로 한다. @Component, @Service, @Controller, @Repository, @Bean 등으로 필요한 Bean을 등록하고, 필요한 위치에서 @Autowired를 통해 주입받아 사용하는 것이 일반적이다.

@Component 관계

위 그림과 같이 @Service, @Controller, @Repository는 모두 @Component를 상속 받으며 해당 어너테이션으로 등록된 클래스는 스프링 컨테이너에 의해 자동으로 생성되어 스프링 Bean으로 등록된다.

  • @Bean : 개발자가 컨트롤할 수 없는 외부 라이브러리를 Bean으로 등록할 때 사용한다(설정 클래스에서 사용).
  • @Component : 개발자가 직접 만든 클래스를 Bean으로 등록할 때 사용한다(선언된 Class를 Bean으로 등록).
  • @Controller, @Service, @Repository : @Component와 기본적으로 동일하며 역할에 따라 다른 이름을 사용한 것이다.

빈 등록

가장 기본 어너테이션인 @Component를 사용하는 경우를 보면

게임에서 사용될 무기 클래스를 대표할 수 있는 타입으로 Weapon 인터페이스를 정의한다.

package com.example.demo;

public interface Weapon {
	void fire();
}

그리고 Weapon 인터페이스를 구현하는 ShotGun 클래스를 스프링 빈으로 등록하기 위하여 @Component 어너테이션을 사용한다.

@Component
public class ShotGun implements Weapon {
    private String model = "Basic ShotGun";

    public String getModel() {
    	return model;
    }

    public void setModel(String model) {
    	this.model = model;
    }

    @Override
    public void fire() {
    	System.out.println(model+" fire!");
    }
}

설정 클래스를 사용하는 경우 다음과 같이 별도의 클래스를 만들고 @Configuration으로 설정 클래스임을 알리고 @Bean 어너테이션을 Weapon 객체를 등록하는 메서드에 붙여주면 된다. 이때 해당 메서드의 리턴이 빈으로 등록된다.

@Configuration
public class BasicConfiguration {
    @Bean
    public Weapon superShotGun() {
        ShotGun sg = new ShotGun();
        sg.setModel("Super ShotGun");
        return sg;
    }
}

오토와이어링

빈이 등록되었다면 컨트롤러, DAO 등의 구현 클래스에서 해당 객체가 필요할 때 @Autowired 어너테이션을 통해 객체를 참조할 수 있다. 이때 필요한 객체를 오토와이어링하는 방법은 필드, 생성자, setter 주입 세 가지 유형이 있다.

 

Autowired : 필요한 의존 객체의 "타입"에 해당하는 빈을 찾아 주입한다.

  • 필드
  • 생성자
  • setter

위의 3가지 경우에 Autowired를 사용할 수 있다.

Autowired는 기본값이 true이기 때문에 의존성 주입을 할 대상을 찾지 못한다면 애플리케이션 구동에 실패한다.

필드 주입

필드 주입(Field  Injection)은 제일 간편하게 사용할 수 있는 형태다. 말 그대로 클래스의 필드에 @Autowired를 사용하는 방식이다.

class Game {
    @Autowired
    private Weapon w;

    public gameRun() {
        w.fire();
    }
}

간단하고 편리하기는 하지만 순환 의존성 문제가 발생할 수 있으며, final로 지정할 수 없어 불변 객체를 만들 수 없다는 문제점이 있다. 이 외에도 무분별한 사용으로 인해 의존관계가 잘 보이지 않고 복잡해질 수 있어 사용에 주의해야 한다.

생성자 주입(Constructor Dependency Injection)

생성자 주입(Constructor Injection)은 객체가 생성될 때 호출되는 생성자에 참조할 클래스를 인자로 받아 필드에 매핑하는 방식이다. 생성자가 하나인 경우 @Autowired를 사용하지 않아도 된다. 다만 생성자에 참조할 객체가 늘어나게 되면 코드 개선(리팩토링)을 고려할 수 있다.

class Game {
    private final Weapon w;

    @Autowired
    public Game(Weapon w) {
        this.w = w;
    }

    public gameRun() {
        w.fire();
    }
}

필드 주입 방식보다 생성자 주입이 생성자로 집중되기 때문에 관리가 편하고 코드 분석과 테스트에도 유리하며 참조 객체를 final로 받아 사용할 수 있어 보다 안전하다. 일반적으로 권장되는 방식이다.

Setter 주입

Setter 주입(Setter Injection)은 setter 메서드를 통해 빈을 주입하는 방식이다. 가급적 메서드 이름은 set 타입 이름 규칙을 따르는 것이 좋다. 보통 생성자에 과도하게 의존성 주입이 되는 것을 보완하기 위해 사용하거나 의존성이 선택적인 경우에 권장된다. 필드 주입과 마찬가지로 final을 사용할 수 없다.

class Game {
    private Weapon w;

    @Autowired
    public setWeapon(Weapon w) {
        this.w = w;
    }

    public gameRun() {
        w.fire();
    }
}

Autowired 정리

Field Dependency Injection

member field에 @Autowired annotation을 선언하여 주입 받는 방법이다.

 

장점

  • 가장 간단한 선언 방식이다.

단점

  • 의존 관계가 눈에 잘 보이지 않아 추상적이고, 이로 인해 의존성 관계가 과도하게 복잡해질 수 있다.(반대로 Constructor injection과 Setter injection은 의존성을 명확하게 커뮤니케이션 함.)
  • 이는 SRP / 단일 책임 원칙에 반하는 안티패턴이다.
  • DI Container와 강한 결합을 가져 외부 사용이 용이하지 않다.(단위 테스트시 의존성 주입이 용이하지 않다.)
  • 의존성 주입 대상 필드가 final 선언이 불가하다.

Constructor Dependency Injection

생성자 주입은 생성자에 의존성 주입을 받고자 하는 field를 나열하는 방법으로, 권고되는 방법의 하나이다.

 

장점

  • 의존성 주입 대상 필드를 final로 불변 객체를 선언할 수 있다.
  • 필수적으로 사용해야 하는 레퍼런스 없이는 인스턴스를 만들지 못하도록 강제한다.
  • Spring 4.3 이상부터는 생성자가 하나인 경우 @Autowired를 사용하지 않아도 된다.
  • Circular Dependency / 순환 참조 의존성을 알아 차릴 수 있다.
  • 생성자에 점차 많은 의존성이 추가 될 경우 리팩토링 시점을 감지 할 수 있다.
  • 테스트 코드 작성시 생성자를 통해 의존성 주입이 용이하다.

단점

  • 어쩔 수 없는 순환 참조는 생성자 주입으로 해결하기 어렵다.

이러한 경우에는 나머지 주입 방법 중에 하나를 사용한다. 가급적이면 순환 참조가 발생하지 않도록 하는것이 더 중요하다.

Setter Dependency Injection

  • setter 메서드에 @Autowired annotation을 선언하여 주입받는 방법이다.
  • 메서드이름을 setter 대신 다른 것도 주입은 가능하지만 좋은 방법은 아니다.
  • 의존성이 선택적으로 필요한 경우에 사용한다.
  • 생성자에 모든 의존성을 기술하면 과도하게 복잡해질 수 있는 것을 선택적으로 나눠 주입 할 수 있게 부담을 덜어준다.
  • 생성자 주입 방법과 Setter 주입 방법을 적절하게 상황에 맞게 분배하여 사용한다.
  • 의존성 주입 대상 필드가 final 선언이 불가하다.

'Programming > Web' 카테고리의 다른 글

[Web] 절대경로/상대경로  (0) 2022.11.06
[Web] 용어 정리(utility), (Software), (Network), (localhost), (Built-in Object), (HTTP)  (0) 2022.11.06
[Web] JSTL(다운로드, 사용법, 정리), EL(정리)  (1) 2022.11.03
[Web] WebMVC와 RestController 모듈  (0) 2022.10.31
[Web] IoC(Inversion of Control), DI(Dependency Injection), AOP(Aspect-Oriented Programming)  (1) 2022.10.31
'Programming/Web' 카테고리의 다른 글
  • [Web] 절대경로/상대경로
  • [Web] 용어 정리(utility), (Software), (Network), (localhost), (Built-in Object), (HTTP)
  • [Web] JSTL(다운로드, 사용법, 정리), EL(정리)
  • [Web] WebMVC와 RestController 모듈
arajo
arajo
  • arajo
    아라 메모장
    arajo
  • 전체
    오늘
    어제
    • 분류 전체보기 (509)
      • Language (298)
        • HTML (55)
        • CSS (11)
        • JavaScript (70)
        • TypeScript (8)
        • Python (33)
        • Java (119)
        • C (0)
        • C# (2)
      • Programming (92)
        • Programming (14)
        • Web (51)
        • Apache (1)
        • MySQL (23)
        • AWS (3)
      • Framework | Library (26)
        • Framework | Library (3)
        • Vue.js (2)
        • React.js (5)
        • React Native (4)
        • Node.js (1)
        • Ajax (1)
        • Bootstrap (8)
        • Spring (1)
        • Flutter (1)
      • etc (2)
      • 휴식 (19)
        • 책 (13)
        • 일기 (5)
        • 게임 일기 (1)
      • A (71)
        • 공부 (18)
        • 기타 (6)
        • 일 (47)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    TypeScript
    객체
    제어문
    HTML
    JavaScript
    변수
    Java
    자바스크립트
    리액트
    파이썬
    react
    object
    web
    타입스크립트
    array
    event
    next.js
    CSS
    MySQL
    Python
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
arajo
[Web] Spring Bean 선언, 오토와이어링(Autowired)
상단으로

티스토리툴바