본문 바로가기
프로젝트/자바 빈과 JSP만을 사용한 게시판 만들기

11장 메인 페이지와 로그인 처리 만들기

by IT여행자 2020. 5. 10.
728x90

프로젝트의 시작과 전체 페이지의 운영을 담당하는 메인 페이지를 만들겠습니다. 

 

A. 관련 파일명

  • WebContent/index.jsp, header.jsp, footer.jsp, log.jsp, login_out.jsp
  • WebContent/css/index.css, board.css
  • WebContent/js/index.js, board.js

메인 페이지에서 구현할 기능은 아래와 같습니다.

  • 전체 레이아웃 구성.
  • 로그인 여부에 따른 로그인/로그아웃 페이지 표시
  • 메뉴나 사용자 요청에 따른 페이지 처리

 

A.1 전체 레이아웃 설정

 

전체 페이지 골격

위의 그림과 같은 골격을 갖기 위해 먼저 index.jsp 페이지에서 태그들을 사용하여 기초작업을 합니다. HTML5에 의하면 메뉴나 링크 모임 같은 것은 <nav/> 태그를, 헤더는 <header/> 등등을 구분하여 선언해야 하지만 편의상(^^) 모두 <div/> 태그를 사용하여 기초를 세우겠습니다.

 


 

B. Web

 

B.1 메인 페이지(index.jsp)

 

작업 파일 : WebContent/index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>JavaBean+JSP</title>
	
	<!-- 메인페이지와 게시판에서 사용될 css -->
	<link rel='stylesheet' type='text/css' href='./css/index.css'>
	<link rel='stylesheet' type='text/css' href='./css/board.css'>
	
	<!-- 메인페이지와 게시판에서 사용될 자바스크립트 -->
	<script src='./js/index.js'></script>
	<script src='./js/board.js'></script>

</head>
<body>
<%
request.setCharacterEncoding("utf-8");
String inc = "./board/select.jsp";
if(request.getParameter("inc") != null){
	inc = request.getParameter("inc");
}

%>
<div id='index'>
	<!-- login, logout 상태 -->
	<%@include file="log.jsp" %>
	
	<!-- header -->
	<%@include file="header.jsp" %>
	
	<div id='content'>
		<jsp:include page="<%=inc %>"></jsp:include>
	</div>

	<!-- footer -->
	<%@include file="footer.jsp" %>

</div>

<script>
	index.login(); /* 로그인/로그아웃에서 사용될 기능들  */ 
	board.btn();   /* 게시판의 각종 버튼 기능 구현 ) */
</script>
</body>
</html>

 

모든 페이지를 하나의 페이지에서 모두 구현하지 않고 login 영역, header영역과 footer 영역은 외부 파일을 정적 삽입으로 처리하였고, content영역은 메뉴나 사용자 요청에 따라 서로 다른 페이지가 로딩되어야 하기 때문에 동적 삽입으로 처리하였습니다.

 

  • 21~24행 

맨 처음 index 페이지가 실행될 때 content 영역엔 변수 inc에 기본 값으로 저장된 페이지(./board/list.jsp)가 동적으로 삽입될 것이고, 메뉴나 사용자의 요청에 따른 페이지 정보가 바뀌면 inc변수에 값이 동적으로 삽입되어 해당 페이지가 content 영역에 표시됩니다.

 

자바스크립트 부분을 보면 대부분 아래와 같은 방법으로 값이 전달됩니다.

let url = 'index.jsp?inc=./board/';
...
frm.action = url + 'select.jsp';
frm.submit();

 

  • 34~36행

JSP의 액션 태그인 <jsp:include/>를 사용하여 page 속성에 지정된 파일명을 동적으로 삽입합니다. request.getParameter("inc")를 사용하여 사용자가 전달한 값을 가져옵니다. 값을 전달하는 방법은 크게 두 가지가 있을 수 있습니다.

 

첫 번째 방법 : URL(GET 타입)으로 전달하기

http://localhost/index.jsp?inc=./board/select.jsp

파라미터 변수 inc에 './board/select.jsp' 값이 대입되어 전달됩니다. 이때 주의할 사항은 전달될 값 사이에 빈공 백이 포함되어 있지 않아야 합니다. 정확하게는 빈 공백 문자도 값의 일부분으로 인식되어 전달됩니다.

 

두 번째 방법 : form(POST 타입)으로 전달하기

<form action = 'index.jsp' method='POST">
   <input type='hidden' name='inc' value='./board/select.jsp' />
    <input type='submit' />
