회원 정보 수정

이제 흐름이 슬슬 익숙해지기 시작한다.

링크 생성 -> 컨트롤러 매핑 -> Service -> DAO, 쿼리문(리턴) -> Service -> 컨트롤러 모델&뷰 리턴 -> 페이지 이동

회원 정보 수정의 경우는 회원가입과 형태가 비슷하지만, 이미 로그인된 유저의 정보를 가져와서 form에 뿌려주는게 관건이다.

핵심은 이미 더 이상 쿼리문을 생성하지 않고, 이미 만들어놓은 쿼리문과 DAO메소드들로 완성시킬 수 있다는 점이다.

링크 생성

상단 메뉴바에 있는 회원정보수정 메뉴에 하이퍼링크를 등록한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="<%= request.getContextPath() %>/js_css/style.css" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
</head>
<body>
	<div class="topMenu">
		<ul>
			<li><a href="/myapp/">홈</a></li>
			<c:if test="${ logStatus!='Y' }">
				<li><a href="/myapp/member/login">로그인</a></li>
				<li><a href="/myapp/member/signup">회원가입</a></li>
			</c:if>
			<c:if test="${ logStatus=='Y' }">
				<li><a href="/myapp/member/logout">로그아웃</a></li>
<li><a href="/myapp/member/myAccount?username=${ username }&name=${ name }">회원정보수정</a></li>
			</c:if>
			<li><a href="#">게시판</a></li>
			<li><a href="#">자료실</a></li>
		</ul>
	</div>

myAccount로 이동할때, parameter값으로 현재 세션에 기록되어있는 아이디(username)와 이름(name)을 넘겨줬다.

컨트롤러 매핑

컨트롤러에서 url매핑을 하고, 정보수정 뷰페이지 이름과 현재 로그인된 클라이언트의 정보를 attribute로 넘겨주자.

package com.poby.myapp.controller;

import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.poby.myapp.service.MemberService;
import com.poby.myapp.vo.MemberVO;
import com.poby.myapp.vo.ZipcodeVO;

@Controller
public class MemberController {
	// 클래스를 찾아 객체를 생성해주는 어노테이션
	@Autowired
	MemberService service;
	
	// 회원가입 페이지 이동
	@RequestMapping("/member/signup")
	public String signup() {
		return "member/signup";
	}
	
	// 아이디 중복확인 팝업
	@RequestMapping("/member/idCheck")
	public String idCheck(String username, Model model) {
		// DB에 username이 이미 존재하는지 확인
		int result = service.idCheck(username);
		
		model.addAttribute("username", username);	// 검색 조건
		model.addAttribute("result", result);		// 검색 결과
		
		return "member/idCheck";
	}
	
	// 우편번호 검색 팝업
	@GetMapping("/member/searchZipcode")
	public ModelAndView searchZipcode(String street) {
		ModelAndView mav = new ModelAndView();
		
		List<ZipcodeVO> list = null;
		if(street!=null && street!="") {
			// 도로명 주소가 있을때만 DB검색 실시
			list = service.searchZipcode(street);
		}
		
		mav.addObject("list", list);	// 검색값이 있으면 제대로 리턴, 없으면 null
		
		mav.setViewName("member/searchZipcode");
		return mav;
	}
	
	// 회원가입
//	@RequestMapping(value="/member/signupOk", method=RequestMethod.POST)
	@PostMapping("/member/signupOk")
	public ModelAndView signupOk(MemberVO vo) {
		ModelAndView mav = new ModelAndView();
		System.out.println(vo.toString());
		
		int result = service.signupOk(vo);
		
		if(result>0) {
			mav.setViewName("redirect:/");	// 뷰페이지 이름을 jsp파일명 대신 다른 컨트롤러의 매핑 주소로 보낸다
		}else {
			mav.setViewName("member/signupResult");
		}
		return mav;
	}
	
	// 로그인 페이지로 이동
	@RequestMapping("/member/login")
	public String login() {
		return "member/login";
	}
	
