[TIL] 250625_Spring: 스프링 빈과 의존관계(2) - 직접 스프링 빈 등록하기

지코·2025년 6월 25일
0

Today I Learned

목록 보기
76/77
post-thumbnail

🍃 자바 코드로 직접 스프링 빈 등록하기

클래스 간의 의존 관계를 설정하는 방법 중 스프링 빈을 직접 등록하는 방법을 적용해보자.

먼저 컴포넌트 스캔 방법에서 적용했던 @Autowired, @Service, @Repository 어노테이션을 모두 제거한다.

📁 src > main > java > hello.hello_spring > SpringConfig.java

package hello.hello_spring;

import hello.hello_spring.Service.MemberService;
import hello.hello_spring.repository.MemberRepository;
import hello.hello_spring.repository.MemoryMemberRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        // 스프링 빈에 등록된 리포지토리를 서비스 생성자 내 인자로 넣어준다.
        return new MemberService(memberRepository());
    }

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

HelloSpringApplication 과 같은 위치에 파일을 하나 생성한 후, @Configuration 어노테이션을 통해 memberServicememberRepository 가 빈에 등록되도록 한다.

또한 MemberService 생성자는 매개변수로 MemberRepository 객체를 받기 때문에, 스프링 빈에 등록된 memberRepository를 이용해 DI가 적용되도록 한다.

여기까지 따라왔다면, 컴포넌트 스캔 방식을 적용했을 때와 마찬가지로 위 의존 관계가 성립된다.

package hello.hello_spring.controller;

import hello.hello_spring.Service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class MemberController {

    private final MemberService memberService;
    // Autowired: MemberController 클래스 생성 시
    // 스프링빈에 등록되어 있는 MemberService 객체를 가져다 넣어줌. (DI)
    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

여기서 컨트롤러는 어차피 스프링이 관리해야하므로, 컴포넌트 스캔 방식을 적용했을 때와 마찬가지로 @Controller, @Autowired 어노테이션을 사용한다.

💫 TIP

실무에서 주로 정형화된 컨트롤러, 리포지토리, 서비스는 컴포넌트 스캔 방식을 사용하고, 정형화되지 않거나 상황에 따라 구현 클래스를 변경해야 하는 경우에는 설정을 통해 스프링 빈으로 등록한다.

이 프로젝트에서는 추후 구현체를 바꿀 예정이므로, 자바 코드로 직접 설정해 스프링 빈으로 등록한 후, 변경이 필요할 때 📁 SpringConfig.java 파일 내 memberRepository()의 반환값만 변경해주면 된다.

🍃 DI(Dependency Injection)의 종류

1. 생성자 주입

클래스 간 의존 관계를 설정하며, 스프링 빈에 이미 등록되어 있는 객체를 생성자의 매개변수를 통해 주입하는 것을 생성자 주입 이라고 한다.
➡️ 지금까지 계속 활용해온 방식이자, 가장 추천되는 방식❗️

2. 필드 주입

@Autowired private MemberService memberService;

클래스 내 생성자를 따로 만들지 않고, 스프링 빈에 이미 등록되어 있는 객체를 @Autowired 어노테이션을 통해 클래스의 필드에 주입하는 것을 필드 주입 이라고 한다.

3. setter 주입

@Autowired
public void setMemberService(MemberService memberService) {
    this.memberService = memberService;
}

클래스에서 setter를 구현해, 스프링 빈에 이미 등록되어 있는 객체를 클래스의 필드에 주입하는 것을 setter 주입 이라고 한다.

🤔 단점

setter 주입 의 단점은 setter가 public하기 때문에, MemberController를 호출하면서 setter를 통해 필드값이 변경되어 문제가 생길 가능성이 있다는 것이다.

@Autowired
public MemberController(MemberService memberService) {
    this.memberService = memberService;
    memberService.setMemberRepository();
}

예를 들어 위와 같이 MemberService 클래스에 setter 주입 을 적용했을 경우, 컨트롤러에서 memberService 객체를 통한 리포지토리 접근이 가능해진다.

Reference

🎥 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

profile
꾸준하고 성실하게, FE 개발자 역량을 키워보자 !

0개의 댓글