728x90
반응형
💡 이전 내용
UserDetails 인터페이스를 활용하여 로그인 기능을 구현하였습니다.
이번 게시글에서는 회원가입 화면을 생성하고, 회원 가입 기능을 구현하겠습니다.
💻 화면 구현
회원 가입 화면은 다음과 같이 부트스트랩기반의 MDB에서 제공하는 화면을 사용하였습니다.
1. 회원 가입 화면
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>회원가입</title>
<!-- Bootstrap -->
<th:block th:replace="board2/fragments/config :: configFragment"> </th:block>
<!-- Style CSS -->
<link rel="stylesheet" th:href="@{/css/signup.css}"/>
</head>
<body>
<section class="vh-100 bg-image"
style="background-image: url('https://mdbcdn.b-cdn.net/img/Photos/new-templates/search-box/img4.webp');">
<div class="mask d-flex align-items-center h-100 gradient-custom-3">
<div class="container h-100">
<div class="row d-flex justify-content-center align-items-center h-100">
<div class="col-12 col-md-9 col-lg-7 col-xl-6">
<div class="card" style="border-radius: 15px;">
<div class="card-body p-5">
<h2 class="text-uppercase text-center mb-5">Create an account</h2>
<form method="post" th:object="${accountDto}">
<div class="form-outline mb-4">
<label class="form-label" for="form3Example1cg">Your Name</label>
<input type="text" id="form3Example1cg" class="form-control form-control-lg" th:field="*{korName}" th:errorclass="custom-invalid-input"/>
<div class="custom-invalid-feedback">
<span th:if="${#fields.hasErrors('korName')}" th:errors="*{korName}"></span>
</div>
</div>
<div class="form-outline mb-4">
<label class="form-label" for="form3Example3cg">Your ID (Email)</label>
<input type="email" id="form3Example3cg" class="form-control form-control-lg" th:field="*{userId}" th:errorclass="custom-invalid-input"/>
<div class="custom-invalid-feedback">
<span th:if="${#fields.hasErrors('userId')}" th:errors="*{userId}"></span>
</div>
</div>
<div class="form-outline mb-4">
<label class="form-label" for="form3Example4cg">Password</label>
<input type="password" id="form3Example4cg" class="form-control form-control-lg" th:field="*{password}" th:errorclass="custom-invalid-input"/>
<div class="custom-invalid-feedback">
<span th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span>
</div>
</div>
<div class="form-outline mb-4">
<label class="form-label" for="form3Example4cdg">Repeat your password</label>
<input type="password" id="form3Example4cdg" class="form-control form-control-lg" th:field="*{confirmPassword}" th:errorclass="custom-invalid-input"/>
<div class="custom-invalid-feedback">
<span th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}"></span>
</div>
</div>
<div class="form-check d-flex justify-content-center mb-5">
<input id="form2Example3cg" type="checkbox" class="form-check-input me-2" value=""/>
<label class="form-check-label" for="form2Example3cg">
I agree all statements in <a href="#" class="text-body"><u>Terms of service</u></a>
</label>
</div>
<div class="d-flex justify-content-center">
<button type="submit" class="btn btn-success btn-block btn-lg gradient-custom-4 text-body">Register</button>
</div>
<p class="text-center text-muted mt-5 mb-0">Have already an account?
<a th:href="@{/login}" class="fw-bold text-body"><u>Login here</u></a>
</p>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</body>
</html>
.custom-invalid-input {
border-color: #dc3545;
padding-right: calc(1.5em + 0.75rem);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right calc(.375em + .1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
}
.custom-invalid-feedback {
margin-top: 0.25rem;
font-size: .875em;
color: #dc3545;
}
양식 유효성 체크는 부트스트랩 클래스를 활용하려고 하였으나,
클래스 적용 시 글자가 보이지 않아서 style을 가져와서 적용하였습니다.
2. 화면 호출, 회원 가입 기능
Controller에 다음 코드를 추가하여 "/signup" URL로 접근시 회원가입 화면을 보여주고,
"/signup" 화면에서 양식 전송 시, 회원을 등록하는 기능을 구현하겠습니다.
@Slf4j
@Controller
@AllArgsConstructor
public class AccountController {
private final AccountService accountService;
private final SignUpValidator signUpValidator;
@GetMapping("/signup")
public String signup(Model model){
model.addAttribute("accountDto", new AccountDto());
return "account/signup";
}
@PostMapping("/signup")
public String signup(@ModelAttribute("accountDto") AccountDto accountDto, BindingResult result){
signUpValidator.validate(accountDto, result);
if(result.hasErrors()) {
log.info("ERROR : {}", result.getAllErrors());
return "account/signup";
}
accountService.join(accountDto);
return "redirect:/login";
}
}
3. 사용자 입력 유효성 확인
유효성 확인은 Spring Boot Validation 을 사용하였습니다.
먼저 build.gradle에 의존성을 추가합니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
}
@Component
@RequiredArgsConstructor
public class SignUpValidator implements Validator {
private final PasswordEncoder passwordEncoder;
@Override
public boolean supports(Class<?> clazz) {
return false;
}
@Override
public void validate(Object target, Errors errors) {
AccountDto dto = (AccountDto) target;
String strPasswordPattern = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,}$";
if(ObjectUtils.isEmpty(dto.getKorName())) {
errors.rejectValue("korName", "message.korName.required", "별명을 입력해 주세요.");
}
if(ObjectUtils.isEmpty(dto.getUserId())) {
errors.rejectValue("userId", "message.userId.required", "아이디를 입력해 주세요.");
}
if(ObjectUtils.isEmpty(dto.getPassword())) {
errors.rejectValue("password", "message.password.required", "비밀번호를 입력해 주세요.");
}
else if(!dto.getPassword().matches(strPasswordPattern)) {
errors.rejectValue("password", "message.password.required", "영문자,숫자,특수기호 포함 8자 이상입력해주세요.");
}
else if(!dto.getPassword().equals(dto.getConfirmPassword())){
errors.rejectValue("password", "message.password.mismatched", "비밀번호가 일치하지 않습니다.");
}
if(ObjectUtils.isEmpty(dto.getConfirmPassword())) {
errors.rejectValue("confirmPassword", "message.confirmPassword.required", "비밀번호 확인란을 입력해 주세요.");
}
}
}
Validator에서 error발생시, BindingResults에 전달되고,
th:errors="*{korName}" 를 통해 오류 메세지가 화면에 보여집니다.
728x90
반응형
'Web 개발 > 게시판 만들기' 카테고리의 다른 글
[JPA] 게시글 작성자만 수정하게 하기(1) (0) | 2022.09.04 |
---|---|
[Spring Security/Thymeleaf] 로그인 기능 구현 (4) Role 설정 (0) | 2022.08.30 |
[Spring Security] 로그인 기능 구현 (3) 로그인 기능 확장 (0) | 2022.08.26 |
[Spring Security] 로그인 기능 구현 (1) Spring Security Authentication (0) | 2022.08.25 |
[Thymeleaf/Bootstrap5] 게시판 댓글 조회 및 수정 화면 구현 - 실패 (0) | 2022.08.24 |