Programming/스프링(spring) - Enterprise

스프링(spring)/ 회원 시스템 구축 1(회원가입 페이지)

esoog Polaris 2023. 8. 1. 15:29
반응형

0. 무엇보다 회원 데이터를 위해, 새로운 데이터 테이블을 생성 사용할 것이므로,

기존 BoderVO파일이 있는 패키지에, UserVO 파일 생성.(사용할 데이터베이스 테이블을 먼저 만들어 둔다.)

 

package com.project.model;

public class UserVO {
	  	private String id; // 유저 아이디
		private String pwd; // 비밀번호
		private String nick; // 닉네임
		private String ncode; // 국가
		private String email; // 이메일
		private String text; // 추가 텍스트
		private String channel; // 채널 정보
		private int scount; // 카운트 정보
		private String etc1; // 기타 정보 1
		private int etc2; // 기타 정보 2
		private String etc3; // 기타 정보
//		  `etc4` longblob, // 기타 정보(대용량파일 관련)
		private String etc5; // 기타 정보

	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public String getNick() {
		return nick;
	}
	public void setNick(String nick) {
		this.nick = nick;
	}
	public String getNcode() {
		return ncode;
	}
	public void setNcode(String ncode) {
		this.ncode = ncode;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}
	public String getChannel() {
		return channel;
	}
	public void setChannel(String channel) {
		this.channel = channel;
	}
	public int getScount() {
		return scount;
	}
	public void setScount(int scount) {
		this.scount = scount;
	}
	public String getEtc1() {
		return etc1;
	}
	public void setEtc1(String etc1) {
		this.etc1 = etc1;
	}
	public int getEtc2() {
		return etc2;
	}
	public void setEtc2(int etc2) {
		this.etc2 = etc2;
	}
	public String getEtc3() {
		return etc3;
	}
	public void setEtc3(String etc3) {
		this.etc3 = etc3;
	}
	public String getEtc5() {
		return etc5;
	}
	public void setEtc5(String etc5) {
		this.etc5 = etc5;
	}

}

사용할 데이터 테이블의 컬럼들을 나열하고, 게터와 세터로 자료를 정렬해둔다.

 

 

 

 

1. 보통 회원가입은 메인 페이지에 나오니까, 링크를 하나 걸어 둔다.

home.jsp파일에 

 

<a href="/account/join">회원가입</a>

 

 

 

 

2. 그럼 먼저  join.jsp(V)파일을 건드려 준다.

view폴더에 account라는 폴더 생성 후, join.jsp파일을 생성한다.

 

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

