Model 1은 JSP 페이지가 모델(Model), 뷰(View), 컨트롤러(Controller)의 역할을 모두 수행하는 단일화된 구조로 이루어져 있습니다. 즉, 사용자 요청을 받아서 비즈니스 로직을 수행하고, 결과를 사용자에게 반환하는 작업을 모두 JSP가 처리합니다.
JSP Model 1 구조에서 DAO와 DTO를 사용하는 예는 비즈니스 로직과 데이터 접근을 구조화하고, JSP 코드의 유지보수성을 높이는 데 도움이 됩니다. 이 방식은 작은 프로젝트에서도 코드를 보다 체계적으로 관리할 수 있게 해줍니다.
다음은 JSP 페이지에서 DAO와 DTO를 함께 사용하여 간단한 게시판 기능을 구현하는 예입니다. 이 예제에서는 게시물 정보를 저장하고 불러오는 기능을 포함합니다.
BoardDTO
클래스. 데이터 전송 객체로, 데이터베이스에서 가져오거나 사용자 입력을 통해 전달되는 데이터만 담고 있습니다.BoardDAO
클래스.게시물의 데이터를 담는 BoardDTO 클래스입니다. 이 클래스에는 게시물 ID, 제목, 내용과 같은 필드를 정의하고, 각 필드에 대한 getter/setter 메서드를 제공합니다.
// BoardDTO.java
public class BoardDTO {
private int id;
private String title;
private String content;
// 기본 생성자
public BoardDTO() {}
// Getter와 Setter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
id
, title
, content
는 데이터베이스의 게시물 정보를 저장하는 데 사용됩니다.BoardDAO 클래스는 데이터베이스와의 연결을 통해 CRUD 작업을 수행합니다. 아래 예제에서는 데이터베이스에서 게시물을 조회하고, 새로운 게시물을 삽입하는 메서드만 포함합니다.
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class BoardDAO {
private Connection conn;
// 데이터베이스 연결 메서드
private Connection getConnection() throws Exception {
String url = "jdbc:mariadb://localhost:3306/boarddb";
String username = "root";
String password = "password";
conn = DriverManager.getConnection(url, username, password);
return conn;
}
// 게시물 목록 조회
public List<BoardDTO> getAllPosts() throws Exception {
List<BoardDTO> postList = new ArrayList<>();
try {
conn = getConnection();
String sql = "SELECT * FROM board ORDER BY id DESC";
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
BoardDTO post = new BoardDTO();
post.setId(rs.getInt("id"));
post.setTitle(rs.getString("title"));
post.setContent(rs.getString("content"));
postList.add(post);
}
} finally {
if (conn != null) conn.close();
}
return postList;
}
// 게시물 추가
public void addPost(BoardDTO post) throws Exception {
try {
conn = getConnection();
String sql = "INSERT INTO board (title, content) VALUES (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, post.getTitle());
pstmt.setString(2, post.getContent());
pstmt.executeUpdate();
} finally {
if (conn != null) conn.close();
}
}
}
getAllPosts()
: 데이터베이스에서 모든 게시물을 조회하고, BoardDTO
리스트로 반환합니다.addPost()
: BoardDTO
객체를 받아 데이터베이스에 새 게시물을 추가합니다.사용자가 게시물 제목과 내용을 입력할 수 있는 폼을 제공하는 JSP 페이지입니다. 사용자가 입력한 데이터는 BoardDAO
의 addPost()
메서드를 통해 데이터베이스에 저장됩니다.
<!-- boardForm.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.example.BoardDTO, com.example.BoardDAO" %>
<%
if ("POST".equalsIgnoreCase(request.getMethod())) {
// 사용자가 입력한 제목과 내용을 가져옴
String title = request.getParameter("title");
String content = request.getParameter("content");
// BoardDTO에 입력 데이터 설정
BoardDTO post = new BoardDTO();
post.setTitle(title);
post.setContent(content);
// DAO를 통해 데이터베이스에 저장
BoardDAO dao = new BoardDAO();
dao.addPost(post);
// 게시물 목록 페이지로 리다이렉트
response.sendRedirect("boardList.jsp");
return;
}
%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>게시물 작성</title>
</head>
<body>
<h2>게시물 작성</h2>
<form action="boardForm.jsp" method="post">
제목: <input type="text" name="title"><br>
내용: <textarea name="content"></textarea><br>
<input type="submit" value="작성">
</form>
</body>
</html>
데이터베이스에 저장된 모든 게시물을 조회하여 사용자에게 표시하는 JSP 페이지입니다.
<!-- boardList.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.example.BoardDTO, com.example.BoardDAO" %>
<%
// DAO를 통해 게시물 목록 가져오기
BoardDAO dao = new BoardDAO();
List<BoardDTO> postList = dao.getAllPosts();
%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>게시물 목록</title>
</head>
<body>
<h2>게시물 목록</h2>
<a href="boardForm.jsp">새 게시물 작성</a>
<table border="1">
<tr>
<th>번호</th>
<th>제목</th>
<th>내용</th>
</tr>
<%
for (BoardDTO post : postList) {
%>
<tr>
<td><%= post.getId() %></td>
<td><%= post.getTitle() %></td>
<td><%= post.getContent() %></td>
</tr>
<%
}
%>
</table>
</body>
</html>
getAllPosts()
메서드를 호출하여 모든 게시물을 조회하고, BoardDTO
리스트를 통해 데이터를 화면에 출력합니다.BoardDTO
는 데이터 전달 객체로, 게시물 데이터를 담아 이동하는 데 사용됩니다.BoardDAO
는 데이터베이스와의 CRUD 작업을 담당하여 데이터베이스 작업을 JSP 코드와 분리합니다.boardForm.jsp
와 boardList.jsp
는 사용자의 입력을 처리하고 데이터베이스의 데이터를 조회하여 화면에 출력하는 역할을 수행합니다.이와 같은 구조를 사용하면, JSP Model 1에서도 MVC에 가까운 구조로 구현하여 코드의 유지보수성과 확장성을 높일 수 있습니다.
BoardTO.java
package org.example.model;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class BoardTO {
private String seq;
private String subject;
private String writer;
private String mail;
private String password;
private String content;
private String hit;
private String wip;
private String wdate;
private int wgap;
}
BoardDao.java
package org.example.model;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class BoardDAO {
private DataSource dataSource;
public BoardDAO() {
try {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
this.dataSource = (DataSource) envCtx.lookup("jdbc/mariadb1");
} catch (NamingException e) {
System.out.println("[에러] " + e.getMessage());
}
}
public ArrayList<BoardTO> boardList() {
System.out.println("BoardDAO.boardList 호출");
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
ArrayList<BoardTO> list = new ArrayList<>();
try {
conn = dataSource.getConnection(); // 데이터베이스 연결
String sql = "select seq, subject, writer, date_format(wdate, '%Y/%m/%d') wdate, datediff(now(), wdate) wgap, hit from board1 order by seq desc";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
// 레코드 컬럼 추출
BoardTO to = new BoardTO();
to.setSeq(rs.getString("seq"));
to.setSubject(rs.getString("subject"));
to.setWriter(rs.getString("writer"));
to.setWdate(rs.getString("wdate"));
to.setHit(rs.getString("hit"));
to.setWgap(rs.getInt("wgap"));
list.add(to);
}
} catch (SQLException e) {
System.out.println("[에러] " + e.getMessage());
} finally {
try {
rs.close();
} catch (SQLException e) {
}
try {
pstmt.close();
} catch (SQLException e) {
}
try {
conn.close();
} catch (SQLException e) {
}
}
return list;
}
public BoardTO boardView(BoardTO to) {
System.out.println("BoardDAO.boardView 호출");
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
StringBuilder sbHtml = new StringBuilder();
try {
Context initCtx = new InitialContext(); // 컨텍스트 객체 생성
Context envCtx = (Context) initCtx.lookup("java:/comp/env"); // 환경 객체 생성
DataSource dataSource = (DataSource) envCtx.lookup("jdbc/mariadb1"); // 데이터소스 객체 생성
conn = dataSource.getConnection(); // 데이터베이스 연결
// 조회수 증가
String sql = "update board1 set hit=hit+1 where seq=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, to.getSeq());
pstmt.executeUpdate();
// 자세히 보기 데이터
sql = "select subject, writer, mail, wip, wdate, hit, content from board1 where seq = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, to.getSeq());
rs = pstmt.executeQuery();
// 데이터가 있으면 추출
if (rs.next()) {
// 레코드 컬럼 추출
to.setSubject(rs.getString("subject"));
to.setWriter(rs.getString("writer"));
to.setMail(rs.getString("mail"));
to.setWip(rs.getString("wip"));
to.setWdate(rs.getString("wdate"));
to.setHit(rs.getString("hit"));
// 엔터키 -> <br/ >
to.setContent(rs.getString("content").replaceAll("\n", "<br />"));
}
} catch (NamingException e) {
System.out.println("[에러] " + e.getMessage());
} catch (SQLException e) {
System.out.println("[에러] " + e.getMessage());
} finally {
try {
rs.close();
} catch (SQLException e) {
}
try {
pstmt.close();
} catch (SQLException e) {
}
try {
conn.close();
} catch (SQLException e) {
}
}
return to;
}
public void boardWrite() {
System.out.println("BoardDAO.boardWrite 호출");
}
public int boardWriteOk(BoardTO to) {
System.out.println("boardWriteOk 호출");
// 데이터베이스 연결
Connection conn = null;
PreparedStatement pstmt = null;
int flag = 1;
try {
conn = dataSource.getConnection();
String sql = "insert into board1(subject, writer, mail, password, content, hit, wip, wdate) values(?, ?, ?, password(?), ?, 0, ?, now())";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, to.getSubject());
pstmt.setString(2, to.getWriter());
pstmt.setString(3, to.getMail());
pstmt.setString(4, to.getPassword());
pstmt.setString(5, to.getContent());
pstmt.setString(6, to.getWip());
int result = pstmt.executeUpdate();
if (result == 1) {
flag = 0;
}
} catch (SQLException e) {
System.out.println("[에러] " + e.getMessage());
} finally {
try {
pstmt.close();
} catch (SQLException e) {
}
try {
conn.close();
} catch (SQLException e) {
}
}
return flag;
}
public BoardTO boardModify(BoardTO to) {
System.out.println("BoardDAO.boardModify 호출");
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
System.out.println("mail log1 : " + to.getMail());
try {
conn = dataSource.getConnection();
String sql = "select subject, writer, mail, content from board1 where seq=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, to.getSeq());
rs = pstmt.executeQuery();
if (rs.next()) {
to.setSubject(rs.getString("subject"));
to.setWriter(rs.getString("writer"));
to.setMail(rs.getString("mail"));
to.setContent(rs.getString("content"));
}
} catch (SQLException e) {
System.out.println("[에러] " + e.getMessage());
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
System.out.println("mail log2 : " + to.getMail());
return to;
}
public int boardModifyOk(BoardTO to) {
System.out.println("BoardDAO.boardModifyOk 호출");
// 데이터베이스 연결
Connection conn = null;
PreparedStatement pstmt = null;
// 에러를 감별할 변수
int flag = 2; // 0: 비밀번호 오류, 1: 수정 성공, 2: 수정 실패
try {
conn = dataSource.getConnection();
// 비밀번호는 SELECT 문으로 가져오면 안됨.
// 비밀번호는 암호화된 상태로 저장되어 있으므로 password() 함수를 사용하여 암호화
String sql = "update board1 set subject=?, content=?, mail=? where seq=? and password=password(?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, to.getSubject());
pstmt.setString(2, to.getContent());
pstmt.setString(3, to.getMail());
pstmt.setString(4, to.getSeq());
pstmt.setString(5, to.getPassword());
int result = pstmt.executeUpdate();
if (result == 0) {
flag = 1; // 비밀번호가 오류
} else if (result == 1) {
flag = 0; // 삭제 성공
}
} catch (SQLException e) {
System.out.println("[에러] " + e.getMessage());
} finally {
try {
pstmt.close();
} catch (SQLException e) {
}
try {
conn.close();
} catch (SQLException e) {
}
}
return flag;
}
public BoardTO boardDelete(BoardTO to) {
System.out.println("BoardDAO.boardDelete 호출");
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource dataSource = (DataSource) envCtx.lookup("jdbc/mariadb1");
conn = dataSource.getConnection();
String sql = "select subject, writer from board1 where seq=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, to.getSeq());
rs = pstmt.executeQuery();
if (rs.next()) {
to.setSubject(rs.getString("subject"));
to.setWriter(rs.getString("writer"));
}
} catch (NamingException e) {
System.out.println("[에러] " + e.getMessage());
} catch (SQLException e) {
System.out.println("[에러] " + e.getMessage());
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
}
;
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
}
}
;
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
;
}
return to;
}
public int boardDeleteOk(BoardTO to) {
System.out.println("BoardDAO.boardDeleteOk 호출");
Connection conn = null;
PreparedStatement pstmt = null;
// 에러를 감별할 변수
int flag = 2; // 0: 삭제 성공, 1: 비밀번호 오류, 2: 삭제 실패
try {
conn = dataSource.getConnection();
// 비밀번호는 SELECT 문으로 가져오면 안됨.
// 비밀번호는 암호화된 상태로 저장되어 있으므로 password() 함수를 사용하여 암호화
String sql = "delete from board1 where seq=? and password=password(?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, to.getSeq());
pstmt.setString(2, to.getPassword());
int result = pstmt.executeUpdate();
if (result == 0) {
flag = 1; // 비밀번호가 오류
} else if (result == 1) {
flag = 0; // 삭제 성공
}
} catch (SQLException e) {
System.out.println("[에러] " + e.getMessage());
} finally {
try {
pstmt.close();
} catch (SQLException e) {
}
try {
conn.close();
} catch (SQLException e) {
}
}
return flag;
}
}