본문 바로가기
개인 프로젝트/Java Spring 프레임워크

[Board Project] 테이블 구조 ->MVC 패턴 적용

by 응_비 2024. 10. 18.

MVC 패턴은 Model, View, Controller

 

MVC 패턴이란 무엇인가?

  • **MVC (Model-View-Controller)**는 애플리케이션을 세 개의 주요 컴포넌트(모델, 뷰, 컨트롤러)로 나누는 아키텍처 패턴입니다. 이 패턴은 유지 보수성, 확장성, 역할의 분리를 통해 코드 품질을 높이고 개발을 효율적으로 할 수 있게 도와줍니다.
    • Model (모델): 애플리케이션의 데이터비즈니스 로직을 관리합니다. 모델은 데이터베이스와 상호작용하고, 데이터를 처리합니다.
    • View (뷰): 사용자가 보는 UI 부분을 담당합니다. JSP는 뷰(View) 역할을 수행하며, 데이터가 어떻게 사용자에게 보여질지 결정합니다.
    • Controller (컨트롤러): 사용자의 요청을 받아 비즈니스 로직을 처리하고, 필요한 데이터를 가져와 View에 전달합니다. 컨트롤러는 모델과 뷰를 연결하는 역할을 합니다.

JSP와 MVC 패턴의 차이와 연결고리

차이점

  • JSPView(뷰) 역할을 수행하는 기술입니다. JSP는 웹 애플리케이션의 화면(UI)을 구성하고, 사용자에게 보여지는 데이터를 출력하는 데 사용됩니다.
  • MVC는 애플리케이션을 세 개의 주요 컴포넌트인 모델(Model), 뷰(View), **컨트롤러(Controller)**로 나누는 구조적인 패턴입니다. 이 패턴에서 View는 JSP를 사용하여 구현될 수 있습니다.

JSP와 MVC 패턴의 통합 예시 흐름

1) 사용자 요청

사용자가 http://localhost:8080/board/list로 게시글 목록을 요청합니다.

2) Controller

BoardController가 이 요청을 받아 처리합니다. 컨트롤러는 boardService를 호출하여 필요한 데이터를 Model에서 가져오고, 그 데이터를 JSP에 전달할 준비를 합니다.

3) Model

boardService.getBoardList() 메서드가 데이터베이스에서 게시글 목록을 가져옵니다. BoardDAO가 SQL을 실행해 데이터를 가져오는 역할을 담당합니다.

4) View (JSP)

컨트롤러는 boardList.jsp로 데이터를 전달합니다. JSP는 이 데이터를 받아 HTML로 변환하여 웹 브라우저에 출력합니다. 사용자는 게시글 목록을 브라우저에서 확인합니다.

연결고리: JSP와 MVC의 역할 분담

MVC 패턴에서 각 컴포넌트는 서로 명확하게 구분되어 있으며, JSP는 View 부분에서 화면을 렌더링하는 역할을 합니다.

 

1. Model (모델)

Model은 데이터를 다루는 부분입니다. VO, DAO, Service는 모두 Model에 해당합니다.

BoardVO.java (Value Object)

import java.util.Date;

public class BoardVO {
    private int seq;
    private String title;
    private String writer;
    private String content;
    private Date regdate;
    private int cnt;

    // 기본 생성자
    public BoardVO() {}

    // 모든 필드를 가진 생성자
    public BoardVO(int seq, String title, String writer, String content, Date regdate, int cnt) {
        this.seq = seq;
        this.title = title;
        this.writer = writer;
        this.content = content;
        this.regdate = regdate;
        this.cnt = cnt;
    }

    // Getter 및 Setter
    public int getSeq() { return seq; }
    public void setSeq(int seq) { this.seq = seq; }
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public String getWriter() { return writer; }
    public void setWriter(String writer) { this.writer = writer; }
    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
    public Date getRegdate() { return regdate; }
    public void setRegdate(Date regdate) { this.regdate = regdate; }
    public int getCnt() { return cnt; }
    public void setCnt(int cnt) { this.cnt = cnt; }
}​

BoardDAO.java (Data Access Object)

import java.util.List;

public interface BoardDAO {
    // 게시글 등록
    void insertBoard(BoardVO board);

    // 게시글 수정
    void updateBoard(BoardVO board);

    // 게시글 삭제
    void deleteBoard(int seq);

    // 게시글 조회
    BoardVO getBoard(int seq);

    // 게시글 전체 목록 조회
    List<BoardVO> getBoardList();
}

