JSP 게시판 만들기 - 3 (데이터베이스 오류해결, 로그인기능, 회원가입기능, 세션유지)

cathy·2024년 6월 11일

Projects

목록 보기
9/10
post-thumbnail

데이터베이스 오류 해결

오류 1

오류내용

tomcat은 정상적으로 실행이 되지만 login.jsp를 서버에서 실행하여 아무 회원정보를 입력하면 500에러가 발생하였다. 콘솔 로그를 살펴보니 데이터베이스 연결 풀 설정이 올바르지않다고한다. GPT에 따르면

경고 메시지에서 maxActive와 maxWait 속성이 DBCP2에서 사용되지 않으므로 각각 maxTotal과 maxWaitMillis를 사용해야 한다고 나와 있습니다.
context.xml 또는 server.xml 파일에서 데이터베이스 연결 풀 설정을 다음과 같이 변경하십시오:

<Context>
    <Resource
        name="jdbc/mysql"
        auth="Container"
        type="javax.sql.DataSource"
        driverClassName="com.mysql.cj.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/BBS"
        username="root"
        password="비밀번호"
        maxTotal="50"
        maxWaitMillis="-1"
    />
</Context>

해결과정

  • 'maxActive': DBCP2에서는 더 이상 사용되지 않으므로 'maxTotal'로 변경
  • 'maxWait' : DBCP2에서는 더 이상 사용되지 않으므로 'maxWaitMillis'로 변경

GPT의 설명대로 위와같이 context.xml 파일을 수정하니 500에러가 발생하지않았다.

mysql-connector-java.jar

또한 깜빡한 mysql-connector-java.jar 파일을 프로젝트의 lib경로에 복사해서 붙여넣어주었다. /mysql-connector-java-8.0.30

이제 project explorer에서 프로젝트(BBS) 우클릭 - build path - Configure Build Path - add JARS... 하고 프로젝트 경로의 lib 파일의 mysql-connector jar 파일을 추가해주고 Apply 해준다.


오류 2

오류내용

하지만 임의의 회원정보를 입력하였더니 아래와같이 데이터베이스 오류가 있다는 알림이 나왔다.

로그를 분석해보니

'java.sql.SQLException: No suitable driver found for dbURL' : 데이터베이스 드라이버가 없거나 올바르게 로그되지않았음을 뜻함
'java.lang.NullPointerException: Cannot invoke "java.sql.Connection.prepareStatement(String)" because "this.conn" is null' : 데이터베이스 연결객체('conn')가 null 상태임을 나타냄

해결과정

알고보니 이는 UserDAO.java에 있던 오타로 발생한 오류였다. 따옴표를 제거하였더니 정상적으로 실행되었다.

conn = DriverManager.getConnection(dbURL, dbID, dbPassword);

O

