본문 바로가기

JSP

[JSP] mySQL 사용자 정보 수정 시스템 구현

728x90

1. 사용자 정보 수정 시스템 구현

1.1. 로그인 체크 및 사용자 정보 조회

정보 수정 시스템의 첫 번째 단계는 사용자가 로그인한 상태인지를 확인하는 것입니다. 사용자가 로그인을 하지 않은 상태에서 접근을 시도하면, 이를 막고 로그인 페이지로 리디렉션해야 합니다. 이를 위해 세션 정보를 활용하여 userid가 있는지 확인하고, 없다면 2_login.jsp 페이지로 이동시키는 코드가 필요합니다.

if (session.getAttribute("userid") == null) {
    alert('로그인 후 이용하세요');
    location.href='./2_login.jsp';
}

로그인된 사용자의 경우, 데이터베이스에서 해당 사용자의 정보를 조회하여 수정 가능한 폼을 제공합니다. 예를 들어, userid를 기준으로 해당 사용자의 이름, 이메일, 연락처 등을 불러오고, 이를 폼에 미리 채워줍니다.

 

1.2. HTML 폼을 통한 정보 수정

정보 수정 화면에서는 사용자가 자신이 수정할 정보를 입력할 수 있는 폼을 제공합니다. 예를 들어, 이름, 휴대폰 번호, 이메일 주소, 취미 등을 수정할 수 있도록 합니다. HTML 폼에 각 정보를 입력할 수 있는 필드를 설정하고, 사용자가 데이터를 입력한 후 수정 완료 버튼을 눌러 데이터를 서버로 전송할 수 있도록 구성합니다.

<p>아이디 : <%=userid %></p>
<p>비밀번호 : <input type="password" name="userpw" id="userpw" maxlength="20"></p>
<p>이름 : <input type="text" name="name" id="name" value="<%=name %>"></p>
<p>휴대폰 번호 : <input type="text" name="hp" id="hp" value="<%=hp %>"></p>
<p>이메일 : <input type="text" name="email" id="email" value="<%=email %>"></p>

여기서 중요한 점은 사용자가 기존에 저장된 정보를 볼 수 있도록 하는 것입니다. 이를 통해 사용자는 정보 수정에 더 용이함을 느끼게 되며, 입력 실수를 줄일 수 있습니다.

 

2. 데이터 처리 및 수정 반영

2.1. 사용자 정보 수정 처리

사용자가 정보를 수정하고 제출하면, 서버에서는 이를 처리하기 위해 데이터를 받아옵니다. 예를 들어, 비밀번호, 이름, 이메일, 연락처 등의 수정된 정보를 서버로 전송하고, 이를 데이터베이스에 반영하는 과정이 필요합니다. 이 과정에서는 UPDATE SQL 쿼리를 사용하여 데이터베이스에 수정된 정보를 반영합니다.

sql = "update tb_member set mem_userpw=?, mem_name=?, mem_hp=?, mem_email=?, mem_hobby=?, mem_zipcode=?, mem_address1=?, mem_address2=?, mem_address3=? where mem_userid=?";

위 코드처럼 UPDATE 쿼리를 사용하여 데이터베이스에 정보를 반영하게 됩니다. 또한, 수정된 정보를 사용자가 다시 확인할 수 있도록 안내 메시지를 제공하는 것이 중요합니다.

2.2. 데이터 수정 후 사용자 피드백

정보 수정이 완료되면, 성공적인 수정에 대한 피드백을 사용자에게 제공해야 합니다. 사용자 경험을 향상시키기 위해, 성공적인 정보 수정 후 알림 메시지를 출력하고, 다시 정보 수정 페이지로 리디렉션하는 것이 좋습니다. 이를 통해 사용자는 자신이 입력한 정보가 반영되었음을 확인할 수 있습니다.

alert('회원정보 수정 성공');
location.href='2_info.jsp';

 

 

3. 정보 수정 시스템 최적화 및 개선

3.1. 사용자 경험(UX) 향상

