해당 강의는 Inflearn에 등록된 김영한님의 Springboot 강의입니다.
저번시간에 다음과 같은 아키텍쳐(웹 애플리케이션 계층구조)에서 회원 도메인,리포지토리,서비스를 개발 했다,
이번 시간에는 회원 컨트롤러를 생성하고, 각 컴포넌트를 스프링빈에 등록 하겠다.
1. 컴포넌트 스캔과 자동 의존관계 설정
회원 컨트롤러 생성
코드
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController (MemberService memberService )
{
this.memberService=memberService;
}
}
@Cotroller
를 명시하여 스프링 빈에 해당 Controller를 등록했다.
2. 스프링 빈(Spring Bean)이란?
스프링 빈을 알기전에 스프링 컨테이너(Spring Container)를 알아야 한다.
스프링 컨테이너는 스프링에서 객체를 관리하는 곳이다. 이러한 객체를 스프링에선 Bean 이라고 부른다.
빈(Bean)은 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트이다. 객체지향 프로그래밍관점에서 개발자는 객체를 new 키워드를 통해 생성자와 함께 호출 하여 사용한다. 하지만 스프링에서는 객체를 스프링 컨테이너에 빈으로 명시된 객체들을 등록하여 객체들을 관리한다. 이렇게 함으로써 개발자는 객체들의 의존관계를 일일이 설정 안해줘도 된다. 스프링 컨테이너에서 알아서 관리해준다. 여기서 의존관계를 이해하는게 중요하다.
의존관계란 각 객체끼리의 관계가 설정 되어 있어, 한 객체가 변하면 다른 객체도 그에 맞춰 변하게 된다. 만약 스프링 빈을 컨테이너에 등록하지 않으면 이렇게 변하게 되는 상황을 일일이 생각하여 로직을 구현해야 할 것이다.
하지만 스프링 빈에 등록하면 객체를 컨테이너에서 불러오기면 해서( private final 로 선언해야 함) 사용하면 알아서 스프링이 관리 해준다.
그 밖에도 각 컴포넌트들을 스프링 빈에 등록해야하는 이유가 많다.
의존성 관리
: 객체지향 프로그래밍에서는 객체 간의 의존성을 최소화하여 유연하고 확장 가능한 코드를 작성하는 것이 중요하다. 스프링에서는 이를 위해 객체를 스프링 빈으로 등록하여 스프링 컨테이너가 객체 간의 의존성을 관리하고 주입해준다.예를 들어, 주문 관리 시스템에서 주문 객체가 결제 서비스에 의존한다고 가정하자. 주문 객체가 스프링 빈으로 등록되면 스프링 컨테이너가 주문 객체에 필요한 결제 서비스를 주입해줄 수 있다. 이렇게 하면 주문 객체는 직접 결제 서비스를 생성하거나 관리할 필요가 없어진다. 즉, OrderService에 PayService를 생성해서 로직을 구현 안해도 된다. 개발자는 Controller에서 해당 서비스 객체를 불러와서 쓰기만 하면 된다.
스프링의 다양한 기능 사용
: AOP(Aspect-Oriented Programming), 트랜잭션 관리, 보안 등 다양한 기능을 제공하는데, 이러한 기능을 활용하기 위해서는 대상 객체를 스프링 빈으로 등록해야 한다.
3. 스프링 빈 등록 방법
스프링 빈과 스프링 컨테이너가 무엇인지 이제 알았으니 각 컴포넌트를 스프링 빈에 등록하자.
컴포넌트란 한국어로 기능이란 말이다. 통상 콘트롤러,서비스,리포지토리를 의미한다. 도메인은 단순 속성을 정의한 객체이므로 컴포넌트로써 스프링 빈에 등록 대상이 아니다. 그렇다고 도메인 객체끼리의 관계가 없는 것은 아니다.
도메인 객체(ex:회원,주문,결제 등) 끼리의 관계는 E-R 다이어그램으로 일대다, 다대일 등으로 표현하고, 컴포넌트들은 이러한 도메인의 속성들과 관계를 이용해서 데이터를 추출하거나 활용한다.
다음은 2가지 등록방법이다.
1. 컴포넌트 스캔과 자동 의존관계 설정
2. 자바코드로 직접 스프링 빈 등록하기
1. 컴포넌트 스캔과 자동 의존관계 설정
- 컴포넌트 스캔 원리
@Controller annotation은 @Component로 명시되어있다. 다른 service, repository도 마찬가지이다. 따라서 컴포넌트 스캔을 통해 각 컴포넌트를 스프링 빈에 등록 가능하다. 그러면 마저 스프링 빈에 등록해주자.
@Service
public class MemberService {
private final MemberRepository memberRepository;
//Test에서 같은 레포 공유를 위해 생성자에 의존성 주입. 이는 DI의 생성자 주입이라고 한다.
//생성자 주입의 이유는 콘트롤러->서비스->레포지토리의 의존관계가 잘 안바뀌므로 생성자 주입을 권장.
//나머지로 설정하면 다른 개발자가 임의로 setting을 바꿀 수 있다.
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
생성자에@Autowired
를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입한다.
위의 콘트롤러는 서비스 객체에, 서비스는 리포지토리 객체에 의존성을 주입
했다.
사실 @Autowired의 생성자 주입 방식으로 저렇게 객체를 의존관계를 설정하고, 불러오지않아도 가능한 방법이 있다.
이것 또한 롬복의 @RequiredArgsConstructor 을 컴포넌트
에 명시하면 된다. 추후에 JPA활용편에서 설명하겠다.
@Autowired:스프링 컨테이너에서 memService(@Service)를 가져옴.->의존성 주입 디자인패턴
2. 자바 코드로 직접 스프링 빈으로 등록하기
코드
//스프링 설정 파일
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
코드 설명
이 방식은 따로 설정 파일(클래스)를 만들어서 거기에다 스프링 빈을 등록하는 방식이다.
설정 클래스라 @Configuration
으로 클래스에 명시하고, 컴포넌트들을 @Bean
이라고 명시하면 끝이다.
아직 DB가 제대로 설정 되지않아서 컴포넌트 스캔 방식 말고, 직접 등록했다.
아래 사진을 보면 이해가 될 것이다.