conn = DriverManager.getConnection("dbURL", "dbID", "dbPassword)";

X


로그인 로직 성공

이제 데이터베이스에 넣어둔 회원정보로 로그인을 해볼것이다.

mysql> select * from user;
+----------+--------------+-----------+------------+------------------------+
| userID   | userPassword | userName  | userGender | userEmail              |
+----------+--------------+-----------+------------+------------------------+
| yeryoong | 비밀번호    | 이름    | 여자       | yeryeong0519@naver.com |
+----------+--------------+-----------+------------+------------------------+
1 row in set (0.00 sec)

main.jsp는 아직 만들지 않아 404에러가 발생했지만 정상적으로 main.jsp로 넘어가지는것을 확인 할 수 있다.
이제 잘못된 회원정보를 입력해보자~

데이터베이스 처리가 잘 되어 존재하지 않는 아이디라는 알림이 잘 뜨는것을 확인 할 수 있다.

회원가입

회원가입 페이지 생성

우선 회원가입 화면을 JSP 파일로 만들어주었다. 데이터베이스 테이블의 내용과 같이 아이디, 비밀번호, 이름, 성별, 이메일을 입력 할 수 있다. 'type'은 입력 필드의 유형으로 이메일 타입일경우 아래 스크린샷과 같이 @이가 인식되지않아 다음 단계로 넘어가지지않는다. 'placeholder'은 입력 필드에 표시되는 안내 텍스트를 정의한다. 사용자가 입력필드에 아무것도 입력하지 않았을때 표시되는 텍스트이다. 'name'은 입력 필드의 이름을 지정한다. 폼이 제출 될 때 이 입력 필드의 값이 'userName'이나 'userGender'이라는 이름으로 서버에 전송된다. 'maxlength'는 입력필드에 입력 할 수 있는 최대 문자수를 지정한다.

/* join.jsp */
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
	crossorigin="anonymous">
<title>로그인 페이지</title>
<style>
</style>
</head>
<body>
	<nav class="navbar navbar-expand-lg navbar-light bg-light">
		<div class="container-fluid">
			<a class="navbar-brand" href="main.jsp">Green Garden</a>
			<button class="navbar-toggler" type="button"
				data-bs-toggle="collapse" data-bs-target="#navbarNav"
				aria-controls="navbarNav" aria-expanded="false"
				aria-label="Toggle navigation">
				<span class="navbar-toggler-icon"></span>
			</button>
			<div class="collapse navbar-collapse" id="navbarNav">
				<ul class="navbar-nav me-auto mb-2 mb-lg-0">
					<li class="nav-item"><a class="nav-link active"
						aria-current="page" href="main.jsp">Home</a></li>
					<li class="nav-item"><a class="nav-link" href="main.jsp">List</a>
					</li>
				</ul>
				<ul class="navbar-nav ms-auto">
					<li class="nav-item dropdown"><a
						class="nav-link dropdown-toggle" href="#" id="navbarDropdown"
						role="button" data-bs-toggle="dropdown" aria-expanded="false">member</a>
						<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
							<li><a class="dropdown-item active" href="login.jsp">sign
									in</a></li>
							<li><a class="dropdown-item" href="join.jsp">sign up</a></li>
						</ul></li>
				</ul>
			</div>
		</div>
	</nav>
	<div class="container">
		<div class="col-lg-4"></div>
		<div class="col-lg-4">
			<div class="jumbotron" style="padding-top: 20px">
				<form method="post" action="joinAction.jsp">
					<h3>Sign up and get special promotions!</h3>

					<div class="form-group">
						<input type="text" class="form-control" placeholder="Username"
							name="userID" maxlength="20">
					</div>
					<div class="form-group">
						<input type="password" class="form-control" placeholder="Password"
							name="userName" maxlength="20">
					</div>
					<div class="form-group">
						<input type="password" class="form-control" placeholder="Name"
							name="userPassword" maxlength="20">
					</div>
					<div class="form-group" style = "text-align: center;">
						<div class="btn-group" data-toggle="buttons">
							<label class="btn btn-primary active"> <input
								type="radio" name="userGender" autocomplete="off" value="남자"
								checked>남자
							</label> <label class="btn btn-primary active"> <input
								type="radio" name="userGender" autocomplete="off" value="여자"
								checked>여자
							</label>
						</div>
					</div>
					<div class="form-group">
						<input type="email" class="form-control" placeholder="Email"
							name="userEmail" maxlength="20">
					</div>
					<input type="submit" class="btn btn-primary form-control"
						value="Sign up!">
				</form>
			</div>
		</div>
	</div>

	<script
		src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
		integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
		crossorigin="anonymous"></script>
</body>
</html>

회원가입 기능 구현

UserDAO.java에 사용자 정보를 데이터베이스에 저장하는 함수를 추가하였다. 사용자가 회원가입 양식을 제출 할 때 호출되어 사용자 정보를 받아 데이터베이스에 저장한다.
'(User user)'은 이 함수가 호출 될 때 'User' 클래스의 객체를 인수로 받는다는것을 의미한다.

이제 사용자 가입을 처리하는 JSP 코드를 만들것이다. 이는 loginAction.jsp를 복사해서 수정하였다.

/* joinAction.jsp */
<%@ 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"); %>
<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" />
<jsp:setProperty name = "user" property = "userGender" />
<jsp:setProperty name = "user" property = "userEmail" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판</title>
</head>
<body>
	<%
		if (user.getUserID() == null || user.getUserPassword() == null || user.getUserName() == null
			|| user.getUserGender() == null || user.getUserEmail() == 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("location.href = 'main.jsp'");
				script.println("</script>");
			}
			else{
				PrintWriter script = response.getWriter();
				script.println("<script>");
				script.println("location.href = 'main.jsp'");
				script.println("</script>");
			}
		}
	%>
