현재까지 진행 상태
- 멤버 서비스, 멤버 리포지토리 인터페이스, 멤버 리포지토리 객체 생성
- 멤버 서비스에서는 멤버 리포지토리 인터페이스가 final 변수로 설정되어있고, 직접 생성(new)하지 않는다.
- 멤버 서비스, 멤버 리포지토리 객체를 생성하여, 생성한 리포지토리 객체를 서비스에게 넘겨준다.
- 멤버 서비스는 생성자에서 받은 파라미터를 입력받아 사용한다. (DI)
- 서비스를 통해 멤버 가입 가능 (리포지토리에 저장되고, 꺼내올 수 있음)
- 테스트 케이스 생성 및 테스트 진행
- 회원 가입된 결과를 화면에 보여주기(컨트롤러, 뷰 템플릿 필요) --> 이제 진행할 차례
스프링 빈 등록 방법 1 : 컴포넌트 스캔과 자동 의존 관계 설정
@Controller /@Service/@Repository
Spring 이 처음에 뜰 때 Spring 컨테이너라는 통이 생기는데, 어노테이션이 붙어있는 객체를 생성하여 넣어두고 Spring이 직접 관리한다. 컨트롤러를 통해 외부 요청을 받고, 서비스에서 비즈니스 로직을 만들고, 리포지토리에서 데이터를 저장하는게 가장 정형화되어있는 패턴이다.
@Controller, @Service, @Repository 어노테이션의 정의를 살펴보면 @Component 어노테이션이 붙어있고, @Component 어노테이션의 특수화된 케이스라는 주석이 달려있다. 그래서 이런 방식을 컴포넌트 스캔이라고 부른다.
@Component와 관련된 어노테이션이 붙어있으면 스프링 객체를 하나씩 생성하여 스프링 컨테이너에 등록하고, @Autowired는 이 사이의 연관관계에 연결을 해준다.
@Autowired
하나의 컨트롤러 내에서 여러 서비스를 사용할 수 있고, 하나의 서비스는 여러 컨트롤러에서 사용될 수 있다.
만약 서비스 객체를 new 하여 사용한다면, 동일한 기능을 가진 서비스 객체가 여러 컨트롤러 내에서 생성되어 인스턴스가 많아지고, 메모리가 비효율적으로 사용된다. 객체가 스프링 빈으로 등록되었을 때 객체의 생성자에 @Autowired 어노테이션을 붙이면 Spring 컨테이너에 등록된 하나의 인스턴스만 공통으로 사용할 수 있다. (싱글톤으로 등록된다. 설정으로 싱글톤 패턴이 아니게 할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.)
컨트롤러에 서비스 객체를 선언만 하고 생성하지 않는다. 대신 컨트롤러 생성자에 @Autowired를 달아두면, 컨트롤러가 생성될 때 스프링 빈에 등록되어있는 서비스 객체를 넣어준다. (= 의존 관계를 주입해준다. = Dpendency Injection)
*스프링 컨테이너에 올라가는 것들만 이 AutoWired 기능이 동작하니 주의!
스프링 빈 등록 방법 2 : 자바 코드로 직접 등록
설정 파일에 어떤 것을 스프링 빈으로 등록할지 직 적어두는 방법이다. 이전에는 xml 파일을 만들었는데, 요즘에는 자바 파일에 작성하는 경우가 더 많다. 자바 class를 만들어 @Configuration 어노테이션을 달아주면 설정 파일로 인식하고, 그 안에서 객체를 new로 생성하여 리턴해주는 함수에 @Bean을 달아주면 등록이 완료된 것이다.
보통은 어노테이션을 사용하는 것이 빠르고 편리하나, 현재 만드는 프로젝트와 같이 상황에 따라 구현 클래스를 변경해야 하면 설정 파일을 통해 스프링 빈으로 등록하는 것이 좋다. 생성하여 리턴시킬 구현체만 변경해주면 되기 때문이다.
(DB가 확정되지 않아 현재 메모리 DB를 사용 중이며, 추후 DB에 맞는 구현체를 다시 만들겠다는 시나리오를 사용중)
@Configuration
public class SpringConfig {
@Bean
public Service service(){
return new Service(repository());
}
@Bean
public Repository repository(){
return new MemoryRepository();
// --> return new DBRepository(); 로 바꾸면 다른 소스 안건드려도 된다
}
}
Dependency Injection 3가지 방법
생성자 주입
@Controller
public class Controller {
private final Service service;
@Autowired
public Controller(Service service) {
this.service = service;
}
}
필드 주입, setter 주입보다 권장하는 방법이며, 스프링이 올라오는 시점에 한번만 조립해두고 변경 못하도록 막을 수 있다.
필드 주입
@Controller
public class Controller {
@Autowired private final Service service;
}
필드 주입을 사용할 경우 스프링이 올라올 때 객체를 넣어주고, 뭔가 상황에 따라 바꿀 수 있는 방법이 없어 폐쇄적이다. (물론 의존 관계가 실행중에 동적으로 변하는 경우는 거의 없다.)
setter 주입
@Controller
public class Controller {
private Service service;
@Autowired
public void setService(Service service) {
this.service = service;
}
}
컨트롤러 생성은 생성대로 되고, 이후에 setter 함수가 호출되어 서비스 객체가 주입되게 된다. 그렇지만 누군가 그 함수를 호출하려면 이 함수가 public으로 열려있어야 하고, 중간에 잘못 호출하여 주입되는 객체 바뀔 수 있다는 단점이 있다.
이 포스팅은 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의를 수강하며 작성되었습니다.
[지금 무료] 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의 - 인프런
스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다., 스프링 학습 첫 길잡이! 개발 공부의 길을 잃지 않도록 도와드립니다. 📣 확인해주세
www.inflearn.com
'Spring Framework' 카테고리의 다른 글
[스프링 입문] 스프링 통합 테스트 (1) | 2024.02.18 |
---|---|
[스프링 입문] 웹 MVC 개발 (0) | 2024.01.25 |
[스프링 입문] 회원 관리 백엔드 개발 (0) | 2024.01.21 |
[스프링 입문] 스프링 웹 개발 기초 (0) | 2024.01.19 |
[스프링 입문] 강의 소개 및 프로젝트 환경 설정 (0) | 2024.01.17 |