본문 바로가기
자바

[MVC Model 2] JSP & Servlet 이용한 학회 홈페이지 제작

by DarrenH 2022. 8. 19.
반응형

프로젝트 기간  < 22년 1월 ~ 22년 3월 초 >

 

저희 홈페이지의 경우 제가 다니는 대학교에서 학회장을 맡고있는데 이 학회에 여러 행사와 책대여 등의 시스템이있는데, 이를 카카오톡 단체채팅방에서 다 이루어지고있기에 불편함을 느꼇습니다.

 

책 대여를 할때에는 카톡방에 책이름/대여일자/이름 이런식으로 카톡방에 올리기 때문에 매우 불편하며 관리가 힘든 상황이였습니다. 또한 학부 행사일정을 카톡으로 공지하였어도 새로운 공지사항이 올라올때마다 기존 공지가 묻히기 때문에 사람들이 잘 모르는 상황도 생겼었습니다. 이에 불편함을 느껴 22년도에 학회장을 맡고서 임원이 되기 전에 해당 프로젝트를 시작하게 되었습니다.

 

Front 1명 & Back 1명으로 해당 프로젝트를 간단하게 제작하였습니다.

 

MVC 1 Pattern으로 제작하려고했으나, 이 기회에 MVC 2 Pattern을 이용하고 싶어 Pattern2를 적용시켰습니다.

오늘은 JAVA로 홈페이지를 제작한걸 포스팅하려합니다.

 

전체 소스

https://github.com/Darren4641/Semtle_web

 

GitHub - Darren4641/Semtle_web: www.semtle-cuk.site [컴퓨터정보공학부 학회 셈틀쟁이 공식 홈페이지]

www.semtle-cuk.site [컴퓨터정보공학부 학회 셈틀쟁이 공식 홈페이지]. Contribute to Darren4641/Semtle_web development by creating an account on GitHub.

github.com

 

먼저 MVC Model로 개발을 진행하였습니다. 먼저 MVC에 대해서 설명 드리겠습니다. 

 

MVC는 약어로 Model, View, Controller로 이루어져있는데, 이에 대해 설명 드리겠습니다.

 

Model

 - 클라이언트요청으로 데이터베이스에 접근하는 클래스

View

  - 사용자에게 보여지는 화면으로 jsp와 같은 파일

Controller

 - 클라이언트에게 요청을 받고 Model에게 내용을 전달하고 View에게 전달한다. 

 

 

MVC 패턴에 대한 전체 흐름입니다.

 

MVC 패턴에는 종류가 있는데 MVC 1 Pattern과 MVC 2 Pattern이 있습니다.

+ 이후에 스프링으로 넘어가면서 MVC N Pattern 등이 있는걸로알고있습니다.

 

MVC1 Pattern에 대한 기본적인 흐름은 다음 그림과 같습니다.

MVC 1 Pattern의 경우는 규모가 작은 경우 빠르게 개발할때 주로 쓰입니다. jsp파일 안에 자바 코드가 같이 있다고 생각하시면 됩니다.

 

하지만 이 경우는 유지보수 시 jsp소스를 다시 볼때 가독성이 떨어집니다. 

이를 보완하기 위해 MVC 2 Pattern이 생겼는데요 다음 그림을 봐주세요.

 

MVC2 Pattern에 대한 기본적인 흐름은 다음 그림과 같습니다.

MVC 1 때와는 조금 다른 모습인데요 Controller와 View가 분리된것을 볼 수 있습니다. 이때 Controller는 Servlet에서 수행합니다. MVC 2 Pattern의 경우는 유지보수 시 소스의 가독성이 올라가며, 관리하기 편합니다.

 

이러한 구조로 해당 프로젝트를 진행 하였습니다. 

 

개발 환경

개발 툴 : Eclipse

- Java 1.8

- Mysql

- Apache Tomcat 9

 

그럼 소스코드를 살펴보겠습니다. 

 

먼저 파일의 디렉토리 구조입니다. 

 