</form>


어떤 방법으로 전달하든 상관없이 모두 request.getParameter("inc")로 받습니다.

 

  • 44~45행

자바스크립트의 객체 종류 중 하나인 리터럴 객체 index = {}와 board={}를 선언하여 해당 리터럴 객체 내에 login() 함수와 btn() 함수를 만들어 로그인과 로그 아웃에 해당하는 버튼 처리를 하였습니다. 자바 스크립트 코드에 아래와 같이 선언되어 있습니다.

// index.js
var index = {};
index.login = function(){ ... };

// board.js
var board={};

board.btn = function(){ ... };

 

 

B.2 로그인 페이지(log.jsp)

 

메인 페이지의 맨 상단에 삽입되어 로그인 상태에 따라 서로 다른 모양의 페이지를 표시해 줍니다.

<!-- log.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
request.setCharacterEncoding("utf-8"); //한글 깨짐 방지
String session_id = (String)session.getAttribute("session_id");
%>    
    
<div class='login'>
	<form name='frm_login' id='frm_login' method='post'>
		<!-- 공통 -->
		<input type='hidden' name='loginFlag' value='' />
		
		<%if(session_id == null) {%>		
			<!-- 로그인 이전 화면 -->
			<label>아이디</label>
			<input type='text' size='7' name='mid'/>
			<label>암호</label>
			<input type='password' size='7' name='pwd'/>
			<input type='button' value='로그인' id='btnLogin'/>
		<%}else{ %>	
			<!-- 로그인 이후 화면 -->
			<span><%=(session_id == null)? "손님" : session_id %> 방가...방가...</span>
			<input type='button' value='로그아웃' id='btnLogout'/>
		<%} %>
	</form>
</div>
  • 7행

session영역에 저장된 속성 중에 'session_id' 값을 가져와 변수에 저장하였습니다. 저장된 변수 값이 null 이면 로그인 화면을, 값이 있으면 로그아웃 화면을 보여줍니다.

 

  • 13행

로그인 버튼을 클릭하면 loginFlag='login' 값이, 로그아웃 버튼이 클릭되면 loginFlag='logout' 값이 대입되어 전달되며 이는 BoardController에 의해서 구분되어 loin인 인 경우 session에 값을 넣고, logout인 경우에는 session의 값을 제거하는 작업을 합니다.

 

 

B.3 로그인/로그아웃 처리(login_out.jsp)

 

log.jsp 페이지에 있는 로그인 버튼이나 로그아웃 버튼이 클릭되면 <form/>에 정보가 저장되어 호출되는 페이지입니다. 

<%@page import="bean.BoardController"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
request.setCharacterEncoding("utf-8"); //한글 깨짐 방지
BoardController ctrl = new BoardController(request, response);

ctrl.loginCheck();//session에 mid를 저장하거나 session의 속성값 제거

%> 
<script>
location.href='./index.jsp';
</script>
  • 6행

사용자의 요청 처리 정보(request)와 응답 정보(response)를 매개변수로 BoardController 클래스가 생성됩니다. 본 프로젝트에서 사용자의 요청 처리는 모두 BoardController가 처리할 것입니다.

 

  • 8행

사용자의 요청 정보를 분석하여 session에 값을 저장할지, 저장된 값을 제거할지를 처리하는 메서드입니다.

 

 

B.4 상단 페이지(header.jsp)

 

header 영역에 메뉴를 우측 하단에 배치할 예정입니다. HTML만으로는 완전한 레이아웃을 보여줄 수는 없습니다. 전체적인 구조만 살펴보시기 바랍니다.  class='header' 영역에는 CSS를 사용하여 바탕 이미지를 넣을 것이고, class='menu'는 CSS를 사용하여 header영역의 우측 하단에 배치할 예정입니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<div class='header'>
	<span>자바빈+JSP만으로 만든 게시판</span>
	
	<div class='menu'>
		<a href='index.jsp'>HOME</a>
		<a href='index.jsp?inc=./board/select.jsp'>게시판</a>
	</div>
	
</div>   

 

B.5 하단 페이지(footer.jsp)

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<div class='footer'>
	<span>JOBTC.KR</span>
	<h6>
		Job Training Center of Korea
	</h6>
</div>

 


C. CSS

 

 

C.1 index.jsp의 CSS

 