</body>
</html>

위의 코드는 사용자의 입력 값이 null인지 확인하여 필수 입력사항이 누락된 경우 경고 알림 메시지를 표시하고 이전 페이지로 돌아간다. 사용자가 모든 값을 입력하였으면 'UserDAO'객체를 생성하고, 'join' 메소드를 호출하여 회원가입을 시도한다. 만약 실패하고 결과가 -1인경우는 아이디가 이미 데이터베이스 내에 존재하는 경우로, 경고 메시지를 표시하고 main.jsp 로 리다이렉션한다. 회원가입이 성공한 경우 main.jsp로 리다이렉션한다.

'jsp:useBean'태그
javaBean 객체를 선언하고 초기화하는것이다.

<jsp:useBean id="user" class = "user.User" scope = "page" />

id = "user" : JavaBean 객체의 식별자로, 이 JSP 페이지에서 'user'라는 이름으로 객체에 접근 할 수 있다.
class = "user.User" : JavaBean 객체의 클래스입니다. 'user'패키지에 있는 'User'클래스이다.
scope = "page" : JavaBean 객체의 범위(scope)를 지정한다. 'page'는 이 JavaBean 객체가 현재 페이지에서만 유효함을 의미한다. 다른 범위로는 'request', 'session', 'application' 이 있다.

'jsp:setProperty' 태그
요청파라미터(request parameter)값을 JavaBean 객체의 속성에 설정한다.
name = "user": 'jsp:useBean' 태그에서 선언한 JavaBean 객체의 식별자이다.
property = "속성명" : 설정한 JavaBean 객체의 속성 이름이다. 요청 파라미터에서 해당 속성명에 맞는 값을 찾아 설정한다.

임의로 회원가입을 진행하고 데이터베이스를 확인해보니 정상적으로 회원정보가 추가된것을 확인 할 수 있었다.

session.setAttribute

session.setAttribute 메소드는 현제 세션에 데이터를 저장하는데 사용된다. 세션은 사용자와 서버 간의 대화상태를 유지하는 방법 중 하나로, 사용자 개별 데이터를 서버에 저장하고 해당 사용자와 여러 요청 간에 이 데이터를 유지할 수 있게 해준다.

session.setAttribute(String name, Object value);

name : 세션에 저장할 데이터의 이름(키)
value : 세션에 저장할 실제 데이터(값)

이제 loginAction.jsp 와 joinAction.jsp에 메소드를 추가해주었다. 사용자가 성공적으로 회원가입하거나 로그인했을 때 세션에 'userID'를 저장하여 이후 페이지에서도 사용자의 로그인 상태를 유지하도록한다. 이렇게 함으로써 불필요한 데이터 저장을 방지하고 필요한 경우에만 세션을 업데이트 할 수 있다.

/* loginAction.jsp */
...
UserDAO userDAO = new UserDAO();
		int result = userDAO.login(user.getUserID(), user.getUserPassword());
		if(result == 1){
			session.setAttribute("userID", user.getUserID());
			PrintWriter script = response.getWriter();
			script.println("<script>");
			script.println("location.href = 'main.jsp'");
			script.println("</script>");
		}
...

/* joinAction.jsp */
...
else{
				session.setAttribute("userID", user.getUserID());
				PrintWriter script = response.getWriter();
				script.println("<script>");
				script.println("location.href = 'main.jsp'");
				script.println("</script>");
			}
...            

0개의 댓글