먼저 Maven 입니다.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Semtle_Web_1.0</groupId>
  <artifactId>Semtle_Web_1.0</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
          <warSourceDirectory>WebContent</warSourceDirectory>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
  	<dependency>
  		<groupId>jstl</groupId>
  		<artifactId>jstl</artifactId>
  		<version>1.2</version>
  	</dependency>
  	<dependency>
  		<groupId>servlets.com</groupId>
  		<artifactId>cos</artifactId>
  		<version>05Nov2002</version>
  	</dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>
      	<dependency>
  		<groupId>org.apache.tomcat</groupId>
  		<artifactId>tomcat</artifactId>
  		<version>9.0.45</version>
  		<type>pom</type>
  	</dependency>
      	<dependency>
      		<groupId>com.googlecode.json-simple</groupId>
      		<artifactId>json-simple</artifactId>
      		<version>1.1.1</version>
      	</dependency>
      	<dependency>
      		<groupId>com.google.code.gson</groupId>
      		<artifactId>gson</artifactId>
      		<version>2.8.7</version>
      	</dependency>
  </dependencies>
</project>

 

톰캣 관련 설정을 위한 Context.xml 파일입니다.

<?xml version="1.0" encoding="UTF-8"?>
<context>
	<Resource name="jdbc/DB_sem"
            auth="Container"
            type="javax.sql.DataSource"
            driverClassName="com.mysql.jdbc.Driver"
            factory="org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory" 
            username="DB_Id"
            password="DB_Password"
            url="jdbc:mysql://mysql IP 주소:3306/DB_sem?useSSL=false"
            maxWait="5000" 
	/>
</context>

JDBC를 이용하여 제작하였습니다.

 

그럼 이제 Controller(Servlet) 부터 보여드리겠습니다.

package com.User;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class UserController
 */
@WebServlet("*.do")
public class UserController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UserController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("doGet");
		doAction(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("doPost");
		doAction(request, response);
	}
	
	private synchronized void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("do UserController");
		
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		HttpSession session = request.getSession();
		PrintWriter writer = response.getWriter();
		String title = "";
		String viewPage = null;
		
		UserCommand command = null;
		
		String requestUri = request.getRequestURI();
		String contextPath = request.getContextPath();
		System.out.println("requestURi : " + requestUri);
		System.out.println("ContextPath : " + contextPath);
		String commandName = null;
		
		viewPage = requestUri;
		commandName = viewPage.substring(contextPath.length());
		
		System.out.println("commandName : " + commandName);
		
		try {
			if(commandName.equals("/signup_user.do" )) {
				viewPage = "/semtle/User/signup.jsp";
				title = "회원가입";
				session.setAttribute("title", title);
			}else if(commandName.equals("/signup.do")) {
				command = new UserSignupCommand();
				command.execute(request, response);
				viewPage = "/semtle/index.jsp";
			}else if(commandName.equals("/login.do")) {
				command = new UserLoginCommand();
				if(command.execute(request, response) == 1) {
					command = new UserInfoCommand();
					command.execute(request, response);
					viewPage = "";
				}else {
					writer.println("<script>alert(\"아이디 또는 비밀번호가 맞지 않습니다.\"); history.go(-1);</script>");
					writer.close();
					viewPage = "/login.do";
				}
				title = null;
				session.setAttribute("title", title);
			}else if(commandName.equals("/confirmId.do")) {
				command = new UserConfirmIdCommand();
				command.execute(request, response);
				viewPage = "/semtle/signup.jsp";
				title = "회원가입";
				session.setAttribute("title", title);
			}else if(commandName.equals("/updateInfo.do")) {
				command = new UserModifyCommand();
				command.execute(request, response);
				viewPage = "login_form.do";
				title = "정보 수정";
				session.setAttribute("title", title);
			}else if(commandName.equals("/userInfo.do")) {
				command = new infoCntCommand();
				command.execute(request, response);
				viewPage = "/semtle/User/mypage.jsp";
				title = "내 정보";
				session.setAttribute("title", title);
			}else if(commandName.equals("/userUpdate.do")) {
				viewPage = "/semtle/User/mypage_info.jsp";
				title = "정보 수정";
				session.setAttribute("title", title);
			}else if(commandName.equals("/infoBook.do")) {
				title = "대여 목록";
				session.setAttribute("title", title);
				command = new infoBookCommand();
				command.execute(request, response);
				viewPage = "/semtle/User/infoBook.jsp";
			}else if(commandName.equals("/infoPost.do")) {
				title = "내가 쓴 글";
				session.setAttribute("title", title);
				command = new infoPostCommand();
				command.execute(request, response);
				viewPage = "/semtle/User/infoPost.jsp";
			}
			else if(commandName.equals("/login_form.do")){
				viewPage = "/semtle/User/login.jsp";
				title = "로그인";
				session.setAttribute("title", title);
			}else if(commandName.equals("/home.do")) {
				viewPage = "";
				title = null;
				session.setAttribute("title", title);
			}else if(commandName.equals("/logout.do")) {
				command = new UserLogoutCommand();
				command.execute(request, response);
			}else if(commandName.equals("/kakao_login.do")) {
				viewPage = "/semtle/index.jsp";
				command = new kakaoLoginCommand();
				command.execute(request, response);
				title = null;
				session.setAttribute("title", title);
				
			}else {
				System.out.println("해당 Command가 없습니다.");
				viewPage = "notCommand.jsp";
			}
			
			RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage);
			dispatcher.forward(request, response);
		}catch(IllegalStateException e) {
			System.out.println("Illegal");
		}
	}

}

