Java Spring-4

손현수·2023년 3월 23일
0

스프링 빈과 의존관계

스프링 빈을 등록하고, 의존관계 설정하기

  • controller가 memberService를 통해서 회원가입 및 데이터를 조회하는 것을 의존관계에 있다고 말한다.
  • 스프링이 처음 동작할 때 @Controller가 붙어있는 것은 먼저 객체를 생성해서 스프링이 가지고 있는다. 이를 스프링 컨테이너에서 스프링 빈이 관리된다고 표현한다.
  • MemberController 코드를 작성하는 과정
@Controller
public class MemberController {
    private final MemberService memberService = new MemberService();
}
  • 위의 코드에서 문제점은 MemberService 객체를 생성해서 사용하면 여러 controller가 MemberService에 접근할 수 있게 된다. 하지만 MemberService에는 현재 특별한 기능이 많이 없기 때문에 비효율적이고 스프링 컨테이너에 등록을 해서 사용하는 것이 좋다. 따라서 다음과 같이 코드를 수정한다.
@Controller
public class MemberController {
    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}
  • 스피링이 동작할 때 @Controller 어노테이션이 붙어있는 클래스의 객체가 생성이 되고 객체 생성을 위해 생성자를 호출한다. 현재 생성자에 @Autowired가 붙어있으므로 스프링이 스프링 컨테이너에 있는 MemberService를 가져다가 연결시켜준다.
  • 하지만 위의 코드를 작성하고 보면 에러가 발생한다. 이유는 현재 MemberService의 경우 어떠한 어노테이션도 없는 순수한 자바 클래스이므로 스프링이 MemberService에 대해서 알 수 있는 방법이 없다. MemberController는 @Controller 어노테이션이 있기 때문에 스프링이 컨테이너에 등록함으로써 정보를 가지고 있는 상태이다.
  • 이를 해결하기 위해서는 MemberService 클래스에 @Service 어노테이션을 붙여주면 된다.
@Service
public class MemberService {
  • 이렇게 되면 스프링이 동작할 때 스프링 컨테이너에 MemberService를 등록한다.
  • 마찬가지로 MemoryMemberRepository 클래스에도 @Repository 어노테이션을 붙여주면 스프링이 처음 동작할 때 controller, service, repository를 모두 컨테이너에 등록한다.
  • 이제 MemberController 클래스의 @Autowired 어노테이션이 붙어있는 생성자를 호출하면 스프링 빈에 등록되어 있는 MemberService 객체를 생성자에 넣어준다. 이것을 dependency injection이라고 한다. 의존관계를 주입시켜주는 것.
  • 한편, MemberService의 생성자에서는 MemberRepository가 필요하기 때문에 마찬가지로 @Autowired 어노테이션을 붙여줘야 한다.
  • 이것의 구조를 그림으로 나타내면 다음과 같다.
  • 스프링 빈을 등록하는 방법에는 두가지가 있다.
  1. 컴포넌트 스캔과 자동 의존관계 설정
  2. 자바 코드로 직접 스프링 빈 등록하기
  • 지금까지 어노테이션을 이용하여 스프링 빈에 등록한 것이 컴포넌트 스캔 방식이다. @Controller, @Service, @Repository에는 모두 @Component 어노테이션이 선언이 되어있기 때문에 컴포넌트 스캔 방식이라고 한다. 사실 각각을 @Component로 바꾸어도 문제가 되지 않는다.
  • @Component 어노테이션이 붙어있으면 스프링 빈으로 자동 등록된다.
  • 스프링을 사용할 때는 웬만한 것들은 다 스프링 빈으로 등록하여 사용해야 한다.
  • 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때 싱글톤으로 등록한다. 즉 같은 스프링 빈이면 모두 같은 인스턴스이다. 예를 들어 orderService라는 클래스의 생성자에 @Autowired가 붙어있고 memberRepository를 필요로 한다면 memberService와 orderService가 같은 memberRepository 객체를 공유한다는 것이다.
  • 설정으로 싱글톤이 아니도록 변경할 수 있지만 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.

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

  • 자바 코드로 직접 등록하는 것을 연습하기 위해 MemberService와 MemoryMemberRepository 클래스에 있는 @Service, @Repository, @Autowired 어노테이션을 모두 제거하고 시작한다.
  • 먼저 service 패키지 아래에 SpringConfig.java 파일을 생성하고 다음과 같이 코드를 작성한다.
@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());//생성자에 무언가를 넣어줘야 할 때 그게 무엇인지 보는 단축키: command + p
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}
  • 이렇게 스프링 빈에 등록하는 방법에는 두가지 방법이 존재하는데, 의존관계가 실행 중에 동적으로 변하는 경우는 거의 없으므로 어노테이션을 사용한 생성자 주입을 권장한다.
  • 만약 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해서 스프링 빈으로 등록한다. 나중에 현재 쓰고 있는 MemoryMemberRepository를 Datebase에 연결하는 다른 Repository로 바꿀 것인데 이때 기존에 운영 중인 코드를 하나도 바꾸지 않고 바꾸는 방법이 있다. 이런 경우에는 스프링 빈에 직접 등록해야 한다.
  • @Autowired 어노테이션은 스프링 빈에 등록되어 있는 클래스에 대해서만 작동하므로 스프링 빈에 없는 클래스에서 @Autowired를 사용하는 것은 의미가 없다.
profile
안녕하세요.

0개의 댓글