BoardDAOImpl.java (DAO 구현체)

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class BoardDAOImpl implements BoardDAO {
    private Connection conn;

    public BoardDAOImpl(Connection conn) {
        this.conn = conn;
    }

    @Override
    public void insertBoard(BoardVO board) {
        String sql = "INSERT INTO BOARD (SEQ, TITLE, WRITER, CONTENT, REGDATE, CNT) VALUES (?, ?, ?, ?, ?, ?)";
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, board.getSeq());
            pstmt.setString(2, board.getTitle());
            pstmt.setString(3, board.getWriter());
            pstmt.setString(4, board.getContent());
            pstmt.setDate(5, new java.sql.Date(board.getRegdate().getTime()));
            pstmt.setInt(6, board.getCnt());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void updateBoard(BoardVO board) {
        String sql = "UPDATE BOARD SET TITLE = ?, CONTENT = ?, CNT = ? WHERE SEQ = ?";
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, board.getTitle());
            pstmt.setString(2, board.getContent());
            pstmt.setInt(3, board.getCnt());
            pstmt.setInt(4, board.getSeq());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void deleteBoard(int seq) {
        String sql = "DELETE FROM BOARD WHERE SEQ = ?";
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, seq);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public BoardVO getBoard(int seq) {
        String sql = "SELECT * FROM BOARD WHERE SEQ = ?";
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, seq);
            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                return new BoardVO(
                    rs.getInt("SEQ"),
                    rs.getString("TITLE"),
                    rs.getString("WRITER"),
                    rs.getString("CONTENT"),
                    rs.getDate("REGDATE"),
                    rs.getInt("CNT")
                );
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<BoardVO> getBoardList() {
        String sql = "SELECT * FROM BOARD";
        List<BoardVO> list = new ArrayList<>();
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                list.add(new BoardVO(
                    rs.getInt("SEQ"),
                    rs.getString("TITLE"),
                    rs.getString("WRITER"),
                    rs.getString("CONTENT"),
                    rs.getDate("REGDATE"),
                    rs.getInt("CNT")
                ));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }
}
 

2. Service (서비스)

BoardService.java (서비스 인터페이스)

import java.util.List;

public interface BoardService {
    void addBoard(BoardVO board);
    void modifyBoard(BoardVO board);
    void removeBoard(int seq);
    BoardVO getBoard(int seq);
    List<BoardVO> getBoardList();
}​

BoardServiceImpl.java (서비스 구현체)

import java.util.List;

public class BoardServiceImpl implements BoardService {

    private BoardDAO boardDAO;

    public BoardServiceImpl(BoardDAO boardDAO) {
        this.boardDAO = boardDAO;
    }

    @Override
    public void addBoard(BoardVO board) {
        boardDAO.insertBoard(board);
    }

    @Override
    public void modifyBoard(BoardVO board) {
        boardDAO.updateBoard(board);
    }

    @Override
    public void removeBoard(int seq) {
        boardDAO.deleteBoard(seq);
    }

    @Override
    public BoardVO getBoard(int seq) {
        return boardDAO.getBoard(seq);
    }

    @Override
    public List<BoardVO> getBoardList() {
        return boardDAO.getBoardList();
    }
}​

3. Controller (컨트롤러)

BoardController.java (컨트롤러 클래스)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
public class BoardController {

    @Autowired
    private BoardService boardService;

    // 게시글 목록
    @GetMapping("/boardList")
    public String boardList(Model model) {
        List<BoardVO> boardList = boardService.getBoardList();
        model.addAttribute("boardList", boardList);
        return "boardList"; // View 파일 이름 (boardList.jsp)
    }

    // 게시글 상세보기
    @GetMapping("/boardDetail")
    public String boardDetail(@RequestParam("seq") int seq, Model model) {
        BoardVO board = boardService.getBoard(seq);
        model.addAttribute("board", board);
        return "boardDetail"; // View 파일 이름 (boardDetail.jsp)
    }

    // 게시글 작성 폼
    @GetMapping("/addBoardForm")
    public String addBoardForm() {
        return "addBoard"; // View 파일 이름 (addBoard.jsp)
    }

    // 게시글 등록
    @PostMapping("/addBoard")
    public String addBoard(BoardVO boardVO) {
        boardService.addBoard(boardVO);
        return "redirect:/boardList";
    }

    // 게시글 삭제
    @GetMapping("/deleteBoard")
    public String deleteBoard(@RequestParam("seq") int seq) {
        boardService.removeBoard(seq);
        return "redirect:/boardList";
    }
}​

 

@RequestMapping을 사용한 Controller 코드

