BugDIARY

[SpringBoot] 스프링 빈 의존 등 정리 본문

IT/Java

[SpringBoot] 스프링 빈 의존 등 정리

HEMON 2023. 6. 4. 16:18

 

이 글은 나중에 프로젝트를 생성할 경우 참고하기 위한 글입니다.
또한 김영한님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술을 학습한 내용입니다.

 

[Service]

- 통상적으로 비즈니스 로직을 주로 처리한다.

- validate체크는 메서드화 해주는 것이 좋다.

- Optinal로 반환되는 경우 따로 변수에 저장하는 것 보다는 바로 ifPresent같은것을 이용해 값을 체크하는 식으로 많이 사용한다.

 

[Repository]

- 기계적으로 개발스럽게 데이터를 넣고 빼는 작업을 주로 한다.

 

[테스트 코드 작성 규칙]

given, when, then
// given 뭔가가 주어졌을 때

// when 이것을 실행했을 때

// then 결과가 이렇게 나와야 한다.

 

[스프링 빈과 의존관계]

- 화면을 연결하려면 Controller와 View 템플릿이 필요하다.

<예시>
Member Controller  →  MemberService  →  MemberRepository
MemberController는 데이터를 사용하려할 때 MemberService를 이용해 데이터에 접근할 수 있고 Service는 Repository를 이용해 데이터를 다루게 된다.

그리고 이러한 것들을 서로 의존하는 관계, 의존관계라고 한다.

아래는 예시의 의존관계 부분을 코드화 한 것이다.

MemberController.java

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

MemberService.java

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

해당 코드처럼 객체의 의존관계를 주입시켜주는것을 의존성 주입이라고 한다.

 

[@Controller]

- Controller를 만든 뒤 어노테이션을 붙일 경우 겉보기엔 아무런 일이 벌어지지 않지만 내부적으로는 아래와 같이 움직이며 결과적으로 스프링은 컨테이너 안에 있는 것들을 관리하게 된다.

1. 스프링 컨테이너가 생성

2. @Controller어노테이션이 있는 Controller클래스의 객체를 스프링 컨테이너에 넣어줌

 

[Service]

- new를 생성해서 서비스를 사용하는 경우 관리가 어렵다. 하나의 컨트롤러만 Service를 사용하는 경우엔 문제가 없으나 두개의 컨트롤러에서 하나의 서비스를 호출할 때 마다 new를 계속해서 생성하여 Service에 등록하기 때문이다.

- @Service로 스프링 컨테이너에 등록하고 등록된 서비스를 가져다 쓰는것이 효율적이다.

- Service를 연결하는 것은 위의 MemberController.java를 참고할 것.

  ▷연결은 생성자를 @Autowired를 해주고 그 안에 service를 입력해주면 된다.

※ @Autowired만 사용할 경우 연결 되지 않는다. 이유는 스프링 컨테이너에 등록되지 않기 때문이다.

    그러므로, @Autowired를 이용해 해당 서비스 혹은 리포지토리를 사용하려면 @Service, @Repository라는 어노테이션을 붙여 스프링 컨테이너에 등록 해야한다.

 

[정리]

▶Spring은 스프링 컨테이너를 생성하는데 그곳에 등록된 객체를 가져다 쓰는것이 일반적이다.
▶Controller에서도 Service나 Repository를 사용할 떄 컨테이너에서 가져다 쓰게 되는데 이때 @Service, @Repository처럼 어노테이션으로 정의를 해야 스프링 컨테이너에 빈으로서 등록이 된다.
▶ 컨트롤러에서 서비스나 리포지토리를 사용하려고 할 때 @Autowired어노테이션을 이용해 스프링 컨테이너에 등록된 객체를 불러오게 되고 이로서 서로 연결해서 사용할 수 있게 된다.
▶ 이것을 DI(Dependency Injection), 의존성 주입이라고 한다.
▶ 실제 현장에서는 컴포넌트 스캔을 사용하며, 정형화 되지 않거나 상황에 따라 구현 클래스로 변경하려 하면 설정을 변경해 스프링 빈으로 등록한다.
▶ @Autowired는 내가 직접 등록한 객체에서는 동작하지 않는다. 스프링 컨테이너에 올라가있는 컴포넌트에 한해서 동작한다. (Controller내부에서 new를 하거나 config로 직접 등록한 빈이 없을 경우 동작하지 않음.)

 

[스프링 빈 등록하는 2가지 방법]

1. 컨포넌트 스캔과 자동 의존관계 설정(@를 이용한 방식)

- @Component 어노테이션이 있으면 스프링 빈으로 자동 등록이 된다.

- @Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문이다.

- @Componen를 포함하는 다른 어노테이션들도 모두 빈에 등록된다.

- SpringApplication.run이 존재하는 곳의 하위 패키지들은 스프링이 스캔할 수 있으나 그곳에서 벗어난 패키지나 클래스들은 기본적으로는 스프링이 스캔할 수 없다.

 

- 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때 기본으로 싱글톤(하나만 등록하여 공유한다.)으로 등록한다.

  (설정으로 싱글톤이 아니게 개발할 수 있지만 기본적으론 싱글톤으로 사용한다.)

 

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

- @Configuration어노테이션을 이용해 빈을 직접 등록할 수 있다.

@Configuration
public class SpringConfig{
    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }
    
    @Bean
    public MemberRepository memberRepository() {
    	// MemberRepository는 인터페이스로 작성하였기 때문에
        // 해당 인터페이스를 Implements하고 있는 MemoryMemberRepository를 반환한다.
        return new MemoryMemberRepository();
    }
}

 

[DI주입 3가지]

- 생성자 주입

   ▷ 생성자를 통해 주입하는것

   ▷ 의존 관계가 서비스 실행 중에 바뀌는 경우는 거의 없으므로 생성자 주입을 추천한다.

        (보통은 변경 사항이 생기면 서버를 내렸다가 다시올림)

 

- 필드 주입

   ▷ 생성자 빼고 필드에다가 @Autowired를 하는 것(변경이 힘들어 선호하지 않음)

- Setter주입

   ▷ 생성은 생성대로 되고, set을 통해 주입이 된다.

        (단점 : public하게 노출이 되어 누군가 Service를 setService로 바꿀 수 있다.)

Comments