보시면 @WebServlet("*.do")로 어노테이션을 달아주었는데요, 이제 홈페이지 url요청 확장자? 패턴을 *.do로 설정해주었습니다.

 

HttpServlet을 상속받게 되면 이제 doGet, doPost메소드를 오버라이딩할수 있게됩니다.

사용자가 Server에게 요청시 Get방식과 Post방식일때 어떠한 동작을 수행할지 적어주면 됩니다.

 

저는 따로 메서드를 추출하여 작성하였는데요 doAction메소드를 살펴보겠습니다.

 

저희 프로젝트의 Login방식은 Session을 이용하였습니다. 

 

코드를 보시면 commandName이 있는데 이는 Front에서 값을 이렇게 넘겨주면

<a href="signup_user.do">Sign Up</a>

UserController가 "signup_user.do"를 commandName 변수에 저장하게 됩니다. 이를 이용해서 if문으로 각 commandName에 따른 동작을 수행해주었습니다.

 

소스를 보시면 알 수 있듯이 디자인패턴을 적용시켰는데요. CommandPattern을 적용시켜 코드를 간결하게 정리했습니다.

if(commandName.equals("/signup_user.do" )) {
				viewPage = "/semtle/User/signup.jsp";
				title = "회원가입";
				session.setAttribute("title", title);
			}

이부분을 보시면 단순히 페이지이동을 시켜주는 부분인데 Get방식입니다. 하지만 이프로젝트에서 저는 doAction 메소드를 이용해 get일때와 post일때 모두 doAction을 타게됩니다. 원래는 doGet에는 Get방식만, doPost에는 Post방식만 적용하는게 더 보기편할수있는데 저는 간단하게 만들기 위해 해당 코드처럼 작성하였습니다. 

 

커맨드패턴을 쓰기위해 Command.interface를 작성해주었습니다.

package com.User;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface UserCommand {
	
	int execute(HttpServletRequest request, HttpServletResponse response) throws IOException;
}

이런 식으로 커맨드별로 클래스를 따로 뺀 뒤 UserCommand를 implements하여 excute를 구현하여 각 Command마다 다른 동작을 하게끔 코드를 짜주시면 됩니다.

 

회원가입 로직을 설명드리겠습니다. 

 

