프로젝트/Staffriends 프로젝트

[Staffriends 프로젝트] (1) 회원 CRUD 구현하기 - 3. 회원 정보 수정

sungw00 2023. 5. 22. 16:10
728x90

정보 수정

회원 정보 수정을 위해서는 현재 로그인 한 회원의 정보를 페이지에 출력해준 후 다시 HTML 태그의 FORM 형식으로 입력받을 필요가 있다. 그래서 유효성 검증을 했다면 이를 다시 진행해주어야 하고, DB에는 새로 변경된 정보로 다시 update하여 변경된 회원에 대한 정보를 업데이트 시켜주어야 한다.

 

1. UserController 작성

package board.controller;

import board.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import board.vo.UserVo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/user")
    public class UserController {

    @GetMapping("/updateForm") // 정보수정 페이지
    public String updateForm() {
        return "/user/updateForm";
    }

    @PostMapping("/updateProc") // 정보 업데이트
    @ResponseBody
    public void updateUser(@RequestBody UserVo userVo) throws Exception {
        System.out.println(userVo.getSerialNum());
        userService.updateUser(userVo);
    }
}
  1. /user/updateForm으로 들어온 요청에 대하여 /user/updateForm.jsp 파일로 반환한다.
  2. /user/updateForm.jsp 파일에서 입력한 정보를 RequestBody 어노테이션을 통해 UserVO 객체 형식으로 가져와 그대로 DB에 업데이트 시켜준다. 여기서 비밀번호는 암호화 과정을 거친 후 DB에 암호화 된 비밀번호가 저장되도록 한다.

 

2. UserService, UserServiceImpl, UserMapper 작성

UserService.java

package board.service;

import board.vo.UserVo;
import org.springframework.stereotype.Service;

@Service
public interface UserService {
    void updateUser(UserVo userVo) throws Exception;
}

UserServiceImpl.java

package board.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import board.vo.UserVo;
import board.mapper.UserMapper;

import java.io.*;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.Map;

@Repository
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public void updateUser(UserVo userVo) throws Exception { // 비밀번호 암호화 후 회원 정보 수정
        messageDigest(userVo, userVo.getPassword());
        userMapper.updateUser(userVo);
    }
}

UserMapper.java

package board.mapper;

import org.apache.ibatis.annotations.Mapper;
import board.vo.UserVo;

@Mapper
public interface UserMapper {
    void updateUser(UserVo userVo);
}

 

3. user.js 작성

function nicknameCheck() { // 닉네임 체크
    let nickname = document.getElementById('nickname').value;
    let nicknameCheck = /^[가-힇a-zA-Z0-9]{2,15}$/; // 닉네임의 정규표현식
    if (nickname.trim() === '') { // 입력값이 없는 경우
        document.getElementById("notInputNickname").style.display = "block"; // 비밀번호를 입력하라는 메시지를 block으로 표시해 화면에 띄워지게 함
        document.getElementById("invalidNickname").style.display = "none";
        document.getElementById("nickname").style.backgroundColor="#FFCECE";
        validNickname = false;
    } else if (nicknameCheck.test(nickname) === false || nickname.length > 15) { // 양식에 맞지 않고 길이 초과 시
        document.getElementById("notInputNickname").style.display = "none";
        document.getElementById("invalidNickname").style.display = "block"; // 양식에 맞지 않는다는 메시지를 block으로 표시해 화면에 띄워지게 함
        document.getElementById("nickname").style.backgroundColor="#FFCECE";
        validNickname = false;
    } else { // 사용 가능한 닉네임
        document.getElementById("notInputNickname").style.display = "none";
        document.getElementById("invalidNickname").style.display = "none";
        document.getElementById("nickname").style.backgroundColor="#B0F6AC";
        validNickname = true;
    }
}