정보 수정 시스템은 사용자가 웹사이트에서 가장 자주 사용하는 기능 중 하나입니다. 따라서 시스템의 직관성 및 편리성을 고려하여 사용자가 쉽게 정보를 수정하고 반영할 수 있도록 해야 합니다. 예를 들어, 주소 검색을 위한 우편번호 찾기 기능을 추가하거나, 잘못된 형식의 입력을 방지하는 유효성 검사를 강화하는 것이 좋습니다.

또한, 취미와 같은 여러 선택 항목은 체크박스를 활용하여 사용자가 쉽게 여러 항목을 선택할 수 있도록 돕습니다.

3.2. 보안 강화

회원 정보 수정 페이지에서는 사용자의 민감한 정보가 다뤄지기 때문에 보안 강화가 매우 중요합니다. 비밀번호 변경 시 반드시 암호화된 방식으로 처리해야 하며, 민감한 정보를 처리하는 모든 과정에서 보안에 신경을 써야 합니다. 또한, SQL 인젝션 공격을 방지하기 위해 준비된 문(PreparedStatement)을 사용하는 것이 좋습니다.

 


전체코드

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	if (session.getAttribute("userid") == null) {
%>
	<script>
		alert('로그인 후 이용하세요');	
		location.href='./2_login.jsp';
	</script>
<%	
	} else {
		//db 연결
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String sql = "";
		String url = "jdbc:mysql://localhost:3306/aiclass";
		String id = "root";
		String pw = "1234";

		String userid = (String)session.getAttribute("userid");
		String name = "";
		String hp  = "";
		String email = "";
		String hobby = "";
		String ssn1 = "";
		String ssn2 = "";
		String zipcode = "";
		String address1 = "";
		String address2 = "";
		String address3 = "";
		
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			conn = DriverManager.getConnection(url, id, pw);
			if (conn != null) {
				sql = "select mem_idx, mem_name, mem_hp, mem_email, mem_hobby, 
                mem_ssn1, mem_ssn2, mem_zipcode, mem_address1, mem_address2, mem_address3 
                from tb_member where mem_userid = ?";
				pstmt = conn.prepareStatement(sql);
				pstmt.setString(1, userid);
				rs = pstmt.executeQuery();
				
				if (rs.next()) {
					name = rs.getString("mem_name");
					hp = rs.getString("mem_hp");
					email = rs.getString("mem_email");
					hobby = rs.getString("mem_hobby");
					ssn1 = rs.getString("mem_ssn1");
					ssn2 = rs.getString("mem_ssn2");
					zipcode = rs.getString("mem_zipcode");
					address1 = rs.getString("mem_address1");
					address2 = rs.getString("mem_address2");
					address3 = rs.getString("mem_address3");
				}
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		
%>    
<!DOCTYPE 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">
    <title>정보수정</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" 
    integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous">
    </script>
    <script src="./js/info.js"></script>
    <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
    <script>
        function sample6_execDaumPostcode() {
            new daum.Postcode({
                oncomplete: function(data) {
                    // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.

                    // 각 주소의 노출 규칙에 따라 주소를 조합한다.
                    // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
                    var addr = ''; // 주소 변수
                    var extraAddr = ''; // 참고항목 변수

                    //사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
                    if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
                        addr = data.roadAddress;
                    } else { // 사용자가 지번 주소를 선택했을 경우(J)
                        addr = data.jibunAddress;
                    }

                    // 사용자가 선택한 주소가 도로명 타입일때 참고항목을 조합한다.
                    if(data.userSelectedType === 'R'){
                        // 법정동명이 있을 경우 추가한다. (법정리는 제외)
                        // 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
                        if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
                            extraAddr += data.bname;
                        }
                        // 건물명이 있고, 공동주택일 경우 추가한다.
                        if(data.buildingName !== '' && data.apartment === 'Y'){
                            extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
                        }
                        // 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
                        if(extraAddr !== ''){
                            extraAddr = ' (' + extraAddr + ')';
                        }
                        // 조합된 참고항목을 해당 필드에 넣는다.
                        document.getElementById("sample6_extraAddress").value = extraAddr;
                    
                    } else {
                        document.getElementById("sample6_extraAddress").value = '';
                    }

                    // 우편번호와 주소 정보를 해당 필드에 넣는다.
                    document.getElementById('sample6_postcode').value = data.zonecode;
                    document.getElementById("sample6_address").value = addr;
                    // 커서를 상세주소 필드로 이동한다.
                    document.getElementById("sample6_detailAddress").focus();
                }
            }).open();
        }
    </script>
    <script>
    	// db에 저장된 취미 체크박스 체크 표시
		$(document).ready(function() {
        	let hobby = '<%=hobby %>';
	       	let hobbyArr = hobby.split(' ');
		    for (let i in hobbyArr) {
		        $("input[name='hobby'][value=" + hobbyArr[i] + "]").prop("checked",true);
		    }
		});
	</script>