	// 로그인
	@PostMapping("/member/loginOk")
	public ModelAndView loginOk(MemberVO vo, HttpSession session) {
		ModelAndView mav = new ModelAndView();
		
		// 아이디와 비밀번호가 일치하면 username, name 선택
		MemberVO VO = service.loginOk(vo);
		
		if(VO==null) {
			// 로그인 실패 시 로그인 페이지로 이동
			mav.setViewName("member/login");
		}else {
			// 세션에 로그인 정보 저장
			session.setAttribute("username", VO.getUsername());
			session.setAttribute("name", VO.getName());
			session.setAttribute("logStatus", "Y");
			// 로그인 성공 시 홈페이지로 이동
			mav.setViewName("redirect:/");
		}
		
		return mav;
	}
	
	// 로그아웃
	@RequestMapping("/member/logout")
	public ModelAndView logout(HttpSession session) {
		ModelAndView mav = new ModelAndView();
		
		session.invalidate();
		mav.setViewName("redirect:/");
		
		return mav;
	}
	
	// 회원정보수정 페이지로 이동
	@RequestMapping("/member/myAccount")
	public ModelAndView myAccount(MemberVO vo) {
		ModelAndView mav = new ModelAndView();
		
		return mav;
	}
}

Service

package com.poby.myapp.service;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import com.poby.myapp.dao.MemberDAO;
import com.poby.myapp.vo.MemberVO;
import com.poby.myapp.vo.ZipcodeVO;

@Service
public class MemberServiceImpl implements MemberService {
	@Inject
	MemberDAO dao;

	@Override
	public int idCheck(String username) {
		return dao.idCheck(username);
	}

	@Override
	public List<ZipcodeVO> searchZipcode(String street) {
		return dao.searchZipcode(street);
	}

	@Override
	public int signupOk(MemberVO vo) {
		return dao.signupOk(vo);
	}

	@Override
	public MemberVO loginOk(MemberVO vo) {
		return dao.loginOk(vo);
	}

	@Override
	public MemberVO myAccount(MemberVO vo) {
		return dao.myAccount(vo);
	}
}

쿼리문

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