function emailCheck() { // 이메일 체크
    let email = document.getElementById('email').value; // email 값을 담아줌
    let emailCheck = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/; // 이메일의 정규표현식
    if (email.trim() === '') { // 입력값이 없는 경우
        document.getElementById("notInputEmail").style.display = "block"; // 이메일을 입력하라는 메시지를 block으로 표시해 화면에 띄워지게 함
        document.getElementById("invalidEmail").style.display = "none";
        document.getElementById("email").style.backgroundColor="#FFCECE";
        validEmail = false;
    } else if (emailCheck.test(email) === false) { // 양식에 맞지 않을 시
        document.getElementById("notInputEmail").style.display = "none";
        document.getElementById("invalidEmail").style.display = "block"; // 양식에 맞지 않는다는 메시지를 block으로 표시해 화면에 띄워지게 함
        document.getElementById("email").style.backgroundColor="#FFCECE";
        validEmail = false;
    } else { // 사용 가능한 이메일
        document.getElementById("notInputEmail").style.display = "none";
        document.getElementById("invalidEmail").style.display = "none";
        document.getElementById("email").style.backgroundColor="#B0F6AC";
        validEmail = true;
    }
}

function updateInfo() { // 회원 정보 수정
    if(validPassword === true && validSamePassword === true && validNickname === true && validEmail === true) {
        const username = document.getElementById('username').value;
        const password = document.getElementById('password').value;
        const nickname = document.getElementById('nickname').value;
        const email = document.getElementById('email').value;
        const serialNum = document.getElementById('serialNum').value;

        // 유효성 검사 완료 후 실행할 로직
        let data = {
            username:username,
            password:password,
            nickname:nickname,
            email:email,
            serialNum:serialNum
        };

        let xhr = new XMLHttpRequest();
        xhr.open("POST", "/user/updateProc");
        xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        xhr.onload = function() {
            if (xhr.status === 200 || xhr.status === 201) {
                let resp = xhr.responseText;
                if (resp.status === 500) {
                    alert("에러가 발생했습니다.");
                } else {
                    if (resp === "success") {
                        alert("정보수정이 완료되었습니다.");
                        location.href = "/";
                    } else {
                        alert("정보수정을 완료하지 못했습니다.");
                    }
                }
            } else {
                console.log(xhr.responseText);
                alert("에러가 발생했습니다. \n에러 코드: " + xhr.status);
            }
        };
        xhr.onerror = function() {
            alert("에러가 발생했습니다. \n에러 코드: " + xhr.status);
        };
        xhr.send(JSON.stringify(data));
    } else {
        alert('입력하신 정보를 다시 한 번 확인해주세요.');
    }
}
  1. if(validPassword === true && validSamePassword === true && validNickname === true && validEmail === true): 비밀번호, 비밀번호확인, 닉네임, 이메일이 유효성 검증을 통과했는지 확인한 후 정보 수정 로직을 실행한다.
  2. username(아이디), password(비밀번호), nickname(닉네임), email(이메일), serialNum(시리얼번호)를 JSON 형태로 변환하여 ajax 요청으로 /user/updateProcPOST 방식으로 전송한다.
  3. 반환받은 결괏값이 "success"라면 정보수정을 완료하고 메인페이지로 이동한다.

 

4. updateForm.jsp 작성

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="../layout/header.jsp"%>
<c:if test="${signIn == null}"><c:redirect url="http://staffriends.duckdns.org/user/needLogin"/></c:if>
<%--<c:if test="${signIn == null}"><c:redirect url="http://staffriends.duckdns.org/user/needLogin"/></c:if>--%>
<html>
<head>
    <title>회원정보수정</title>
</head>
<body>
<h2 style="text-align: center; margin-top: 30px; margin-bottom: 70px; font-family: KakaoBold;">회원정보수정</h2>
<section style="padding-bottom: 50px;">
    <div class="container center-div">
