공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.
홈 화면과 레이아웃
1. homecontroller
HomeController는 웹 애플리케이션의 홈 화면을 처리하는 컨트롤러이다. 사용자가 루트 경로인 /에 접근하면 홈 화면이 표시되며, 로그를 통해 접근을 기록한다.
package jpabook.jpashop.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@Slf4j
public class HomeController {
@RequestMapping("/")
public String home() {
log.info("home controller");
return "home";
}
}
2. 홈 화면 (home.html)
홈 화면은 Thymeleaf 템플릿을 사용하여 구성된다. 화면 상단에는 사이트의 내비게이션이 표시되며, 회원 기능, 상품 기능, 주문 기능을 제공하는 버튼들이 배치되어 있다. 각각의 버튼을 클릭하면 해당 기능 페이지로 이동할 수 있다.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="~{fragments/header :: header}">
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<div class="container">
<div th:replace="~{fragments/bodyHeader :: bodyHeader}"/>
<div class="jumbotron"><h1>HELLO SHOP</h1>
<p class="lead">회원 기능</p>
<p>
<a class="btn btn-lg btn-secondary" href="/members/new">회원 가입</a>
<a class="btn btn-lg btn-secondary" href="/members">회원 목록</a></p>
<p class="lead">상품 기능</p>
<p>
<a class="btn btn-lg btn-dark" href="/items/new">상품 등록</a>
<a class="btn btn-lg btn-dark" href="/items">상품 목록</a></p>
<p class="lead">주문 기능</p>
<p>
<a class="btn btn-lg btn-info" href="/order">상품 주문</a> <a class="btn btn-lg btn-info" href="/orders">주문
내역</a>
</p></div>
<div th:replace="~{fragments/footer :: footer}"/>
</div> <!-- /container -->
</body>
</html>
3. 헤더 (header.html)
헤더는 사이트 전체에 걸쳐 공통적으로 사용되는 상단 네비게이션 바를 정의한다. 여기에는 사이트의 기본적인 정보와 브라우저 창 크기에 맞게 반응하는 meta 태그가 포함되어 있다. 또한, 외부 CSS 파일 (부트스트랩)을 불러와 웹사이트의 스타일을 정의한다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="header">
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="/css/bootstrap.min.css">
<!-- Custom styles for this template -->
<link href="/css/jumbotron-narrow.css" rel="stylesheet">
<title>Hello, world!</title>
</head>
4. 푸터 (footer.html)
푸터는 페이지 하단에 표시되며, 사이트의 저작권 정보를 담고 있다. 사이트의 버전이나 간단한 저작권 문구가 포함되어 있다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="footer" th:fragment="footer">
<p>© Hello Shop V2</p>
</div>
5. 바디 헤더 (bodyHeader.html)
바디 헤더는 사이트 내에서 페이지 상단에 위치한 헤더 부분을 구성하며, 주요 내비게이션 링크를 포함한다. 이 부분은 "Home"으로 이동할 수 있는 버튼을 포함하여 사용자가 쉽게 홈으로 돌아갈 수 있도록 돕는다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="header" th:fragment="bodyHeader">
<ul class="nav nav-pills pull-right">
<li><a href="/">Home</a></li>
</ul>
<a href="/"><h3 class="text-muted">HELLO SHOP</h3></a>
</div>
6. 레이아웃 적용 후 홈 화면 실행 결과
아래 화면은 회원, 상품, 주문 기능을 빠르게 접근할 수 있도록 구성되어 있으며, 직관적인 레이아웃을 통해 사용자가 쉽게 탐색할 수 있다.
회원 등록
1. build.gradle 설정
build.gradle 파일에서 Hibernate Validator를 추가하여 폼 데이터에 대한 유효성 검증을 수행할 수 있다. 이를 통해 입력값에 대한 검증 로직을 간단하게 처리할 수 있다. 특히, 회원 이름과 같은 필수 입력 항목에 대한 유효성 검사를 할 때 유용하다.
// Hibernate Validator 추가 (Bean Validation)
implementation 'org.hibernate.validator:hibernate-validator:8.0.0.Final'
implementation 'jakarta.validation:jakarta.validation-api:3.0.2'
- 이 두 가지 의존성을 추가하면 Bean Validation을 사용할 수 있게 된다.
- hibernate-validator는 Hibernate가 제공하는 유효성 검사 기능이며, jakarta.validation-api는 검증을 위한 표준 API를 제공한다.
- 이를 통해 @NotEmpty, @Valid와 같은 어노테이션을 활용하여 폼 데이터의 유효성을 쉽게 관리할 수 있다.
2. MemberForm
MemberForm 클래스는 회원 가입 폼의 데이터를 담는 DTO(Data Transfer Object) 역할을 한다. 이 클래스는 유효성 검증을 위한 어노테이션을 사용하여 입력값을 제어한다. 특히 @NotEmpty 어노테이션을 통해 이름 필드가 반드시 입력되도록 강제한다.
package jpabook.jpashop.controller;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotEmpty;
@Getter
@Setter
public class MemberForm {
@NotEmpty(message = "회원 이름은 필수 입니다.")
private String name;
private String city;
private String street;
private String zipcode;
}
3. MemberController
유효성 검사는 MemberController에서 처리되며, 사용자가 입력한 데이터가 유효하지 않을 경우 폼으로 다시 돌아가 오류 메시지를 출력한다. 이 과정에서 BindingResult를 통해 오류를 확인하고, 문제가 있을 경우 다시 입력 폼으로 돌려보낸다.
package jpabook.jpashop.controller;
import jakarta.validation.Valid;
import jpabook.jpashop.domain.Address;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@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";
}
@PostMapping("/members/new")
public String create(@Valid MemberForm form, BindingResult result) {
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:/";
}
}
- @Valid 어노테이션은 MemberForm 객체의 유효성을 검증하며, 오류가 발생하면 해당 오류 메시지를 사용자가 볼 수 있도록 설정된다.
4. 회원 등록 화면 (createMemberForm.html)
이 페이지는 회원 등록을 위한 화면을 구성하는 HTML 파일이다. 사용자로부터 이름, 도시, 거리, 우편번호 등의 정보를 입력받고, 이를 서버로 제출하기 위한 폼을 제공한다.
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/header :: header"/>
<style>
.fieldError {
border-color: #bd2130;
}
.errorMessage {
color: #bd2130;
font-size: 0.9em;
margin-top: 5px;
}
</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"
th:class="${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control'"
placeholder="이름을 입력하세요">
<p th:if="${#fields.hasErrors('name')}"
th:errors="*{name}" class="errorMessage">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>
5. 실행화면
회원가입 버튼을 클릭하면 아래와 같은 회원 가입 폼이 나타난다. 사용자는 이름, 도시, 거리, 우편번호를 입력할 수 있다.
- 이름 미입력 시: 이름은 필수 입력 항목으로 설정되어 있으며, 입력하지 않을 경우 memberForm에서 유효성 검사를 통해 "회원 이름은 필수입니다."라는 오류 메시지가 빨간색으로 표시된다.
정상 입력 후 제출
모든 필드를 올바르게 입력한 후 Submit 버튼을 누르면 POST 메서드를 통해 서버로 데이터가 전송된다. 이때 회원 정보는 데이터베이스에 저장되며, 저장된 회원 정보는 추후 회원 목록에서 확인할 수 있다.
이를 통해 폼이 정상적으로 동작하며, Hibernate Validator를 사용한 유효성 검사를 통과한 데이터만 데이터베이스에 저장된다.
'BackEnd > JPA' 카테고리의 다른 글
[JPA] 웹 계층 개발(3) (0) | 2024.10.05 |
---|---|
[JPA] 웹 계층 개발(2) (0) | 2024.10.05 |
[JPA] 주문 도메인 개발 (3) | 2024.10.03 |
[JPA] 상품 도메인 개발 (0) | 2024.10.03 |
[JPA] 회원 도메인 개발 (0) | 2024.10.02 |