[spring] 웹 애플리케이션 모델 MVC

sang·2024년 3월 28일

웹 애플리케이션 모델

웹 표준화 소스 구조

종류

  • 모델 1 방식
    브라우저 - JSP - DAO 클래스 - DB
    JSP가 모든 클라이언트 요청 및 비즈니스 로직 처리
    쉬운 기능 구현
    기능 복잡도 증가 시 유지보수 문제 발생
    비즈니스 로직과 화면 기능이 섞여있어 낮은 코드 재사용성

  • 모델 2 방식
    브라우저 - (분리된 각 기능들) - DB
    웹 애플리케이션의 각 기능 분리 모듈화
    높은 개발 효율성
    편리한 유지보수
    높은 코드 재사용성
    작업 분업화 가능

MVC 디자인 패턴

Model - View - Controller

화면 부분, 요청 처리 부분, 로직 부분으로 나누어 개발하는 것

Controller: 클라이언트 요청 분석, 필요한 모델 호출, 비즈니스 로직 처리 제어 (서블릿)
Model: 데이터베이스 연동 (DAO, VO 클래스들)
View: 처리 결과 화면 구현 및 클라이언트 전송 (JSP)

커맨드 패턴

http://localhost:8090/컨텍스트명/기능대분류/기능
브라우저가 URL 패턴을 이용해 컨트롤러에게 수행 작업을 요청하는 방법
보통 두 단계의 요청 형식 (기능대분류 >> 기능)

  • 컨트롤러:
    1. 브라우저에게 받은 요청 종류 확인
    2. 요청에 대응하는 모델 선택 및 작업 전달


회원 관리 실습

pro17/src/sec01/ex01/MemberController.java

package sec01.ex01;
...
@WebServlet("/member/*") //두 단계 요청 형식
public class MemberController extends HttpServlet {
  private static final long serialVersionUID = 1L;
  MemberDAO memberDAO;

  public void init() throws ServletException { memberDAO = new MemberDAO(); }
  
  /** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) **/
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doHandle(request, response);
  }
  
  /** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) **/
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doHandle(request, response);
  }
  
  private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String nextPage = null;
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
    
    String action = request.getPathInfo(); //브라우저 요청명 가져오기
    System.out.println("action:" + action);
    
    /* 회원 목록 요청 */
    if (action == null /*최초 요청*/ || action.equals("/listMembers.do")) {
      List<MemberVO> membersList = memberDAO.listMembers(); //회원 목록 조회
      request.setAttribute("membersList", membersList);
      nextPage = "/test02/listMembers.jsp";
    }
    /* 회원 추가 요청 */
    else if (action.equals("/addMember.do")) {
      String id = request.getParameter("id");
      String pwd = request.getParameter("pwd");
      String name = request.getParameter("name");
      String email = request.getParameter("email");
      MemberVO memberVO = new MemberVO(id, pwd, name, email);
      memberDAO.addMember(memberVO); //회원 추가
      nextPage = "/member/listMembers.do"; // -> 회원 목록 요청
    }
    /* 회원 가입창 요청 */
    else if (action.equals("/memberForm.do")) {
      nextPage = "/test02/memberForm.jsp"; //jsp -> 회원 추가 요청
    }
    
    /* 회원 수정창 요청 */
    else if (action.equals("/modMemberForm.do")) {
      String id = request.getParameter("id");
      MemberVO memInfo = memberDAO.findMember(id); //특정 회원 조회
      request.setAttribute("memInfo", memInfo);
      nextPage = "/test03/modMemberForm.jsp"; //jsp -> 회원 정보 수정 요청
    }
    /* 회원 정보 수정 요청 *
    else if (action.equals("/modMember.do")) {
      String id = request.getParameter("id");
      String pwd = request.getParameter("pwd");
      String name = request.getParameter("name");
      String email = request.getParameter("email");
      MemberVO memberVO = new MemberVO(id, pwd, name, email);
      memberDAO.modMember(memberVO); //회원 정보 수정
      request.setAttribute("msg", "modified");
      nextPage = "/member/listMembers.do"; // -> 회원 목록 요청
    }
    /* 회원 삭제 요청 */
    else if (action.equals("/delMember.do")) {
      String id = request.getParameter("id");
      memberDAO.delMember(id); //회원 삭제
      request.setAttribute("msg", "deleted");
      nextPage = "/member/listMembers.do"; // -> 회원 목록 요청
    }
    
    /* 그 외 요청 */
    else {
      List<MemberVO> membersList = memberDAO.listMembers(); //회원 목록 조회
      request.setAttribute("membersList", membersList);
      nextPage = "/test02/listMembers.jsp";
    }
    
    /* 공통: 포워딩 */
    RequestDispatcher dispatch = request.getRequestDispatcher(nextPage);
    dispatch.forward(request, response);
  }
  
}

