상세 컨텐츠

본문 제목

Spring 블로그 만들기 - 18. 회원가입 및 관리

개발/Spring 블로그 만들기

by 똘똘이박사 2019. 4. 11. 17:16

본문

 

이 포스팅의 샘플 게시판 개발 환경은 MAC OS, STS, OpenJDK11 입니다.

 

블로그 만들기 - 17. 회원가입 및 관리

로그인 폼을 만들었지만, 아직 회원 정보가 아무것도 없어서 로그인을 할 수 없습니다.

이번 포스팅에서는 간단히 회원가입을 위한 폼을 만들어 보도록 하겠습니다.

 

테이블 생성하기

아래의 SQL문을 실행해 회원정보를 저장할 테이블을 생성합니다.

create table tbl_user
(
    uid    varchar(20)  not null
        primary key,
    name   varchar(100) not null,
    pwd    varchar(100) not null,
    email  varchar(100) null,
    grade  varchar(30)  null,
    reg_dt date         null
);

 

userMapper 만들기

회원 정보를 관리할 SQL문을 만들어 봅니다.

<?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="com.freehoon.web.user.userMapper">
	<select id="getUserInfo" resultType="com.freehoon.web.user.model.UserVO">
		SELECT
			UID
			, NAME
			, PWD
			, EMAIL
			, GRADE
			, REG_DT
		FROM
			TBL_USER
		WHERE
			UID = #{uid}
	</select>
	
	<select id="getUserList" resultType="com.freehoon.web.user.model.UserVO">
		SELECT
			UID
			, NAME
			, PWD
			, EMAIL
			, GRADE
			, REG_DT
		FROM
			TBL_USER
	</select>
	
	<insert id="insertUser" parameterType="com.freehoon.web.user.model.UserVO">
		INSERT INTO TBL_USER (UID, NAME, PWD, EMAIL, REG_DT)
		VALUES (
			#{uid}
			, #{name}
			, #{pwd}
			, #{email}
			, now()
		)
	</insert>
	
	<update id="updateUser" parameterType="com.freehoon.web.user.model.UserVO">
		UPDATE TBL_USER SET
			NAME = #{name}
			, PWD = #{pwd}
			, EMAIL = #{email}
			, GRADE = #{grade}
		WHERE
			UID = #{uid}
	</update>
	
	<delete id="deleteUser" parameterType="int">
		DELETE FROM TBL_USER
		WHERE UID = #{uid}
	</delete>
</mapper>

 

VO, DAO, Service 만들기

회원정보를 처리할 패키지 들을 아래 그림과 같이 만들어 줍니다. 그리고 VO, DAO, Service 파일도 아래와 같이 만들어 줍니다.

UserVO.java (신규)

package com.freehoon.web.user.model;

public class UserVO {
	String uid;
	String name;
	String pwd;
    String re_pwd;
	String email;
	String grade;
	String reg_dt;
	
	public String getUid() {
		return uid;
	}
	
	public void setUid(String uid) {
		this.uid = uid;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getPwd() {
		return pwd;
	}
	
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	
    public String getRe_Pwd() {
		return re_pwd;
	}
	
	public void setRe_Pwd(String re_pwd) {
		this.re_pwd = re_pwd;
	}
    
	public String getEmail() {
		return email;
	}
	
	public void setEmail(String email) {
		this.email = email;
	}

	public String getGrade() {
		return grade;
	}

	public void setGrade(String grade) {
		this.grade = grade;
	}

	public String getReg_dt() {
		return reg_dt;
	}

	public void setReg_dt(String reg_dt) {
		this.reg_dt = reg_dt;
	}

	@Override
	public String toString() {
		return "UserVO [uid=" + uid + ", name=" + name + ", pwd=" + pwd + ", re_pwd=" + re_pwd + ", email=" + email + ", grade=" + grade
				+ ", reg_dt=" + reg_dt + "]";
	}
	
}

 

UserDAO.java (신규)

package com.freehoon.web.user.dao;

import java.util.List;

import com.freehoon.web.user.model.UserVO;

public interface UserDAO {

	public List<UserVO> getUserList() throws Exception;
	
	public UserVO getUserInfo(String uid) throws Exception;
	
	public int insertUser(UserVO userVO) throws Exception;
	
	public int updateUser(UserVO userVO) throws Exception;
	
	public int deleteUser(String uid) throws Exception;
}

 

UserDAOImpl.java (신규)

package com.freehoon.web.user.dao;

import java.util.List;

import javax.inject.Inject;

import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;

import com.freehoon.web.user.model.UserVO;

@Repository
public class UserDAOImpl implements UserDAO{

