<(jsp)동빈나 게시판작성 참조> 카피하며 배운것들 - 2

大 炫 ·2020년 7월 20일
2

jsp게시판

목록 보기
2/2
post-thumbnail

개발환경은 ?

모든 개발환경이 최신버전으로 진행됬다. jdk14 및 이클립스2020-06 톰캣9.0 mysql8.0 mysql-connector8.0 정도로 대부분 최신버전을 사용했다. 강의를 보고 댓글을 보다보면 낮은버전으로 진행하시는분이 많은데 각자의 자유라고 생각한다. 나또한 중간에 몇번이나 mysql의 버전을 갈아치우기 일쑤였고 많은 구글링을 참고했지만, 결국 어찌어찌 굴러가는게 프로그래밍이아닐까 싶다.

개발환경 세팅

개발환경을 설치하는 포스팅은 따로 하지않겠다. 워낙 자세하게 나와있는 포스팅이 엄청나게 많기에 적당한 구글링을 해도 많은 자료를 찾을 수 있을것이다.

login.jsp(로그인/회원가입 폼)

로그인 소스와 회원가입이 같이 들어있는 페이지이다.
후에 계속 login페이지에서 loginAction으로 넘어가야하는 정보들이 무슨 이유때문인지 넘어가지 않길래 form태그가 login과 join 두개라 정보가 넘어갈때 두개의 정보를 문자열로 전부 받아서 null값을 반환하는가 싶었는데 아무런 관계없었다. 주의할건 form태그 속성에
enctype="multipart/form-data" 속성이 들어가버리니깐 무슨 이유인지 계속하여 ID값과 Password 값을 입력해도 서버에는 null값이 들어가 null값을 항상 리턴했는데 이부분은 나중에 공부를 더 해서 적겠다.(잘 모르는 부분을 복사해와서 아는체 하고싶지는 않다.)

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="css/login.css">
</head>
<body>
	<section class="container">
		<article class="half">
			<h1>Simple Note</h1>
			<div class="tabs">
				<span class="tab signin active"><a href="#signin">Sign in</a></span>
				<span class="tab signup"><a href="#signup">Sign up</a></span>
			</div>
			<div class="content">
				<div class="signin-cont cont">
					<form method="post" action="LoginAction.jsp">
						<input type="text" name="userID" class="inpt" placeholder="Your ID" maxlength="20" required> 
						<input type="password" name="userPassword" class="inpt" placeholder="Your password" maxlength="20" required> 
						<input type="checkbox" class="checkbox" checked> <label for="remember">Remember me</label>
							<div class="submit-wrap">
								<input type="submit" value="Sign in" class="submit"> 
								<a href="#" class="more">Forgot your password?</a>
							</div>
					</form>
				</div>
				<div class="signup-cont cont">
					<form method="post" action="joinAction.jsp">
						<input type="text" name="userID" class="inpt" required="required" placeholder="Your ID"> 
						<input type="password" name="userPassword" class="inpt" required="required" placeholder="Your password"> 
						<input type="text" name="userName" class="inpt" required="required" placeholder="Your name">
						<div class="submit-wrap">
							<input type="submit" value="Sign up" class="submit">
							 <a href="#" class="more">Terms and conditions</a>
						</div>
					</form>
				</div>
			</div>
		</article>
		<div class="half bg"></div>
	</section>


	<script
		src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
	<script type="text/javascript">
        $('.tabs .tab').click(function () {
            if ($(this).hasClass('signin')) {
                $('.tabs .tab').removeClass('active');
                $(this).addClass('active');
                $('.cont').hide();
                $('.signin-cont').show();
            }
            if ($(this).hasClass('signup')) {
                $('.tabs .tab').removeClass('active');
                $(this).addClass('active');
                $('.cont').hide();
                $('.signup-cont').show();
            }
        });
        $('.container .bg').mousemove(function (e) {
            var amountMovedX = (e.pageX * -1 / 30);
            var amountMovedY = (e.pageY * -1 / 9);
            $(this).css('background-position', amountMovedX + 'px ' + amountMovedY + 'px');
        });
    </script>
</body>
</html>


실제 실행을 했을 때 모습이고 출저는 블루비 웹스토어에서 가져온 소스이다.
상업적 용도없이 무료로 가져올 수 있는 소스였다. 실제 생판 모르는 로그인/회원가입 폼에 적용시켜보고 싶어서 가져왔다.
밑에 js는 클릭으로 sign in 과 sign up을 오갈 수 있게 해놓은 코드같다.

user.java (게터세터)

package user;

public class User {

	private String userID;
	private String userPassword;
	private String userName;

	public String getUserID() {
		return userID;
	}

	public void setUserID(String userID) {
		this.userID = userID;
	}

	public String getUserPassword() {
		return userPassword;
	}

	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
}