pro17/src/sec01/ex01/MemberDAO.java

package sec01.ex01;
...
public class MemberDAO {
  private DataSource dataFactory;
  private Connection conn;
  private PreparedStatement pstmt;

  public MemberDAO() {
    try {
      Context ctx = new InitialContext();
      Context envContext = (Context) ctx.lookup("java:/comp/env");
      dataFactory = (DataSource) envContext.lookup("jdbc/oracle");
    } catch (Exception e) { e.printStackTrace(); }
  }
  
  public List<MemberVO> listMembers() { //회원 목록 조회
    List<MemberVO> membersList = new ArrayList<MemberVO>();
    try {
      conn = dataFactory.getConnection();
      String query = "select * from t_member order by joinDate desc";
      System.out.println(query);
      pstmt = conn.prepareStatement(query);
      ResultSet rs = pstmt.executeQuery();
      while (rs.next()) {
        String id = rs.getString("id");
        String pwd = rs.getString("pwd");
        String name = rs.getString("name");
        String email = rs.getString("email");
        Date joinDate = rs.getDate("joinDate");
        MemberVO memberVO = new MemberVO(id, pwd, name, email, joinDate);
        membersList.add(memberVO);
      }
      rs.close();
      pstmt.close();
      conn.close();
    } catch (SQLException e) { e.printStackTrace(); }
    
    return membersList;
  }
  
  public void addMember(MemberVO m) { //회원 추가
    try {
      conn = dataFactory.getConnection();
      String id = m.getId();
      String pwd = m.getPwd();
      String name = m.getName();
      String email = m.getEmail();
      String query = "INSERT INTO t_member(id, pwd, name, email)" + " VALUES(?, ? ,? ,?)";
      System.out.println(query);
      pstmt = conn.prepareStatement(query);
      pstmt.setString(1, id);
      pstmt.setString(2, pwd);
      pstmt.setString(3, name);
      pstmt.setString(4, email);
      pstmt.executeUpdate();
      pstmt.close();
      conn.close();
    } catch (SQLException e) { e.printStackTrace(); }
  }
  
  public MemberVO findMember(String _id) { //특정 회원 조회
    MemberVO memInfo = null;
    try {
      conn = dataFactory.getConnection();
      String query = "select * from t_member where id=?";
      pstmt = conn.prepareStatement(query);
      pstmt.setString(1, _id);
      System.out.println(query);
      ResultSet rs = pstmt.executeQuery();
      rs.next();
      String id = rs.getString("id");
      String pwd = rs.getString("pwd");
      String name = rs.getString("name");
      String email = rs.getString("email");
      Date joinDate = rs.getDate("joinDate");
      memInfo = new MemberVO(id, pwd, name, email, joinDate);
      pstmt.close();
      conn.close();
    } catch (Exception e) { e.printStackTrace(); }
    return memInfo;
  }
  