<html>
	<head>
		<!-- 합쳐지고 최소화된 최신 CSS -->
		<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
		<!-- 부가적인 테마 -->
		<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
	 	<!-- jquery 사용 -->
	 	<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
        
		<title>회원가입</title>
		<style>
			.help-block{
				color:red;
			}
		</style>
	</head>

	<body>
		<section id="container">
			<form method="post">
			<!-- 아래나오는 클래스들은 부트스트랩 테마로 사용됨. -->
				<div class="form-group has-feedback">
					<label class="control-label" for="id">아이디</label>
					<input class="form-control" type="text" id="id" name="id" required/>
					<button type="button" id="checkIdBtn">아이디 중복확인</button>
					<!-- 그리고 버튼 #을 사용해서 중복확인 로직을 만들어 줌. -->
				</div>
				
				<div class="form-group has-feedback">
					<label class="control-label" for="pwd">패스워드</label>
					<input class="form-control" type="password" id="pwd" name="pwd" required/>
				</div>
				<div class="form-group has-feedback">
				    <label class="control-label" for="confirmPwd">패스워드 확인</label>
				    <input class="form-control" type="password" id="confirmPwd" name="confirmPwd" required/>
				    <span id="passwordMatchMessage" class="help-block"></span>
				</div>
				
				<div class="form-group has-feedback">
					<label class="control-label" for="nick">닉네임</label>
					<input class="form-control" type="text" id="nick" name="nick" required/>
					<button type="button" id="checkNickBtn">닉네임 중복확인</button>
				</div>
				
				<div class="form-group has-feedback">
					<label class="control-label" for="email">이메일</label>
					<input class="form-control" type="email" id="email" name="email" required/>
				</div>
				
				<div class="form-group has-feedback">
				    <label class="control-label" for="ncode">국가</label>
				    <select class="form-control" id="ncode" name="ncode" required>
				        <option value="">선택하세요</option>
				        <!-- option태그로 선택지를 만들어 사용. -->
				        <!-- 데이터베이스 단에서 데이터 받아서 뷰로 출력 -->
				        <c:forEach items="${countryCodes}" var="code">
				            <option value="${code}">${code}</option>
				        </c:forEach>
				    </select>
				</div>
				
				<div class="form-group has-feedback">
					<button class="btn btn-success" type="submit" id="submit" disabled>회원가입</button>
					<!-- disabled 속성으로 중복확인 안되면 사용 불가능하게 만듦. -->
					<button class="cancle btn btn-danger" type="button">취소</button>
				</div>
			</form>
		</section>
		
	<script type="text/javascript">
	    var idChecked = false;
	    var nickChecked = false;
	    var pwdChecked = false;
		
		$(document).ready(function(){
			// 취소
			$(".cancle").on("click", function(){
				location.href = "/";	    
			});
		})
		
		// 패스워드 확인
        $("#confirmPwd").keyup(function() {
	        var password = $("#pwd").val();
	        var confirmPassword = $(this).val();
	
	        if (password !== confirmPassword) {
	            $("#passwordMatchMessage").text("패스워드가 일치하지 않습니다.");
	            pwdChecked = false;
	        } else {
	            $("#passwordMatchMessage").text("패스워드가 일치합니다.");
	            pwdChecked = true;
	        }
	    });
		
		/* 아이디와 닉네임 중복확인을 위한 js사용 */
	    $(document).ready(function() {
	        $("#checkIdBtn").click(function() {
	        	
	        	var id = $("#id").val();
	            if (id === "") {
	                alert("아이디를 입력해주세요.");
	                $("#id").focus();
	                return;
	            }
	            $.ajax({
	                type: "POST",
	                url: "/checkId",
	                data: { id: id },
	                success: function(response) {
	                    if (response=="available") {
	                        alert("사용 가능합니다.");
	                        idChecked = true;
	                        checkSubmitButton();
	                    } else {
	                    	alert("중복되는 아이디입니다.");
	                        idChecked = false;
	                        checkSubmitButton();
	                    }
	                },
	                error: function() {
	                    alert("서버와 통신 중 오류가 발생했습니다.");
	                }
	            });
	        });
	    });
	    $(document).ready(function() {
		    $("#checkNickBtn").click(function() {
		    	var nick = $("#nick").val();
		        if (nick === "") {
		            alert("닉네임을 입력해주세요.");
		            $("#nick").focus();
		            return;
		        }
		        $.ajax({
		            type: "POST",
		            url: "/checkNick",
		            data: { nick: nick },
		            success: function(response) {
		                if (response=="available") {
		                    alert("사용 가능합니다.");
	                        nickChecked = true;
	                        checkSubmitButton();
		                } else {
		                    alert("중복되는 닉네임입니다.");
	                        nickChecked = false;
	                        checkSubmitButton();
		                }
		            },
		            error: function() {
		                alert("서버와 통신 중 오류가 발생했습니다.");
		            }
		        });
		    });
	    });
	    
	    function checkSubmitButton() {
	        if (idChecked && nickChecked && pwdChecked) {
	            $("#submit").prop("disabled", false);
	        } else {
	            $("#submit").prop("disabled", true);
	        }
	    }
	</script>

	</body>
</html>

 

 

 

 

3. 그리고 이 jsp파일을 가운데서 컨트롤 할

UserController파일을 따로 생성.(회원 시스템이므로 따로 컨트롤러 생성)

 

package com.project.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.ui.Model;


import com.project.model.UserVO;
import com.project.service.UserService;

@Controller
public class UserController {
	
	// @Inject와 @Autowired는 비슷하게 의존성 자동 주입 기능을 하는 어노테이션인데;
	// @Autowired는 스프링에 특화됨. 일반적이로 스프링에서 사용.
	@Autowired
	private UserService userService;
	
	// @RequestMapping(value = "/account/join", method = RequestMethod.GET)
	// @GetMapping("/account/join")
	// @RequestMapping 이것으로 모두 통합적 사용했으나,(아직 기업에서는 이것을 사용할 듯하다)
	// @GetMapping 더 직관적으로 업그레이드. 일반적으로 4.3 이상 버전에서 사용.
	@GetMapping("/account/join")
	public void getJoin(Model model) throws Exception{
		// 회원가입 페이지를 보여주는 겟코드
		// 국가 코드 리스트를 가져와서 JSP에 전달
        List<String> countryCodes = null;
        countryCodes = userService.getCountryCodes();
        model.addAttribute("countryCodes", countryCodes);
	}
	 
	@PostMapping("/account/join")
	public String joinProcess(UserVO userVo) {
		// 회원가입 처리 코드
		try {
			userService.join(userVo);
		} catch (Exception e) {
			// 예외 처리 로직 추가
			e.printStackTrace();
			// 실패 시 에러 페이지 또는 회원가입 실패 페이지로 이동하도록 처리
			return "error-page";
		}
		// 회원가입 성공 시 홈으로 리다이렉트
		return "redirect:/";
	}
	
