스프링 입문 맛보기 5

Spring 정리 2021. 7. 14. 13:28

인프런 강의 5일차.

 - 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 (김영한 강사님)

 

* 회원 관리 예제 - 웹 MVC 개발

 1. MemberController.java

package hello.hellospring.controller;

import hello.hellospring.Service.MemberService;
import hello.hellospring.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;

@Controller
public class MemberController {

    //MemberService.java내에 @Service가 선언되어 있지 않으면 최소 서버 띄울 때 ComponentScan에서 에러가 발생한다!
    //에러 내용 : Consider defining a bean of type 'hello.hellospring.Service.MemberService' in your configuration.
    private final MemberService memberService;
/*
    //필드 주입
    @Autowired private MemberService memberService;

    //세터 주입
    @Autowired
    public void setMemberService(MemberService memberService) {
        this.memberService = memberService;
    }
*/
    //생성자 주입
    @Autowired
    public MemberController(MemberService memberService){
        this.memberService = memberService;
    }

    @GetMapping("/members/new")
    public String createForm(){
        return "members/createMemberForm";
    }

    @PostMapping("/members/new")
    public String create(MemberForm form){
        Member member = new Member();
        member.setName(form.getName());

        memberService.join(member);

        return "redirect:/";
    }

    @GetMapping("/members")
    public String list(Model model){
        List<Member> members = memberService.findMembers();
        model.addAttribute("members", members);
        return "members/memberList";
    }
}

 > createForm, create, list 메소드 추가

 2. MemberForm.java

package hello.hellospring.controller;

public class MemberForm {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 3. home.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <div>
        <h1>Hello Spring</h1>
        <p>회원 기능</p>
        <p>
            <a href="/members/new">회원 가입</a>
            <a href="/members">회원 목록</a>
        </p>
    </div>
</div>
</body>
</html>

 > 최초 화면 폼

 

 4. createMemberForm.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <form action="/members/new" method="post">
        <div class="form-group">
            <label for="name">이름</label>
            <input type="text" id="name" name="name" placeholder="이름을 입력하세요">
        </div>
        <button type="submit">등록</button>
    </form>
</div>
</body>
</html>

 > 회원가입 폼

 

 5. memberList.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <div>
        <table>
            <thead>
            <tr>
                <th>#</th>
                <th>이름</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="member : ${members}">
                <td th:text="${member.id}"></td>
                <td th:text="${member.name}"></td>
            </tr>
            </tbody>
        </table>
    </div>
</div>
</body>
</html>

 > 회원 리스트 폼

 

 

'Spring 정리' 카테고리의 다른 글

스프링 입문 맛보기 7  (0) 2021.08.05
스프링 입문 맛보기 6  (0) 2021.08.04
스프링 입문 맛보기 4  (0) 2021.07.06
스프링 입문 맛보기 3  (0) 2021.05.04
스프링 입문 맛보기 2  (0) 2021.04.29

스프링 입문 맛보기 4

Spring 정리 2021. 7. 6. 20:49

인프런 강의 4일차.

 - 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 (김영한 강사님)

 

1. 자바 코드로 직접 스프링 빈 등록해보기

 - @Bean 애노테이션을 통해 직접 스프링 빈 등록이 가능하다.

 - Service, Repository 전부 @Bean으로 설정이 가능하나, @Controller는 선언이 불가능하기에 항상 DI로 사용.

 - 과거엔 java 코드로 설정하지 않고 xml 문서로 설정하기도 했으나 실무에서 xml 문서로 설정하는 경우는 거의 없다.

package hello.hellospring;

import hello.hellospring.Service.MemberService;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    //사용자가 직접 Spring Bean 등록
    //Spring이 올라올 때 @Bean에 등록된 빈을 직접 넣어준다.
    //@Controller는 어쩔 수 없이 자동 의존관계 선언이 필요하다.
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
}

  

2. Dependency Injection 3가지 방법

 - field 주입 : 스프링 최초 실행 때 주입된 내용을 바꿀 수 없기 때문에 사용되지 않음.

 - Setter 주입 : setter()를 통해 주입되지만, 누군가 세터를 호출할 수 있게 public으로 열려있어야 하는 단점이 있다. (서비스는 어플리케이션 로딩 중 컨테이너 세팅할 때 바꾸는 것이지 중간에 바뀔 이유가 없기 때문에 public은 단점임)

 - Constructor 주입

  * 의존관계가 실행중에 동적으로 변경되는 경우는 거의 없기 때문에 Contructor 주입으로 구현하는 것을 권장함.

//필드 주입
@Autowired private MemberService memberService;

//세터 주입
@Autowired
public void setMemberService(MemberService memberService) {
	this.memberService = memberService;
}

//생성자 주입
@Autowired
public MemberController(MemberService memberService){
    this.memberService = memberService;
}

 

3. 참고

 - 실무에서는 주로 정형화된 컨트롤러, 서비스, 리파지토리 같은 코드는 컴포넌트 스캔을 통해 사용한다.

 - 정형화되지 않거나 상황에 따라 구현 클래스를 변경해야하면 @Bean을 통해 스프링 빈으로 등록 후 사용한다.

 - @Bean으로 등록한 경우 특정 상황 (예를 들어 DB가 변경될 경우) 해당 @Bean이 호출하는 @Repository만 변경하여 수정이 가능하므로 설정파일 관리가 간단하다.

 

