용꿀
꼬마개발자허니
용꿀
전체 방문자
오늘
어제
  • 분류 전체보기 (247)
    • 개발 (74)
      • 스프링 입문 (7)
      • 스프링 기본 (9)
      • ToDo List using JPA (2)
      • 스프링 개념 (9)
      • 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 (8)
      • 스프링 MVC (3)
      • CS (18)
      • 개발 팁 (8)
      • 스프링 MSA (5)
      • 곰터뷰🐻 (5)
    • 알고리즘 (169)
      • 알고리즘 문제 풀이 (165)
    • 잡동사니 (1)
      • 노래 가사 (1)
hELLO · Designed By 정상우.
용꿀

꼬마개발자허니

(스프링 입문) 4. 스프링 빈과 의존관계
개발/스프링 입문

(스프링 입문) 4. 스프링 빈과 의존관계

2022. 9. 24. 02:10

이 글은 김영한 님의 스프링 입문 강좌 수강 후에 정리한 글입니다.

(https://www.inflearn.com/course/스프링-입문-스프링부트/dashboard)

스프링 빈과 의존관계

회원 컨트롤러가 회원 서비스와 회원 리포지토리를 사용할 수 있게 의존관계를 추가하여야 한다.

package hello.hellospring.controller;

import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class MemberController {
    private final MemberService memberService;

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

 

MemberController에 의존관계를 추가한 것이다.

생성자에 @Autowired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어주는데 이것을 의존성 주입, 즉 DI이라고 한다.

저번 회원 서비스 테스트 시에도 DI를 했었는데 그때는 개발자가 직접 주입한 형식이었고, 지금은 @Autowired를 사용하여 스프링이 직접 주입해준다.

 

Consider defining a bean of type 'hello.hellospring.service.MemberService' in your configuration.

 

하지만 실행 시에 다음과 같은 오류가 생긴다. 이는 memberService가 스프링 빈으로 등록되지 않았기 때문에 일어난 오류이다.

 

스프링 빈을 등록하는 2가지 방법이 있다. 첫 번째 방법은 컴포넌트 스캔과 자동 의존관계 설정이고, 두 번째 방법은 자바 코드로 직접 스프링 빈을 등록하는 방법이다.

 

● 컴포넌트 스캔과 자동 의존관계 설정

 

1. 컴포넌트 스캔 원리

@Component가 있으면 스프링 빈으로 자동 등록된다. 그리고 @Component를 포함하는 @Controller, @Service, @Repository도 스프링 빈으로 자동 등록된다.

 

2. 회원 서비스 스프링 빈 등록

@Service
public class MemberService {
	private final MemberRepository memberRepository;
	
    @Autowired
	public MemberService(MemberRepository memberRepository) {
	this.memberRepository = memberRepository;
	}
}

MemberService 클래스에 @Service를 사용하여 스프링 빈으로 자동 등록한다.

MemberService 생성자에 @Autowired를 사용하여 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입한다.

생성자가 하나인 경우에는 @Autowired를 생략할 수 있다.

 

3. 회원 리포지토리 스프링 빈 등록

@Repository
public class MemoryMemberRepository implements MemberRepository {}

위와 마찬가지로 MemoryMemberRepository 클래스에 @Repository를 사용하여 스프링 빈으로 자동 등록한다.

 

4. 스프링 빈 등록 이미지

 

1~3의 과정을 통해 memberService와 memberRepository도 memberController와 마찬가지로 스프링 컨테이너에 스프링 빈으로 등록이 완료되었다.

참고로 스프링 빈이 등록될 때 기본적으로 싱글톤(유일하게 하나만 등록해서 공유)으로 등록한다. 그래서 같은 스프링 빈이면 모두 같은 인스턴스다.

 

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

 

우선 memberService와 memoryMemberRepository의 @Service, @Repository, @Autowired를 제거하고 진행한다.

 

package hello.hellospring;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
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();
	}
}

 

현재 진행 중인 프로젝트는 DB를 어떤 것으로 할지 정해져 있지 않으므로 향후에 MemoryRepository를 다른 Repository로 대체할 예정이다. 그래서 컴포넌트 스캔 대신에 자바 코드로 스프링 빈을 설정하여 나중에 간단하게 수정하는 방법이 더 적당하다.

 

1. @Configuration

설정 파일을 만들거나, 스프링 빈을 등록할 때 사용하는 어노테이션이다.

 

2. @Bean

스프링 컨테이너에 스프링 빈을 등록할 때 사용하는 어노테이션이다.

특히 @Bean은 개발자가 직접 제어가 불가능하거나 정형화 되어있지 않거나, 상황에 따라 구현 클래스를 변경해야 할 때사용한다.

반면에 정형화된 Controller, Service, Repository 같은 코드는 컴포넌트 스캔을 사용한다.

 

위에서는 DI를 할 때 생성자 주입을 사용했는데 그 외에도 필드 주입과 setter 주입이 존재한다.

 

//필드 주입
@Autowired private MemberService memberService;

//setter 주입
@Autowired
public void setMemberService(MemberService memberService){
	this.memberService = memberService;
}

//생성자 주입
@Autowired
public MemberController(MemberService memberService){
	this.memberService = memberService;
}

 

필드 주입은 외부에서의 변경이 불가능해지므로 테스트 케이스 등을 작성할 때 객체 수정이 불가능하기 때문에 어려움을 겪을 수 있다.

setter 주입은 setter가 public으로 공개되기 때문에 잘못 수정되어 문제가 발생할 가능성이 있다.

생성자 주입은 생성자의 호출 시점에 1회 호출이 보장되고, 주입받은 객체는 변하지 않고, DI를 강제할 수 있다는 장점이 있다.

(출처: https://velog.io/@zihs0822/DI의존성-주입-방식별-장단점)

 

마지막으로 @Autowired 어노테이션을 통한 DI는 helloConroller , memberService 등과 같이 스프링이 관리하는
객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

'개발 > 스프링 입문' 카테고리의 다른 글

(스프링 입문) 6. 스프링 DB 접근 기술  (0) 2022.09.24
(스프링 입문) 5. 회원 관리 예제 (웹 MVC 개발)  (0) 2022.09.24
(스프링 입문) 3. 회원 관리 예제  (0) 2022.09.24
(스프링 입문) 2. 스프링 웹 개발 기초  (0) 2022.09.24
(스프링 입문) 1. 프로젝트 환경 설정  (0) 2022.09.06
    '개발/스프링 입문' 카테고리의 다른 글
    • (스프링 입문) 6. 스프링 DB 접근 기술
    • (스프링 입문) 5. 회원 관리 예제 (웹 MVC 개발)
    • (스프링 입문) 3. 회원 관리 예제
    • (스프링 입문) 2. 스프링 웹 개발 기초
    용꿀
    용꿀

    티스토리툴바