package com.User;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class UserSignupCommand implements UserCommand{
	
	@Override
	public int execute(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// TODO Auto-generated method stub
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		sdf.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));
		int grade = Integer.parseInt(request.getParameter("grade"));
		String nickName = request.getParameter("nickName");
		int userCode = Integer.parseInt(request.getParameter("userCode"));
		String userName = request.getParameter("userName");
		String userId = request.getParameter("userId");
		String userPassword = request.getParameter("userPassword");
		String userEmail = request.getParameter("userEmail");
		String userPhone = request.getParameter("userPhone");
		String userRole = "셈틀회원";
		String createAt = sdf.format(new Timestamp(System.currentTimeMillis()));
		String updateAt = sdf.format(new Timestamp(System.currentTimeMillis()));
		String status = "1";
		userDAO dao = userDAO.getInstance();
		dao.signUp(grade, nickName, userCode, userName, userId, userPassword, userEmail, userPhone, userRole, createAt, updateAt, status);
		
		PrintWriter writer = response.getWriter();
		writer.println("<script>alert('셈틀회원이 되신걸 축하합니다~~'); location.href='home.do';</script>");
		writer.close();
		
		userDTO dto = dao.selectInfo(userId, userPassword);
		
		return 1;

	}
	/* 참고 자료 https://chrismare.tistory.com/entry/MVC-%ED%8C%A8%ED%84%B4Model1-Model2 */
}

 

회원가입시 저희는 Front측에서 값을 가져옵니다. 해당 값은 Form에서 가져오기때문에 다음과 같이 작성해주었습니다. 

 

 

그럼 UserDAO 클래스를 살펴보겠습니다.

 

package com.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.DB.DBDAO;

public class userDAO {

	private static userDAO instance = null;
	//싱글톤 정적변수
	private static DBDAO db = DBDAO.getInstance();
	
	private Connection conn = null;
	private PreparedStatement pstmt= null;
	private ResultSet rs = null;
	
	
	//싱글톤 패턴
	public static userDAO getInstance() {
		if(instance == null)
			instance = new userDAO();
		
		return instance;
	}
	
	//private 로 기본 생성자 차단
	private userDAO() { }
	
	//회원가입 메소드
	public void signUp(int grade, String nickName, int userCode, String userName, String userId, String userPassword, String userEmail, String userPhone, String userRole, String createAt, String updateAt, String status) {
		String query = 
				"INSERT INTO `DB_sem`.`User`" + 
				"(" + 
					"`grade`," +
					"`nickName`," + 
					"`userCode`," +
					"`userName`," + 
					"`userId`," + 
					"`userPassword`," + 
					"`userEmail`," + 
					"`userPhone`," + 
					"`userRole`," + 
					"`createdAt`," + 
					"`updateAt`," + 
					"`status`" + 
				")" + 
				"VALUES" + 
				"(" +
					"?," +
					"?," +
					"?," + 
					"?," + 
					"?," + 
					"?," + 
					"?," + 
					"?," + 
					"?," + 
					"?," + 
					"?," + 
					"?" + 
				")"; 
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			
			pstmt.setInt(1,  grade);
			pstmt.setString(2, nickName);
			pstmt.setInt(3,  userCode);
			pstmt.setString(4,  userName);
			pstmt.setString(5,  userId);
			pstmt.setString(6,  Utility.encoding(userPassword));
			pstmt.setString(7,  userEmail);
			pstmt.setString(8,  userPhone);
			pstmt.setString(9,  userRole);
			pstmt.setString(10,  createAt);
			pstmt.setString(11,  updateAt);
			pstmt.setString(12,  status);
			
			pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		
	}
	
	//사용자 로그인 
	public int login(String id, String passwd) {
		int check = -1;
		String query = 
				"select * from User where userId = ? and userPassword = ? and status = '1'";
		
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			pstmt.setString(1, id);
			pstmt.setString(2, Utility.encoding(passwd));
			
			rs = pstmt.executeQuery();
			
			if(rs.next()) 
				check = 1;
			else
				check = 0;
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		return check;
	}
	