	@Inject
	private SqlSession sqlSession;
	
	@Override
	public List<UserVO> getUserList() throws Exception {
		return sqlSession.selectList("com.freehoon.web.user.userMapper.getUserList");
	}

	@Override
	public UserVO getUserInfo(String uid) throws Exception {
		return sqlSession.selectOne("com.freehoon.web.user.userMapper.getUserInfo", uid);
	}

	@Override
	public int insertUser(UserVO userVO) throws Exception {
		return sqlSession.insert("com.freehoon.web.user.userMapper.insertUser", userVO);
	}

	@Override
	public int updateUser(UserVO userVO) throws Exception {
		return sqlSession.update("com.freehoon.web.user.userMapper.updateUser", userVO);
	}

	@Override
	public int deleteUser(String uid) throws Exception {
		return sqlSession.delete("com.freehoon.web.user.userMapper.deleteUser", uid);
	}
}

 

UserService.java(신규)

package com.freehoon.web.user.service;

import java.util.List;

import com.freehoon.web.user.model.UserVO;

public interface UserService {

	public List<UserVO> getUserList() throws Exception;
	
	public UserVO getUserInfo(String uid) throws Exception;
	
	public void insertUser(UserVO userVO) throws Exception;
	
	public void updateUser(UserVO userVO) throws Exception;
	
	public void deleteUser(String uid) throws Exception;
}

 

UserServiceImpl.java (신규)

package com.freehoon.web.user.service;

import java.util.List;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.freehoon.web.user.dao.UserDAO;
import com.freehoon.web.user.model.UserVO;

@Service
public class UserServiceImpl implements UserService{
	
	private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

	@Inject
	private UserDAO userDAO;
	
	@Override
	public List<UserVO> getUserList() throws Exception {
		return userDAO.getUserList();
	}

	@Override
	public UserVO getUserInfo(String uid) throws Exception {
		return userDAO.getUserInfo(uid);
	}

	@Override
	public void insertUser(UserVO userVO) throws Exception {
		userDAO.insertUser(userVO);
	}

	@Override
	public void updateUser(UserVO userVO) throws Exception {
		userDAO.updateUser(userVO);
	}

	@Override
	public void deleteUser(String uid) throws Exception {
		userDAO.deleteUser(uid);
	}
}

 

UserController 만들기

회원관리 부분도 게시판처럼 수정과 삭제 부분이 필요 하지만 이번 포스팅에서는 생략하고 넘어 가도록 하겠습니다.

UserController.java(신규)

package com.freehoon.web.user.controller;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.freehoon.web.user.model.UserVO;
import com.freehoon.web.user.service.UserService;

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

	private static final Logger logger = LoggerFactory.getLogger(UserController.class);
	
	@Inject
	private UserService userService;
	
	@RequestMapping(value = "/getUserList", method = RequestMethod.GET)
	public String getUserList(Model model) throws Exception{
		logger.info("getUserList()....");
		
		model.addAttribute("userList", userService.getUserList());
		
		return "user/userList";
	}
	
	@RequestMapping(value = "/insertUser", method = RequestMethod.POST)
	public String insertUser(@ModelAttribute("userVO") UserVO userVO
			, RedirectAttributes rttr) throws Exception {
		userService.insertUser(userVO);
		
		return "redirect:/user/getUserList";
	}
	
}

 

 

회원 목록 화면은 아래와 같이 작성합니다.

userList.jsp (신규)

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

<script>
	$(document).on('click', '#btnSearch', function(e){
		e.preventDefault();
		var url = "${getBoardListURL}";
		url = url + "?searchType=" + $('#searchType').val();
		url = url + "&keyword=" + $('#keyword').val();
		console.log(url);
		location.href = url;
		
	});
		
	function fn_prev(page, range, rangeSize, searchType, keyword) {
		
		var page = ((range - 2) * rangeSize) + 1;
		var range = range - 1;
		
		var url = "${globalCtx}/user/getUserList";
		url = url + "?page=" + page;
		url = url + "&range=" + range;
		url = url + "&searchType=" + searchType;
		url = url + "&keyword=" + keyword;
		
		location.href = url;
	}

	function fn_pagination(page, range, rangeSize, searchType, keyword) {
		var url = "${getUserListURL}";
		url = url + "?page=" + page;
		url = url + "&range=" + range;
		url = url + "&searchType=" + searchType;
		url = url + "&keyword=" + keyword;
		console.log(url);
		location.href = url;
		
	}
	
	function fn_next(page, range, rangeSize, searchType, keyword) {
		var page = parseInt((range * rangeSize)) + 1;
		var range = parseInt(range) + 1;
		
		var url = "${globalCtx}/user/getUserList";
		url = url + "?page=" + page;
		url = url + "&range=" + range;
		url = url + "&searchType=" + searchType;
		url = url + "&keyword=" + keyword;
		
		location.href = url;
	}
	
