본문 바로가기

백엔드 개발/SpringMVC

회원 가입 화면 작성하기

1. 회원 가입 화면  HTML 리뷰

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" />
    
    <!--Style 태그 이용해서 HTML 안에 CSS를 넣어줬다.-->
    <style>
        * { box-sizing:border-box; }

        form {
            width:400px;
            height:600px;
            display : flex;
            flex-direction: column;
            align-items:center;
            position : absolute;
            top:50%;
            left:50%;
            transform: translate(-50%, -50%) ;
            border: 1px solid rgb(89,117,196);
            border-radius: 10px;
        }

        .input-field {
            width: 300px;
            height: 40px;
            border : 1px solid rgb(89,117,196);
            border-radius:5px;
            padding: 0 10px;
            margin-bottom: 10px;
        }
        label {
            width:300px;
            height:30px;
            margin-top :4px;
        }

        button {
            background-color: rgb(89,117,196);
            color : white;
            width:300px;
            height:50px;
            font-size: 17px;
            border : none;
            border-radius: 5px;
            margin : 20px 0 30px 0;
        }

        .title {
            font-size : 50px;
            margin: 40px 0 30px 0;
        }

        .msg {
            height: 30px;
            text-align:center;
            font-size:16px;
            color:red;
            margin-bottom: 20px;
        }
        .sns-chk {
            margin-top : 5px; 
        }
    </style>
    <title>Register</title>
</head>
<body>

<!--form 태그 ->	사용자로부터 입력을 받아 백엔드에 제출하려면, 
     		     입력 받는 내용들 전부 form 태그로 감싸야 한다.-->