<form method="post" class="container center-div container-size">
    <div class="form-group">
        <h5>아이디</h5><input type="text" name="username" id="username" class="form-control" disabled style="text-align: center" value="${signIn.username}"><p/>
    </div>
    <c:if test="${empty signIn.oauth}"> <%-- 일반 유저는 비밀번호 수정이 가능 --%>
    <div class="form-group">
        <h5>비밀번호</h5><input type="password" class="form-control" placeholder="문자/숫자 포함 8자리 이상" name="password" id="password" style="text-align: center" oninput="pwCheck()">
        <span style="display: none; text-align: center; color: red; " id="notInputPw">비밀번호를 입력해주세요.</span>
        <span style="display: none; text-align: center; color: red; " id="invalidPw">문자/숫자 포함 8자리 이상 입력해야합니다.</span>
    </div>
    <div class="form-group">
        <h5>비밀번호확인</h5><input type="password" class="form-control" placeholder="비밀번호를 한번 더 입력하세요." name="samePassword" id="samePassword" style="text-align: center" oninput="samePwCheck()">
        <span style="display: none; text-align: center; color: red; " id="notInputSamePw">비밀번호를 한번 더 입력해주세요.</span>
        <span style="display: none; text-align: center; color: red; " id="invalidSamePw">문자/숫자 포함 8자리 이상 입력해야합니다.</span>
        <span style="display: none; text-align: center; color: red;" id="notSamePw">비밀번호가 일치하지 않습니다.</span>
        <span style="display: none; text-align: center; color: green;" id="validSamePw">비밀번호가 일치합니다.</span>
    </div>
    </c:if>
    <div class="form-group">
        <h5>닉네임</h5><input type="text" class="form-control" placeholder="한글, 영문 대/소문자, 숫자 포함 2~15자" name="nickName" id="nickname" style="text-align: center" value="${signIn.nickname}" oninput="nicknameCheck()">
        <span style="display: none; text-align: center; color: red;" id="notInputNickname">닉네임을 입력해주세요.</span>
        <span style="display: none; text-align: center; color: red;" id="invalidNickname">한글, 영문 대/소문자, 숫자 포함 2~15자로 입력해야합니다.</span>
        <span style="display: none; text-align: center; color: green;" id="validNickname">사용 가능한 닉네임입니다.</span>
    </div>
    <div class="form-group">
        <h5>이메일</h5><input type="text" class="form-control" placeholder="이메일을 입력하세요." name="email" id="email" style="text-align: center" value="${signIn.email}" oninput="emailCheck()">
        <span style="display: none; text-align: center; color: red;" id="notInputEmail">이메일을 입력해주세요.</span>
        <span style="display: none; text-align: center; color: red;" id="invalidEmail">이메일 형식이 올바르지 않습니다.</span>
        <span style="display: none; text-align: center; color: green;" id="validEmail">사용 가능한 이메일입니다.</span>
    </div>
    <div class="form-group">
        <h5>이름</h5><input type="text" name="name" class="form-control" disabled style="text-align: center" value="${signIn.name}"><p/>
    </div>
    <div class="form-group">
        <h5>시리얼번호</h5><input type="text" class="form-control" placeholder="시리얼번호를 입력하세요." name="serialNum" id="serialNum" value="${signIn.serialNum}" style="text-align: center">
    </div>
    <div class="form-group text-center">
        <input class="btn btn-staffriends btn-lg center-div" type="button" value="정보수정" id="updateBtn" onclick="updateInfo()">
    </div>
</form>
    </div>
</section>

<script>
    window.onload = function () { // 페이지 진입 시 모든 정보들을 체크
        nicknameCheck();
        emailCheck();
    }
</script>
</body>
<%@ include file="../layout/footer.jsp"%>
</html>
  1. window.onload 함수를 이용해서 웹 문서를 불러올 때, nicknameCheck() 함수와 emailCheck() 함수를 먼저 실행해서 변경 사항이 없다면 validNickname을 true로, validEmail을 true로 설정해준다.
  2. 만약 이후에 닉네임 또는 이메일을 변경하려는 키 입력이 감지된다면 다시 nicknameCheck() 함수와 emailCheck() 함수를 실행한다.

 

5. sql-user.xml 작성

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="board.mapper.UserMapper">
    <update id="updateUser" parameterType="board.vo.UserVo">
        <![CDATA[
            UPDATE
                user
            SET
                password = #{password},
                nickname = #{nickname},
                email = #{email},
                serial_num = #{serialNum}
            WHERE
                username = #{username}
        ]]>
    </update>
</mapper>

 

프로젝트 전체 코드 Github 주소

https://github.com/sungwoo-jo/Staffriends-Project

 

GitHub - sungwoo-jo/Staffriends-Project: AI 스마트 시각장애인 지팡이

AI 스마트 시각장애인 지팡이. Contribute to sungwoo-jo/Staffriends-Project development by creating an account on GitHub.

github.com

 

728x90