  public void modMember(MemberVO memberVO) { //회원 정보 수정
    String id = memberVO.getId();
    String pwd = memberVO.getPwd();
    String name = memberVO.getName();
    String email = memberVO.getEmail();
    try {
      conn = dataFactory.getConnection();
      String query = "update t_member set pwd=?,name=?,email=? where id=?";
      System.out.println(query);
      pstmt = conn.prepareStatement(query);
      pstmt.setString(1, pwd);
      pstmt.setString(2, name);
      pstmt.setString(3, email);
      pstmt.setString(4, id);
      pstmt.executeUpdate();
      pstmt.close();
      conn.close();
    } catch (Exception e) { e.printStackTrace(); }
  }
  
  public void delMember(String id) { //회원 삭제
    try {
      conn = dataFactory.getConnection();
      String query = "delete from t_member where id=?";
      System.out.println(query);
      pstmt = conn.prepareStatement(query);
      pstmt.setString(1, id);
      pstmt.executeUpdate();
    } catch (Exception e) { e.printStackTrace(); }
  }
  
}

pro17/src/sec01/ex01/MemberVO.java

package sec01.ex01;
import java.sql.Date;

public class MemberVO {
  ...
  public MemberVO() {
    System.out.println("MemberVO 생성자 호출");
  }
  
  public MemberVO(String id, String pwd, String name, String email) {
    this.id = id;
    this.pwd = pwd;
    this.name = name;
    this.email = email;
  }
  
  public MemberVO(String id, String pwd, String name, String email, Date joinDate) {
    this.id = id;
    this.pwd = pwd;
    this.name = name;
    this.email = email;
    this.joinDate = joinDate;
  }

  // 각 속성에 대한 getter/setter
  ...

pro17/WebContent/test01/listMembers.jsp

회원 정보 창

<%@ page language="java" contentType="text/html; charset=UTF-8" import=" java.util.*,sec01.ex01.*" pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<%  request.setCharacterEncoding("UTF-8"); %>

<html>
<head>
  <c:choose>
  <c:when test='${msg=="addMember" }'>
      <script>
        window.onload = function () {
          alert("회원을 등록했습니다.");
        }
      </script>
    </c:when>
    <c:when test='${msg=="modified" }'>
      <script>
        window.onload = function () {
          alert("회원 정보를 수정했습니다.");
        }
      </script>
    </c:when>
    <c:when test='${msg=="deleted" }'>
      <script>
        window.onload = function () {
          alert("회원 정보를 삭제했습니다.");
        }
      </script>
    </c:when>
  </c:choose>

  <meta charset="UTF-8">
  <title>회원 정보 출력창</title>
  <style>
    .cls1 {
      font-size: 40px;
      text-align: center;
    }
    .cls2 {
      font-size: 20px;
      text-align: center;
    }
  </style>
</head>
<body>
  <p class="cls1">회원정보</p>
  <table align="center" border="1">
    <tr align="center" bgcolor="lightgreen">
      <td width="7%"><b>아이디</b></td>
      <td width="7%"><b>비밀번호</b></td>
      <td width="7%"><b>이름</b></td>
      <td width="7%"><b>이메일</b></td>
      <td width="7%"><b>가입일</b></td>
      <td width="7%"><b>수정</b></td>
      <td width="7%"><b>삭제</b></td>
    </tr>
    
    <c:choose>
      <c:when test="${empty membersList}">
        <tr>
          <td colspan=5> <b>등록된 회원이 없습니다.</b> </td>
        </tr>
      </c:when>
      <c:when test="${!empty membersList}">
        <c:forEach var="mem" items="${membersList}">
          <tr align="center">
            <td>${mem.id}</td>
            <td>${mem.pwd}</td>
            <td>${mem.name}</td>
            <td>${mem.email}</td>
            <td>${mem.joinDate}</td>
            
            <td><a href="${contextPath}/member/modMemberForm.do?id=${mem.id }">수정</a></td>
            <td><a href="${contextPath}/member/delMember.do?id=${mem.id }">삭제</a></td>
          </tr>
        </c:forEach>
      </c:when>
    </c:choose>
    
