Joon's Space
[Spring] 스프링 부트 스프링 빈과 의존 관계, 웹 MVC 개발 (4) 본문
스프링 빈 등록하기
- MemberController, MemberService, MemberRepository class에 각각 @Controller, @Service, @Repository를 붙여 주면, 자동으로 의존관계가 등록이 된다. (컴포넌트 스캔 방식) -> main app이 돌아가는 하위 패키지에서만 자동으로 찾아서 등록
DI에는 필드 주입, setter 주입, 생성자 주입 3가지가 있는데, 의존관계가 실행중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장.
package hello.hellospring.controller;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired // Controller에 Service를 연결
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Autowired // Service를 Repository에 연결
public MemberService(MemberRepository memberRepository) { // 직접 생성이 아닌 외부 memberRepository를 설정하여 저장한다.
this.memberRepository = memberRepository;
}
// 회원 가입
public Long join(Member member) {
// 같은 이름이 있는 중복 회원 X
validateDuplicateMember(member); // 중복 회원 검증 ctrl+t 단축키(extract method)
memberRepository.save(member);
return member.getId();
}
...
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.springframework.stereotype.Repository;
import java.util.*;
@Repository
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L; // id key값을 생성할 때 필요한 변수
...
- 자바코드로 직접 스프링 빈 등록한다.
hellopsring 패키지 밑에 SpringConfig class 생성 (controller는 그대로 유지, 직접 등록 x)
package hello.hellospring;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
실무에서는 위 두 가지 방법 중 컴포넌트 스캔을 주로 사용한다. -> 컨트롤러, 서비스, 레포지토리 같은 코드는 정형화가 되어있기 때문
정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 할 때 설정을 통해 스프링 빈으로 등록한다.
웹 MVC 개발
- 홈 화면 추가
controller에 HomeController 생성
package hello.hellospring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home"; // template에 home.html로드
}
}
resources/template/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> <!-- /container -->
</body>
</html>
회원 가입 페이지
먼저 form데이터에서 데이터를 받아서 name을 받아 올 form class를 생성.
package hello.hellospring.controller;
public class MemberForm {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
MemberController에 회원가입 form을 로드하고, input 태그에 입력한 name값을 service의 join기능을 통해 등록하고, 다시 home 화면으로 redirect 한다.
// MemberController.java
@GetMapping("/members/new")
public String createForm() {
return "members/createMemberForm";
}
@PostMapping("/members/new") // html의 form action에서 받아온 name을 받아옴.
public String create(MemberForm form) {
Member member = new Member();
member.setName(form.getName());
memberService.join(member); // service의 회원가입 메소드
return "redirect:/"; // home 화면으로 돌아가기
}
회원가입 페이지 html 코드는 다음과 같이 입력
// resources/template/members/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> <!-- /container -->
</body>
</html>
회원 목록 페이지
// MemberController.java
@GetMapping("/members")
public String list(Model model) {
List<Member> members = memberService.findMembers();
model.addAttribute("members", members); // members에 모든 member 정보를 넘겨줌.
return "members/memberList";
}
회원 등록을 한 member들의 list를 받아 model의 members로 리스트 값을 넘겨준다. 그리고 나서 members/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> <!-- /container -->
</body>
</html>
여기서는 타임리프가 작동이 되는데, model에 넘겨준 members가 each를 통해 loop가 돌아 각 member의 값이 member에 넘어가 테이블의 열로 하나씩 추가된다.
위 회원 데이터는 memory에 저장되어 있기 때문에, 서버를 다시 시작하면 모두 사라지게 되므로, 서버를 재시작해도 등록한 회원정보를 계속 로드할 수 있게 데이터 베이스가 필요하다.
'Web > Spring' 카테고리의 다른 글
[Spring] H2 데이터베이스, 순수JDBC, JdbcTemplate, JPA (5) (0) | 2022.01.26 |
---|---|
[Spring] 스프링 부트 회원 관리 예제 (repository, service) (3) (0) | 2022.01.12 |