[Spring] 스프링 빈과 의존관계 설정

김유진·2022년 10월 22일
0

Spring

목록 보기
9/12
post-custom-banner

우리가 기존에 만들었던 회원관리 예제에서

  • Repository를 만들어 회원의 DB에 접근하는 방법에 대해서 정리할 수 있었습니다.
  • Domaim을 통하여 관리할 데이터의 자료형에 대해서 정리할 수 있는 시간을 가졌습니다.
  • Service를 통하여 실제로 관리를 할 내용을 작성해 두었습니다.

    이 모든것을 화면에 연결해서 보여주고 싶어요!

회원가입하고, 회원가입된 결과를 화면에 보여주려면 어떻게 해야 할까? 그럼 당연히 controller를 만들어야 겠지!
controller는 service를 통하여 회원가입하고, 멤버를 조회할 수 있어야 한다.
이러한 관계를 서로 의존관계에 있다고 합니다.

그 작업을 스프링스럽게 합시다. 자, 이제 회원 컨트롤러가 회원 서비스와 회원 리포지토리를 사용할 수 있게끔 의존관계를 만들어보도록 하자!

1. 스프링 빈을 등록하는 두가지 방법 정리!

  • 컴포넌트 스캔과 자동 의존관계 설정
  • 자바 코드로 직접 스프링 빈 등록하기

2. 스프링 빈을 등록해보자! - 컴포넌트 스캔


이렇게 controller 폴더 안에 member를 컨트롤 할 수 있는 java파일을 하나 생성합니다.

package Inflearn_spring.studyspring.controller;

import org.springframework.stereotype.Controller;

@Controller
public class MemberController {
}

이렇게 생성을 해두기만 해도 스프링 컨테이너에 이 controller 객체를 만들어서 컨테이너에 넣어둔다.

컨트롤러 안에다가 MemberServic와 관련된 객체를 만들고 싶을 때

private final MemberService memberService = new MemberService();

이렇게 만들면 안된다. 왜냐하면, 다른 친구들도 이 친구를 가져다 써야할텐데 그때마다 독립적으로 new라고 만들어주면 안되니까?

그러니까, Spring Container에 하나만 등록하고 그것을 계속 이용하면 되잖아?

@Autowired를 추가해주자!!

생성자에 @Autowired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게 객체 의존관계를 외부에서 넣어주는것을 DI (Dependency Injection), 의존성 주입이라한다.

constructor을 이용하여서 임의로 데이터를 연결해준 내용을 다시 한번 복습해보자.

@Controller
public class MemberController {

    private final MemberService memberService;

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

이렇게 생겼다. 이제 잘 실행하나 했더니..오류가 발생한다.


오잉, Memberservice가 컨테이너에 등록이 되어 있지 않나보다.
Memberservice에 가보면 얘는 순수한 자바 클래스이고, 컨테이너가 이것을 알아차릴 수 없는 것!

(helloController는 스프링이 제공하는 컨트롤러여서 스프링 빈으로 자동 등록된거. - @Controller는 자동 등록됨! 서비스랑 컨트롤러 연결해주는 그런거는 직접 해주어야 한다는 점!)

그러니까 Service 파일에 가서 아래 코드를 추가해주자.

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

@Service를 통하여,스프링이 스프링 컨테이너에 member serivce를 스프링 빈으로 등록을 해준다. 리포지토리도 마찬가지이다.

@Repository
public class MemoryMemberRepository implements MemberRepository  {

    private static Map<Long, Member> store = new HashMap<>();
    private static long sequence = 0L;
...

스프링이 컨트롤러, 리포지토리, 서비스를 좍 가져올 수 있도록 한 것.
이제 컨트롤러와 서비스를 연결시켜주어야 하니까, @Autowired를 사용하는 것이다. @Autowired를 사용하면, 해당되는 객체가 생성되는 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입합니다.

자, 이제 MemberController가 생성이 될 때, Spring bean 안에 들어있는 Memberservice 객체를 가져와서 주입을 해준다. 이것을 바로 dependency injection.이라고 하는 것이다. 밖에서 넣어준 것!!

이 사진을 보면 memberSerivicememberRepository가 필요하니까 아래와 같이 @AutoWired를 넣어서 레포지토리를 주입시켜주어야 한다.

@Service
public class MemberService {
    private final MemberRepository memberRepository;

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

자 그럼 얘네 이제 연결이 잘 되었네~ 실행시켜보자.

이제 문제 없이 컴파일이 완성되었다.

우리가 위에서 수행한 방법은 바로 컴포넌트 스캔과 자동 의존관계설정이다.
사실 우리가 위에서는 @Service, @Repository와 같이 작성을 했지만, 그것을 따라서 원본 파일로 들어가 보면 이러한 현상이 일어난다.

컴포넌트 안에 Service가 존재하네! 그래서 원래 이름을 컴포넌트 스캔이라고 하는 것이다. 컴포넌트와 관련한 에노테이션이 있으면 컨테이너에 등록을 하기 때문에.

핵심정리

  • @Component 에노테이션이 있으면 스프링 빈으로 자동 등록된다.
  • @Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문이다.
  • @Controller, @Service, @Repository도 @Component를 포함하기 때문에 자동으로 스프링 빈으로 등록된다.

+)추가! 그럼 , 아무 패키지나 만들어서 에노테이션 설정하면 어케됨?

아쉽게도 그건 불가능하다.

여기 들어가서 확인을 해보면... 스캔해서 실행시키는 패키지는 자신의 하위 패키지만 스캔하여 실행하기 때문에 아무거나 막 만든다고 해서 얘가 다 해주지를 않아요~

+) 참고!

스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다. 유일하게 하나만 등록해서 공유하기 때문에, 같은 스프링 빈은 같은 인스턴스로 인식하고 사용해야 한다.

3. 스프링 빈을 등록해보자! - 자바 코드로 직접 스프링 빈 등록

일단 앞서 우리가 작성했던 애노테이션을 다 지워야한다.

그리고 파일을 하나 생성해서 SpringConfig라고 이름짓습니다.
아래 코드에서 직접 Bean을 하나하나 등록해줍니다.

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

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

여기서 주의해야 할 점은 MemberServiceMemberRepository의 Bean이 필요합니다. 그렇기 때문에 생성한 내용을 저기에 꼭 연결을 해 주어야 해~

컨트롤러는 어짜피 Spring에서 관리하는 것이기 때문에 내가 뭐 어떻게 더 할 게 없습니다요. 여기까지 하면 아래 그림이 완성된다! :)


타란~ 얘도 문제없이 빌드가 잘 되어서 포트 8080 열렸따!

post-custom-banner

0개의 댓글