  </table>
  <a href="${contextPath}/member/memberForm.do"><p class="cls2">회원 가입하기</p></a>
</body>
</html>

pro17/WebContent/test02/MemberForm.jsp

회원 가입 창

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>회원 가입창</title>
<body>
  <form method="post" action="${contextPath}/member/addMember.do">
    <h1 style="text-align:center">회원 가입창</h1>
    <table align="center">
      <tr>
        <td width="200"><p align="right">아이디</td>
        <td width="400"><input type="text" name="id"></td>
      </tr>
      <tr>
        <td width="200"><p align="right">비밀번호</td>
        <td width="400"><input type="password" name="pwd"></td>
      </tr>
      <tr>
        <td width="200"><p align="right">이름</td>
        <td width="400"><p><input type="text" name="name"></td>
      </tr>
      <tr>
        <td width="200"><p align="right">이메일</td>
        <td width="400"><p><input type="text" name="email"></td>
      </tr>
      <tr>
        <td width="200"><p>&nbsp;</p></td>
        <td width="400"><input type="submit" value="가입하기"><input type="reset" value="다시입력"></td>
      </tr>
    </table>
  </form>
</body>
</html>

pro17/WebContent/test03/modMemberForm.jsp

회원 정보 수정 창

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<%  request.setCharacterEncoding("UTF-8"); %>

<head>
  <meta charset="UTF-8">
  <title>회원 정보 수정창</title>
  <style>
    .cls1 {
    font-size:40px;
    text-align:center;
  }
</style>
</head>

<body>
  <h1 class="cls1">회원 정보 수정창</h1>
  
  <form method="post" action="${contextPath}/member/modMember.do?id=${memInfo.id}">
    <table align="center">
      <tr>
        <td width="200"><p align="right">아이디</td>
        <td width="400"><input type="text" name="id" value="${memInfo.id}" disabled></td>
      </tr>
      <tr>
        <td width="200"><p align="right">비밀번호</td>
        <td width="400"><input type="password" name="pwd" value="${memInfo.pwd}"></td>
      </tr>
      <tr>
        <td width="200"><p align="right">이름</td>
        <td width="400"><input type="text" name="name" value="${memInfo.name}"></td>
      </tr>
      <tr>
        <td width="200"><p align="right">이메일</td>
        <td width="400"><input type="text" name="email" value="${memInfo.email}"></td>
      </tr>
      <tr>
        <td width="200"><p align="right">가입일</td>
        <td width="400"><input type="text" name="joinDate"
        value="${memInfo.joinDate }" disabled></td>
      </tr>
      <tr align="center">
        <td colspan="2" width="400"><input type="submit" value="수정하기"><input type="reset" value="다시입력"></td>
      </tr>
    </table>
  </form>
</html>

모델1 방식과 비교

링크



스프링 프레임워크

자바 웹 애플리케이션 개발을 위한 오픈 소스 프레임워크
경량 프레임워크: 무거운 EJB의 단점 개선
경량 컨테이너: bean(클래스 객체) 관리 권한을 가짐

*프레임워크:
클래스나 인터페이스 등으로 미리 기능을 만들어 제공하는 반제품
빠른 개발 시간, 유지보수 및 기능 확장의 고품질 보장

특징

IoC 제어 역행: 프레임워크가 직접 서블릿, bean 수행
DI 의존성 주입: 프레임워크가 직접 클래스 객체 생성
AOP 관점 지향: 분리 구현, 모듈성 증가
영속성 지원
라이브러리 연동

주요 기능

Core: IoC 기능
Context: 기본 기능, bean 접근 방법 제공
DAO: JDBC 기능
ORM: 하이버네이트, 마이바티스 등 영속성 관련 프레임워크 연동 기능
AOP: AOP 기능
Web: 웹 개발 기능
WebMVC: MVC 구현 기능



*자바 웹을 다루는 기술

profile
CS 메모장

0개의 댓글