[Likelion] Spring 스터디 2주차

99winnmin·2022년 7월 20일
0

likelion

목록 보기
2/5
2주차 7/14~7/20
강의자료 및 내용 출처 : 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
목표 : 섹션3,4,5 강의 수강

비지니스 요구사항 정리

데이터 : 회원ID,이름
기능 : 회원등록, 조회
아직 데이터 저장소가 선정되지 않음(memoryDB 이용)

Controller : 웹 MVC의 컨트롤러 역할
Service : 핵심 비즈니스 로직 구현
Repository : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
Domain : 비즈니스 도메인 객체, 예) 회원, 주문, 쿠폰 등등 주로 데이터베이스에 저장하고 관리됨

Member Domain & Repository 개발 및 테스트

Member Service 개발 및 테스트

https://github.com/99winnmin/Spring-Study.git

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에 의해 스프링이 주입해준다.

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

  • 컴포넌트 스캔과 자동 의존관계 설정

    • @Controller, @Service, @Repository(모두 @Component의 특수한 case)는 컴포넌트 스캔 방식!
      • Controller : 외부요청을 받는 역할
       @Controller
       public class MemberController {
        		~~~
       }
      • Service : 비지니스 로직을 처리
        @Service
        public class MemberService {
        		~~~
        }
      • Repository : DB에 데이터를 저장
        @Repository
        public class MemoryMemberRepository implements MemberRepository {
        		~~~
        }
    • 컴포넌트 스캔 원리
      • @Component 애노테이션이 있으면 스프링 빈으로 자동 등록된다.
      • @Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문이다
      • @Component 를 포함하는 @Controller, @Service, @Repository도 스프링 빈으로 자동 등록된다.
    • 우리가 만든 프로젝트의 Application.java에서 package hello.hellospring;를 기준으로 hellospring 하위 객체들만 bean으로 등록가능하다!

      참고: 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다(유일하게 하나만 등록해서 공유한다) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.

  • 자바 코드로 직접 스프링 빈 등록하기

    이때 @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;
    • setter 주입 : setter가 public으로 노출된다는 점이 문제임
      		@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";
    }
profile
功在不舍

0개의 댓글