-
웹 계층 개발 - 회원 등록, 목록 조회JPA/JPA 활용 2023. 7. 11. 18:11
위의 사진은 강의를 들으면서 개발할 기능들이다. 회원가입을 하고 상품 등록을 하고 주문을 할 수 있는 웹 애플리케이션을 만들 것이다. 이번 포스팅에서는 회원가입을 할 수 있는 회원가입 폼을 만들 것이다.
html과 css 코드가 있긴 한데 스프링과 스프링부트, JPA를 공부하는 과정이기 때문에 프론트엔드 개발쪽은 직접 코드를 작성하지 않고 복사, 붙여넣기를 사용했다.
MemberController
@Controller @RequiredArgsConstructor public class MemberController { private final MemberService memberService; @GetMapping("/members/new") public String createForm(Model model) { model.addAttribute("memberForm", new MemberForm()); return "members/createMemberForm"; }
홈 화면에서 회원 가입 버튼을 누르면 http://localhost:8080/members/new로 이동하는 것으로 html을 작성해놨다. GetMapping을 통해 /members/new로 이동하고, 모델을 통해 model.addAttribute로 html에 MemberForm 객체를 넘겨주었다. return을 통해 members/createMemberForm으로 연결시켜주면 resource에 있는 templates에서 createMemberForm.html을 찾아서 해당 html을 연결시켜준다.
creatMemberForm.html
<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head th:replace="fragments/header :: header" /> <style> .fieldError { border-color: #bd2130; } </style> <body> <div class="container"> <div th:replace="fragments/bodyHeader :: bodyHeader"/> <form role="form" action="/members/new" th:object="${memberForm}" method="post"> <div class="form-group"> <label th:for="name">이름</label> <input type="text" th:field="*{name}" class="form-control" placeholder="이름을 입력하세요" th:class="${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control'"> <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect date</p> </div> <div class="form-group"> <label th:for="city">도시</label> <input type="text" th:field="*{city}" class="form-control" placeholder="도시를 입력하세요"> </div> <div class="form-group"> <label th:for="street">거리</label> <input type="text" th:field="*{street}" class="form-control" placeholder="거리를 입력하세요"> </div> <div class="form-group"> <label th:for="zipcode">우편번호</label> <input type="text" th:field="*{zipcode}" class="form-control" placeholder="우편번호를 입력하세요"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> <br/> <div th:replace="fragments/footer :: footer" /> </div> <!-- /container --> </body> </html>
createMemberForm이다. 내가 직접 짠 코드는 아니지만 간단히 요약을 하자면 타임 리프를 사용했고, th:object="${memberForm}"으로 memberForm의 객체에 th:field=*{city} 등으로 사용자가 화면에서 입력하는 것을 데이터에 넘길 수 있는 기능을 작동한다.
회원가입 버튼을 눌렀을 때 나오는 화면이다. 이름, 도시, 거리, 우편번호를 th:filed로 받아온다.
PostMapping으로 회원가입 완료
@PostMapping("/members/new") public String create(@Valid MemberForm form, BindingResult result) { // BindingResult는 valid에서 오류가 발생했을 때 오류를 가지고 동작을 해줄 수 있게 해줌 // 스프링이 MemberForm에 있는 message를 출력해줌 // 물론 thymeleaf로 html에서 에러 메세지 출력하게 해서 가능한거 if (result.hasErrors()) { return "members/createMemberForm"; } Address address = new Address(form.getCity(), form.getStreet(), form.getZipcode()); Member member = new Member(); member.setName(form.getName()); member.setAddress(address); memberService.join(member); return "redirect:/"; }
아까는 @GetMapping으로 /members/new에 연결했다. 하지만 이번에는 @PostMapping으로 연결한다. @GetMapping은 Get방식으로 페이지를 보여주는 기능이었다. @PostMapping이란 사용자가 페이지에서 값을 입력하고 버튼을 눌렀을 때의 동작을 Mapping하는 것이다. /members/new라는 페이지에서 버튼을 누르기 때문에 @PostMapping("/members/new")로 PostMapping이 진행된다.
일단 if문을 뒤로하고 보면 member을 만든 다음 name과 address를 set으로 입력하고 Service 계층에서 만들었던 join을 통해 member를 저장해주면 된다. return "redirect:/"가 되어있는데 redirect는 다시 보낸다는 뜻이고 / 로 보내는 것이기 때문에 회원 가입을 하면 홈화면으로 돌려보내 준다는 뜻이다. 그냥 화면을 이동시켜주는 것이 아니라 리다이렉트하는 것이다.
지금까지 설명해준 것은 memberForm의 조건에 부합해서 정상적으로 예외없이 회원가입될 때의 절차이다.
MemberForm
@Getter @Setter public class MemberForm { @NotEmpty(message = "회원 이름은 필수입니다") private String name; private String city; private String street; private String zipcode; }
위의 코드는 MemberForm객체인데, 여기에 name위에 @NotEmpty라는 애노테이션이 붙었다. 이 뜻은 이름은 무조건 공백이 될 수 없다는 뜻이다. 만약 이름을 공백으로 둔 상태에서 submit 버튼을 누르게 된다면 에러를 발생해야한다.
코드를 보면 파라미터안에 @Valid와 BindingResult가 들어가있다. 우선 Valid는 MemberForm에 있는 @NotEmpty처럼 조건이 있을 때 조건에 부합하는지 검증하는 애노테이션이다. NotEmpty가 있는데 회원 이름을 공백으로 두고 submit을 하게 된다면 검증에서 걸리게 된다. BindingResult는 valid에서 검증에 실패했을 때 검증을 가지고 에러 메시지를 출력하게 해준다. MemberForm에 message가 있는데, createMemberForm에 있는
th:class="${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control'">
<p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect date</p>에러 발생 코드로 인해서 MemberForm에 있는 메시지가 사용자에게 보여지는 것이다.
회원 목록 조회
회원 가입을 한 회원들의 목록을 조회하는 기능을 만들 것이다.
@GetMapping("/members") public String list(Model model) { List<Member> members = memberService.findMembers(); model.addAttribute("members", members); return "members/memberList"; }
코드는 간단한데, MemberService에서 findMembers를 한 다음, 그 객체를 모델에 넘겨주면 된다.
Service 계층에서 findMembers는 JPA를 이용해 모든 member를 찾아오는 기능이었다.
여기서 member 엔티티를 그대로 모델에 넘겨주었는데 이렇게하면 복잡한 프로젝트에서는 엔티티가 복잡해지기 때문에 실무에서 잘 사용하지 않는다고 한다. 회원 가입때 했던 것처럼 MemberForm 같은 컨트롤러 전용 DTO를 만들어서 엔티티를 그대로 보내는 것이 아니라 따로 만든 DTO로 변환해서 화면에 꼭 필요한 데이터들만 모델에 넘겨야한다.
첫 번째 회원을 가입시키고 회원 목록을 들어가보니 첫 번째 회원이 잘 나온 것을 확인할 수 있었다.
'JPA > JPA 활용' 카테고리의 다른 글
웹 계층 개발 - 상품 수정 (0) 2023.07.11 웹 계층 개발 - 상품 등록, 목록 조회 (0) 2023.07.11 주문 기능 테스트 (0) 2023.07.11 주문 리포지토리, 서비스 개발 (0) 2023.07.11 주문 도메인 개발 - 주문 로직 추가 (0) 2023.07.11