실제 로그인할때는 id와 password , 회원가입시는 name까지 입력하게끔 했기때문에 user.java파일은 이렇게 3개로만 이루어졌다. (동빈나 게시판은 email, gender 까지 적용하지만 나는 조금씩이라도 변경해보았다.) user의 정보를 private로 접근제어를 하고 세터로 값을 전달하고 게터로 값을 받아올 수 있게 끔 user의 정보에 게터세터를 적용한 모습이다.

userDAO.java(실질적 데이터베이스 테이블에 접근하는 함수)

package user;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class UserDAO {
	// JSP에서 회원 데이터베이스 테이블에 접근할 수 있도록 생성
	// DAO = Data Access Object, 실질적으로 데이터베이스에서 회원정보를 관리, 처리할때 사용

	private Connection conn;
	// DB 접근 객체

	private PreparedStatement pstmt;
	private ResultSet rs;
	// 정보를 담을 객체

	// Ctrl + Shift + O => "Organize Imports" = 클래스에 불필요한 import구문은 제거, 필요한 구문은 자동으로
	// 추가

	public UserDAO() {
		try {
			String dbURL = "jdbc:mysql://localhost:3306/bbs?characterEncoding=UTF-8&serverTimezone=UTC";
			// localhost:3306 => 내컴퓨터에 설치된 MySQL, port 3306의 BBS라는 DB에 접속

			String dbID = "root";
			String dbPassword = "root";
			Class.forName("com.mysql.jdbc.Driver");
			// MySQL에 접속할 수 있도록 매개체 역할을 해주는 하나의 라이브러리, JDBC 드라이버 로드

			conn = DriverManager.getConnection(dbURL, dbID, dbPassword);
			// DB 접속되면 conn객체에 접속정보가 저장

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public int login(String userID, String userPassword) 
	{
		String SQL = "SELECT userPassword FROM user WHERE userID = ?";
		try {
			pstmt = conn.prepareStatement(SQL); //sql쿼리문을 대기 시킨다
			pstmt.setString(1, userID); //첫번째 '?'에 매개변수로 받아온 'userID'를 대입
			rs = pstmt.executeQuery(); //쿼리를 실행한 결과를 rs에 저장
			
//			System.out.println("rs.next() :" + rs.next());
//			System.out.println("rs.getSrting(1) : " +  rs.getString(1));
//			System.out.println("userID :" + userID);
//			System.out.println("userPassword" + userPassword);
			
			if (rs.next()) // 결과가 존재한다면
			{
				if (rs.getString(1).equals(userPassword))
				// 결과로 나온 userPassword를 받아서 접속을 시도한 userPassword와 동일하다면
				{
					return 1; // 로그인 성공
				} else
					return 0; // 로그인 실패(비밀번호 틀림)

			}
			return -1; // 아이디가 없음 userID=?부분 확인
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -2; // 데이터베이스 오류
	}

	public int join(User user) {
		String SQL = "INSERT INTO USER VALUES (?,?,?)";
//		System.out.println(user.getUserID());
//		System.out.println(user.getUserPassword());
//		System.out.println(user.getUserName());

		try {
			pstmt = conn.prepareStatement(SQL);
			pstmt.setString(1, user.getUserID());
			pstmt.setString(2, user.getUserPassword());
			pstmt.setString(3, user.getUserName());
			return pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1; // DB 오류
	}
}

그리고는 userDAO.java 파일인데 코드를 보면 알겠지만 conn은 userDAO를 통해 DB에 접속되면 dbURL과 dbID, dbPassword를 conn객체에 접속정보를 저장시키는 객체라고한다.
pstmt과 rs 모두 그런 정보를 담는 객체라고 하는데 conn에 담은 정보를 pstmt에 저장시키고 다시 실행할 결과를 rs에 저장시킨다는 그런정도만 이해하고 넘어갔다.

loginAction.jsp (login창에서 입력받은 userID와userPasword를 login함수로 보내는역할)

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page import="user.UserDAO"%>
<%@ page import="java.io.PrintWriter"%>
<!-- 자바스크립트문을 작성하기 위해 사용 -->
<% request.setCharacterEncoding("UTF-8"); %>
<!-- 모든 데이터를 UTF-8로 받음 -->
<jsp:useBean id="user" class="user.User" scope="page" />
<!-- scope => 현재의 페이지에서만 빈즈 사용 -->
<jsp:setProperty name="user" property="*" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판!!</title>
</head>
<body>
	<%
	UserDAO userDAO = new UserDAO();
	int result = userDAO.login(user.getUserID(), user.getUserPassword());
	
	if (result == 1) {
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("location.href = 'main.jsp'");
		script.println("</script>");
	}
	if (result == 0) {
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('비밀번호가 틀립니다')");
		script.println("history.back()");
		script.println("</script>");
	}
	if (result == -1) {
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('존재하지 않는 아이디 입니다.')");
		script.println("history.back()");
		script.println("</script>");
	}

	if (result == -2) {
		PrintWriter script = response.getWriter();
		script.println("<script>");
		script.println("alert('데이터 베이스 오류가 발생하였습니다. ')");
		script.println("history.back()");
		script.println("</script>");
	}
	%>
</body>
</html>

로그인 폼에서 입력받은 값을 getUserID와 getUserPassword로 가져와 login함수에 인자로 넣어주어 int result값을 낸다. ID와 Password가 정상적으로 일치할때 1의 값을 반환하여 로그인 성공을 나타내고 main페이지로 넘어가게끔 설정해놓았다.

joinAction.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="user.UserDAO" %> <!-- userdao의 클래스 가져옴 -->
<%@ page import="java.io.PrintWriter" %> <!-- 자바 클래스 사용 -->
<% request.setCharacterEncoding("UTF-8"); %>
<!-- 한명의 회원정보를 담는 user클래스를 자바 빈즈로 사용 / scope:페이지 현재의 페이지에서만 사용-->
<jsp:useBean id="user" class="user.User" scope="page" />
<jsp:setProperty name="user" property="userID" />
<jsp:setProperty name="user" property="userPassword" /> 
<jsp:setProperty name="user" property="userName" />
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>jsp 게시판 웹사이트</title>
</head>
<body>
	<%
		if (user.getUserID() == null || user.getUserPassword() == null 
				|| user.getUserName() == null
			){
				PrintWriter script = response.getWriter();
				script.println("<script>");
				script.println("alert('입력이 안 된 사항이 있습니다.')");
				script.println("history.back()");
				script.println("</script>");
			} else{
				UserDAO userDAO = new UserDAO(); //인스턴스생성
				int result = userDAO.join(user);				
				if(result == -1){ // 아이디가 기본키기. 중복되면 오류.
					PrintWriter script = response.getWriter();
					script.println("<script>");
					script.println("alert('이미 존재하는 아이디 입니다.')");
					script.println("history.back()");
					script.println("</script>");
				}
				//가입성공
				else {
					session.setAttribute("userID", user.getUserID());
					PrintWriter script = response.getWriter();
					script.println("<script>");
					script.println("location.href = 'main.jsp'");
					script.println("</script>");
				}
			}
			%>
</body>
</body>
</html>

user.getUserID값이나 user.getUserPassword, user.getUserName 회원가입창에 만약 빈칸으로 회원가입신청을 한다면(null)값이라면 "입력이 안 된 사항이 있습니다"를 출력하도록 하는식이다. loginAction이나 joinAction은 비슷한 부분이 많다.

나는 이런오류가 떴어요 !

실제로 제가 많은 오류를 겪었고 그 경험담을 얘기하는거라 주관적인 부분이 많이 들어있습니다.

데이터베이스 오류입니다 !

데이터베이스 오류같은 경우는 보통 userDAO.java 파일에서 오류가 난다고 생각합니다.
생성자 부분의 try부분에서 오류가 나거나 login함수 try부분에서 오류가 나거나 인데 mysql버전에 따라 String dbURL = "~" ~값이 다른경우가 많으니까 여기저기서 바꿔서 해보시길 권장드립니다. 또 mysql id와 password 복사 붙여넣기가 아닌 자신이 설정한것에 맞게 넣었는지 확인하고 login함수부분에는 SQL문에는 오타가 없는지 잘 살펴보시길 바랍니다. 흔한경우는 아니지만 mysql에서 user테이블 안 values에 userID와 userPassword에 오타가 있을 수도 있습니다.

존재하지 않는 아이디 입니다 !(login)

입력이 안 된 사항이 있습니다 !(join)

이 둘의 문제점은 입력form에 값을 넣어도 어떤값이든 null값으로 전달되기때문에 존재하지않는 아이디 입력이 안된사항이 있는 회원가입이 일어났었다. mysql과 접속은 했지만 인자값을 전달받지 못하는 이유로는 많은 이유가 있겠지만 내경우는 form태그에 enctype="multipart/form-data" 속성 때문이었다 7~8시간 내내 끙끙 앓으며 오류를 찾고있었는데 고작 이 한줄 제거했을 뿐이었는데 login과join모두 성공하게 되었다.
내경우처럼 mysql과 연동은 된것같은데 입력값을 전달받지 못하고 계속 null값을 반환한다면 대부분 login.jsp 파일에 form태그 안에 문제가 있을것이라고 생각한다.

마무리

많은 시행착오 끝에 login과 join을 어느정도 내것으로 만들었지만 구글도 많은 도움이 되었고 okky사이트도 많은 도움이 되었다. 며칠을 끙끙 앓진 않았으니 운이 좋다고 말할 수도 있지 않을까 ?
이제 뭔가 오류를 찾아낼 수 있을것같은 그런느낌이라면 공부가 조금 된것은 아닐까 ?

profile
대현

0개의 댓글