	//정보 조회
	public userDTO selectInfo(String userId, String userPassword) {
		userDTO user = null;
		String query = 
				"select * from User where userId = ? and userPassword = ? and status = '1'";
		
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			
			pstmt.setString(1, userId);
			pstmt.setString(2, Utility.encoding(userPassword));
			
			rs = pstmt.executeQuery();
			if(rs.next()) {
				user = new userDTO();
				user.setGrade(rs.getInt("grade"));
				user.setNickName(rs.getString("nickName"));
				user.setUserCode(rs.getInt("userCode"));
				user.setUserId(rs.getString("userId"));
				user.setUserName(rs.getString("userName"));
				user.setUserPassword(rs.getString("userPassword"));
				user.setUserEmail(rs.getString("userEmail"));
				user.setUserPhone(rs.getString("userPhone"));
				user.setUserRole(rs.getString("userRole"));
				user.setStatus(rs.getString("status"));
				
			}
		}catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		
		return user;
	}
	
	//정보 변경
	public int updateInfo(int grade, String nickName, int userCode, String userName, String userEmail, String userPhone, String status, String updateAt, String userId) {
		int x = -1;
		String query = 
				"UPDATE `DB_sem`.`User`" + 
					"SET" + 
					"`grade` = ?," +
					"`nickName` = ?," + 
					"`userCode` = ?," +
					"`userName` = ?," + 
					"`userEmail` = ?," + 
					"`userPhone` = ?," + 
					"`status` = ?," +
					"`updateAt` = ?" +
				"WHERE `userId` = ?";
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			
			pstmt.setInt(1,  grade);
			pstmt.setString(2, nickName);
			pstmt.setInt(3,  userCode);
			pstmt.setString(4,  userName);
			pstmt.setString(5,  userEmail);
			pstmt.setString(6,  userPhone);
			pstmt.setString(7,  status);
			pstmt.setString(8,  updateAt);
			pstmt.setString(9,  userId);
			
			pstmt.executeUpdate();
			x = 1;
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		
		return x;
	}
	
	//ID 중복체크
	public int confirmId(String id) {
		int x = -1;
		String query = 
				"select userId from User where userId = ?";
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			pstmt.setString(1, id);
			
			rs = pstmt.executeQuery();
			
			if(rs.next())
				x = 1;   //중복
			else
				x = -1;  //사용 가능
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		return x;
	}
	
	//비밀번호 변경
	public int changePassword(String id, String passwd) {
		int x = -1;
		String query =
				"update User set userPassword = ? where userId = ?";
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			pstmt.setString(1, Utility.encoding(passwd));
			pstmt.setString(2, id);
			
			pstmt.executeUpdate();
			x = 1;
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		
		return x;
	}
	
	//아이디 찾기
	public String findUserId(String userName, int grade, int userCode) {
		String id = "";
		String query = 
				"select userId from User where userName = ? and grade = ? and userCode = ?";
		
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			pstmt.setString(1, userName);
			pstmt.setInt(2, grade);
			pstmt.setInt(3,  userCode);
			
			rs = pstmt.executeQuery();
			
			if(rs.next()) 
				id = rs.getString("userId");
			else
				id = null;
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		
		return id;
	}
	
	//<관리자> 회원수 조회
	public int getUserCnt() {
		int cnt = 0;
		
		String query = 
				"select count(*) from User";
		
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			
			rs = pstmt.executeQuery();
			
			if(rs.next())
				cnt = rs.getInt(1);
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		
		return cnt;
	}
	
	//<관리자>사용자 목록 출력
	public List<userDTO> getUserList(int start, int end) {
		List<userDTO> userlists = null;
		String query = 
				"SELECT `User`.`grade`," +
					"`User`.`nickName`," + 
					"`User`.`userName`," + 
					"`User`.`userId`," + 
					"`User`.`userPassword`," + 
					"`User`.`userEmail`," + 
					"`User`.`userPhone`," + 
					"`User`.`userRole`," + 
					"`User`.`createdAt`," + 
					"`User`.`updateAt`," + 
					"`User`.`status`" + 
				"FROM `DB_sem`.`User` order by createdAt desc limit ?,?";
		
		try {
			conn = db.getConnection();
			pstmt = conn.prepareStatement(query);
			
			pstmt.setInt(1,  start - 1);
			pstmt.setInt(2,  end);
			rs = pstmt.executeQuery();
			
			if(rs.next()) {
				userlists = new ArrayList<userDTO> (end);
				do {
					userDTO article = new userDTO();
					article.setGrade(rs.getInt("grade"));
					article.setNickName(rs.getString("nickName"));
					article.setUserName(rs.getString("userName"));
					article.setUserCode(rs.getInt("userCode"));
					article.setUserId(rs.getString("userId"));
					article.setUserPassword(rs.getString("userPassword"));
					article.setUserEmail(rs.getString("userEmail"));
					article.setUserPhone(rs.getString("userPhone"));
					article.setUserRole(rs.getString("userRole"));
					article.setCreateAt(rs.getString("createdAt"));
					article.setUpdateAt(rs.getString("updateAt"));
					article.setStatus(rs.getString("status"));
					
					userlists.add(article);
				}while(rs.next());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(rs != null) try {rs.close();}catch(SQLException ex ) {}
			if(pstmt != null) try {pstmt.close();}catch(SQLException ex) {}
			if(conn != null) try {conn.close();}catch(SQLException ex) {}
		}
		
		return userlists;
	}
	
}

