프로토타입
프로토타입(Prototype)이란 개발 초기에 만드는 일종의 모형이다.
웹 애플리케이션의 프로토타입은 화면에 해당하는 뷰(JSP 또는 html)를 중심으로 작성한다.
프로그램 로직은 테스트에 필요하거나 개발 종료까지 변경되지 않는 명확한 부분만 작성한다.
구현하려는 프로젝트는 모델 1 게시판이다.
모델 1은 클라이언트가 직접 JSP를 요청한다.
다음은 모델 1 게시판 프로젝트에 필요한 JSP 파일 목록이다.
도큐먼트 베이스
- /index.jsp : 홈페이지
- /error.jsp : 에러 페이지
/inc
- header.jsp : 로고와 회원메뉴 버튼(로그인, 회원 가입 또는 로그아웃, 내 정보 수정)을 담는다.
- main-menu.jsp : 메인 메뉴
- extra.jsp : 화면 오른쪽에 위치하며 외부 링크를 담는다.
- footer.jsp : 카피라이트, 주소, 연락처 표시
- loginCheck.jsp : 로그인이 필요한 페이지에서 인클루드하는 파일로, 로그인하지 않은 사용자는 로그인 페이지로 이동시킨다.
/users
- user-sub.jsp : 회원 관련 메뉴
- login.jsp : 로그인 폼
- login_proc.jsp : 로그인 처리
- logout_proc.jsp : 로그아웃 처리
- signUp.jsp : 회원 가입 폼
- signUp_proc.jsp : 회원 가입 처리
- welcome.jsp : 회원 가입 환영
- editAccount.jsp : 내 정보 수정 폼
- editAccount_proc.jsp : 내 정보 수정 처리
- changePasswd.jsp : 비밀번호 변경 폼
- changePasswd_proc.jsp : 비밀번호 변경 처리
- changePasswd_confirm.jsp : 비밀번호 변경 확인
- bye.jsp : 탈퇴 폼
- bye_proc.jsp : 탈퇴 처리
- bye_confirm.jsp : 탈퇴 확인
/bbs
- bbs-sub.jsp : 게시판 메뉴
- list.jsp : 게시판 목록
- write.jsp : 글쓰기 폼
- write_proc.jsp : 글쓰기 처리
- view.jsp : 상세보기
- addComment_proc.jsp : 댓글 쓰기 처리
- updateComment_proc.jsp : 댓글 수정 처리
- deleteComment_proc.jsp : 댓글 삭제 처리
- deleteAttachFile_proc.jsp : 첨부 파일 삭제 처리
- del_proc.jsp : 게시글 삭제 처리
- modify.jsp : 게시글 수정 폼
- modify_proc.jsp : 게시글 수정 처리
/java
- index.jsp : 서브페이지 예제
메인 페이지, 서브 페이지
메인 페이지와 서브 페이지 디자인이 웹사이트 프로토타입의 첫 번째 작업이다.
메인 페이지는 웹사이트를 방문할 때 보이는 페이지를 말하는데, 홈페이지라고도 한다.
서브 페이지는 메인 페이지 외의 모든 페이지다.
여기서 도큐먼트 베이스(DocumentBase)는 C:\www\JSPProject\WebContent 이다.
스타일 시트과 이미지
스타일 시트와 이미지 파일은 CSS Layout 최종 결과물을 사용한다.
(https://github.com/kimjonghoon/css-layout 참조)
내려받은 압축 파일을 풀고 스타일 시트와 이미지 파일을 css와 images 폴더에 복사하고 HTML 파일은 도큐먼트 베이스에 복사한다.
메인 페이지
로그인 로직을 프로토타입에 추가하겠다.
따라서 메인 페이지를 작성하기 전에 다음 User 클래스가 먼저 생성한다.
User.java
package net.java_school.user; public class User { private String email; private String passwd; private String name; private String mobile; public User() {} public User(String email, String passwd) { this.email = email; this.passwd = passwd; } public User(String email, String passwd, String name, String mobile) { this.email = email; this.passwd = passwd; this.name = name; this.mobile = mobile; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPasswd() { return passwd; } public void setPasswd(String passwd) { this.passwd = passwd; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } }
User 클래스에 아이디가 없다.
아이디로 이메일을 사용할 것이다.
로그인 정책
- 로그인이 필요한 페이지에 로그인하지 않은 사용자가 방문하면 사용자를 로그인 페이지로 보낸다. 이때 처음 방문하려던 URL를 로그인 페이지로 전달한다.
- 로그인이 성공하면 전달받은 URL로 이동한다.
- 로그인 페이지에서 로그인하면 자유 게시판 목록의 첫 번째 페이지로 이동한다.
- 로그아웃하면 홈페이지로 이동한다.
도큐먼트베이스의 index.html을 index.jsp로 파일명을 변경한 후 아래와 같이 수정한다.
/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.user.User" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="메인 페이지" /> <meta name="Description" content="메인 페이지" /> <title>메인 페이지</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> </head> <body> <div id="wrap"> <div id="header"> <h1 style="float: left; width: 150px;"><a href="/"><img src="/images/ci.gif" alt="java-school" /></a></h1> <div id="memberMenu" style="float: right; position: relative; top: 7px;"> <% User loginUser = (User) session.getAttribute("user"); if (loginUser == null) { %> <input type="button" value="로그인" onclick="location.href='/users/login.jsp'" /> <input type="button" value="회원 가입" onclick="location.href='/users/signUp.jsp'" /> <% } else { %> <input type="button" value="로그아웃" onclick="location.href='/users/logout_proc.jsp'" /> <input type="button" value="내 정보 수정" onclick="location.href='/users/editAccount.jsp'" /> <% } %> </div> </div> <div id="main-menu"> <ul id="nav"> <li><a href="/java">Java</a></li> <li><a href="/jdbc">JDBC</a></li> <li><a href="/jsp">JSP</a></li> <li><a href="/css-layout">CSS Layout</a></li> <li><a href="/jsp-pjt">JSP Project</a></li> <li><a href="/spring">Spring</a></li> <li><a href="/javascript">JavaScript</a></li> <li><a href="/bbs/list.jsp?boardCd=chat&curPage=1">BBS</a></li> </ul> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <h1>Main</h1> </div> <div id="extra"> <a href="http://www.youtube.com"><img src="/images/youtube.png" alt="youtube.com" /></a> <a href="http://www.twitter.com"><img src="/images/twitter.png" alt="twitter.com" /></a> <a href="http://www.facebook.com"><img src="/images/facebook.png" alt="facebook.com" /></a> <a href="http://www.gmail.com"><img src="/images/gmail.png" alt="gmail.com" /></a> <a href="http://www.java-school.net"><img src="/images/java-school.png" alt="java-school.net" /></a> </div> <div id="footer"> <ul> <li><a href="#">이용약관</a></li> <li><a href="#">개인정보보호정책</a></li> <li><a href="#">이메일무단수집거부</a></li> <li id="company-info">전화 : 02-123-5678, FAX : 02-123-5678<br /> people@ggmail.org<br /> Copyright java-school.net All Rights Reserved.</li> <li><a href="#">찾아오시는 길</a></li> </ul> </div> </div> </body> </html>
서브 페이지
홈페이지 /index.jsp를 Save As... 메뉴를 이용하여 java 서브 디렉터리에 index.jsp 파일을 만든 후 아래와 같이 수정한다. 홈페이지와 달리 이 페이지는 서브 디렉터리에 있으므로 상대 경로를 수정해야 한다.
/java/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ page import="net.java_school.user.User" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="자바 홈" /> <meta name="Description" content="자바 홈" /> <title>자바 홈</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> </head> <body> <div id="wrap"> <div id="header"> <h1 style="float: left; width: 150px;" ><a href="/"><img src="/images/ci.gif" alt="java-school" /></a></h1> <div id="memberMenu" style="float: right; position: relative; top: 7px;"> <% User loginUser = (User) session.getAttribute("user"); if (loginUser == null) { %> <input type="button" value="로그인" onclick="location.href='/users/login.jsp'" /> <input type="button" value="회원 가입" onclick="location.href='/users/signUp.jsp'" /> <% } else { %> <input type="button" value="로그아웃" onclick="location.href='/users/logout_proc.jsp'" /> <input type="button" value="내 정보 수정" onclick="location.href='/users/editAccount.jsp'" /> <% } %> </div> </div> <div id="main-menu"> <ul id="nav"> <li><a href="/java">Java</a></li> <li><a href="/jdbc">JDBC</a></li> <li><a href="/jsp">JSP</a></li> <li><a href="/css-layout">CSS Layout</a></li> <li><a href="/jsp-pjt">JSP Project</a></li> <li><a href="/spring">Spring</a></li> <li><a href="/javascript">JavaScript</a></li> <li><a href="/bbs/list.jsp?boardCd=chat&curPage=1">BBS</a></li> </ul> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <h1>Java</h1> </div> <div id="extra"> <a href="http://www.youtube.com"><img src="/images/youtube.png" alt="youtube.com" /></a> <a href="http://www.twitter.com"><img src="/images/twitter.png" alt="twitter.com" /></a> <a href="http://www.facebook.com"><img src="/images/facebook.png" alt="facebook.com" /></a> <a href="http://www.gmail.com"><img src="/images/gmail.png" alt="gmail.com" /></a> <a href="http://www.java-school.net"><img src="/images/java-school.png" alt="java-school.net" /></a> </div> <div id="footer"> <ul> <li><a href="#">이용약관</a></li> <li><a href="#">개인정보보호정책</a></li> <li><a href="#">이메일무단수집거부</a></li> <li id="company-info">전화 : 02-123-5678, FAX : 02-123-5678<br /> people@ggmail.org<br /> Copyright java-school.net All Rights Reserved.</li> <li><a href="#">찾아오시는 길</a></li> </ul> </div> </div> </body> </html>
공통 JSP 페이지
화면 배치가 같으면 JSP 인클루드 지시어를 사용하여 코드를 분리할 수 있다.
페이지를 분리하면 유지 보수가 편해진다.
#header에 있는 로고와 로그인/로그아웃 버튼, #main-menu의 메인 메뉴, #extra의 외부 링크, #footer의 글로벌 메뉴는 모든 페이지에서 공통이다.
inc 서브 디렉터리에 다음 JSP 파일을 생성한다.
/java/index.jsp 파일을 참고하여 다음 파일을 생성한다.
/inc/header.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.user.User" %> <h1 style="float: left; width: 150px;"><a href="/"><img src="/images/ci.gif" alt="java-school" /></a></h1> <div id="memberMenu" style="float: right; position: relative; top: 7px;"> <% User loginUser = (User) session.getAttribute("user"); if (loginUser == null) { %> <input type="button" value="로그인" onclick="location.href='/users/login.jsp'" /> <input type="button" value="회원 가입" onclick="location.href='/users/signUp.jsp'" /> <% } else { %> <input type="button" value="로그아웃" onclick="location.href='/users/logout_proc.jsp'" /> <input type="button" value="내 정보 수정" onclick="location.href='/users/editAccount.jsp'" /> <% } %> </div>
/inc/main-menu.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <ul id="nav"> <li><a href="/java">Java</a></li> <li><a href="/jdbc">JDBC</a></li> <li><a href="/jsp">JSP</a></li> <li><a href="/css-layout">CSS Layout</a></li> <li><a href="/jsp-pjt">JSP Project</a></li> <li><a href="/spring">Spring</a></li> <li><a href="/javascript">JavaScript</a></li> <li><a href="/bbs/list.jsp?boardCd=chat&curPage=1">BBS</a></li> </ul>
/inc/extra.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <a href="http://www.youtube.com"><img src="/images/youtube.png" alt="youtube.com" /></a> <a href="http://www.twitter.com"><img src="/images/twitter.png" alt="twitter.com" /></a> <a href="http://www.facebook.com"><img src="/images/facebook.png" alt="facebook.com" /></a> <a href="http://www.gmail.com"><img src="/images/gmail.png" alt="gmail.com" /></a> <a href="http://www.java-school.net"><img src="/images/java-school.png" alt="java-school.net" /></a>
/inc/footer.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <ul> <li><a href="#">이용약관</a></li> <li><a href="#">개인정보보호정책</a></li> <li><a href="#">이메일무단수집거부</a></li> <li id="company-info">전화 : 02-123-5678, FAX : 02-123-5678<br /> people@ggmail.org<br /> Copyright java-school.net All Rights Reserved.</li> <li><a href="#">찾아오시는 길</a></li> </ul>
공통 JSP 파일을 만들 때 페이지 지시어의 contentType 속성은 포함하는 페이지와 같아야 한다.
같지 않다면 서블릿으로 변환되지 않는다.
따라서 공통 JSP 파일의 contentType은 다음과 같아야 한다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
공통 JSP 파일을 이용하여 서브 페이지 수정
/java/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="자바 홈" /> <meta name="Description" content="자바 홈" /> <title>자바 홈</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <h1>Java</h1> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
로그인 폼, 로그인 처리, 로그아웃 처리 페이지 생성
로그인 테스트를 위해 로그인 폼, 로그인 처리, 로그아웃 처리 페이지를 생성한다.
모든 회원 관련 페이지가 인클루드해야 하는 회원 메뉴 페이지, user-sub.jsp를 /users 디렉터리에 생성한다.
/users/user-sub.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <h1>회원</h1> <% User loginUser = (User) session.getAttribute("user"); if (loginUser == null) { %> <ul> <li><a href="login.jsp">로그인</a></li> <li><a href="signUp.jsp">회원 가입</a></li> <li><a href="#">ID 찾기</a></li> <li><a href="#">비밀번호 찾기</a></li> </ul> <% } else { %> <ul> <li><a href="editAccount.jsp">내 정보 수정</a></li> <li><a href="changePasswd.jsp">비밀번호 변경</a></li> <li><a href="bye.jsp">탈퇴</a></li> </ul> <% } %>
로그인 폼 페이지를 만든다.
/java/index.jsp를 연 상태에서 Save As... 메뉴를 이용하여 login.jsp라는 이름의 새 파일을 /users 디렉터리에 만든 후 아래와 같이 수정한다.
/users/login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% request.setCharacterEncoding("UTF-8"); String url = request.getParameter("url"); if (url == null) url = ""; %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="로그인" /> <meta name="Description" content="로그인" /> <title>로그인</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">회원</div> <h2>로그인</h2> <form id="loginForm" action="login_proc.jsp" method="post"> <input type="hidden" name="url" value="<%=url %>" /> <table> <tr> <td style="width: 200px;">Email</td> <td style="width: 390px"><input type="text" name="email" style="width: 99%;" value="captain@heist.com" /></td> </tr> <tr> <td>비밀번호(Password)</td> <td><input type="password" name="passwd" style="width: 99%;" value="1111" /></td> </tr> </table> <div style="text-align: center;padding-top: 15px;"> <input type="submit" value="전송" /> <input type="button" value="회원 가입" onclick="location.href='signUp.jsp'" /> </div> </form> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="user-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
로그인을 처리하는 페이지를 만든다.
/users/login_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.user.User"%> <% String url = request.getParameter("url"); String email = request.getParameter("email"); String passwd = request.getParameter("passwd"); session.setAttribute("user", new User(email, passwd, "홍길동", "010-1234-5678")); if (url != null && !url.equals("")) { response.sendRedirect(url); } else { response.sendRedirect("../bbs/list.jsp?boarCd=chat&curPage=1"); } %>
로그아웃을 처리하는 페이지를 만든다.
로그아웃 후 홈페이지로 이동하도록 구현한다.
/users/logout_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% session.removeAttribute("user"); response.sendRedirect("../"); %>
웹 브라우저로 로그인과 로그아웃을 테스트한다.
로그인하면 아직 만들지 않은 게시판으로 이동하여 404 에러를 보게 된다.
다시 상단의 로고를 클릭하여 홈페이지로 이동,
홈페이지에서 Java 메인 메뉴를 클릭하여 서브 페이지로 이동한 후 로그아웃하면 홈페이지로 이동한다.
JSP 에러 핸들링
web.xml 파일을 열고 </web-app> 직전에 다음을 추가한다.
web.xml
<error-page> <error-code>403</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error.jsp</location> </error-page> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/error.jsp</location> </error-page>
주요 에러를 모두 /error.jsp가 담당하도록 하는 설정이다.
에러 페이지
홈페이지를 연 상태에서 Save As... 메뉴를 이용하여 error.jsp라는 새 파일을 도큐먼트 베이스에 만든 후 아래와 같이 수정한다.
/error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.user.User" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="Error" /> <meta name="Description" content="Error" /> <title>Error</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> </head> <body> <% //Analyze the servlet exception Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception"); Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); String servletName = (String) request.getAttribute("javax.servlet.error.servlet_name"); if (servletName == null) { servletName = "Unknown"; } String requestUri = (String) request.getAttribute("javax.servlet.error.request_uri"); if (requestUri == null) { requestUri = "Unknown"; } %> <div id="wrap"> <div id="header"> <h1 style="float: left; width: 150px;"><a href="/"><img src="/images/ci.gif" alt="java-school" /></a></h1> <div id="memberMenu" style="float: right; position: relative; top: 7px;"> <% User loginUser = (User) session.getAttribute("user"); if (loginUser == null) { %> <input type="button" value="로그인" onclick="location.href='/users/login.jsp'" /> <input type="button" value="회원 가입" onclick="location.href='/users/signUp.jsp'" /> <% } else { %> <input type="button" value="로그아웃" onclick="location.href='/users/logout_proc.jsp'" /> <input type="button" value="내 정보 수정" onclick="location.href='/users/editAccount.jsp'" /> <% } %> </div> </div> <div id="main-menu"> <ul id="nav"> <li><a href="/java">Java</a></li> <li><a href="/jdbc">JDBC</a></li> <li><a href="/jsp">JSP</a></li> <li><a href="/css-layout">CSS Layout</a></li> <li><a href="/jsp-pjt">JSP Project</a></li> <li><a href="/spring">Spring</a></li> <li><a href="/javascript">JavaScript</a></li> <li><a href="/bbs/list.jsp?boardCd=chat&curPage=1">BBS</a></li> </ul> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">Error</div> <h2>Error Page</h2> <% if (statusCode != null && statusCode != 500) { out.write("<h3>Error Details</h3>"); out.write("<strong>Status Code</strong>:" + statusCode + "<br>"); out.write("<strong>Requested URI</strong>:"+requestUri); } if (throwable != null) { out.write("<h3>Exception Details</h3>"); out.write("<ul><li>Servlet Name:" + servletName + "</li>"); out.write("<li>Exception Name:" + throwable.getClass().getName() + "</li>"); out.write("<li>Requested URI:" + requestUri + "</li>"); out.write("<li>Exception Message:" + throwable.getMessage() + "</li>"); out.write("</ul>"); } %> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <h1>Error</h1> </div> <div id="extra"> <a href="http://www.youtube.com"><img src="/images/youtube.png" alt="youtube.com" /></a> <a href="http://www.twitter.com"><img src="/images/twitter.png" alt="twitter.com" /></a> <a href="http://www.facebook.com"><img src="/images/facebook.png" alt="facebook.com" /></a> <a href="http://www.gmail.com"><img src="/images/gmail.png" alt="gmail.com" /></a> <a href="http://www.java-school.net"><img src="/images/java-school.png" alt="java-school.net" /></a> </div> <div id="footer"> <%@ include file="./inc/footer.jsp" %> </div> </div> </body> </html>
다시 로그인을 시도한다. 아직 만들지 않는 페이지를 요청하게 된다. 에러 페이지가 작동하는지 확인한다.
게시판
게시판 관련 페이지를 작성한다.
게시판 메뉴(bbs-sub.jsp) 페이지
게시판 모듈에서 화면을 담당하는 모든 페이지가 인클루드해야 하는 페이지부터 작성한다.
도큐먼트 베이스에 bbs라는 서브 디렉터리를 만들고, /bbs에 bbs-sub.jsp 파일을 만든다.
bbs-sub.jsp 파일은 게시판에 대한 링크를 제공한다.
/bbs/bbs-sub.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <h1>게시판</h1> <ul> <li> <ul> <li><a href="list.jsp?boardCd=chat&curPage=1">자유 게시판</a></li> <li><a href="list.jsp?boardCd=qna&curPage=1">QnA게시판</a></li> <li><a href="list.jsp?boardCd=data&curPage=1">자료실</a></li> </ul> </li> </ul>
로그인 체크(loginCheck.jsp) 페이지
이 페이지는 사용자가 로그인했는지를 검사하고, 로그인하지 않은 사용자는 로그인 페이지로 리다이렉트시킨다.
이때 로그인 후 다시 사용자가 요청한 원래 페이지로 이동하기 위해 url 정보를 로그인 페이지에 전달한다.
공통 인클루드 파일 디렉터리인 /inc에 loginCheck.jsp 파일을 만든다.
이 파일을 공통 인클루드 파일 디렉터리에 생성하는 이유는 게시판 모듈 외에도 사용될 수 있기 때문이다.
/inc/loginCheck.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="net.java_school.user.*"%> <%@ page import="java.net.URLEncoder"%> <% User user = (User) session.getAttribute("user"); if (user == null) { //로그인 후 되돌아갈 URL를 구한다. String uri = request.getRequestURI(); String query = request.getQueryString(); String url = uri; if (query != null) url += "?" + query; //로그인 페이지로 리다이렉트 url = URLEncoder.encode(url, "UTF-8"); response.sendRedirect("/users/login.jsp?url=" + url); return; } %>
목록 페이지
게시판 목록을 보여주는 페이지를 만든다.
CSS 포지셔닝에서의 만든 list.html 파일을 연 상태에서 Save As... 메뉴를 이용하여 list.jsp라는 이름의 새 파일을 /bbs 디렉터리에 만든 후 아래와 같이 수정한다.
/bbs/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="../inc/loginCheck.jsp" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="게시판 목록" /> <meta name="Description" content="게시판 목록" /> <title>자유 게시판</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> <script type="text/javascript"> function goList(curPage) { var form = document.getElementById("listForm"); form.curPage.value = curPage; form.submit(); } function goView(articleNo) { var form = document.getElementById("viewForm"); form.articleNo.value = articleNo; form.submit(); } function goWrite() { var form = document.getElementById("writeForm"); form.submit(); } </script> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">자유 게시판</div> <table class="bbs-table"> <!-- 게시판 목록 머리말 --> <tr> <th style="width: 60px">NO</th> <th>TITLE</th> <th style="width: 84px;">DATE</th> <th style="width: 60px;">HIT</th> </tr> <!-- 반복 구간 시작 --> <tr> <td style="text-align: center;">11</td> <td> <a href="javascript:goView('1')">제목</a> <img src="/images/attach.png" alt="첨부 파일" style="vertical-align: middle;" /> <span class="bbs-strong">[5]</span> </td> <td style="text-align: center;">2011.11.15</td> <td style="text-align: center;">4555</td> </tr> <!-- 반복 구간 끝 --> </table> <div id="paging"> <a href="javascript:goList('5')">[이전]</a> <span class="bbs-strong">6</span> <a href="javascript:goList('7')">7</a> <a href="javascript:goList('8')">8</a> <a href="javascript:goList('9')">9</a> <a href="javascript:goList('10')">10</a> <a href="javascript:goList('11')">[다음]</a> </div> <div id="list-menu"> <input type="button" value="새 글쓰기" onclick="goWrite()" /> </div> <div id="search"> <form action="list.jsp" method="get"> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="boardCd" value="chat" /> <div> <input type="text" name="searchWord" size="15" maxlength="30" /> <input type="submit" value="검색" /> </div> </form> </div> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="bbs-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> <div id="form-group" style="display: none"> <form id="listForm" action="list.jsp" method="get"> <p> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </p> </form> <form id="viewForm" action="view.jsp" method="get"> <p> <input type="hidden" name="articleNo" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </p> </form> <form id="writeForm" action="write.jsp" method="get"> <p> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </p> </form> </div> </body> </html>
글쓰기 폼 페이지
다음은 게시판 글쓰기 폼 페이지를 작성한다.
CSS 포지셔닝에서 만든 write.html 파일을 연 상태에서 Save As... 메뉴를 이용하여 write.jsp라는 이름의 새 파일을 /bbs 디렉터리에 만든 후 아래와 같이 수정한다.
/bbs/write.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="../inc/loginCheck.jsp" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="글쓰기 화면" /> <meta name="Description" content="글쓰기 화면" /> <title>자유 게시판</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> <script type="text/javascript"> function goList() { var form = document.getElementById("listForm"); form.submit(); } function goView() { var form = document.getElementById("viewForm"); form.submit(); } </script> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">자유 게시판</div> <h3>새 글쓰기</h3> <form id="writeForm" action="write_proc.jsp" method="post" enctype="multipart/form-data"> <input type="hidden" name="boardCd" value="chat" /> <table id="write-form" class="bbs-table"> <tr> <td>제목</td> <td><input type="text" name="title" style="width: 90%;" /></td> </tr> <tr> <td colspan="2"> <textarea name="content" rows="17" cols="50"></textarea> </td> </tr> <tr> <td>첨부 파일</td> <td><input type="file" name="attachFile" /></td> </tr> </table> <div style="text-align: center;padding-bottom: 15px;"> <input type="submit" value="전송" /> <input type="button" value="목록" onclick="goList()" /> <input type="button" value="상세보기" onclick="goView()" /> </div> </form> <!-- 본문 끝 --> </div> </div> <div id="sidebar"> <%@ include file="bbs-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> <div id="form-group" style="display: none"> <form id="viewForm" action="view.jsp" method="get"> <input type="hidden" name="articleNo" value="5" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> <form id="listForm" action="list.jsp" method="get"> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> </div> </body> </html>
글쓰기 처리 페이지
글쓰기 처리 페이지를 작성한다.
이 페이지는 글쓰기 폼에서 전달받는 파라미터로 실제로 데이터베이스에 인서트를 담당한다.
/bbs/write_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 새 게시글을 등록하는 페이지로 모델 2에서는 삭제해야 할 페이지다. -구현- 로그인 사용자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Not Login"); return; 로그인 체크를 통과하면 boardCd, title, content, attachFile 파라미터를 가지고 새 글을 인서트한다. form의 enctype 속성이 "multipart/form-data"인 경우 request.getParameter();로 파라미터의 값을 얻을 수 없다. 이 경우 프로그래밍을 손쉽게 하려면 아파치 commons-fileupload 또는 cos와 같은 외부 라이브러리를 이용한다. 새 글을 등록한 후 목록의 첫 번째 페이지로 되돌아가야 한다. */ response.sendRedirect("list.jsp?boardCd=chat&curPage=1"); %>
상세보기 페이지
목록에서 제목을 클릭하면 보이게 되는 게시글 상세보기 페이지를 만든다.
CSS 포지셔닝에서 만든 view.html 파일을 연 상태에서 Save As... 메뉴를 이용하여 view.jsp 이름의 새 파일을 /bbs 디렉터리에 만든 후 아래와 같이 수정한다.
/bbs/view.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="../inc/loginCheck.jsp" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="게시판 상세보기" /> <meta name="Description" content="게시판 상세보기" /> <title>자유 게시판</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> <script type="text/javascript"> function modifyCommentToggle(articleNo) { var p_id = "comment" + articleNo; var form_id = "modifyCommentForm" + articleNo; var p = document.getElementById(p_id); var form = document.getElementById(form_id); var p_display; var form_display; if (p.style.display) { p_display = ''; form_display = 'none'; } else { p_display = 'none'; form_display = ''; } p.style.display = p_display; form.style.display = form_display; } function goList(curPage) { var form = document.getElementById("listForm"); form.curPage.value = curPage; form.submit(); } function goView(articleNo) { var form = document.getElementById("viewForm"); form.articleNo.value = articleNo; form.submit(); } function goWrite() { var form = document.getElementById("writeForm"); form.submit(); } function goModify() { var form = document.getElementById("modifyForm"); form.submit(); } function goDelete() { var check = confirm("정말로 삭제하시겠습니까?"); if (check) { var form = document.getElementById("delForm"); form.submit(); } } function deleteAttachFile(attachFileNo) { var check = confirm("첨부 파일을 정말로 삭제하시겠습니까?"); if (check) { var form = document.getElementById("deleteAttachFileForm"); form.attachFileNo.value = attachFileNo; form.submit(); } } function deleteComment(commentNo) { var check = confirm("댓글을 정말로 삭제하시겠습니까?"); if (check) { var form = document.getElementById("deleteCommentForm"); form.commentNo.value = commentNo; form.submit(); } } </script> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">자유 게시판</div> <div class="view-menu" style="margin-top: 15px;margin-bottom: 5px;"> <div class="fl"> <input type="button" value="수정" onclick="goModify()" /> <input type="button" value="삭제" onclick="goDelete()"/> </div> <div class="fr"> <input type="button" value="다음 글" onclick="goView('6')" /> <input type="button" value="이전 글" onclick="goView('4')" /> <input type="button" value="목록" onclick="goList('1')" /> <input type="button" value="새 글쓰기" onclick="goWrite()" /> </div> </div> <table class="bbs-table"> <tr> <th style="width: 37px;text-align: left;vertical-align: top;font-size: 1em;">TITLE</th> <th style="text-align: left;color: #555;font-size: 1em;">What makes us happy?</th> </tr> </table> <div id="detail"> <div id="date-writer-hit">edited 2014-10-09 17:55:30 by 홍길동 hit 1330</div> <div id="article-content"> What makes us happy?What makes us happy?What makes us happy?<br /> What makes us happy?What makes us happy?What makes us happy?<br /> </div> <div id="file-list" style="text-align: right"> <div class="attach-file"> <a href="#" >TEST.png</a> <a href="javascript:deleteAttachFile('23')">x</a> </div> </div> </div> <!-- 댓글 쓰기 --> <form id="addCommentForm" style="margin: 10px 0;" action="addComment.jsp" method="post"> <input type="hidden" name="articleNo" value="5"/> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> <div id="addComment"> <textarea id="addComment-ta" name="memo" rows="7" cols="50"></textarea> </div> <div style="text-align: right;"> <input type="submit" value="댓글 남기기" /> </div> </form> <!-- 댓글 반복 시작 --> <div class="comments"> <span class="writer">xman</span> <span class="date">2011.12.11 12:14:32</span> <span class="modify-del"> <a href="javascript:modifyCommentToggle('5')">수정</a> | <a href="javascript:deleteComment('5')">삭제</a> </span> <p id="comment5">What makes us happy?</p> <form id="modifyCommentForm5" class="comment-form" action="updateComment.jsp" method="post" style="display: none;"> <input type="hidden" name="commentNo" value="5" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="articleNo" value="12" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> <div class="fr"> <a href="javascript:document.forms.modifyCommentForm5.submit()">수정하기</a> | <a href="javascript:modifyCommentToggle('5')">취소</a> </div> <div> <textarea class="comment-textarea" name="memo" rows="7" cols="50">무궁화꽃이 피었습니다.</textarea> </div> </form> </div> <!-- 댓글 반복 끝 --> <div id="next-prev"> <p>다음 글 : <a href="javascript:goView('6')">무궁화꽃이 피었습니다.</a></p> <p>이전 글 : <a href="javascript:goView('4')">무궁화꽃이 피었습니다.</a></p> </div> <div class="view-menu" style="margin-bottom: 47px;"> <div class="fl"> <input type="button" value="수정" onclick="goModify()" /> <input type="button" value="삭제" onclick="goDelete()"/> </div> <div class="fr"> <input type="button" value="다음 글" onclick="goView('6')" /> <input type="button" value="이전 글" onclick="goView('4')" /> <input type="button" value="목록" onclick="goList('1')" /> <input type="button" value="새 글쓰기" onclick="goWrite()" /> </div> </div> <!-- 목록 --> <table class="bbs-table"> <tr> <th style="width: 60px">NO</th> <th>TITLE</th> <th style="width: 84px;">DATE</th> <th style="width: 60px;">HIT</th> </tr> <tr> <td style="text-align: center;"><img src="/images/arrow.gif" alt="현재 글" /></td> <td> <a href="javascript:goView('1')">제목</a> <img src="/images/attach.png" alt="첨부 파일" style="vertical-align: middle;" /> <span class="bbs-strong">[5]</span> </td> <td style="text-align: center;">2011.11.15</td> <td style="text-align: center;">4555</td> </tr> </table> <div id="paging"> <a href="javascript:goList('5')">[이전]</a> <span class="bbs-strong">6</span> <a href="javascript:goList('7')">7</a> <a href="javascript:goList('8')">8</a> <a href="javascript:goList('9')">9</a> <a href="javascript:goList('10')">10</a> <a href="javascript:goList('11')">[다음]</a> </div> <div id="list-menu"> <input type="button" value="새 글쓰기" onclick="goWrite()" /> </div> <div id="search"> <form action="list.jsp" method="get"> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="boardCd" value="chat" /> <div> <input type="text" name="searchWord" size="15" maxlength="30" /> <input type="submit" value="검색" /> </div> </form> </div> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="bbs-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> <div id="form-group" style="display: none"> <form id="listForm" action="list.jsp" method="get"> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> <form id="viewForm" action="view.jsp" method="get"> <input type="hidden" name="articleNo" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> <form id="writeForm" action="write.jsp" method="get"> <input type="hidden" name="articleNo" value="5" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="12" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> <form id="modifyForm" action="modify.jsp" method="get"> <input type="hidden" name="articleNo" value="5" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> <form id="delForm" action="del_proc.jsp" method="post"> <input type="hidden" name="articleNo" value="5" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> <form id="deleteCommentForm" action="deleteComment_proc.jsp" method="post"> <input type="hidden" name="commentNo" /> <input type="hidden" name="articleNo" value="12" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> <form id="deleteAttachFileForm" action="deleteAttachFile_proc.jsp" method="post"> <input type="hidden" name="attachFileNo" /> <input type="hidden" name="articleNo" value="23" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </form> </div> </body> </html>
댓글 쓰기 처리 페이지
댓글 쓰기 처리 페이지는 상세보기 페이지에서 새 댓글을 쓰고 확인을 클릭하면 실제 댓글을 데이터베이스에 인서트 하는 페이지이다.
/bbs/addComment_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 새로운 댓글을 인서트하는 페이지로 모델 2에서는 삭제해야 할 페이지이다. -구현- 로그인 사용자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Not Login"); return; 로그인 체크를 통과하면 먼저 요청의 캐릭터 셋을 UTF-8로 설정한다. boardCd, articleNo, curPage, searchWord, memo 파라미터를 받아서 댓글을 인서트한다. 댓글을 인서트한 후 상세보기를 돌아가기 위해선 검색어 searchWord를 URLEncoder의 encode 메소드로 UTF-8로 인코딩해야 한다. */ response.sendRedirect("view.jsp?articleNo=5&boardCd=chat&curPage=1&searchWord=무궁화꽃"); %>
댓글 수정 처리 페이지
이 페이지는 상세 보기에서 댓글의 작성자가 자신의 댓글 내용을 수정한 후 확인을 클릭하면 데이터베이스에 있는 댓글의 내용을 수정하는 페이지이다.
/bbs/updateComment_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 댓글 업데이트를 실행하는 페이지로 모델 2에서는 삭제해야 할 페이지이다. -구현- 작성자인지를 검사하여 작성자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Authentication Failed"); return; 작성자 체크를 통과하면 요청의 캐릭터 셋을 UTF-8로 설정한다. commentNo, boardCd, articleNo, curPage, searchWord, memo 파라미터를 받아서 댓글을 업데이트한다. 댓글을 업데이트 처리한 후 상세보기를 돌아가기 위해선 검색어 searchWord를 URLEncoder의 encode 메소드로 UTF-8로 인코딩해야 한다. */ response.sendRedirect("view.jsp?articleNo=5&boardCd=chat&curPage=1&searchWord=무궁화꽃"); %>
댓글 삭제 처리 페이지
이 페이지는 상세 보기에서 댓글 삭제를 클릭하면 데이터베이스에 있는 해당 댓글을 삭제하는 페이지이다.
/bbs/deleteComment_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 댓글 삭제를 실행하는 페이지로 모델 2에서는 삭제해야 할 페이지이다. -구현- 작성자인지를 검사하여 작성자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "작성자가 아닙니다"); return; 요청의 캐릭터 셋을 UTF-8로 설정해야 한다. 요청에서 참조해야 하는 파라미터는 commentNo, boardCd, articleNo, curPage, searchWord 이다. 댓글을 삭제 후 상세보기를 돌아가기 위해선 searchWord를 URLEncoder의 encode 메소드로 UTF-8로 인코딩한다. */ response.sendRedirect("view.jsp?articleNo=5&boardCd=chat&curPage=1&searchWord=무궁화꽃"); %>
첨부 파일 삭제 처리 페이지
이 페이지는 상세 보기에서 첨부 파일 옆의 x 링크를 클릭하면 데이터베이스에 있는 첨부 파일을 삭제하는 페이지이다.
파일시스템의 파일은 삭제하지 않는다.
/bbs/deleteAttachFile_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 첨부 파일 삭제를 실행하는 페이지로 모델 2에서는 삭제해야 할 페이지이다. -구현- 작성자인지를 검사하여 작성자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "작성자가 아닙니다"); return; 요청의 캐릭터 셋을 UTF-8로 설정해야 한다. 요청에서 참조해야 하는 파라미터는 attachFileNo,articleNo,boardCd,curPage,searchWord 이다. 첨부 파일를 삭제 후 상세보기를 돌아가기 위해선 searchWord를 URLEncoder의 encode 메소드로 UTF-8로 인코딩한다. */ response.sendRedirect("view.jsp?articleNo=5&boardCd=chat&curPage=1&searchWord=무궁화꽃"); %>
게시글 삭제 처리 페이지
이 페이지는 상세보기 페이지에서 게시글을 삭제하는 삭제 버튼을 클릭하면 실제 게시글을 데이터베이스에서 삭제 처리한다.
/bbs/del_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 게시글을 삭제하는 페이지로 모델 2에서는 삭제해야 할 페이지이다. -구현- 작성자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Authentication Failed"); return; 작성자 체크를 통과하면 요청의 캐릭터 셋을 UTF-8로 설정한다. articleNo, boardCd, curPage, searchWord 파라미터를 받고 articleNo로 게시글을 삭제한다. 게시글 삭제 후 목록를 돌아가기 위해선 검색어 searchWord를 URLEncoder의 encode 메소드로 UTF-8로 인코딩해야 한다. */ response.sendRedirect("list.jsp?boardCd=chat&curPage=1&searchWord=무궁화꽃"); %>
게시글 수정 폼 페이지
글 소유자가 자신의 글을 수정하기 위한 페이지를 만든다.
CSS 포지셔닝에서 만든 write.html 파일을 연 상태에서 Save As... 메뉴를 이용하여 modify.jsp라는 이름의 새 파일을 /bbs 폴더에 만든 후 아래와 같이 수정한다.
/bbs/modify.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <% User user = (User) session.getAttribute("user"); if (user == null) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "Not Login User"); return; } request.setCharacterEncoding("UTF-8"); int articleNo = Integer.parseInt(request.getParameter("articleNo")); String boardCd = request.getParameter("boardCd"); String curPage = request.getParameter("curPage"); String searchWord = request.getParameter("searchWord"); //TODO articleNo로 게시글 객체를 얻어서 현재 로그인된 사용자가 글 소유자인지를 검사한다. %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="게시판 수정하기 폼" /> <meta name="Description" content="게시판 수정하기 폼" /> <title>자유 게시판</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> <script type="text/javascript"> function goView() { var form = document.getElementById("viewForm"); form.submit(); } </script> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">자유 게시판</div> <h3>수정</h3> <form id="writeForm" action="modify_proc.jsp" method="post" enctype="multipart/form-data"> <input type="hidden" name="articleNo" value="5" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> <table id="write-form" class="bbs-table"> <tr> <td>제목</td> <td><input type="text" name="title" style="width: 90%;" value="무궁화꽃" /></td> </tr> <tr> <td colspan="2"> <textarea name="content" rows="17" cols="50">What makes us happy?</textarea> </td> </tr> <tr> <td>첨부 파일</td> <td><input type="file" name="attachFile" /></td> </tr> </table> <div style="text-align: center;padding-bottom: 15px;"> <input type="submit" value="전송" /> <input type="button" value="상세보기" onclick="goView()" /> </div> </form> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="bbs-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> <div id="form-group" style="display: none"> <form id="viewForm" action="view.jsp" method="get"> <p> <input type="hidden" name="articleNo" value="5" /> <input type="hidden" name="boardCd" value="chat" /> <input type="hidden" name="curPage" value="1" /> <input type="hidden" name="searchWord" value="무궁화꽃" /> </p> </form> </div> </body> </html>
게시글 수정 처리 페이지
게시글 수정 폼에서 전달받은 파라미터를 가지고 실제로 게시글 수정을 처리하는 페이지이다.
/bbs/modify_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 게시글을 수정하는 페이지로 모델 2에서는 삭제해야 할 페이지다. -구현- 작성자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Authentication Failed"); return; articleNo, boardCd, curPage, searchWord, title, content, attachFile 파라미터를 받고 게시글을 수정한다. form의 enctype 속성이 "multipart/form-data"인 경우 request.getParameter()로 파라미터의 값을 얻을 수 없다. 쉽게 프로그래밍하기 위해 아파치 commons-fileupload 또는 cos와 같은 외부 라이브러리를 이용한다. 게시글을 수정한 후 상세보기를 돌아가기 위해 searchWord를 URLEncoder의 encode 메소드를 이용해 UTF-8로 인코딩한다. */ response.sendRedirect("view.jsp?articleNo=5&curPage=1&boardCd=chat&searchWord=무궁화꽃"); %>
게시판 관련 프로토타입 작업을 완료했다.
충분히 테스트해야 한다.
테스트 후 회원 관련 프로토타입을 작업한다.
회원
회원 가입 폼 페이지
회원 가입 폼 페이지를 만든다.
CSS 포지셔닝에서 만든 singUp.html 파일을 연 상태에서 Save As... 메뉴를 이용하여 signUp.jsp라는 이름의 새 파일을 /users 디렉터리에 만든 후 아래와 같이 수정한다.
/users/signUp.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="회원 가입" /> <meta name="Description" content="회원 가입" /> <title>회원 가입</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> <script type="text/javascript"> function check() { //var form = document.getElementById("signUpForm"); //TODO 유효성 검사 return true; } </script> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">회원</div> <h2>회원 가입</h2> <form id="signUpForm" action="signUp_proc.jsp" method="post" onsubmit="return check()"> <table> <tr> <td style="width: 200px;">이름(Full Name)</td> <td style="width: 390px"><input type="text" name="name" style="width: 99%;" value="홍길동" /></td> </tr> <tr> <td>비밀번호(Password)</td> <td><input type="password" name="passwd" style="width: 99%;" value="1111" /></td> </tr> <tr> <td colspan="2" style="text-align: center;font-weight: bold;"> Email이 아이디로 쓰이므로 비밀번호는 Email 계정 비밀번호와 같게 하지 마세요. </td> </tr> <tr> <td>비밀번호 확인(Confirm)</td> <td><input type="password" name="confirm" style="width: 99%;" value="1111" /></td> </tr> <tr> <td>Email</td> <td><input type="text" name="email" style="width: 99%;" value="captain@heist.com" /></td> </tr> <tr> <td>이동전화(Mobile)</td> <td><input type="text" name="mobile" style="width: 99%;" value="010-1234-5678" /></td> </tr> </table> <div style="text-align: center;padding-bottom: 15px;"> <input type="submit" value="전송" /> </div> </form> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="user-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
회원 가입 처리 페이지
실제로 회원 가입을 처리하는 페이지이다.
회원을 데이터베이스에 등록 후 환영 페이지(welcome.jsp)로 이동하게 구현했다.
/users/signUp_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 회원 가입을 처리하는 페이지로 모델 2에서는 삭제해야 할 페이지다. -구현- 자동으로 로그인하지 않는다. 회원 가입이 완료되면 환영페이지로 이동한다. */ response.sendRedirect("welcome.jsp"); %>
회원 가입 환영 페이지
이 페이지는 사용자에게 회원 가입이 성공했음을 알려준다.
실제 회원 가입이 되지 않았는데 이 페이지를 보게 해서는 안 된다.
signUp.jsp 파일을 연 상태에서 Sava As.. 메뉴를 이용하여 welcome.jsp라는 새 파일을 /users 디렉터리에 만든 후 아래와 같이 수정한다.
/users/welcome.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="회원 가입 환영" /> <meta name="Description" content="회원 가입 환영" /> <title>회원 가입이 완료되었습니다.</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">회원</div> <h2>환영합니다.</h2> 회원 가입시 입력한 Email이 아이디로 사용됩니다.<br /> <input type="button" value="로그인" onclick="javascript:location.href='login.jsp'" /> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <h1>Welcome</h1> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
내 정보 수정 폼 페이지
로그인한 사용자가 자신의 정보를 수정할 수 있도록 양식을 보여주는 페이지이다.
signUp.jsp 파일을 연 상태에서 Save As... 메뉴를 이용하여 editAccount.jsp라는 이름의 새 파일을 /users 디렉터리에 만든 후 아래와 같이 수정한다.
/users/editAccount.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="../inc/loginCheck.jsp" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="내 정보 수정" /> <meta name="Description" content="내 정보 수정" /> <title>내 정보 수정</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> <script type="text/javascript"> function check() { //var form = document.getElementById("editAccountForm"); //TODO 유효성 검사 return true; } </script> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">회원</div> <h2>내 정보 수정</h2> <p> 비밀번호외의 자신의 계정 정보를 수정할 수 있습니다.<br /> 비밀번호는 <a href="changePasswd.jsp">비밀번호 변경</a>메뉴를 이용하세요.<br /> </p> <form id="editAccountForm" action="editAccount_proc.jsp" method="post" onsubmit="return check()"> <table> <tr> <td>이름(Full Name)</td> <td><input type="text" name="name" value="<%=user.getName() %>" /></td> </tr> <tr> <td>이동전화(Mobile)</td> <td><input type="text" name="mobile" value="<%=user.getMobile() %>" /></td> </tr> <tr> <td>현재 비밀번호(Password)</td> <td><input type="password" name="passwd" /></td> </tr> <tr> <td colspan="2"><input type="submit" value="전송" /></td> </tr> </table> </form> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="user-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
내 정보 수정 처리 페이지
내 정보 수정 폼 페이지에서 전달된 정보로 회원정보를 실제로 수정하는 페이지이다.
/users/editAccount_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 회원정보를 수정하는 페이지로 모델 2에서는 삭제해야 할 페이지다. -구현- 로그인되어 있지 않으면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Not Login"); return; 회원정보를 수정한 후 다시 로그인하고 비밀번호 변경화면으로 이동한다. 비밀번호 변경 화면에서는 비밀번호 외에 회원정보를 모두 볼 수 있기 때문이다. */ response.sendRedirect("changePasswd.jsp"); %>
비밀번호 변경 폼 페이지
비밀번호를 변경하는 페이지를 만든다.
editAccount.jsp 파일을 연 상태에서 Save As... 메뉴를 이용하여 changePasswd.jsp라는 이름의 새 파일을 /users 디렉터리에 만든 후 아래와 같이 수정한다.
/users/changePasswd.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="../inc/loginCheck.jsp" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="비밀번호 변경" /> <meta name="Description" content="비빌번호 변경" /> <title>비밀번호 변경</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> <script type="text/javascript"> function check() { var form = document.getElementById("changePasswordForm"); if (form.newPasswd.value == form.confirm.value) { return true; } else { alert("[변경 비밀번호]와 [변경 비밀번호 확인] 값이 같지 않습니다."); return false; } } </script> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">회원</div> <h2>비밀번호 변경</h2> <%=user.getName() %><br /> 이동전화 <%=user.getMobile() %><br /> <form id="changePasswordForm" action="changePasswd_proc.jsp" method="post" onsubmit="return check()"> <table> <tr> <td>현재 비밀번호</td> <td><input type="password" name="currentPasswd" /></td> </tr> <tr> <td>변경 비밀번호</td> <td><input type="password" name="newPasswd" /></td> </tr> <tr> <td>변경 비밀번호 확인</td> <td><input type="password" name="confirm" /></td> </tr> <tr> <td colspan="2"><input type="submit" value="전송" /></td> </tr> </table> </form> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="user-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
비밀번호 변경 처리 페이지
비밀번호 변경 폼 페이지에서 전달된 비밀번호로 회원 테이블의 비밀번호를 수정하는 페이지이다.
/users/changePasswd_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 비밀번호를 변경하는 페이지로 모델 2에서는 삭제해야 할 페이지다. -구현- 로그인 사용자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Not Login"); return; 비밀번호 변경 후 비밀번호 변경 확인 페이지로 이동한다. */ response.sendRedirect("changePasswd_confirm.jsp"); %>
비밀번호 변경 확인 페이지
비밀번호 변경이 완료되었음을 알려주는 역할만을 담당하는 페이지를 만든다.
비밀번호 변경이 실패했는데 이 페이지가 보여서는 안 된다.
welcome.jsp 파일을 연 상태에서 Save As... 메뉴를 이용하여 changePasswd_confirm.jsp라는 이름의 새 파일을 /users 디렉터리에 만든 후 아래와 같이 수정한다.
/users/changePasswd_confirm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="비밀번호 변경 확인" /> <meta name="Description" content="비밀번호 변경 확인" /> <title>비밀번호 변경 확인</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">회원</div> <h2>비밀번호가 변경되었습니다.</h2> 변경된 비밀번호로 다시 로그인하실 수 있습니다.<br /> <input type="button" value="로그인" onclick="javascript:location.href='login.jsp'" /> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="user-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
회원 탈퇴 폼 페이지
회원 탈퇴를 위한 이메일과 비밀번호 폼을 보여주는 페이지를 만든다.
editAccount.jsp 파일을 연 상태에서 Save As... 메뉴를 이용하여 bye.jsp라는 이름의 새 파일을 /users 디렉터리에 만든 후 아래와 같이 수정한다.
/users/bye.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="../inc/loginCheck.jsp" %> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="탈퇴" /> <meta name="Description" content="탈퇴" /> <title>탈퇴</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> <script type="text/javascript"> function check() { //var form = document.getElementById("byeForm"); //유효성 검사 return true; } </script> </head> <body> <div id="wrap"> <div id="header"> <%@ include file="../inc/header.jsp" %> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">회원</div> <h2>탈퇴</h2> <form id="byeForm" action="bye_proc.jsp" method="post" onsubmit="return check()"> <table> <tr> <td>이메일</td> <td><input type="text" name="email" /></td> </tr> <tr> <td>비밀번호</td> <td><input type="password" name="passwd" /></td> </tr> <tr> <td colspan="2"><input type="submit" value="전송" /></td> </tr> </table> </form> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <%@ include file="user-sub.jsp" %> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
회원 탈퇴 처리 페이지
회원 탈퇴를 처리하는 페이지를 만든다.
/users/bye_proc.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% /* 회원탈퇴를 처리하는 페이지로 모델 2에서는 삭제해야 한다. -구현- 로그인 사용자가 아니면 response.sendError(HttpServletResponse.SC_FORBIDDEN, "Not Login"); return; 회원테이블에서 회원정보를 지운다. 세션을 지운다. 탈퇴 확인 페이지로 이동한다. */ response.sendRedirect("bye_confirm.jsp"); %>
회원 탈퇴 확인 페이지
회원 탈퇴가 완료되었음을 확인시켜주는 페이지를 만든다.
welcome.jsp 파일을 연 상태에서 Save As... 메뉴를 이용하여 bye_confirm.jsp라는 이름의 새 파일을 /users 디렉터리에 만든 후 아래와 같이 수정한다.
/users/bye_confirm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="Keywords" content="탈퇴 확인" /> <meta name="Description" content="탈퇴 확인" /> <title>탈퇴 확인</title> <link rel="stylesheet" href="/css/screen.css" type="text/css" /> </head> <body> <div id="wrap"> <div id="header"> </div> <div id="main-menu"> <%@ include file="../inc/main-menu.jsp" %> </div> <div id="container"> <div id="content"> <!-- 본문 시작 --> <div id="content-categories">회원</div> <h2>회원 탈퇴 확인</h2> 회원님의 모든 정보가 삭제되었습니다.<br /> <!-- 본문 끝 --> </div><!-- content 끝 --> </div><!-- container 끝 --> <div id="sidebar"> <h1>Goodbye</h1> </div> <div id="extra"> <%@ include file="../inc/extra.jsp" %> </div> <div id="footer"> <%@ include file="../inc/footer.jsp" %> </div> </div> </body> </html>
게시판 화면에 해당하는 페이지는 list.jsp, view.jsp, write.jsp, modify.jsp이다.
이 중에 modify.jsp를 제외하고 모두 loginCheck.jsp 파일을 인클루드하는데,
modify.jsp만 빠진 이유는 로그인뿐 아니라 글 소유자인지 검사하는 로직이 필요하기 때문이다.
(이 로직은 구현 단계로 넘긴다)
회원 페이지 중 editAccount.jsp, changePasswd.jsp, bye.jsp는 loginCheck.jsp 파일을 인클루드한다.
화면을 보여주지 않고 처리만을 담당하는 페이지는 파일명에 _proc를 붙여서 구별했다.
로그인 정책 정리
구현에 앞서 로그인 정책을 다시 확인한다.
- 게시판과 관련된 모든 페이지는 로그인이 필요하다.
- 회원 모듈에서 내 정보 수정, 비밀번호 변경, 탈퇴는 로그인이 필요하다.
- 로그인이 성공하면 /bbs/list.jsp?boardCd=chat&curPage=1로 이동한다.
- 로그인하지 않고 로그인이 필요한 페이지를 방문하면 로그인 페이지로 이동하고, 로그인이 성공하면 원래 방문하려 했던 페이지로 이동한다.
- 로그아웃하면 홈페이지로 이동한다.
이로써 프로토타입을 완성했다.