17장. 모델2 방식으로 효율적으로 개발하기 - ①모델1과 모델2(MVC)

17.1 웹 애플리케이션 모델

- 웹 애플리케이션을 개발할 때 일일이 처음부터 새로 개발하는 것이 아니라 기존에 웹 애플리케이션 개발 방법이나 방식을 따름

- 따라서 지금의 웹 애플리케이션 개발은 표준화 소스 구조(=웹 애플리케이션 모델)를 만들어 진행

- 웹 애플리케이션 모델의 종류에는 모델1과 모델2 방식이 있음

 

<모델1 방식>

- 비즈니스 로직 작업(ex. db연동)과 그 작업 결과를 나타내주는 작업을 동일한 JSP에서 수행(앞서 했던 실습들)

- 모든 클라이언트의 요청과 비즈니스 로직 처리를 JSP가 담당

- 유지보수가 어려움, 코드 재사용성이 떨어짐

 

<모델2 방식>

- 웹 애플리케이션의 각 기능(클라이언트의 요청 처리, 응답 처리, 비즈니스 로직 처리)을 분리해서 구현

- 각 기능이 서로 분리되어 있어 개발 및 유지보수가 쉽고 각 기능(모듈)의 재사용성이 높음

- 현재 모든 웹 프로그램은 모델2 방식으로 개발함

 

 

17.2 MVC 디자인 패턴

- 모델2 구조에는 여러 가지 개념들이 사용되는데 그 중 가장 자주 사용되는 개념이 MVC

- MVC : Model-View-Controller(모델-뷰-컨트롤러) 

         (: 일반 pc프로그램 개발에 사용되는 디자인 패턴을 웹 애플리케이션에 도입한 것)

- 모델2 방식으로 구현한다는 말은 곧 MVC로로 구현한다는 것과 같은 의미

  • Controller : 사용자의 요청을 받아 어떤 비즈니스 로직을 처리해야 할지 제어
    • 서블릿이 담당
    • 요청에 대해서 필요한 모델을 호출
    • 모델에서 처리한 결과를 보여주기 위해 JSP를 선택
  • Model : 비즈니스 로직을 처리(ex. db연동)
    • 일반적으로 DAO와 VO 클래스로 이루어짐
  • View : 사용자에게 보여줄 화면을 담당, 모델에서 처리한 결과를 화면에 구현
    • JSP가 화면 기능을 담당
    • 모델에서 처리한 결과를 화면에 표시

 

 

17.3 MVC를 이용한 회원 관리

- 앞서 했던 회원 관리 기능을 MVC 방식으로 구현해보자!

- 서블릿 : 브라우저 요청 / 모델(DAO) : 비즈니스 처리 / JSP : 화면

 

회원 정보 조회 

  • 과정
    1. 브라우저에서 /mem.do로 요청
    2. 서블릿(Controller)가 요청을 받아 MemberDAO의 listMembers() 메서드 호출
    3. MemberDAO의 listMembers() 메서드에서 SQL 문으로 회원 정보를 조회한 후 회원 정보를 MemberVO에 설정하여 반환
    4. 다시 MemberController에서 조회한 회원 정보를 회원 목록창(listMembers.jsp)으로 포워딩
    5. 회원 목록창(listMembers.jsp)에서 포워딩한 회원 정보를 목록으로 출력

- memberController.java

...
List members=dao.listMember();
request.setAttribute("members", members);
RequestDispatcher dispatcher=request.getRequestDispatcher("test01/listMembers.jsp");
dispatcher.forward(request, response);

- listMembers.jsp

...
<c:choose>
	<c:when test= "${empty members }">
		 <tr>
        <td colspan=5 align="center">
          <b>등록된 회원이 없습니다.</b>
       </td>  
      </tr>
    </c:when>
    <c:otherwise>
    	<c:forEach var="mem" items="${members }">
    		<tr align="center">
    			<td>${mem.id }</td>
    			<td>${mem.pwd }</td>
          		<td>${mem.name}</td>     
          		<td>${mem.email }</td>     
          		<td>${mem.joinDate}</td>     
    		</tr>
    	</c:forEach>
    </c:otherwise>