</head>
<body>
    <h2>정보수정</h2>
    <form action="./2_info_ok.jsp" method="post" name="regform" id="regform" onsubmit="return sendit()">
        <p>아이디 : <%=userid %></p>
        <p>비밀번호 : <input type="password" name="userpw" id="userpw" maxlength="20"></p>
        <p>비밀번호 확인 : <input type="password" name="userpw_re" id="userpw_re" maxlength="20"></p>
        <p>이름 : <input type="text" name="name" id="name" value=<%=name %>></p>
        <p>휴대폰 번호 : <input type="text" name="hp" id="hp" value=<%=hp %>></p>
        <p>이메일 : <input type="text" name="email" id="email" value=<%=email %>></p>
        <p>취미 : 
            <label>드라이브<input type="checkbox" name="hobby" value="드라이브"></label>
            <label>영화감상<input type="checkbox" name="hobby" value="영화감상"></label>
            <label>쇼핑<input type="checkbox" name="hobby" value="쇼핑"></label>
            <label>게임<input type="checkbox" name="hobby" value="게임"></label>
            <label>운동<input type="checkbox" name="hobby" value="운동"></label>
        </p>
        <p>주민등록번호 : <%=ssn1 %> - <%=ssn2 %></p>
        <p>우편번호 : 
	        <input type="text" name="zipcode" id="sample6_postcode" value=<%=zipcode %>> 
	        <input type="button" value="우편번호 검색" onclick="sample6_execDaumPostcode()">
        </p>
        <p>주소 : <input type="text" name="address1" id="sample6_address" value=<%=address1 %>></p>
        <p>상세주소 : <input type="text" name="address2" id="sample6_detailAddress" value=<%=address2 %>></p>
        <p>참고항목 : <input type="text" name="address3" id="sample6_extraAddress" value=<%=address3 %>></p>
        <p>
        	<input type="submit" value="수정완료"> 
        	<input type="reset" value="다시 작성"> 
        	<input type="button" value="뒤로가기" onclick="history.back()">
       	</p>
    </form>

</body>
</html>
<%
	}
%>

 

 

정보수정 js info.js

function sendit() {

    const userpw = document.getElementById('userpw');
    const userpw_re = document.getElementById('userpw_re');
    const name = document.getElementById('name');
    const hp = document.getElementById('hp');
    const email = document.getElementById('email');
    const hobby = document.getElementsByName('hobby');

    // 정규식
    const exNameText = /[가-힣]+$/; // 가 ~ 힣 글자수 제한 x $ : 끝.
    const exHpText = /^\d{3}-\d{3,4}-\d{4}$/;
    // d{3} : 10진수 3자리 - d{3,4} : 10진수 3자리 또는 4자리 - d{4} 10진수 4자리  d : decimal
    const exEmailText = /^[A-Za-z0-9\-\.]+@[A-Za-z0-9\-\.]+\.[A-Za-z0-9]+$/; 
    // ^ : 이 범위의 형태로 시작  A-Z, a-z, -, . 글자수 제한 x @포함 
    // @제외하고 특수문자 넣어야 할 경우 \+특수문자

    // 비밀번호
    if (userpw.value == '') {
        alert('비밀번호 입력하세요')
        userpw.focus();
        return false;
    }

    if (userpw.value.length < 4 || userpw.value.length > 20) {
        alert('비밀번호 4자 이상 20자 이하로 입력하세요');
        userpw.focus();
        return false;
    }

    // 비밀번호 확인
    if (userpw.value != userpw_re.value) {
        alert('비밀번호를 다시 확인해주세요')
        userpw_re.focus();
        return false;
    }

    // 이름
    if (!exNameText.test(name.value)) { //test() : 정규표현식에 대입한 문자열이 부합하면 true, 아니면 false
        alert('이름 형식을 확인하세요. \n한글만 입력 가능합니다.');
        name.focus();
        return false;
    }

    // 휴대폰번호
    if (!exHpText.test(hp.value)) {
        alert('휴대폰번호 형식을 확인하세요\n하이픈(-)을 포함해야 합니다.');
        hp.focus(); 
        return false;
    }

    // 이메일
    if (!exEmailText.test(email.value)) {
        alert('이메일 형식을 확인하세요.');
        email.focus(); 
        return false;
    }

    // 취미
    let count = 0;
    for (let i in hobby) {
        if (hobby[i].checked) {
            count++;
        }
    }

    if (count == 0) {
        alert('취미는 적어도 하나이상 선택하세요');
        return false;
    }


    return true;
}

 

