[Spring] 4. 스프링 빈과 의존 관계 - 백엔드 개발

sunnny·2023년 7월 5일
1

Spring

목록 보기
1/2
post-thumbnail

스프링에서 정형화되어있는 패턴

  • Controller 통해서 외부 요청 받고,
  • Service 통해서 비즈니스 로직 만들고,
  • Repository에서 데이터 저장한다.

DI (의존성 주입, Dependency Injection)

  • 의존 관계를 외부에서 주입(결정)해주는 것을 말한다.
  • 클래스 간의 의존관계를 스프링 컨테이너가 자동으로 연결해주는 것

의존관계란?

의존 대상 B가 변하면, 그것이 A에 영향을 미친다 -> A는 B와 의존관계이다.
ex. memberService는 repository에 의존한다.
(repository가 변경된다면, service는 이에 영향을 받는다)
(service는 repository에 의존한다.)

public class MemberService {
    
    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

의존 관계 주입 방법

1. 필드 주입 방법 (별로 안좋음,,)

@Controller 
public class MemberController {
    @Autowired private MemberService memberService;
}

2. Constructor 주입 방법

@Controller
public class MemberController {
    private final MemberService memberService;
      
    @Autowired		
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}
  • 스프링이 뜰 때 스프링 컨테이너가 MemberController와 memberService를 연결해준다.
    but 컨트롤러 내부에서 MemberService가 자동으로 등록되지는 않는다.
    -> 컨트롤러에 service 주입 (DI)
  • 스프링 최신버전에서는 생성자가 하나만 있는 경우 (@Autowired가 없어도) 자동으로 injection 해준다

3. Setter 주입 방법 (얘도 별로 안좋음,,)

@Controller
public class MemberController {
    private MemberService memberService;

    @Autowired
    public void setMemberService(MemberService memberService) {
        this.memberService = memberService;
    }
}
  • 단점
    누군가가 memberController를 호출했을 때, setter(serMemberService)가 public으로 열려있어야 한다. -> 원래 setService는 처음에 한 번 쓰고 바꿀 일이 없는데, public으로 되어있으면 중간에 잘못 바꿀 수 있다 -> 문제 발생

의존관계가 실행중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다.

  • 화면을 붙이고? 싶으면 -> controller랑 view template이 필요하다 -> MemberController를 만들어야 한다. -> 얘는 memberService를 통해서 회원가입+조회할 수 있어야 한다. == controller가 service를 의존한다.

@Autowired

//컨트롤러에 service 주입 (DI)
@Autowired 
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
  • 스프링이 관리하는 빈(Bean)을 주입 받는다.
  • 스프링이 뜰 때, 스프링 컨테이너가 MemberController를 MemberService와 연결해준다.
    MemberService를 주입한다 (DI)
  • 스프링이 관리하는 객체에서만 동작한다.
    스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

스프링 빈을 등록하는 방법

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

  • 컴포넌트 스캔 : @Controller, @Service, @Repository 사용 (얘네 모두 @Component를 상속받은 어노테이션이다)
  • 스프링이 올라올 때, 컴포넌트와 관련된 어노테이션이 있으면, 스프링은 객체를 하나씩 다 생성해서 스프링 컨테이너에 등록을 한다. -> controller, service, repository가 스프링 컨테이너에 스프링 빈으로 자동 등록된다.
  • cf) 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 싱글톤으로 등록한다. (유일하게 하나만 등록해서 공유한다.)
  • @Autowired : 객체(컴포넌트)를 연결해주는 역할

-> hello.hellospring 패키지 내부 에 있는 파일만 컴포넌트 스캔을 한다.

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

MemberService, MemoryMemberRepository 에 있는 @Service, @Repository, @Autowired 를 지우고 Springconfig에 @Configuration, @Bean 어노테이션을 통해 직접 의존성을 주입해준다.

  • 장점 : 지금의 코드는 DB가 정해져있지 않다는 가정 하에, MemoryMemberRepository를 구현하고 나중에 다른 repository로 변경하는 방식이다. 이 때, 자바 코드로 직접 스프링 빈을 등록하면 코드를 하나도 수정하지 않고 DB와 Repository를 연결할 수 있다. (SpringConfig 파일에서 memberRepository()의 리턴값만 new DbRepository();로 바꿔주면 된다.)

참고/출처

0개의 댓글