본 프로젝트의 콘셉트가 퍼블리싱이나 디자인이 아니기 때문에 될 수 있으면 이와 관련된 내용은 최소화하도록 하겠습니다. 심지어 요즘은 필수가 돼버린 반응형이나 모바일 페이지의 디자인 요소도 배제하겠습니다.

 

header영역에 바탕 이미지를 넣기 위해서는 WebContent/images/back.png 파일이 필요합니다.

 

작업 파일 : WebContent/css/index.css

 

@charset "UTF-8";

/* 모든 태그들의 기본 속성 */
*{
	padding: 0;
	margin: 0;
}
/* body안에 있는 모든 글자크기 지정*/
body{
	font-size:10pt;
}

/* 앵커 태그의 밑줄 제거 */
a{
	text-decoration: none;
}

#index{
	width:1000px;
	margin:0 auto;
	background: #fff;
}
/* 로그인 영역에 있는 폼태그를 화면의 오른쪽으로 */
#index .login{
	text-align: right;
	height:25px;
}

/* header 영역 ------------------------------ */
#index .header{
	position:relative;
	height:150px;
	background-image : url(../images/back.png);
	
}
#index .header>span{
	position: absolute;
	font-size:20pt;
	color:#ffff44;
	font-weight: bold;
	margin-left:20px;
	margin-top:15px;	
}

/* header 메뉴 부분 */
#index .header .menu{
	position:absolute;
	right:3px;
	bottom:3px;
	background: #8888ff88;
}
#index .header .menu a{
	display :inline-block;
	text-align:center;
	width:90px;	
	height:28px;
	line-height: 28px;
}
#index .header .menu a:hover{
	border-bottom-width:30px;
	background: #7777ff44;
	color:#eee;
}


#index .content{
	
}
/* index 영역 안쪽에서 항상 밑으로 */
#index .footer{
	width:100%;
	height:100px;
	background:#aaf;
	bottom:0;
	padding:24px;
	box-sizing:border-box;
	font-size:25px;
	text-align:center;
	background:#555; 
	color:#ffff99;
	margin-top:10px;
}

#index .footer h6{
	margin:0;
	padding:0;
	font-size:10px;
	
}

 

CSS 파일을 작성한 후 index페이지를 실행하면 아래와 같은 페이지 모양이 나옵니다.

 

[실행결과]

 

CSS만 적용된 화면

 


D. Session 제어하기

 

D.1 서버의 scope 종류와 특징

 

로그인/로그아웃 처리를 이해하기 위해서는 웹서버가 갖고 있는 scope 영역의 종류와 특징을 이해해야 합니다. 본 프로젝트에서 주로 사용하는 scope는 session과 request 가 있습니다. 이 부분을 특히 주의 깊게 살펴보아야 합니다.

 

scope 종류 설명
application 프로젝트(웹서비스)당 하나의 영역이 생성되며 접속자 모두가 사용할 수 있는 영역이며, 브라우저가 종료되도 내용은 삭제되지 않는다.
session 접속자 한명의 브라우저가 사용하는 영역. 브라우저를 종료할 때 저장된 내용이 제거됨.
request 요청정보가 발생할 때 마다 생성되고 내용이 갱신됨.
page 하나의 웹페이지에 할당되는 영역.

 

D.2 로그인/로그아웃 페이지 전환

 

실제 데이터베이스에 있는 회원의 정보를 조회하여 로그인 처리는 하지 않지만,  로그인 전 화면에서 '로그인' 버튼을 클릭하면 session 영역에 사용자가 입력한 아이디를 저장하여 로그인 후 화면을 보여주고, 로그인 후 화면에서 '로그아웃' 버튼이 클릭되면 session에 저장된 아이디 값을 제거하여 로그인 전 화면을 보여 주도록 하겠습니다.

 

로그인/로그아웃

 

 

 

프로젝트 서두에서도 언급한 것과 같이 실제 데이터베이스는 연동하지 않지만 아이디와 암호를 전달받아 간단하게 session영역에 로그인 정보를 저장한 후 그 결과에 따라 로그인 전후 화면을 교차로 표시해 보도록 하겠습니다.

 


E. JavaScript

 

E.1 로그인/로그아웃 버튼 이벤트 처리

 

작업 파일 : WebContent/js/index.js

 

/**
 * file : index.js
 */

// id값을 손쉽게 가져오는 함수
var $id = function(id){ return document.getElementById(id) }

var index = {};

