- node를 공부하며 간단한 웹서버(회원가입페이지) 만들기를 해보려고 합니다.
- node를 중심으로 웹페이지를 보여주고, DB에 저장,호출해 보려고 합니다.
- 먼저 view 부분인 html(이후 ejs)부분입니다.
- 크게 javascript, html, css 부분으로 나눌수 있습니다.
- 먼저 html 부분입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | <!DOCTYPE html> <html lang='ko'> <head> <meta charset='utf-8'/> <title>boards</title> <link rel="stylesheet" type="text/css" href="style/mycss2.css"> <script type="text/javascript" src="js/jquery-1.9.1.min.js"></script> <script type="text/javascript" src="js/myscript2.js"></script> </head> <body> <header></header> <div class = "body"> <form name="joinfrm" id="joinfrm" action="joinProc.do" method="post"> <input type="hidden" id="id_ch" name="id_ch" value="false"/> <input type="hidden" id="pass_ch" name="pass_ch" value="false"/> <input type="hidden" id="email_ch" name="email_ch" value="false"/> <input type="hidden" id="m_tel" name="m_tel" value=""/> <div class ="wrapper_table"> <div class="join_header"> <p>회원 가입</p> </div> <div class="join_body"> <dl> <div> <dt><label>User ID</label></dt> <dd><input id="m_id" name="m_id" type="text" size = "30" maxlength="10" name="m_id" id="m_id" placeholder="아이디"></dd> </div> <div class='arrow_box' id="id_notice"> <ul> <li><a class="notice" id="info_id1">* 영문 또는, 영문과 숫자의 조합으로 설정해주시기 바랍니다. </a></li> <li><a class="notice" id="info_id2">* 5자 이상 12자 이하로 설정 가능합니다.</a></li> </ul> </div> <div> <dt><label>PassWord</label></dt> <dd><input id="m_pass" name="m_pass" type="password" size = "30" maxlegnth="10" placeholder="비밀번호"></dd> </div> <div class='arrow_box' id="pass_notice"> <ul> <li><a class = "notice" id="info_pass1">* 영문과 숫자의 조합으로 설정해주시기 바랍니다.</li> <li><a class = "notice" id="info_pass2">* 8자 이상으로 설정 가능합니다.</a></li> </ul> </div> <dt><label>PassWord Check</label></dt> <dd><input id="m_pass_ch" name="m_pass_ch" type="password" size = "30" maxlength="10" placeholder="비밀번호 확인"></dd> <div class='arrow_box' id="pass_ch_notice" style="display:none;"> <ul> <li><a class = "notice" style="color:red;">비밀번호를 확인해 주세요.</a></li> </ul> </div> <dt><label>Name</label></dt> <dd><input id="m_name" name="m_name" type="text" size = "30" maxlength="10" placeholder="이름"></dd> <dt><label>Birth Date</label></dt> <dd><input id="m_date" name="m_date" type="date" min="1930-01-01" max='2010-12-31'></dd> <dt><label>Phone Number</label></dt> <dd class = "tel"><select id = "m_tel1" name ="tel1"><option selected>010</option> <option>011</option> <option>016</option> <option>017</option> <option>019</option> </select>  - <input id = "m_tel2" name ="m_tel2" type="text" minlength="3" maxlength="4" size="4" required/>  - <input id = "m_tel3" name ="m_tel3" type="text" maxlength="4" minlength="4" size="4" required/> </dd> <dt><label>Gender</label></dt> <dd><input id="m_gender" name="m_gender" type="radio" value="남" required>남</input>  <input name="m_gender" id="m_gender" type="radio" value="여"required>여</input></dd> <dt><label>Email</label></dt> <dd><input id="m_email" name="m_email" type="text" placeholder="E-mail"/></dd> <div class='arrow_box' id="email_notice" style="display:none;"> <ul> <li><a class = "notice" style="color:red;">이메일 형식이 맞지 않습니다.</a></li> </ul> </div> </dl> </div> <div class="join_footer"> <input type="button" value="가입" onclick="doSubmit()"> </div> </div> </form> </div> </body> </html> |
- table로 작성하려다가 여러 사이트의 회원가입 사이트를 구경하다가 '생활코딩'의 회원가입폼 소스를 뜯어보고 참조해서 만들었기 때문에 table이 아닌 div, dt,dd를 이용하여 만들어 봤습니다.
- 여기서 중요한 것은 전달되는 값들의 name값입니다. DB의 테이블의 컬럼값과 변수명을 통일하지 않는다면 나중에 node를 통하여 mysql로 값을 넘겨줄 경우 새로 맵핑해줘야 하는 번거로움이 발생합니다.
- form에서 전달하는 방법은 post로 해줘야 합니다. get으로 전송할 경우 인젝션에 취약해지기 때문입니다. 또한 통상적으로 값을 입력하고 수정,삭제하는 페이지로의 값 전송에 있어서는 post를 사용하고 단순히 값을 보여주는 페이지, 예로들어 게시판 글보기 페이지 같은 경우는 get을 이용하여 그 글에 대한고유 url을 만들어 줄 수 있기 때문에 get을 사용한다고 합니다.
- 단순한 html은 아무런 기능은 없으니 바로 css로 넘어가겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain) */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; } /*초기화 끝 css 시작*/ .body{ width: 1000px; margin: 0 auto; } table .label{ font-size: 1em; color : #aabbcc; } table .notice{ color: blue; font-size: 0.7em; display : none; } .wrapper_table{ margin: 50px auto; box-shadow :0 0 10px #bbb; /*border: 1px solid blue;*/ height: auto; text-align: center; width: 500px; } /*join_header*/ .wrapper_table .join_header{ background-color: #77b9cb; border-bottom: 1px solid #bbb; height: 50px; } .join_header p{ float: left; font-size: 1.2em; font-weight: bold; padding: 13px 0px 30px 13px; } /*join_body*/ .wrapper_table .join_body{ border-bottom: 1px solid #bbb; height: auto; text-align: center; padding: 0px 50px 20px 50px; } .join_body dt{ margin-top: 20px; height: 20px; text-align: left; } .join_body dt label{ font-size: 0.8em; color: #aaa; } .join_body dd input{ width: 360px; height: 40px; padding: 0 20px; font-size: 20px; } .join_body dd select{ font-size: 20px; width: 115px; height: 40px; } #m_tel2, #m_tel3{ width: 110px; height: 36px; padding : 0; } #m_gender{ width: 100px; } /*join_footer*/ .wrapper_table .join_footer{ height: 50px; text-align: center; } .join_footer input{ border: 0px; background: #3c9; width: 400px; height: 40px; margin: 5px; font-size: 20px; color: #ddd; } .arrow_box { margin-top:20px; position: relative; padding: 5px; background: #88b7d5; border: 4px solid #c2e1f5; text-align: left; } .arrow_box:after, .arrow_box:before { bottom: 100%; left: 50%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; } .arrow_box:after { border-color: rgba(136, 183, 213, 0); border-bottom-color: #88b7d5; border-width: 10px; margin-left: -180px; } .arrow_box:before { border-color: rgba(194, 225, 245, 0); border-bottom-color: #c2e1f5; border-width: 16px; margin-left: -186px; } .arrow_box a{ font-size:0.7em; } |
- 1~49번 라인은 css 초기화를 위한 문자으로 제일 처음 적어주게 됩니다.
- css 초기화를 하는 이유는 브라우저마다 padding, margin등의 기본값이 초금씩 다르기 때문입니다. 즉 모든 브라우저에서 디자인으로 보여질수 있도록 하기 위해서 입니다.
- .arrow 부분은 http://cssarrowplease.com/ 를 참조하여 작성하였습니다.
- 다음은 마지막 부분인 Javascript 부분,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | function atrim(str){ return str.replace(/\s/g,''); } function blankcheck(el,msg){ if(el.value==""){ alert(msg+"를(을) 입력해주세요."); el.focus(); return true; } if(el.value.length != atrim(el.value).length){ alert(msg+"에는 공백을 허용하지 않습니다."); el.focus(); return true; } } function doSubmit() { console.log("doSubmit"); if(blankcheck(joinfrm.m_id,'아이디') || joinfrm.id_ch.value == false) { return; } if(blankcheck(joinfrm.m_pass,'비밀번호') || joinfrm.pass_ch.value == false) { return; } if(blankcheck(joinfrm.m_pass_ch,'비밀번호')) return; if(blankcheck(joinfrm.m_name,'이름')) return; if(blankcheck(joinfrm.m_date,'날자')) return; if(blankcheck(joinfrm.m_tel1,'전화')) return; if(blankcheck(joinfrm.m_tel2,'전화')) return; if(blankcheck(joinfrm.m_tel3,'전화')) return; joinfrm.m_tel.value = joinfrm.m_tel1.value+"-"+joinfrm.m_tel2.value+"-"+joinfrm.m_tel3.value; if(blankcheck(joinfrm.m_gender,'성별')) return; if(blankcheck(joinfrm.m_email,'이메일' || joinfrm.email_ch.value == false)) return; joinfrm.submit(); } $(document).ready(function() { var check_Eng= /[a-z]|[A-Z]/; var check_Num= /[0-9]/; var check_Num_Eng= /[0-9]|[a-z]|[A-Z]/; var check_kor = /([^가-힣ㄱ-ㅎㅏ-ㅣ\x20])/i; var check_email = /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i; $("#m_id").change(function(){ joinfrm.id_ch.value = false; //id_ch 히든값 초기화 후 검사 시작 console.log('1. '+joinfrm.id_ch.value); // alert('id값 변경'); var id = joinfrm.m_id.value; var id_flag = false; if(id.match(check_Num_Eng) == null || id.match(check_Eng) == null){ /*if(!check_kor.test(id)){*/ $("#info_id1").css("color","red"); // alert('영문 또는 영문,숫자 조합을 사용하여야 합니다.'); id_flag = true; }else{$("#info_id1").css("color","blue");} if(id.length<5 || id.length >13){ $("#info_id2").css("color","red"); id_flag = true; }else{$("#info_id2").css("color","blue");} if(id_flag){ joinfrm.m_id.focus(); return; } joinfrm.id_ch.value = true; console.log('2. '+joinfrm.id_ch.value); }); $("#m_pass").change(function(){ joinfrm.pass_ch.value = false; // joinfrm.m_pass_ch.value = ""; //비밀번호 변경시 비밀번호 확인 칸 초기화 var pass = joinfrm.m_pass.value; // alert("포커스 아웃 " + pass); var pass_flag = false; if(pass.match(check_Num_Eng) == null || pass.match(check_Num) == null || pass.match(check_Eng) == null){ // alert("패스워드 잘못됨"); $("#info_pass1").css("color","red"); pass_flag = true; }else{$("#info_pass1").css("color","blue");} if(pass.length<8){ $("#info_pass2").css("color","red"); pass_flag = true; }else{$("#info_pass2").css("color","blue");} if(pass_flag){ joinfrm.m_pass.focus(); return; } joinfrm.pass_ch.value = true; console.log(pass); }); $("#m_pass_ch").change(function() { alert("ㅎㅇ"); joinfrm.pass_ch.value = false; if(joinfrm.m_pass_ch.value != joinfrm.m_pass.value){ alert("ㅎㅇ"); $("#pass_ch_notice").css("display","block"); joinfrm.m_pass_ch.focus(); return; } $("#pass_ch_notice").css("display","none"); joinfrm.pass_ch.value = true; }); $("#m_email").change(function(){ joinfrm.email_ch.value = false; if(!joinfrm.m_email.value.match(check_email)){ $("#email_notice").css("display","block"); joinfrm.m_email.focus(); return; } $("#email_notice").css("display","none"); joinfrm.email_ch.value = true; }); }); |
- 1~3번 Line : 공백에 대한 유효성검사를 위해서 만들어 봤습니다. 변수의 공백을 없애고 그 값을 반환합니다.
- 4~10번 Line : 빈칸에 대한 검사를 하고 atrim함수를 호출하여 공백에대한 유효성 검사도 같이합니다.
- 16~50번 Line : html 아래 부분의 버튼을 눌렀을 경우 호출하며 위의 유효성 검사 함수를 호출하여 실행합니다.
- 52번~ : 아이디, 비밀번호, 이메일에 대한 유효성 검사를 위해서 jquery의 change함수를 이용하여 구현해봤습니다. 이 부분에 대한 유효성은 정규표현식을 이용하였습니다.
혹시 52~ 부분에서도 유효성을 통과하지 못하면 submit 되지 못하게 할 수는 없을까요?
답글삭제늦었어요!
삭제상태값을 바깥쪽에 하나 두어서 change가 이루어질때마다 false로 만들어주고 1번라인부터 적혀진 부분에서 체크를 하고 넘기면 되겠죠?
세개 페이지 다 만들었는데 실행은 어떻게 하나요?..제가 아직 잘 몰라서ㅠㅠ 답변 부탁드립니다..
답글삭제3개 게시물 다 하셨다는거면 콘솔로 node.js 위치에서 "npm start" 또는 "node ./bin/www" 로 실행하셔서 127.0.0.1:3000/member/join으로 접속하시면됩니다.
삭제이 게시물의 3개 파일만 작성하셨다면, 그냥 html파일을 여시면 될겁니다.