정보수정 확인 페이지 2_info_ok.jsp

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	// 로그인 하지 않았을 경우 login.jsp로 이동
	if (session.getAttribute("userid") == null) {
%>
		alert('로그인 후 이용하세요');
		location.href="2_login.jsp";
<%		
	} else {
		// 데이터를 받음
		request.setCharacterEncoding("UTF-8");
		String userid = (String)session.getAttribute("userid");
		String userpw = request.getParameter("userpw");
		String name = request.getParameter("name");
		String hp = request.getParameter("hp");
		String email = request.getParameter("email");
		String hobby[] = request.getParameterValues("hobby"); 
		// 취미 여러개 저장
		String hobbyStr = "";
		for (int i = 0; i < hobby.length; i++) {
			hobbyStr = hobbyStr + hobby[i] + " ";
		}
		String zipcode = request.getParameter("zipcode");
		String address1 = request.getParameter("address1");
		String address2 = request.getParameter("address2");
		String address3 = request.getParameter("address3");

		//db 연결
		Connection conn = null;
		PreparedStatement pstmt = null;
		
		String sql = "";
		String url = "jdbc:mysql://localhost:3306/aiclass";
		String id = "root";
		String pw = "1234";
		
		
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			conn = DriverManager.getConnection(url, id, pw);
			if (conn != null) {
				// update를 사용하여 반영
				sql = "update tb_member set mem_userpw=?, mem_name=?, mem_hp=?, 
                mem_email=?, mem_hobby=?, mem_zipcode=?, mem_address1=?, mem_address2=?, 
                mem_address3=? where mem_userid=?";
				pstmt = conn.prepareStatement(sql);
				pstmt.setString(1, userpw);
				pstmt.setString(2, name);
				pstmt.setString(3, hp);
				pstmt.setString(4, email);
				pstmt.setString(5, hobbyStr);
				pstmt.setString(6, zipcode);
				pstmt.setString(7, address1);
				pstmt.setString(8, address2);
				pstmt.setString(9, address3);
				pstmt.setString(10, userid);
				pstmt.executeUpdate();
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	%>
		// 2_info.jsp로 이동
		<script>
			alert('회원정보 수정 성공');
			location.href='2_info.jsp';
		</script>	
<%
	}
%>

정보 수정 시스템은 사용자 편의성을 높이고, 사이트의 신뢰도를 증가시킬 수 있는 중요한 기능입니다. 이 글에서는 기본적인 정보 수정 시스템을 구현하는 방법에 대해 살펴보았고, 시스템을 개선할 수 있는 몇 가지 방법도 제안했습니다. 이를 통해 사용자가 쉽게 자신의 정보를 수정할 수 있도록 돕고, 사이트와의 지속적인 상호작용을 유도할 수 있습니다.

따라서, 정보 수정 페이지는 단순히 정보를 변경하는 기능을 넘어서, 사용자 경험을 개선하고 보안을 강화하는 중요한 요소로 작용합니다. 이를 잘 구현하면 사용자에게 더 나은 서비스를 제공할 수 있습니다.

728x90