본문 바로가기

Dev/Spring Boot

스프링 빈 주입방법과 템플릿 우선순위

스프링 빈 주입방법에는 크게 두가지로 나뉜다.

 

1. 컴포넌트 스캔을 이용한 등록방법

  • 컴포넌트 스캔을 이용한 방법은 주로 실무에서 정형화된 컨트롤러, 서비스, 리포지토리 같은 곳에 사용한다.
  • 즉, 고정화 되어 바뀔일이 없을 경우! 사용한다고 보면 된다. 무작정 쓰는거보다 상황에 맞게 사용하는것이 중요!!
-- MemberController(컨트롤러)

@Controller
public class MemberController {

    private final MemberService memberService;

    /**
     * DI 주입방법 중 필드주입 방법
     * 별로 좋지 않음
     */
//    @Autowired private final MemberService memberService;


    /**
     * DI 주입방법 중 생성자 주입 방법
     * 요즘 권장하는 주입방법
     */
    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

 

아래 MemberService를 보면 @Service 어노테이션을 확인할 수 있다. 

이 어노테이션은 내부적으로 @Component를 포함하고 있다. 동작과정은 다음과 같다.

/**
* 어노테이션 내부 구성
* @Component를 들고있다.
*/

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
public @interface Repository { // 얘도 서비스와 동일한 구성이므로 아래 추가적으로 씀

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 */
	@AliasFor(annotation = Component.class)
	String value() default "";

}

 

1. 스프링이 시작하게 됬을 때 @Service 어노테이션을 보고 아! 이부분이 서비스구나 하고 MemberService를 스프링 컨테이너에 등록한다.

2. 그리고 @Autowired를 통해 아! 얘는 MemberRepository와 연결이 되는구나 하고 관계를 등록해준다.

3. 스프링에서의 모든 등록은 싱글톤 방식으로 한번만 등록해주는 방식을 가진다.

-- MemberService(서비스)
@Service
public class MemberService {

    private final MemberRepository memberRepository;

    /**
     * DI 주입방법 중 생성자를 통한 주입방법
     * 요즘 권장하는 주입방법
     */
    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

 

@Repository 에도 마찬가지로 @Component 어노테이션이 포함되어 있으므로 스프링이 시작될 때 스프링 컨테이너에 리포지토리를 등록해준다.

@Repository
public class MemoryMemberRepository implements MemberRepository {

    private static Map<Long, Member> store = new HashMap<>();

※ 컴포넌트 스캔방식 종류

  • 필드주입방식
  • setter를 사용한 주입방식
  • 생성자를 이용한 주입방식 - 대게 자주 사용하는 방식으로 권하는 방식이다!!!

세 가지 방식중에서 생성자를 이용한 주입방식을 주로 사용하지만 예외적인 사항이 있다.

테스트 케이스를 작성하는 테스트 파일의 경우에는 굳이 생성자를 이용한 주입방식을 사용할 필요가 없다!!

왜냐!? 

테스트를 어디 다른데서 가져다가 사용하는게 아니고 테스트할 때만 사용하고 끝!! 이기 때문이다.

그래서 테스트에서는 보통 필드주입방식으로 사용한다.

-- MemberServiceIntegrationTest (테스트 파일)

@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {
	
    # jUnit을 사용하여 테스트 하는 파일은 보통 아래와같이 필드주입방식으로 사용한다.
    # why??? 테스트 파일을 어디서 가져다가 사용하는 것이 아니기 때문에!! 여기서만 사용하고 끝이기 떄문이다
    @Autowired MemberService memberService;
    @Autowired MemoryMemberRepository memberRepository;

 

2. 자바를 통한 직접 등록방법

주로 정형화 되지 않거나 상황에 따라 구현 클래스를 변경해야 할일이 생기게 되거나, 그럴 여지가 있는 경우 직접 설정을 통해 등록한다.

즉, 변경될 일 혹은 여지가 있는 경우에 직접 등록하게되면, 코드를 크게 수정하지않아도 쉽게 변경할 수 있는 장점이 있다!!

  • 별도의 Config 파일을 생성하여 직접 주입하는 방법이다.
  • 스프링이 시작될때 @Configuration을 찾아가게 된다.

@Bean 으로 되어있는 것을 보고 아! MemberService가 등록되어야하는구나 하고 스프링 컨테이너 등록해주고

MemberRepository도 등록되어야하네? 하고 등록해주며 아 MemberService는 MemberRepository와 관계가 있구나 하고 인식해준다.

@Configuration
public class SpringConfig {
    /**
     * 자바로 스프링 빈 직접 등록하기
     * 실무에서는 보통 정형화된 컨트롤러 서비스 리포지토리는 컴포넌트 스캔을 사용한다.
     * 상황에 따라 바뀌어야 할 경우에는 설정을 통해 스프링 빈을 등록한다.
     */
    // 스프링이 뜰 때 Configuration을 읽고 이거는 스프링 빈에 등록하라는 거네! 하고 등록해줌
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

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

 

스프링 부트 VIEW TEMPLATE 우선 순위

src/main/resource 부분

보통 스프링 부트가 실행이 되어 요청(WELCOME PAGE 요청) 이 들어오면 localhost:8080 형태의 요청

우선적으로 스프링 컨테이너에서 컨트롤러가 있는지 확인한다!

 → 컨트롤러가 있을 경우에 그 컨트롤러가 가리키는 템플릿으로 우선적으로 불러준다. (우선순위 1번)

 → 컨트롤러가 없을 경우에 static(정적)에 있는 html(뷰 템플릿)을 불러준다. (우선순위 2번)