JDBC를 이용하였으며 이 UserDAO클래스는 싱클톤패턴을 이용하였습니다. 객체를 여러개 생성할 필요가없고 자원낭비인거같아 싱글톤을 적용 시켰습니다.

그리고 try-catch구문 다음으로 finally로 항상 rs, pstmt, conn을 닫아주셔야합니다. 그래야 sql에서 과부하가 안옵니다.

 

보시면 사용자의 비밀번호는 RSAKey를 이용하여 암호화를 진행하였습니다.

 

UserDTO클래스입니다.

package com.User;


public class userDTO {
	private int grade;
	private String nickName;
	private int userCode;
	private String userName;
	private String userId;
	private String userPassword;
	private String userEmail;
	private String userPhone;
	private String userRole;
	private String createAt;
	private String updateAt;
	private String status;
	
	public int getGrade() {
		return grade;
	}
	public int getUserCode() {
		return userCode;
	}
	public String getUserName() {
		return userName;
	}
	public String getUserId() {
		return userId;
	}
	public String getUserPassword() {
		return userPassword;
	}
	public String getUserEmail() {
		return userEmail;
	}
	public String getUserPhone() {
		return userPhone;
	}
	public String getUserRole() {
		return userRole;
	}
	public String getCreateAt() {
		return createAt;
	}
	public String getUpdateAt() {
		return updateAt;
	}
	public String getStatus() {
		return status;
	}
	public void setGrade(int grade) {
		this.grade = grade;
	}
	public void setUserCode(int userCode) {
		this.userCode = userCode;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}
	public void setUserEmail(String userEmail) {
		this.userEmail = userEmail;
	}
	public void setUserPhone(String userPhone) {
		this.userPhone = userPhone;
	}
	public void setUserRole(String userRole) {
		this.userRole = userRole;
	}
	public void setCreateAt(String createAt) {
		this.createAt = createAt;
	}
	public void setUpdateAt(String updateAt) {
		this.updateAt = updateAt;
	}
	public void setStatus(String status) {
		this.status = status;
	}
	public String getNickName() {
		return nickName;
	}
	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

}

 

이렇게 UserSignUpCommand를 다끝내고 나면 다시 UserController로 가서 

사용자에게 보여줄 페이지를 index 페이지를 ReDirect해줍니다. 

 

+) 추가자료로 index.jsp 소스를 첨부하겠습니다. Controller의 값을 이용하기 위해 jstl을 사용하였습니다.

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

