JAVA

스프링부트 블로그 만들기 – 유효성 검사

blog app

스프링부트 블로그 만들기 – 유효성 검사

유효성 검사

1.user와 board 테이블의 칼럼에 제약 조건을 추가한다.
package com.cos.blogapp.domain.user;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class User {
  @Id 
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id; 
  @Column(nullable = false, length = 20, unique = true) 
  private String username;
  @Column(nullable = false, length = 20)
  private String password;
  @Column(nullable = false, length = 50)
  private String email;
  
}
package com.cos.blogapp2.domain.board;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.ManyToAny;

import com.cos.blogapp2.domain.user.User;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Table(name = "board")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@Entity
public class Board {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id;
  
  @Column(nullable = false, length = 70)
  private String title;
  
  @Lob
  private String content;
  
  @JoinColumn(name = "userId")
  @ManyToOne(fetch = FetchType.EAGER)
  private User user;
  
}

nullable = false : 무조건 username 받도록 만들기

length = 20 : 20글자로 제외

unique = true : 중복 제한

위 코드를 적용하기 위해서는 .yml 파일에서 ddl-auto : create를 만들어 줘야합니다. 동일한 데이터로 회원가입이 가능한지 확인해 보세요.

QA(Quality Assurance)는 품질 보증이라는 의미로 프로그램이 잘 돌아가는 지 확인하는 일을 한다.

2.Dto에서 회원가입과 로그인 그리고 글쓰기 제약조건을 만들어준다.
package com.cos.blogapp.web.dto;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import com.cos.blogapp.domain.user.User;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class JoinReqDto {
  
  @Size(min = 2, max = 20)
  @NotBlank //java validation
  private String username;
  
  @Size(min = 4, max = 20)
  @NotBlank 
  private String password;
  
  @Size(min = 4, max = 50)
  @NotBlank 
  private String email;
  
  public User toEntity() {
    User user = new User();

    user.setUsername(username);
    user.setPassword(password);
    user.setEmail(email);
    
    return user;
  }
}
package com.cos.blogapp.web.dto;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginReqDto {
  
  @Size(min = 2, max = 20)
  @NotBlank 
  private String username;
  
  @Size(min = 4, max = 20)
  @NotBlank 
  private String password;
  
  
}
package com.cos.blogapp.web.dto;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import com.cos.blogapp.domain.board.Board;
import com.cos.blogapp.domain.user.User;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BoardSaveReqDto {
  
  @Size(min = 1, max = 50)
  @NotBlank 
  private String title;
  private String content;
  
  public Board toEntity(User principal) {
    Board board = new Board();
    board.setTitle(title);
    board.setContent(content);
    board.setUser(principal);
    return board;
  }
  
}
프론트에서도 input 태그 내에 maxlength를 걸어주면 제약을 걸 수 있는데 서버에서도 한번 더 제약을 걸어주는 이유는 외부에서 데이터를 입력하는 것을 막기위해서 입니다.
3.임시로 사용할 에러 페이지를 하나 만들어준다.
<error.jsp>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>에러 터졌어요!!</h1>
${errorMap}
</body>
</html>
여기까지 만든 부가기능은 view/error/error.jsp에서 불러왔습니다. 하지만 사용자 경험(UX)를 좋게하기 위해서 오류 메시지를 보여줄 때 페이지 이동을 시키지 않고 알림창만 뜨도록 만드는 것이 좋습니다.
blog app
스프링부트 블로그 만들기 - 사용자 경험프로그램을 만들 때 핵심기능을 만들기 전후로 부가기능을 추가해줘야 한다. 핵심기능을 부가기능과 분리시켜 함수로 만들어 재사용하면 아주 편하게 코딩을 할 수 있다. 하지만 함수로 만들기 위한 공통 로직을 찾는 것은 결코 쉬운 일이 아니다....
4.회원가입과 로그인 그리고 글쓰기 메서드에서 유효성 검사후 에러페이지로 이동하게 만든다.
@PostMapping("/join")
  public String join(@Valid JoinReqDto dto, BindingResult bindingResult, Model model) {
    
    //유효성 검사 실패
    if(bindingResult.hasErrors()) {
      Map<String, String>errorMap = new HashMap<>();
      for(FieldError error : bindingResult.getFieldErrors()) {
        errorMap.put(error.getField(),error.getDefaultMessage());
      }
      model.addAttribute("errorMap",errorMap);
      return "error/error";
    }

    //유효성 검사 성공 
    //비밀번호 해시로 변경
    String encPassword = SHA.encrypt(dto.getPassword());
    dto.setPassword(encPassword);
    User user = dto.toEntity();
    userRepository.save(user);
    return "redirect:/loginForm";

  }
@PostMapping("/login")
  public String login(@Valid LoginReqDto dto, BindingResult bindingResult, Model model) {

    //유효성 검사 실패
    if (bindingResult.hasErrors()) {
      Map<String, String> errorMap = new HashMap<>();
      for (FieldError error : bindingResult.getFieldErrors()) {
        errorMap.put(error.getField(), error.getDefaultMessage());
      }
      model.addAttribute("errorMap", errorMap);
      return "error/error";
    }

    //유효성 검사 성공 
    String encPassword = SHA.encrypt(dto.getPassword());
    User principal = userRepository.mLogin(dto.getUsername(), encPassword);

    if (principal == null) {
      return "redirect:/loginForm";
    } else {
      session.setAttribute("principal", principal);
      return "redirect:/";
    }
  }
@PostMapping("/board")
public String save(@Valid BoardSaveReqDto dto, BindingResult bindingResult, Model model) {

  // 글쓰기 유효성 검사
  User principal = (User) session.getAttribute("principal");
  if (principal == null) {
    // 로그인이 되지 않은 상태에서 글쓰기한 경우
    return "error/error";
  }
  
  //유효성 검사 실패 
  if (bindingResult.hasErrors()) {
    Map<String, String> errorMap = new HashMap<>();
    for (FieldError error : bindingResult.getFieldErrors()) {
      errorMap.put(error.getField(), error.getDefaultMessage());
    }
    model.addAttribute("errorMap",errorMap);
    return "error/error";
  }

  //유효성 검사 성공 
  boardRepository.save(dto.toEntity(principal));
  return "redirect:/";
}

 

테스트할 때는 jsp파일에서 input 태그 안에 required를 제거한 후에 해보세요!
회원가입 유효성 검사 실패 했을 경우 결과 화면
error
로그인 유효성 검사 실패 했을 경우 결과 화면
error
글쓰기 유효성 검사 실패 했을 경우 결과 화면
<로그인 하지 않고 글쓰기한 경우>
error
<제목을 쓰지 않고 글쓰기한 경우>
error

 

최신글