<mapper namespace="com.poby.myapp.dao.MemberDAO">
	<select id="idCheck" resultType="int">
		SELECT count(username) cnt FROM member_tbl WHERE username=#{param1}
	</select>
	<select id="searchZipcode" resultType="com.poby.myapp.vo.ZipcodeVO">
		SELECT zipcode, city, street, bldg1, bldg2, bldgname, dong, num1, num2 
		FROM zipcode_tbl WHERE street LIKE '%${param1}%'
	</select>
	<insert id="signupOk">
		INSERT INTO member_tbl(username, password, name, tel, email, zipcode, addr, detailaddr) 
		VALUES (#{username}, #{password}, #{name}, #{tel}, #{email}, #{zipcode}, #{addr}, #{detailaddr})
	</insert>
	<select id="loginOk" resultType="com.poby.myapp.vo.MemberVO">
		SELECT username, name FROM member_tbl WHERE username=#{username} AND password=#{password}
	</select>
	<select id="myAccount" resultType="com.poby.myapp.vo.MemberVO">
		SELECT username, password, name, tel, email, zipcode, addr, detailaddr
		FROM member_tbl WHERE username=#{username} AND name=#{name}
	</select>
</mapper>

컨트롤러 모델&뷰

// 회원정보수정 페이지로 이동
@RequestMapping("/member/myAccount")
public ModelAndView myAccount(MemberVO vo) {
	ModelAndView mav = new ModelAndView();
	MemberVO VO = new MemberVO();
	
	VO = service.myAccount(vo);
	
	mav.addObject("vo", VO);
	mav.setViewName("member/myAccount");
	
	return mav;
}

페이지 이동

이제 myAccount.jsp를 만들어서 수정 form을 만들자. 형태는 회원가입과 비슷하게 만들 수 있다.

대신 attribute로 넘겨받은 vo로 기존의 회원 정보를 채워넣는다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- attribute로 넘어온 변수 : vo -->
<title>내 정보 수정</title>
<div class="container">
	<h1>내 정보 수정 Form</h1>
	<form method="post" action="/myapp/member/myAccountOk" id="myAccountForm">
		<ul>
			<li>아이디</li>
			<li><input type="text" name="username" id="username" value="${ vo.username }" disabled></li>
			<li>새 비밀번호</li>
			<li><input type="password" name="password" id="password"></li>
			<li>새 비밀번호 확인</li>
			<li><input type="password" name="v-password" id="v-password"></li>
			<li>이름</li>
			<li><input type="text" name="name" id="name" value="${ vo.name }" disabled></li>
			<li>연락처</li>
			<li>
				<input type="text" name="tel1" id="tel1" value="${ vo.tel1 }">-
				<input type="text" name="tel2" id="tel2" value="${ vo.tel2 }">-
				<input type="text" name="tel3" id="tel3" value="${ vo.tel3 }">
			</li>
			<li>이메일</li>
			<li><input type="text" name="email" id="email" value="${ vo.email }"></li>
			<li>우편번호</li>
			<li>
				<input type="text" name="zipcode" id="zipcode" value="${ vo.zipcode }">
				<input type="button" value="우편번호 찾기" id="searchZipcode">
			</li>
			<li>주소</li>
			<li><input type="text" name="addr" id="addr" style="width:50%" value="${ vo.addr }"></li>
			<li>상세주소</li>
			<li><input type="text" name="detailaddr" id="detailaddr" value="${ vo.detailaddr }"></li>
			<li><input type="submit" value="저장"><input type="button" value="취소" onclick="history.back()"></li>
		</ul>
	</form>
</div>

아이디와 이름은 바꾸지 못하게 disable시켰고, 비밀번호는 새로 바꿀 수 있게 비워놓았다.

마지막에 취소 버튼을 만들어서 뒤로가기 기능을 넣어주었다.

 

이제 기능을 추가하자. 이 또한 회원가입과 비슷한 양상으로 흘러간다.

signup.jsp에서 jQuery스크립트를 가져와서 필요없는 기능은 지우자.

아이디 중복확인 기능, 유효성 검사 중 아이디와 이름에 관한 기능은 필요가 없다. 추가로 바뀐 정보가 없을 때, alert로 알려주는 기능을 추가하자.

<script>
	$(function(){
		// 우편번호 찾기 버튼 누르면
		$("#searchZipcode").click(function(){
			// 우편번호 검색 팝업창 생성
			window.open("/myapp/member/searchZipcode","zipcode","width=600px, height=500px, top=200px, left=200px");
		});
		
		// 회원가입 유효성 검사
		$("#myAccountForm").submit(function(){
			// 비밀번호 확인
			if($("#password").val() != $("#v-password").val()){
				alert("비밀번호를 확인하세요.");
				return false;
			}
			
			// 연락처 검사
			var tel = $("#tel1").val()+"-"+$("#tel2").val()+"-"+$("#tel3").val();
			console.log("tel -> ", tel);	// 브라우저 콘솔에 전화번호 표시
			// 지역번호 : 010, 02, 031, 032, 041, 042
			reg = /^(010|02|031|032|041|042)-[0-9]{3,4}-[0-9]{4}$/
			if(!reg.test(tel)){
				alert("전화번호를 확인하세요.");
				return false;
			}
			
			// 이메일 검사
			// smg1024@naver.com	smg1024@cau.ac.kr
			if($("#email").val()!=""){	// 이메일은 필수 입력 항목이 아님
				// 이메일은 다른 사이트의 이메일을 가져오는 것이기 때문에 최대한 널널한 조건으로 설정
				// ? : 있거나 없거나
				reg = /^\w{6,15}[@][a-z0-9]{2,8}[.][a-z]{1,3}([.][a-z]{1,3})?$/
				if(!reg.test($("#email").val())){
					alert("잘못된 이메일 주소입니다.");
					return false;
				}
			}
			
			// 수정된 정보가 없을 때
			if($("#password").val()==${ vo.password } &&
					$("#tel1").val()==${ vo.tel1 } &&
					$("#tel2").val()==${ vo.tel2 } &&
					$("#tel3").val()==${ vo.tel3 } &&
					$("#email").val()==${ vo.email } &&
					$("#zipcode").val()==${ vo.zipcode } &&
					$("#addr").val()==${ vo.addr } &&
					$("#detailaddr").val()==${ vo.detailaddr }){
				alert("변경된 내용이 없습니다.");
				return false;
			}
		});
	});
</script>

myAccountOk페이지를 만들고 매핑을 해서 쿼리문으로 DB에 있는 회원 정보를 수정하자.

// 회원정보수정 저장
@PostMapping("/member/myAccountOk")
public ModelAndView myAccountOk(MemberVO vo) {
	ModelAndView mav = new ModelAndView();
	
	return mav;
}
package com.poby.myapp.service;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import com.poby.myapp.dao.MemberDAO;
import com.poby.myapp.vo.MemberVO;
import com.poby.myapp.vo.ZipcodeVO;

@Service
public class MemberServiceImpl implements MemberService {
	@Inject
	MemberDAO dao;

	@Override
	public int idCheck(String username) {
		return dao.idCheck(username);
	}

	@Override
	public List<ZipcodeVO> searchZipcode(String street) {
		return dao.searchZipcode(street);
	}

	@Override
	public int signupOk(MemberVO vo) {
		return dao.signupOk(vo);
	}

	@Override
	public MemberVO loginOk(MemberVO vo) {
		return dao.loginOk(vo);
	}

	@Override
	public MemberVO myAccount(MemberVO vo) {
		return dao.myAccount(vo);
	}

	@Override
	public MemberVO myAccountOk(MemberVO vo) {
		return dao.myAccountOk(vo);
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.poby.myapp.dao.MemberDAO">
	<select id="idCheck" resultType="int">
		SELECT count(username) cnt FROM member_tbl WHERE username=#{param1}
	</select>
	<select id="searchZipcode" resultType="com.poby.myapp.vo.ZipcodeVO">
		SELECT zipcode, city, street, bldg1, bldg2, bldgname, dong, num1, num2 
		FROM zipcode_tbl WHERE street LIKE '%${param1}%'
	</select>
	<insert id="signupOk">
		INSERT INTO member_tbl(username, password, name, tel, email, zipcode, addr, detailaddr) 
		VALUES (#{username}, #{password}, #{name}, #{tel}, #{email}, #{zipcode}, #{addr}, #{detailaddr})
	</insert>
	<select id="loginOk" resultType="com.poby.myapp.vo.MemberVO">
		SELECT username, name FROM member_tbl WHERE username=#{username} AND password=#{password}
	</select>
	<select id="myAccount" resultType="com.poby.myapp.vo.MemberVO">
		SELECT username, password, name, tel, email, zipcode, addr, detailaddr 
		FROM member_tbl WHERE username=#{username} AND name=#{name}
	</select>
    <update id="myAccountOk">
		UPDATE member_tbl 
		SET password=#{password}, tel=#{tel}, 
			email=#{email}, zipcode=#{zipcode}, 
			addr=#{addr}, detailaddr=#{detailaddr}
		WHERE username=#{username} AND name=#{name}
	</update>	
</mapper>

쿼리문을 만들었으니 컨트롤러에서 모델과 뷰를 생성하여 페이지로 넘겨주자.

// 회원정보수정 저장
@PostMapping("/member/myAccountOk")
public ModelAndView myAccountOk(MemberVO vo) {
    ModelAndView mav = new ModelAndView();

    int result = service.myAccountOk(vo);

    if(result>0) {
        mav.setViewName("redirect:/");
    }else {
        mav.setViewName("member/myAccountOk");
    }

    return mav;
}

result는 쿼리 실행 횟수이고, update가 0번 실행됐다는 건 수정 실패했다는 뜻이다.

성공했을땐 바로 홈페이지로 redirect시켜주고, 실패 시 /myapp/member/myAccountOk로 이동시켰다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- attribute로 넘어온 변수 : result -->
<!DOCTYPE html>
<script>
	alert("수정 실패.");
	history.back();
</script>

실패했을땐 뒤로가기를 시켰다.

+ Recent posts