// 로그인/로그아웃에서만 사용하는 함수
index.login = function(){
	let frm = $id('frm_login');
	if($id('btnLogin')){
		$id('btnLogin').onclick = function(){
			if(frm.mid.value=='' || frm.pwd.value == ''){
				alert('아이디와 암호는 반드시 입력해야 합니다.');
				return;
			}
			frm.loginFlag.value = 'login';
			frm.action='login_out.jsp';
			frm.submit();
		}
	}
	
	if($id('btnLogout')){
		$id('btnLogout').onclick = function(){
			frm.loginFlag.value='logout';
			frm.action='login_out.jsp';
			frm.submit();
		}
	}
	
	
}

사용자 함수 $id는 매개변수로 전달받은 id에 해당하는 요소의 객체를 반환하도록 구성하였습니다.

 

ver index = {}는 리터럴 타입으로 정의된 객체명입니다.

 

index.login = function(){ ... } 은 index 리터럴에 포함된 login 함수입니다. btnLogin과 btnLogout의 아이디 값을 갖는 버튼이 클릭되면 frm.loginFlag 요소에 'login' 또는 'logout' 문자를 대입하여 다시 login_out.jsp로 폼 정보를 전송합니다. B.3 부분과 연결되는 부분입니다. 폼에 값을 가지고 BoardController의 loginCheck() 메서드를 호출하여 로그인/로그아웃을 판단합니다.

 

[ login_out.jsp의 일부분 ]

...
BoardController ctrl = new BoardController(request, response);
ctrl.loginCheck();
...

 


F. Controller & Dao

web, css, javascript 코드를 살펴보았으니 이제 마지막으로 session에 아이디 값을 저장하거나 제거하는 부분을 살펴보도록 하겠습니다. 이전 부분에서 부터 여러 번 언급한 것과 같이 사용자의 요청 처리는 가장 먼저 BoardController에 의해서 분석되어 BoardDao에 전달하게 됩니다.

 

F.1 BoardController.java

 

생성자 부분과 loginCheck() 메서드를 중심으로 코드를 분석해 주시기 바랍니다. 소스에 대한 설명은 주석으로 대신하도록 하겠습니다.

 

package bean;

import java.util.List;

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

public class BoardController {
	HttpServletRequest req;
	HttpServletResponse resp;
	BoardDao dao;
	
	public BoardController(HttpServletRequest req, HttpServletResponse resp) {
		this.req = req;
		this.resp = resp;
		dao = new BoardDao();
	}
	
	//login.jsp페이지에서 호출됨
	public void loginCheck() {
		// form 정보를 가져옴.
		String loginFlag = req.getParameter("loginFlag");
		String mid = req.getParameter("mid");
		String pwd = req.getParameter("pwd");

		// 요청 객체로 부터 세션을 가져옴.
		HttpSession session = req.getSession();
		
		
		if(loginFlag.equals("login")){
			boolean b = dao.loginCheck(mid, pwd);
			if(b) {
				//세션에 아이디 저장
				session.setAttribute("session_id", mid);
			}
			
		}else if(loginFlag.equals("logout")){
			// 세션에서 session_id 속성 제거
			session.removeAttribute("session_id");
		}
	}
	
}

 

F.2 BoardDao.java에서 로그인/로그아웃 처리

 

BoardController로부터 아이디와 암호를 전달받아 해당 아이디와 암호가 있는 경우 참을 리턴하여 로그인 여부를 판단해야 하지만, 데이터 베이스를 연결하지 않았기 때문에 아이디와 암호가 공백이 아니라면 무조건 참을 리턴하였습니다.

 

 

package bean;


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

public class BoardDao {
	public boolean loginCheck(String mid, String pwd) {
		boolean b=true;
		if(mid.equals("") || pwd.equals("")) b=false;
		return b;
	}
}

 

여기까지가 다소 복잡하고 어려웠지만 로그인/로그아웃 처리를 메인 페이지와 함께 작성해 보았습니다. 한두 번쯤 웹 프로젝트를 진행해 본 개발자들도 많이 어려워하는 로직입니다. 데이터의 흐름에 따라 웹페이지가 어떻게 바뀌는지 다시 한번 분석해 보시기 바랍니다.

 

로그인 처리 과정

 

이것으로 메인 페이지 구성과 로그인/로그아웃 처리에 대한 포스팅을 마치도록 하겠습니다.

 

아래는 관련 동영상입니다.

 

[메인 페이지 레이아웃 설정 영상(묵음)]

 

 

 

 

[메인 페이지의 메뉴 영역 설정 영상(묵음)]

 

 

 

[로그인 / 로그아웃 처리하기(묵음)]