<!DOCTYPE html> 
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="${pageContext.request.contextPath}/semtle/css/style.css" />
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;500;700&display=swap" rel="stylesheet" />
	<link rel="shortcut icon" href="${pageContext.request.contextPath}/semtle/images/favicon.ico" type="image/x-icon" sizes="16X16">
	<link rel="icon" href="${pageContext.request.contextPath}/semtle/images/favicon.ico" type="image/x-icon" sizes="16X16">
    <link rel="stylesheet" href="https://unpkg.com/swiper@7/swiper-bundle.min.css" />

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" />
  </head>
  <body>   
	

    <section class="home">
    <jsp:include page="${pageContext.request.contextPath}/semtle/header.jsp" flush="true" />
      <div class="home-main">
        <img src="${pageContext.request.contextPath}/semtle/images/logo.PNG" alt="" />
        <h3>셈틀쟁이</h3>
      </div>
    </section>

    <section class="member">
      <div class="member-box">
        <div class="member-main1">
		<c:choose>
			<c:when test="${not empty userInfo.userId}">
				<c:set var="userId" value="${userId}" />
		          <div class="member-subject">셈하 :)</div>
		          <div class="member-header">
					<h3>${userInfo.userName}</h3>
		            <span> 님 환영합니다</span>
		          </div>
		        </div>
		        <div class="member-main2">
		          <img src="${pageContext.request.contextPath}/semtle/images/char.PNG" alt="" />
		        </div>
	        </c:when>
	        <c:otherwise>
				<div class="member-subject"></div>
         			 <div class="member-header">
						<h3><a href="login_form.do">로그인</a></h3>
           					 <span> 해주시기 바랍니다.</span>
         			</div>
        		</div>
		        <div class="member-main2">
		          <img src="${pageContext.request.contextPath}/semtle/images/char.PNG" alt="" />
		        </div>
	        </c:otherwise>
		</c:choose>
      </div>
    </section>

    <section class="calendar">
      <div class="calendar-subject">
        <span>셈틀 일정</span>
        <i class="fas fa-angle-right"></i>
      </div>
      <div class="calendar-box">
      	<jsp:include page="${pageContext.request.contextPath}/semtle/calendar.jsp" flush="true" />
      </div>
    </section>

	<section class="notice">
      <div class="notice-subject">
        <a href="notice.jsp"><span>공지사항</span></a>
        <a href="notice.jsp"><i class="fas fa-angle-right"></i></a>
      </div>

      <div class="notice-box">
        <div class="notice-heading">
          <h3>셈틀쟁이는 어떤 학회인가요?</h3>
          <i class="fas fa-angle-down"></i>
        </div>
        <div class="notice-content" id="thisone">
          <p>셈틀쟁이는 컴퓨터정보공학부 학회로써 학회원들에게 스터디와 여러 활동 (엠티, 개강파티, 종강파티)를 하는 컴퓨터정보공학을 1전공, 2전공 하시는 분이라면 모두 가입가능한 학회입니다 :)</p>
        </div>
      </div>

      <div class="notice-box">
        <div class="notice-heading">
          <h3>셈틀쟁이 웹은 어떻게 이용하나요?</h3>
          <i class="fas fa-angle-down"></i>
        </div>
        <div class="notice-content">
          <p>회원가입 하시면 관리자 승인에 의해 활동을 하실 수 있습니다~~</p>
        </div>
      </div>
    </section>
    <div class="book">
      <div class="book-subject">
        <span> 책 대여</span>
        <i class="fas fa-angle-right"></i>
      </div>
    	<jsp:include page="${pageContext.request.contextPath}/semtle/booker.jsp" flush="true" />
	</div>
	<jsp:include page="${pageContext.request.contextPath}/semtle/footer.jsp" flush="true" />
  </body>
</html>

 

 

이런 방식으로 구성하였으며, 추가로 KaKaoTalk 로그인 및 multipart/form-data도 이용하였는데 이와 관련해서는 다음에 포스팅하겠습니다. 

 

참고자료

https://chrismare.tistory.com/entry/MVC-%ED%8C%A8%ED%84%B4Model1-Model2

 

 

셈틀쟁이 학회 홈페이지 (AWS FreeTier 기간이 끝나면 접속이 안될수 있습니다.)

http://www.semtle-cuk.site/

 

SemtleWeb

셈틀쟁이는 컴퓨터정보공학부 학회로써 학회원들에게 스터디와 여러 활동 (엠티, 개강파티, 종강파티)를 하는 컴퓨터정보공학을 1전공, 2전공 하시는 분이라면 모두 가입가능한 학회입니다 :)

www.semtle-cuk.site

 

반응형