<form>
    <div class="title">Register</div>
    
    <!--에러 메세지가 뜨는 위치 id ="msg"인 div의 빈공간으로 에러 메세지가 들어옴-->
    <div id="msg" class="msg"> </div> 
    
    <!--label의 for은 레이블과 같이 묶일 input의 id를 치면 된다. 
    	근데 여기선 input들이 id 말고 다 class를 쓴다. 
        원래 for = "묶일 input의 id"로 레이블과 인풋을 서로 묶으면, 
        레이블 클릭 시 해당 input의 입력창이 눌러지도록 할 수 있다.-->
    <label for="">아이디</label>
    
    <!--input의 type은 입력 받을 값의 자료형을 설정하는 것이다. 
    	( text == 글자 숫자 // number == only 숫자만 )
        
        name ="A"에서 A는 해당 인풋에 사용자가 입력한 값과 같이 백엔드로 넘어간다.
        따라서 A는 해당 인풋을 설명할 수 있는 말이 들어가야 한다.
        
        placeholder는 입력 창 안 눌렀을 때 회색으로 희미하게 뜨는 글자이다. 
        해당 input을 어떻게 작성해야 하는지 가이드라인을 제시하는 것이 좋다.	-->
        
    <input class="input-field" type="text" name="id" placeholder="8~12자리의 영대소문자와 숫자 조합">
    <label for="">비밀번호</label>
    <input class="input-field" type="text" name="pwd" placeholder="8~12자리의 영대소문자와 숫자 조합">
    <label for="">이름</label>
    <input class="input-field" type="text" name="name" placeholder="홍길동">
    <label for="">이메일</label>
    <input class="input-field" type="text" name="email" placeholder="example@fastcampus.co.kr"> 
    <label for="">생일</label>
    <input class="input-field" type="text" name="birth" placeholder="2020/12/31">
    
    
    <!--sns-chk라는 클래스 div에 checkbox 태그들을 묶어 놨다.-->
    <div class="sns-chk">
    
    <!--label과 input을 id로 연결하지 않고, input을 label로 감싸서도 표현이 가능하다.
    	input의 type을 checkbox로 설정하면, 체크 박스가 나온다. 
        check box type에서 value는 버튼 내의 텍스트로 버튼 눌렀을 때, 해당 내용이 전송된다.-->
    
        <label><input type="checkbox" name="sns" value="facebook"/>페이스북</label>
        <label><input type="checkbox" name="sns" value="kakaotalk"/>카카오톡</label>
        <label><input type="checkbox" name="sns" value="instagram"/>인스타그램</label>
    </div>
    
    <!--button의 default type은 submit이다. submit을 누르면 
    	form 태그의 action에 적힌 목적지로 사용자가 적은 값들이 배달 된다.-->
    <button>회원 가입</button>
   </form> 
   
   
   <!--JS 부분: 에러 메세지를 띄우기 위해 존재한다.-->
   <script>
   <!-- 함수 선언 html form 내용 자체를 인수로 받음.-->
       function formCheck(frm) {
            
            <!--변수 msg 선언 setMessage의 매개 변수로서 이용-->
            var msg ='';

            if(frm.id.value.length<3) {
            	
                <!--id 길이가 3미만이면, 에러 띄우기(밑에 setMessage함수 존재)-->
                setMessage('id의 길이는 3이상이어야 합니다.', frm.id);
                return false;
            }

           return true;
       }

       function setMessage(msg, element){
       
       <!--	getElementById - id= "msg"인 태그를 찾는다. 
       		그 태그에 내용물로 ''내용을 넣는다. i태그는 아무 의미 없이 기울이는 태그-->
            document.getElementById("msg").innerHTML 
            = `<i class="fa fa-exclamation-circle">${msg}</i>`;


			<!--select() 함수는 값 입력이 잘못 되었을 때, 
            	에러 메세지 띄우고, 자동으로 잘못 입려된 요소가 선택되게 하는 함수이다.-->
            if(element) {
                element.select();
            }
       }
   </script>
</body>
</html>

해당 html의 화면

하지만 해당 HTML에 값을 채워서 내보냈다고 해도 작동하지 않는다.  왜냐하면 해당 문서의 form 태그에 값을 보낼 목적지와 요청 API가 뭔지 하나도 안 썼기 때문이다. 이를 안 썼을 때 목적지의 default는 자기 자신이고 REST - API는 GET이 된다. 

따라서 해당 내용을 써서 form 태그를 수정하다. 나는 요청 내용을 ch2의 registerinfo로 보낼 예정이다. 

또한 GET 요청은 요청 내용이 스트링 쿼리로 브라우저에 적히는 게 싫다 따라서 바디가 있는 POST로 API 요청을 바꾸겠다. 

   <form action = "/ch2/registerInfo.jsp" method = "POST" onsubmit="return formCheck(this)">

form 태그의 속성에는 onsumit이란 이벤트 등록 속성이 있다.

이벤트 등록이란 폼태그의 내용에 대해 어떠한 동작을 추가로 하도록 하는 것을 의미한다.

onsubmit = "return formcheck(this)" 란 formcheck란 함수를 작동시켜서 결과를 반환 하라는 뜻이고, this를 인수로 넣은 것은 현재 작성된 form을 함수의 인수로 넣겠다는 뜻이다. 

onsubmit = ture 일 경우 해당 폼을 목적지로 전송하고 false일 경우 전송하지 않는다. 

아이디 3글자 이상 안 썼을 때

--입력을 올바르게 해서 내용이 목적지로 넘어갔다고 해보자.

2. 전송된 내용을 받는  registerInfo.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>id=${param.id}</h1>
<h1>pwd=${param.pwd}</h1>
<h1>name=${param.name}</h1>
<h1>email=${param.email}</h1>
<h1>birth=${param.birth}</h1>
<h1>sns=${param.sns}</h1>

</body>
</html>


<!--param은 EL의 내부 객체이다.
	param.id는 name=id인 태그의 value를 가져오는 것이다.-->

결과값

이상한점 - 

내가 sns에 facebook, kakaotalk, instagram 다 체크해도 facebook만 뜬다. 

그 이유는

<h1>sns=${param.sns}</h1>

이와 같이 sns의 파라미터 변수를 하나만 설정 했기 때문이다. 이 경우, 맨 처음 값인 페이스북만 들어오고 나머지는 버려진다. 해당 부분은 다음과 같이 고친다. 

<!-- 먼저 sns라는 name의 input을 배열로 받는다. -->
<h1>sns=${paramValues.sns}</h1>

<!--배열을 순서대로 출력한다.-->
<h1>sns=${paramValues.sns[0]}</h1>
<h1>sns=${paramValues.sns[1]}</h1>
<h1>sns=${paramValues.sns[2]}</h1>

 

3. 스프링 컨트롤러를 이용, 백엔드 거쳐서 웹페이지가 작동하도록 하기

지금까지는 모두 HTML 문서 사이에서 왔다갔다 하였다. 

이렇게 하면, 결과 내용들을 데이터베이스의 저장 하는 등의 고차원 작업을 할 수 없다. 

지금 당장은 이런 고차원 작업을 하지 않겠지만 HTML 내용을 모두 JAVA 코드와 이어보자. 

 

(1) HTML 모두 JSP로 변환 

컨트롤러의 리턴값으로 html을 쓸 수 있긴 한데, 일단 편의상 전부 jsp로 바꾸자

HTML을 JSP로 바꾸려면 상단에 JSTL을 사용하겠다는 c tag library 선언과 인코딩을 뭘로 해야하는지 선언하는 내용을 적어야한다. 

<%@ page contentType="text/html;charset=utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

** 참고 ** 

확장자를 바로 html > jsp 로 바꾸면 한글이 다 깨질 수 있다. 

이 경우  preference > HTML files, Jsp files 의 인코딩이 utf-8이 아닌 다른 걸로 되어 있어서 이다. 이를 utf-8로 고쳐주면 된다. 

 

(2) 컨트롤러 등록 및 RequestMapping

package com.fastcampus.ch2;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller //ctrl + shift + o 누르면 자동 import
public class RegisterController {
	@RequestMapping("/register/add")
	public String register() {
		return "registerForm"; //WEB-INF/registerForm.jsp
	}

//registerForm의 action url value="/register/save" 로 바꿔주자. 

@RequestMapping("/register/save")	
public String save(){
	return "registerinfo";
	}
}

(3) 변환한 registerform.jsp 에서 변경해줘야할 내용 

<!--컨트롤러로 가도록 변경 이때 상대주소 적기보단 jstl 이용-->
<!--같은 말 action = /ch2/regoster/save-->

<!--왜 상대주소를 적기보단 jstl을 이용할까? 
	내용의 젤 앞대가리인 ch2를 context root라고 부른다. (내용물의 뿌리)
    해당 루트는 우리가 자바 파일을 다른 곳으로 옮기면 바뀔 수 있다. 
    바뀐 경우 상대주소로는 더 이상 열 수 없다. 
    따라서 context root를 안 적어도 되는 c:url value = "" 태그를 이용한다.-->

<form action = "<c:url value="/register/save"/>"


<!--msg El을 한번 더 ${}로 감싸주기-->
            document.getElementById("msg").innerHTML 
            = `<i class="fa fa-exclamation-circle"> ${'${msg}'}'</i>`;

<!--Why? 왜냐하면 자바스크립트6에서 나온 template literal이란 문법이 EL과 똑같음.
	그리고 ${msg}는 자바스크립트에서 쓸려고 넣어놓은 내용이다.
	하지만 해당 내용은 서버에서 EL에 의해 읽히고 사용되어 소진된다.
    왜냐하면 백엔드와 연결하므로서 내용이 먼저 서버에서 실행되고, 브라우저에서 실행되기 때문이다.
    (javaScript는 브라우저에서 실행)
    따라서 EL에 의해 읽혀서 소진되는 용으로 ${}로 감싸준다.-->

3. 스스로 해보기 (jsp 두 개 컨트롤러 다 지우고 다시 쓰기)

requestform 계속 하는데 안됐다. 오류 찾는데 1시간 반 걸렸다. 문제는 내가 글은 3이상 쓰라고 해놓고 글자 3개를 써놓고 왜 오류 구문이 안 뜨지 하고 찾고 있었다. 후 

컨트롤러까지는 완료