BoardController.java (컨트롤러 클래스)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
@RequestMapping("/board")
public class BoardController {

    @Autowired
    private BoardService boardService;

    // 게시글 목록
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String boardList(Model model) {
        List<BoardVO> boardList = boardService.getBoardList();
        model.addAttribute("boardList", boardList);
        return "boardList"; // View 파일 이름 (boardList.jsp)
    }

    // 게시글 상세보기
    @RequestMapping(value = "/detail", method = RequestMethod.GET)
    public String boardDetail(@RequestParam("seq") int seq, Model model) {
        BoardVO board = boardService.getBoard(seq);
        model.addAttribute("board", board);
        return "boardDetail"; // View 파일 이름 (boardDetail.jsp)
    }

    // 게시글 작성 폼
    @RequestMapping(value = "/addForm", method = RequestMethod.GET)
    public String addBoardForm() {
        return "addBoard"; // View 파일 이름 (addBoard.jsp)
    }

    // 게시글 등록
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addBoard(BoardVO boardVO) {
        boardService.addBoard(boardVO);
        return "redirect:/board/list";
    }

    // 게시글 삭제
    @RequestMapping(value = "/delete", method = RequestMethod.GET)
    public String deleteBoard(@RequestParam("seq") int seq) {
        boardService.removeBoard(seq);
        return "redirect:/board/list";
    }
}

 


4. View (뷰)

boardList.jsp

<html>
<head>
    <title>Board List</title>
</head>
<body>
    <h1>Board List</h1>
    <table border="1">
        <tr>
            <th>SEQ</th>
            <th>Title</th>
            <th>Writer</th>
            <th>Date</th>
            <th>Views</th>
            <th>Action</th>
        </tr>
        <c:forEach var="board" items="${boardList}">
            <tr>
                <td>${board.seq}</td>
                <td><a href="boardDetail?seq=${board.seq}">${board.title}</a></td>
                <td>${board.writer}</td>
                <td>${board.regdate}</td>
                <td>${board.cnt}</td>
                <td><a href="deleteBoard?seq=${board.seq}">Delete</a></td>
            </tr>
        </c:forEach>
    </table>
    <br>
    <a href="addBoardForm">Add New Board</a>
</body>
</html>

boardDetail.jsp

<html>
<head>
    <title>Board Detail</title>
</head>
<body>
    <h1>Board Detail</h1>
    <p>Title: ${board.title}</p>
    <p>Writer: ${board.writer}</p>
    <p>Content: ${board.content}</p>
    <p>Views: ${board.cnt}</p>
    <p>Date: ${board.regdate}</p>
    <a href="boardList">Back to List</a>
</body>
</html>

addBoard.jsp

<html>
<head>
    <title>Add New Board</title>
</head>
<body>
    <h1>Add New Board</h1>
    <form action="addBoard" method="post">
        <label>Title: </label>
        <input type="text" name="title"><br>
        <label>Writer: </label>
        <input type="text" name="writer"><br>
        <label>Content: </label>
        <textarea name="content"></textarea><br>
        <input type="submit" value="Submit">
    </form>
    <a href="boardList">Cancel</a>
</body>
</html>

결론

이제 MVC 패턴에 맞춰 Model, View, Controller가 모두 작성되었습니다.

  • Model: BoardVO, BoardDAO, BoardService 계층에서 데이터를 처리하고, 데이터베이스와 상호작용하는 로직을 담당합니다.
  • View: JSP 파일들은 사용자에게 데이터를 시각적으로 제공하고, 사용자로부터 입력을 받습니다.
  • Controller: 사용자의 요청을 처리하고, 그 결과를 View에 전달하는 역할을 합니다.

이 구조를 사용하면 유지보수성과 확장성이 높아지고, 각 컴포넌트의 역할이 명확해집니다.

 

JSP와 MVC  패턴 연결고리 (결론)

  • JSPView로서 UI 화면을 렌더링하는 데 사용되는 기술입니다. MVC 패턴은 애플리케이션 전체를 세 개의 주요 구성 요소로 나누어 구조화하는 방법이며, 이 중 View 부분을 JSP가 담당할 수 있습니다.
  • JSP와 MVC 패턴은 서로 보완적인 관계에 있습니다. JSP는 MVC 패턴의 View 역할을 하여 사용자가 볼 수 있는 화면을 출력하고, MVC는 데이터 처리 및 흐름 제어를 담당합니다. 이 두 가지는 함께 사용되어, 유지 보수가 쉽고 확장성이 좋은 웹 애플리케이션을 구축하는 데 큰 도움이 됩니다.
 

댓글