4. 주의

 - @Autowired를 통한 DI는 'helloController', 'MemberService' 등과 같이 스프링이 관리하는 객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

 

 

 

 

 

'Spring 정리' 카테고리의 다른 글

스프링 입문 맛보기 6  (0) 2021.08.04
스프링 입문 맛보기 5  (0) 2021.07.14
스프링 입문 맛보기 3  (0) 2021.05.04
스프링 입문 맛보기 2  (0) 2021.04.29
스프링 입문 맛보기  (0) 2021.04.28

스프링 입문 맛보기 3

Spring 정리 2021. 5. 4. 20:57

인프런 강의 3일차. 

 - 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 (김영한 강사님)

 

1. 테스트 클래스 생성(Ctrl + Shift + T)

 - 한글로 작성해도 상관없음 (빌드될 때 실제 코드에 포함되지 않는다)

 - 테스트 메소드 작성 시 추천하는 방법 (given, when, then)

  

2. AssertThrow

 - 메소드 실행 시 해당 에러가 발생해야 test 통과를 의미

 - A와 B의 테스트 결과는 같다.

A. try - catch exception

//given
Member member1 = new Member();
member1.setName("Spring");

Member member2 = new Member();
member2.setName("Spring");
        
//when
memberService.join(member1);		//member1 회원가입
try {
     memberService.join(member2);	//member2 회원가입, 이 때 name이 둘 다 Spring이므로 익셉션발생.
     fail();
}catch (IllegalStateException e){
     assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다"); //발생한 에러 메시지가 "이미 ~ "와 같다면 테스트 통과
}

B. AssertThrow

//given
Member member1 = new Member();
member1.setName("Spring");

Member member2 = new Member();
member2.setName("Spring");

//when
memberService.join(member1);		//member1 회원가입
//member2 회원가입 시 IllegalStateException 발생 시 assertThrow 발생. 즉, 테스트 통과
assertThrows(IllegalStateException.class, () -> memberService.join(member2));

 

3. Dependency Injection

 - 각 테스트를 실행하기 전 같은 인스턴스를 사용하기 위해 인스턴스 생성 때 외부에서 인스턴스를 인자로 넣어줌

//MemberService.java
private final MemberRepository memberRepository;

public MemberService(MemberRepository memberRepository){
	this.memberRepository = memberRepository;	//생성자에서 DI
}


//MemberServiceTest.java
MemberService memberService;
    MemoryMemberRepository memberRepository;

    @BeforeEach
    public void beforeEach(){
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);		//Dependency Injection
    }

 

4. 스프링 빈과 의존 관계 설정

 - 스프링이 빈이 관린된다는 의미 : 스프링이 최초 실행될 때 스프링 컨테이너가 생성되는데, 이 때 @Controller 가 있으면 해당 Controller 객체를 생성해서 스프링이 넣어두고 관리한다.

 - 스프링이 관리는 객체의 경우 스프링에서 관리할 수 있게끔 생성자에 @Autowired을 붙여서 관리해야한다.

 - 생성자에 @Autowired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게 객체 의존 관계를 외부에서 넣어주는 것을 DI, 의존성 주입이라 한다.

 - 3번에서는 개발자가 직접 넣어주었고, 아래 소스는 @Autowired에 의해 스프링이 주입해준다.

@Controller
public class MemberController {

    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService){
        this.memberService = memberService;
    }
    //위 코드 실행 시 아래 오류 발생
    /*
      Parameter 0 of constructor in hello.hellospring.controller.MemberController required 
      a bean of type 'hello.hellospring.Service.MemberService' that could not be found.
    */
    
    //memberService는 스프링 빈에 등록되어 있지 않기 때문에 최초 스프링 컨테이너 실행 때 찾을 수 없는 객체이다.
    //memberService클래스에 @Service를 사용하여 스프링 빈에 등록해주면 정상적으로 실행된다.
    //Repository도 마찬가지로 @Repository를 사용하여 스프링 빈에 등록해주어야 한다.
}

 

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

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

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

 

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

 - @Component : 애노테이션이 있으면 스프링 빈으로 자동 등록된다.

 - 스프링 시작 시 Component 애노테이션이 있으면 자동으로 객체를 생성해서 스프링 컨테이너에 가지고 있다.

 - @Autowired가 있을 시 해당 객체들을 연결시켜둔다.

 - @Component를 포함하는 다음 애노테이션도 스프링 빈으로 자동 등록된다.

     ->@Contoller, @Service, @Repository : 해당 애노테이션에 들어가보면 @Component로 선언되어있다.

 - 단, 이 때 스캔하는 대상은 @SpringBootApplication 에 등록된 하위 패키지만 스캔한다.

     -> @SpringBootApplication 애노테이션에 들어가보면 @ComponentScan 애노테이션이 있다.

 - 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때 기본으로 싱글톤으로 등록한다(하나의 인스턴스만 등록해서 공유)

 - 설정을 통해 싱글톤이 아니게 할 수 있지만 특별한 경우가 아니면 전부 싱글톤을 사용한다.

 

 

 

* Ctrl + R : 가장 최근에 실행한 테스트 재실행

'Spring 정리' 카테고리의 다른 글

스프링 입문 맛보기 6  (0) 2021.08.04
스프링 입문 맛보기 5  (0) 2021.07.14
스프링 입문 맛보기 4  (0) 2021.07.06
스프링 입문 맛보기 2  (0) 2021.04.29
스프링 입문 맛보기  (0) 2021.04.28