2주차 7/14~7/20
강의자료 및 내용 출처 : 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
목표 : 섹션3,4,5 강의 수강
비지니스 요구사항 정리
데이터 : 회원ID,이름
기능 : 회원등록, 조회
아직 데이터 저장소가 선정되지 않음(memoryDB 이용)
Controller : 웹 MVC의 컨트롤러 역할
Service : 핵심 비즈니스 로직 구현
Repository : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
Domain : 비즈니스 도메인 객체, 예) 회원, 주문, 쿠폰 등등 주로 데이터베이스에 저장하고 관리됨
Member Domain & Repository 개발 및 테스트
Member Service 개발 및 테스트
Spring Bean과 의존관계
MemberController에서 MemberServiced와 MemberRepository를 사용하려면 의존관계를 설정해줘야한다. 단순히 생각해서 private final MemberService memberService = new MemberService();로 작성한다면 이는 효율적이지 않다. 그 이유는 MemberService 객체를 여러개 생성할 필요가 없음 -> 그냥 spring container에 한번만 등록해놓고 그걸 계속 사용하는 것이 좋음
private final MemberService memberService;
@Autowired // @Autowired는 container에 등록되어있는 녀석을 자동으로 가져와줌
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
생성자에 @Autowired 가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. (이때 연관된 객체들은 spring bean에 등록되어 있어야한다!!)
이렇게 객체 의존관계를 외부에서 넣어주는 것을 DI (Dependency Injection), 의존성 주입이라 한다.
new MemberService()는 개발자가 직접 주입했던 것이고, 여기서는 @Autowired에 의해 스프링이 주입해준다.
@Controller
public class MemberController {
~~~
}
@Service
public class MemberService {
~~~
}
@Repository
public class MemoryMemberRepository implements MemberRepository {
~~~
}
참고: 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다(유일하게 하나만 등록해서 공유한다) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.
이때 @Service, @Repository, @Autowired 애노테이션을 제거하고 진행한다.
위 방식과 장단점에서 차이가 있겠지만 직접 bean을 관리하므로 bean 등록,제거,변경이 쉽다.
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
}
DI에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있다. 의존관계가 실행중에
동적으로 변하는 경우는 없으므로 생성자 주입을 권장한다.
@Autowired private MemberService memberService;
@Autowired
public void setMemberService(MemberService memberService){
this.memberService = memberService;
}
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다. 그리고 정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.
주의 : @Autowired 를 통한 DI는 helloConroller , memberService 등과 같이 스프링이 관리하는 객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.
회원 관리 예제 - 웹 MVC 개발
기본적인 MVC Controller 예제여서 간단히 하고 넘어가겠음...
@GetMapping("/members/new")
public String createForm(){
return "members/createMemberForm";
}
@PostMapping("/members/new")
public String create(MemberForm memberForm){
Member member = new Member();
member.setName(memberForm.getName());
memberService.join(member);
return "redirect:/";
}
@GetMapping(value = "/members")
public String list(Model model) {
List<Member> members = memberService.findMember();
model.addAttribute("members", members);
return "members/memberList";
}