</script>
 
<article>
	<div class="container">
		<h2>User list</h2>
		
		<div class="table-responsive">
			<table class="table table-striped table-sm">
				<colgroup>
					<col style="width:auto;" />
					<col style="width:25%;" />
					<col style="width:25%;" />
					<col style="width:15%;" />
					<col style="width:15%;" />
				</colgroup>
				<thead>
					<tr>
						
						<th>USER ID</th>
						<th>USER NAME</th>
						<th>EMAIL</th>
						<th>GRADE</th>
						<th>가입일</th>
					</tr>
				</thead>
				<tbody>
					<c:choose>
						<c:when test="${empty userList }" >
							<tr><td colspan="5" align="center">데이터가 없습니다.</td></tr>
						</c:when> 
						<c:when test="${!empty userList}">
							<c:forEach var="list" items="${userList}">
								<tr>
									<td><c:out value="${list.uid}"/></td>
									<td><c:out value="${list.name}"/></td>
									<td><c:out value="${list.email}"/></td>
									<td><c:out value="${list.grade}"/></td>
									<td><c:out value="${list.reg_dt}"/></td>
								</tr>
							</c:forEach>
						</c:when>
					</c:choose>
				</tbody>
			</table>
		</div>

		<!-- pagination{s} -->
		<div id="paginationBox">
			<ul class="pagination">
				<c:if test="${pagination.prev}">
					<li class="page-item"><a class="page-link" href="#" onClick="fn_prev('${pagination.page}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.searchType}', '${pagination.keyword}')">Previous</a></li>
				</c:if>
				
				<c:forEach begin="${pagination.startPage}" end="${pagination.endPage}" var="idx">
					<li class="page-item <c:out value="${pagination.page == idx ? 'active' : ''}"/> "><a class="page-link" href="#" onClick="fn_pagination('${idx}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.searchType}', '${pagination.keyword}' )"> ${idx} </a></li>
				</c:forEach>
				
				<c:if test="${pagination.next}">
					<li class="page-item"><a class="page-link" href="#" onClick="fn_next('${pagination.page}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.searchType}', '${pagination.keyword}')">Next</a></li>
				</c:if>
			</ul>
		</div>
		<!-- pagination{e} -->
		
		<!-- search{s} -->
		<div class="form-group row justify-content-center">
			<div style="padding-right:10px">
				<select class="form-control form-control-sm" name="searchType" id="searchType">
					<option value="title" <c:if test="${pagination.searchType eq 'title'}">selected</c:if> >제목</option>
					<option value="content" <c:if test="${pagination.searchType eq 'content'}">selected</c:if>>본문</option>
					<option value="reg_id" <c:if test="${pagination.searchType eq 'reg_id'}">selected</c:if>>작성자</option>
				</select>
			</div>
			<div style="padding-right:10px">
				<input type="text" class="form-control form-control-sm" name="keyword" id="keyword" value="${pagination.keyword}">
			</div>
			<div>
				<button class="btn btn-sm btn-primary" name="btnSearch" id="btnSearch">검색</button>
			</div>
		</div>
		<!-- search{e} -->

	</div>
</article>

 

 

login 화면 만들기

회원가입 화면은 아래와 같이 만들 만듭니다.

위 그림을 보면 회원정보 입력 화면에는 메뉴바가 없습니다. 회원관리 부분의 하나이지만 View 파일(signupForm.jsp)를 login 부분에 위치 시키도록 합니다. 

회원가입 화면으로 이동하기 위한 Controller의 처리는 loginController에 아래와 같이 메소드를 추가 합니다.

 

LoginController.java(수정 - signupForm() 메소드 추가)

	@RequestMapping(value = "/signupForm", method = RequestMethod.GET)
	public String signupForm(Model model) throws Exception {
		model.addAttribute("userVO", new UserVO());
		return "login/signupForm";
	}

 

signupForm.jsp (신규)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>


