-
[Java] SpringBoot 프로젝트 : 회원가입 기능 구현 - 회원가입 폼(<form:form>, <form:input>, <form:errors>, validation)프로젝트/기능 정리 2023. 6. 28. 15:09
목적
- 게시판 형식 웹사이트 개발 시 회원가입 기능 구현 정리
- 아이디 중복확인, 비밀번호 확인, 이메일 인증번호 등 세부 기능 정리
두 번째 SpringBoot 프로젝트를 진행하면서 회원가입, 로그인 기능 구현을 맡았었다.
이전 프로젝트에서 다른 팀원이 진행했던 회원가입 기능 구현 코드를 거의 그대로 가져와서 이 프로젝트에 맞게 조금 변형하여 사용했는데,
이후 프로젝트를 위해 작성된 코드들을 하나씩 뜯어보고 리뷰해보도록 하겠다.
데이터 흐름은 다음과 같다.
[데이터 흐름도]
회원가입 데이터 흐름도 회원가입 과정에서 필수적인 두 가지가 있다.
하나는 아이디 중복체크이고, 또 하나는 이메일 본인인증이다.
추가로 전화번호 입력과 비밀번호 확인도 있지만 해당 부분들은 JS에서만 처리 가능하여 흐름도엔 넣지 않았다.
이후 다루게될 내용엔 모두 포함될 것이니 나중에 정리하도록 하자.
우선 중복확인 데이터 흐름은 다음과 같다(흐름도 좌측).
- 가입폼jsp에서 원하는 ID입력 후 중복확인 클릭시 작성한 ID가 js로 전달된다.
- ID를 전달 받은 js는 Ajax 처리를 통해 컨트롤러에 ID를 넘겨준다.
- 컨트롤러는 쿼리문에 ID를 넣어 DB 내 해당 ID로 가입된 계정이 있는지 확인한다.
- DB에서 해당 아이디가 있으면 해당 회원 정보를 리턴 받고 없으면 null을 받는다.
- 컨트롤러는 회원정보 유무에 따라 Ajax에 대한 응답으로 "found" 또는 "notFound"를 전달한다.
- js는 전달받은 응답값에 따라 jsp에 "가입된 아이디" 또는 "사용가능" 메시지를 화면에 표시한다.
이메일 인증 데이터 흐름은 다음과 같다(흐름도 우측).
- 가입폼jsp에서 원하는 이메일 입력 후 전송 클릭시 작성한 이메일이 js로 전달된다.
- 이메일을 전달 받은 js는 Ajax 처리를 통해 컨트롤러에 GET방식으로 이메일을 넘겨준다.
- 컨트롤러는 인증코드를 생성하고, 전달 받은 이메일, 메일 제목, key를 주입받은 서비스에 전달한다.
- 컨트롤러 : Ajax에 대한 응답으로 key를 리턴한다. / 서비스 : 이메일로 메일을 전송한다.
- 회원가입자가 메일을 통해 전달받은 key를 다시 입력하면 js는 가지고 있던 key와 일치여부를 확인한다.
- 일치 여부에 따라 화면에 "인증번호 일치" 또는 "인증번호 불일치" 메시지를 표시한다.
두 과정이 모두 완료되고, 기타 다른 정보가 모두 입력된 상태에서 회원가입 버튼을 누르면
최종적으로 form에 데이터가 모두 memberVO에 담겨 컨트롤러로 전달되고, DB 내 회원 테이블에 회원 데이터 한 행이 생성된다.
우선 최종적으로 완성한 폼을 먼저 보자면 다음과 같다.
회원가입 폼 [JSP]
디자인을 위해 사용한 div등은 제하고 코드를 살펴보자.
[form:form]
<form:form action="registerUser.do" id="register_form" modelAttribute="memberVO"> <ul> <li> <label for="mem_id"><small>아이디</small></label> <form:input path="mem_id" class = "align-left" autocomplete="off" placeholder = "아이디를 입력하세요"/> <input type="button" id="confirmId" class = "checkSome" value="중복체크"> <div id="message_id"></div> <form:errors path="mem_id" cssClass="error-color"/> <!-- 에러문구 --> </li> <!-- 이하 코드 생략-->
우선 Spring에서 제공하는 <form:form> 태그를 사용했다.
사용을 위해서 상단에 다음과 같이 입력해주면 된다.
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
각 파라미터를 설명해보자면 다음과 같다.
- action: 요청할 주소값
- id: 태그 ID
- modelAttribute: 이 폼에서 사용될 모델 객체 이름 지정 키
다른 옵션은 기본 HTML의 <form> 태그와 동일하지만 modelAttribute는 Spring <form:form>태그에서 제공하는 옵션이다.
참고 : https://www.baeldung.com/spring-mvc-form-tutorial
위 사이트에 Spring <form:form> 태그 튜토리얼이 있는데, 일부 설명을 가져와보겠다.
spring form tutorial - 1 위에서 말한대로 HTML의 <form>과 유사하지만 modelAttribute 속성은 아래 form의 모델 객체 이름을 명시하는 키라고 설명되어 있다.
그리고 저 키에 명시한 속성은 컨트롤러의 @ModelAttribute 어노테이션 값에 해당하는 것이다.
@ModelAttribute 어노테이션은 이전 글에서 설명한적이 있는데(여기), 클라이언트가 전달하는 값을 컨트롤러의 파라미터로 받을 때 사용한다고 보면 된다.
따라서 위와 같이 modelAttribute="memberVO"라고 적었다면, 폼을 전달 받는 컨트롤러는 아래와 같이 작성해야 한다.
@PostMapping("/member/registerUser.do") public String submit(@Valid MemberVO memberVO, BindingResult result, Model model) {
@Valid와 BindingResult는 실제 작성했던 코드를 복사해서 가져온 것이라 여기서는 무시해도 된다.
중요한 건 memberVO 이름이 일치해야 한다는 것이다.
혹은 아래와 같이 적어도 된다.
@PostMapping("/member/registerUser.do") public String submit(@ModelAttribute("memberVO") MemberVO vo, Model model) {
@ModelAttribute 어노테이션을 생략하지 않고 그 안에 <form:form>태그에 작성한 modelAttribute 값과 일치한 이름을 적어준 후, 아래 코드에서 사용할 변수명을 따로 선언해도 된다는 뜻이다.
[form:input]
다음은 아이디 부분인 <form:input> 태그를 보자.
나머지 태그는 기본 HTML 태그와 동일하니 넘어가고 해당 부분만 보면 다음과 같다.
<form:input path="mem_id" class = "align-left" autocomplete="off" placeholder = "아이디를 입력하세요"/>
이 태그에 대한 설명도 위에 제시한 튜토리얼 페이지 내용으로 보도록 하자.
spring form tutorial - 2 <form:form> 태그는 이하 입력 필드도 제공하는데 <form:input>, <form:password>, <form:select> 등과 같이 사용할 수 있다.
나머지 파라미터는 기본 HTML 태그 파라미터와 동일한 기능이나 위 태그를 사용할 땐 path를 지정해줘야한다.
이때 path는 모델 객체의 getter/setter에 대응되어야 한다.
위에서 보면 <form:input path="mem_id">로 지정되어 있는데 MemberVO 클래스를 보면 다음과 같이 선언되어있다.
public class MemberVO { private String mem_id; public String getMem_id() { return mem_id; } public void setMem_id(String mem_id) { this.mem_id = mem_id; } }
즉, VO에 선언한 프로퍼티 명과 path명이 같아야 한다는 의미다.
그 이유는 아래 설명을 보면 알 수 있다.
페이지가 로딩되면 Spring이 입력필드의 path와 일치하는 각 프로퍼티들의 getter를 호출해서, 값이 있으면 가져온다.
만약 form이 서버로 전송(submit)되면 setter를 호출해서, form의 값들을 모델 객체에 저장한다.
정리하면, Spring이 자동으로 path의 이름과 VO의 프로퍼티 이름이 같은 것을 찾아서, form에 지정된 입력 필드의 값을 프로퍼티에 저장하거나 프로퍼티에 저장된 값을 입력 필드에 꺼내오기 때문에 같은 이름으로 설정해야 한다는 것이다.
하지만 <form:form>태그를 사용했다고 이하 필드를 모두 <form:something>으로 할 필요는 없다.
이전 글에서 setter에 대해 설명하면서(여기) 필드 속성중 name에 대해 언급한 적이 있는데,
기본 HTML 태그를 사용하고 싶다면, name 속성명을 VO의 프로퍼티명과 동일하게 설정해줘도 잘 작동한다.
정확한 설명일진 모르겠지만, 결과를 통해 이유를 설명하자면 어차피 path에 입력한 값이 <input>태그의 id와 name 명으로 바뀌기 때문이다.
<form:input path="mem_id"> 위와 같이 path="mem_id"가 id="mem_id"와 name="mem_id"로 바뀐다.
[form:errors]
마지막으로 <form:errors> 태그가 있다.
<form:errors path="mem_id" cssClass="error-color"/> <!-- 에러문구 -->
이는 Validation error을 출력하기 위해 쓴 태그이다.
예를 들어, 회원의 아이디가 영문자 4~12자의 소문자와 숫자로만 이루어져야 한다고 할 때, 혹은 필수적으로 입력해야 하는 값일 때 등 입력 받는 값에 조건이 있는 경우가 있다.
물론 폼을 전송할 때 JS에서 처리할 수 있지만 validation을 이용하면 서버쪽에서 전송 받은 값을 검사하여 에러문구를 표시하거나 에러 페이지로 이동하도록 할 수 있다.
아무튼 이 validation 설정을 이용하면 적당한 요구사항이 충족되지 않았을 때 화면에 표시할 메시지를 미리 설정해 둘 수 있는데, 이 메시지를 받아서 표시하는 부분을 적어준게 <form:errors> 태그라고 할 수 있다.
path는 위에서 설명한 것과 동일한 역할을 한다.
여기서는 간단한 형태의 사용법만 알아보자(
작성은 되어 있지만, JS로 체크했다..).우선 기본적으로 프로젝트를 생성할 때 Validation을 추가해뒀으므로, pom.xml을 보면 아래와 같이 dependency가 추가되어 있다.
pom.xml - validation 추가적인 어노테이션을 위해 아래 dependency도 추가해준다.
pom.xml - hibernate 다음은 application.yml 또는 application.properties파일에 설청을 해줘야 한다.
application.yml 이 프로젝트는 spring 설정을 yml로 했기에 yml 파일을 보자. 아래와 같이 설정을 추가해주면 된다.
yml 설정 추가 프로젝트 소스에 보면 validation.properties 파일이 있는데, 그걸 열어준다.
validation.properties 원하는 어노테이션.프로퍼티명 = 에러문구 순으로 적어준다.
에러문구 프로퍼티가 선언된 VO에서 아래와 같이 적어준다.
public class MemberVO { @Pattern(regexp = "^[a-z0-9]{4,12}$") private String mem_id; //이하 생략
@Pattern 어노테이션 안에 이상한 문자들은 정규표현식이다.
해석하자면 ^는 문자 시작 $는 문자 끝을 표현하고, [a-z0-9]는 a~z, 0~9중 하나의 문자를 선택하겠다는 뜻이다.
{4,12}는 최소 4번에서 최대 12번 반복된다는 의미로, 앞에서 선택한 문자가 총 4글자에서 12글자까지만 된다는 뜻으로 해석하면 된다(한 개씩 4번 반복 ~ 12번 반복).
이제 컨트롤러에서 해당 VO를 받을 때 앞에 @Valid 어노테이션을 적어주고, 오류 검사를 위해 BindingResult를 선언해준다.
//등록 폼 호출 @GetMapping("/member/registerUser.do") public String form() { return "memberRegister"; } @PostMapping("/member/registerUser.do") public String submit(@Valid MemberVO memberVO, BindingResult result, Model model) {
이렇게 할 땐, 전송 받은 데이터 오류 시 다시 폼을 호출해줘야 하므로 GET과 POST 매핑을 따로 해두었다.
마지막으로 에러 검사를 아래와 같이 해주면 끝이다.
if(result.hasErrors()) { return form(); } //이하코드 생략
아이디 부분만 봤지만 나머지 부분도 동일한 방식으로 작성되어 있다.
jsp에서 가장 기본적으로 다루고 있는 <form:form> 태그에 대해 정리했고, 다음 글에서는 아이디 중복체크 과정을 다루도록 하겠다.
'프로젝트 > 기능 정리' 카테고리의 다른 글
[JavaScript] SpringBoot 프로젝트 : 회원가입 기능 구현 - 비밀번호 재확인, 전화번호 자동 하이픈(정규표현식) (0) 2023.07.01 [Java] SpringBoot 프로젝트 : 회원가입 기능 구현 - 아이디 중복확인 (0) 2023.06.29 [Java] SpringBoot 프로젝트 : 리스트 페이징 처리(5) - PagingUtil 클래스 (0) 2023.06.21 [Java] SpringBoot 프로젝트 : 리스트 페이징 처리(4) - 페이징 처리 수식 유도 (0) 2023.06.20 [Java] SpringBoot 프로젝트 : 리스트 페이징 처리(3) - DB에서 리스트 불러오기(Mapper.xml, Generics, ROWNUM) (2) 2023.06.17