스프링 컨테이너의 사용 이유 및 Bean, Config등을 다뤄보자.
프로젝트를 하다보면 컨트롤러, 서비스, 리포지토리의 관계에서 서로간 Dependency Injection이 존재한다.
즉, 컨트롤러는 서비스에게 의존적이고, 서비스는 리포지토리에 의존적이다.
이러한 의존성에 의해 생각해보자.
웹 쇼핑 사이트를 운영하는 입장이라고 생각해보자.
회원관리를 하는 컨트롤러에서 Member 서비스를 필요로 하고, 주문관리 컨트롤러에서도 Member 서비스를 필요로 할 것이다.
그렇다면 이러한 Member 서비스를 각 컨트롤러마다 new를 이용해서 새롭게 생성해주어야 할까?
마치 이렇게..?!
아무리 생각해도 뭔가 비효율적이라는 생각이 든다.
굳이 하나만 있어도 충분한 회원 관리 서비스를 늘어나는 컨테이너마다 새롭게 만들어준다니...
즉, 회원관리를 하는 똑같은 서비스 로직(함수)를 사용하는데, 사용하는 곳 마다 새 걸로 생성해서 쓰는 것이다.
이를 해결하기 위한 방법이 바로 Spring 컨테이너이다.
자, 회원관리 컨트롤러에서 Member 서비스를 필요로하는 예제로 생각해 보자.
컨트롤러의 생성자를 만들고, Member 서비스를 할당하는 구문을 넣는다.
이 컨트롤러 생성자 위에 @Autowired를 쓴다.
Member 서비스 클래스위에 @Service 어노테이션을 붙여준다.
이렇게 클래스 위에 다음과 같은 어노테이션을 해놓게 되면 자동으로 자바에서 이를보고, "아 먼저 이 클래스 객체는 하나 만들어서 스프링 컨테이너에 넣어둬야 겠구나" 라고 생각하고 동작하게 된다.
이를 통해 처음 소스코드가 실행될 때, 자동으로 스프링 컨테이너에 단 하나의 서비스 객체가 생성되고, 이후 컨트롤러에서는 이 서비스 객체를 스프링 컨테이너로 부터 찾아 엮어(Autowired)줌으로써 의존성이 주입되게 된다.
@Service만 되는 것이 아니라, 서비스에 DI되는 레포지토리 또한 @Repository를 통해서 똑같이 Spring 컨테이너에 등록해서 사용할 수 있다.
스프링 컨테이너에 단 하나씩 등록을 해놓고 이를 다 같이 사용하는 방식으로 (컨트롤러-서비스-레포지토리)로 정형화 된 패턴이기에 이렇게 사용할 수 있는 것이다.
이를 컴포넌트 스캔 방식이라고 한다.
스프링이 올라올 때 컴포넌트와 관련된 어노테이션이 있으면 자동으로 스프링 컨테이너에 넣어주는 방식이 컴포넌트 스캔 방식이다.
따라서 @Componet라고 써도 동일하게 동작한다.
스프링 컨테이너에 등록되는 컨트롤러, 서비스, 레포지토리를 마치 콩과 같다하여 스프링 Bean이라고 부른다.
스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤(하나의 객체만)으로 등록한다.