<script>
	$(document).on('click', '#btnSignup', function(e){
		e.preventDefault();

		$("#form").submit();
	});
	
	$(document).on('click', '#btnCancle', function(e){
		e.preventDefault();
		
        $('#uid').val('');
		$('#name').val('');
		$('#pwd1').val('');
		$('#pwd2').val('');
		$('#email').val('');
		//location.href="${pageContext.request.contextPath}/home";
	});

</script>

<article>
	<div class="container  col-md-6" role="main">
		<div class="card">
			<div class="card-header">Register</div>
			<div class="card-body">
				<form:form name="form" id="form" class="form-signup" role="form" modelAttribute="userVO" method="post" action="${pageContext.request.contextPath}/user/insertUser">
					<div class="form-group row">
						<label for="uid" class="col-md-3 col-form-label text-md-right">아이디</label>
						<div class="col-md-5">
							<form:input path="uid" id="uid" class="form-control" placeholder="아이디을 입력해 주세요" />
						</div>
					</div>
		
					<div class="form-group row">
						<label for="name" class="col-md-3 col-form-label text-md-right">이름</label>
						<div class="col-md-5">
							<form:input path="name" id="name" class="form-control" placeholder="이름을 입력해 주세요" />
						</div>
					</div>
					
					<div class="form-group row">
						<label for="pwd" class="col-md-3 col-form-label text-md-right">비밀번호</label>
						<div class="col-md-5">
							<form:password path="pwd" id="pwd" class="form-control" placeholder="비밀번호를 입력해 주세요" />
						</div>
					</div>
					<div class="form-group row">
						<label for="re_pwd" class="col-md-3 col-form-label text-md-right">비밀번호 확인</label>
						<div class="col-md-5">
							<form:password path="re_pwd" id="re_pwd" class="form-control" placeholder="비밀번호를 입력해 주세요" />
						</div>
					</div>
					
					<div class="form-group row">
						<label for="email" class="col-md-3 col-form-label text-md-right">이메일</label>
						<div class="input-group col-md-7">
							<div class="input-group-prepend">
								<span class="input-group-text">@</span>
							</div>
							<form:input path="email" id="email" class="form-control" placeholder="이메일을 입력해 주세요" />
						</div>
					</div>
				</form:form>
			</div>
		</div>
		<div style="margin-top:10px">
			<button type="button" class="btn btn-sm btn-primary" id="btnSignup">회원가입</button>
			<button type="button" class="btn btn-sm btn-primary" id="btnCancel">취소</button>
		</div>
	</div>
	
</article>

 

 

login 화면 수정

우리는 이전 포스팅에서 로그인 화면을 만들면서 'sign up' 문구를 출력하고, 아무런 조치도 취하지 않았습니다. 이제 이 문구를 클릭하면 회원가입 페이지로 이동 할 수 있도록 아래와 같이 login.jsp페이지에 이벤트를 추가해 줍니다.

 

login.jsp (수정)

	<span style="font-size:11pt;">
	<a href="#" onClick="fn_btnSignupClick()">Sign up</a>
	</span>
    
	<script>
		function fn_btnSignupClick(){
			location.href ="${pageContext.request.contextPath}/user/signupForm";
        	}    
	</script>

 

 

이제 로그인 페이지에서 'sign up' 문구를 클릭해 회원가입 페이지로 이동 하는지 확인해 봅니다. 그리고 간단히 회원 정보를 입력하고 회원정보가 DB에 입력 되는지 확인해 봅니다. 그리고 회원정보 리스트 화면에 회원 목록이 제대로 출력이 되는지 확인해 봅니다.

 

현재 이 페이지에는 중요한 문제점이 몇 가지 있습니다.

우선 위에서 말했던 내용으로 비밀번호를 정확히 입력했는지 확인하는 부분이 빠져 있습니다.

그리고 비밀번호의 암호화 처리가 빠져 있습니다.

마지막으로 회원가입을 하고 돌아갈 페이지가 회원 목록 페이지로 되어 있습니다. 회원 목록 페이지는 관리자만이 접근 할 수 있도록 하는 것이 올바른 방법입니다. 따라서 회원가입시 '메인 페이지' 나 '로그인 페이지' 로 이동하는 것이 좋습니다. 여기서는 로그인 페이지로 이동 하도록 수정 할 예정입니다. 

위 3가지 내용은 다음에 이어질 스프링 시큐리티를 적용하며 수정 할 예정입니다.

 

 

 

 

 

 

 

 

 

※ 포스팅에 오타나 잘못된 부분, 추가적으로 더 알고 싶은 부분이 있으면 댓글 주세요~

 

반응형

관련글 더보기