</c:choose>
...

 

- 바인딩한 속성은 표현언어로 바로 접근하면 됨!

 

 

회원 정보 추가

- 요청사항이 많아졌기 때문에 컨트롤러가 브라우저로부터 어떤 요청을 받았는지 알아내서 그 요청에 대해 해당하는 모델을 선택하여 작업을 요청 함 >> 커맨드 방법

- 커맨드 패턴 : 브라우저가 URL 패턴을 이용해 컨트롤러에게 수행 작업을 요청하는 방법

- 컨트롤러는 HttpServletRequest의 getPathInfo() 메서드를 이용해 URL 패턴에서 요청명을 받아와 작업을 수행

- 요청형식 : http://localhost:8090/pro17/member/listMembers.do

                  >> /member : 첫번째 단계의 요청, 회원 기능을 의미, /listMembers.do : 두 번째 요청, 회원 조회 기능을 의미

  • 회원 가입 과정
    1. 브라우저에서 회원가입하기 버튼을 누르면 ~/member/memberForm.do로 요청
    2. MemberController에서 getPathInfo()를 통해 요청명(memberForm.do)를 받아와 /test02/memberForm.jsp(회원 가입창)로 dispatch
    3. 회원 가입창에서 회원 정보를 입력하고 URL 패턴을 /member/addMember.do로 서버에 요청
    4. MemberController에서 getPathInfo()를 통해 요청명(addMember.do)를 받아옴
    5. 요청명에 대해 MemberDAO의 addMember()메서드 호출
    6. addMember() 메서드에서 SQL문으로 테이블에 회원 정보를 추가

 

회원 정보 수정/삭제

- MemberController.java

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);
        request.setAttribute("msg", "added");
        nextPage = "/member/listMembers.do";
    } 
    else if (action.equals("/memberForm.do")) {
        nextPage = "/test03/memberForm.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";
    }
    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", "updated");
         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";
    }

- MemberDAO.java

public MemberVO findMember(String id) {
    MemberVO memInfo=null;
    try {
        con=dataFactory.getConnection();
        String query="select * from t_member where id=?";
        pstmt=con.prepareStatement(query);
        pstmt.setString(1, id);

        ResultSet rs=pstmt.executeQuery();

        rs.next();

        String name=rs.getString("name");
        String pwd=rs.getString("pwd");
        String email=rs.getString("email");
        Date joinDate=rs.getDate("joinDate");

        memInfo=new MemberVO(id,pwd,name,email,joinDate);
        pstmt.close();
        con.close();
        rs.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return memInfo;
}

public void modMember(MemberVO memberVO) {
    try {
        con=dataFactory.getConnection();
        String query="update t_member set pwd=?, name=?, email=? where id=?";
        pstmt=con.prepareStatement(query);

        pstmt.setString(1, memberVO.getPwd());
        pstmt.setString(2, memberVO.getName());
        pstmt.setString(3, memberVO.getEmail());
        pstmt.setString(4, memberVO.getId());

        pstmt.executeUpdate();

        pstmt.close();
        con.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

public void delMember(String id) {
    try {
        con=dataFactory.getConnection();
        String query="delete from t_member where id=?";
        pstmt=con.prepareStatement(query);
        pstmt.setString(1, id);

        pstmt.executeUpdate();

        pstmt.close();
        con.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }

}

- modMemberForm.jsp

<form method="post" action="${contextPath }/member/modMember.do?id=${memInfo.id}"> 
<!-- 지금 id가 disabled되어 있어서 id는 전송이 안되므로 주소 뒤에 id를 꼭 붙여줘야 함 -->
<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" 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"><p><input type="text"  name="name" value="${memInfo.name }"></td>
      </tr>
      <tr>
          <td width="200"><p align="right">이메일</td>
          <td width="400"><p><input type="text"  name="email" value="${memInfo.email }"></td>
      </tr>
      <tr>
          <td width="200"><p align="right">가입일</td>
          <td width="400"><p><input type="text"  name="joinDate" value="${memInfo.joinDate }" disabled></td>
      </tr>
      <tr>