	@PostMapping("/checkId")
    @ResponseBody
    // @ResponseBody 메서드 반환 값을 HTTP로 직접 반환.
    public String checkId(@RequestParam  String id) throws Exception {
        // ID 중복 확인 로직을 구현합니다.
        // 중복되는 ID가 있는 경우 "duplicate"를 반환하고, 사용 가능한 ID인 경우 "available"을 반환합니다.
        if (userService.isIdDuplicated(id)) {
            return "duplicate";
        } else {
            return "available";
        }
    }
	
	@PostMapping("/checkNick")
    @ResponseBody
    public String checkNick(@RequestParam  String nick) throws Exception {
        if (userService.isNickDuplicated(nick)) {
            return "duplicate";
        } else {
            return "available";
        }
    }
}

 

 

 

 

4. 그렇다면 이제 매퍼. 회원 시스템이니까 이것도 따로 만들어준다.

기존 매퍼가 있는 폴더에 accountMapper.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="com.project.mappers.account">

<!-- 회원가입 -->
<insert id="join" parameterType="com.project.model.UserVO">
 insert into
  user(id, pwd,  nick, ncode, email)
   values(#{id}, #{pwd}, #{nick}, #{ncode}, #{email}  )
</insert>

<!-- 중복 확인 시스템 -->
<select id="isIdDuplicated" parameterType="java.lang.String" resultType="java.lang.Integer">
        SELECT COUNT(*) FROM projects.user WHERE id = #{id}
</select>
<select id="isNickDuplicated" parameterType="java.lang.String" resultType="java.lang.Integer">
        SELECT COUNT(*) FROM projects.user WHERE nick = #{nick}
</select>

<!-- 국가 선택지 데이터베이스 셀렉트 -->
<select id="getCountryCodes" resultType="java.lang.String">
    SELECT code_en FROM nation ORDER BY code_en;
</select>



</mapper>

국가 선택지 테이블도 사용해보려고 따로 만들었다. 인터넷 자료 참고해서 데이터는 구축하면 된다.

 

 

 

 

5. 마지막으로 DAO와 Service 파일에 추가

UserDAO, UserDAOImpl, UserService, UserServiceImpl 파일을 기존의 model과 service패키지에 추가로 만들어 준다.

package com.project.model;

import java.util.List;

public interface UserDAO {
	
	public void join(UserVO vo) throws Exception;

	public boolean isIdDuplicated(String id);
	public boolean isNickDuplicated(String nick);
	
	public List<String> getCountryCodes();
}

UserService는 UserDAO와 인터페이스 이름만 다르고 나머지 모두 같다.

 

 

그리고, UserDAOImpl 파일에는 아래 코드 추가(실제로 데이터베이스와 상호작용하는 녀석)

 

package com.project.model;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class UserDAOImpl implements UserDAO {
	
	@Autowired
	private SqlSession sqlSession;
	 
	 private static String namespace = "com.project.mappers.account";
	
	@Override
	public void join(UserVO vo) throws Exception {
		// TODO Auto-generated method stub
		sqlSession.insert(namespace + ".join", vo);
	}

	@Override
	public boolean isIdDuplicated(String id) {
		// TODO Auto-generated method stub
		int count = sqlSession.selectOne(namespace + ".isIdDuplicated", id);
		return count > 0;
	}
	@Override
	public boolean isNickDuplicated(String nick) {
		// TODO Auto-generated method stub
		int count = sqlSession.selectOne(namespace + ".isNickDuplicated", nick);
		return count > 0;
	}
	
	// 국가 코드 리스트를 가져오는 메서드 추가
    public List<String> getCountryCodes() {
        return sqlSession.selectList(namespace + ".getCountryCodes");
    }
	

}

 

 

그리고, UserServiceImpl  파일에는 아래 코드 추가(간접적 상호작용. 보안효과)

 

package com.project.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.project.model.UserDAO;
import com.project.model.UserVO;

@Service("userService")
public class UserServiceImpl implements UserService {

	@Autowired
	private UserDAO userDAO;

	@Override
	public void join(UserVO vo) throws Exception {
		userDAO.join(vo);
	}
	
	@Override
	public boolean isIdDuplicated(String id) {
	    // 데이터베이스에서 아이디 중복 확인 로직을 구현하고 결과를 반환합니다.
	    // 예를 들어, 아이디가 이미 존재하면 true, 존재하지 않으면 false를 반환하도록 구현합니다.
	    return userDAO.isIdDuplicated(id);
	}
	@Override
	public boolean isNickDuplicated(String nick) {
	    // 데이터베이스에서 아이디 중복 확인 로직을 구현하고 결과를 반환합니다.
	    // 예를 들어, 아이디가 이미 존재하면 true, 존재하지 않으면 false를 반환하도록 구현합니다.
	    return userDAO.isNickDuplicated(nick);
	}

	@Override
	public List<String> getCountryCodes() {
		return userDAO.getCountryCodes();
	}
}

 

 

 

 

확인. 나이스. 

 

 

728x90