MVC 패턴

최현주·2023년 10월 31일
1

MVC란?
시각적으로 보여지는 부분과 데이터를 처리하는 부분을 분리하여 유연한 구조를 설계한다.

MVC 구성
세 영역으로 구분하고, 영역간 결합도를 최소화한다

MODEL은 실행에 직접적인 관여를 하지않는다
데이터를 담거나, 데이터를 보내거나, 수정, 삭제하는 객체이다

Controllersms 어플리케이션의 행위를 정의한다.
Logic 결과에 따라 적절한 View를 선택하여 응답한다.

View는 Model 데이터를 기반으로 실제 사용자에게 보여지는 페이지이다.

Model1은 웹 어플리케이션을 개발할 때 JSP만을 사용하는 설계방법이다
클라이언트의 요청 처리, DB연동, 세션관리, 응답처리 등과 같은 작업을 JSP만으로 구현하는 방법이다.

Model2sms Presentation Logic과 Business Login처리를 명확하게 분리한다

Model1과 Model2의 차이점

MVC패턴


바인드 변수를 쓰는 이유 : 성능향상을 위해서(soft parsing)

404 -> 페이지를 못찾는 오류 -> action 값 확인
500 -> console창 보고 어떤 오류 났는지 확인 후 해당 위치로 이동해서 코드 확인

메인화면

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 페이지</title>
<style type="text/css">
	fieldset{
		display:inline;
	}
</style>
</head>
<body>

<fieldset>
	<legend> Main </legend>
	<a href="./Join.jsp"><button> 회원가입 </button></a>
	<a href="./Login.jsp"><button> 로그인 </button></a>
</fieldset>

</body>
</html>

회원가입 페이지

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입</title>
<style >
	fieldset{
		display:inline;
	}
</style>
</head>
<body>

<fieldset>
		<legend align="center"> 회원가입 </legend>
		<!-- action에 적을 때
			servlet을 요청 : url mapping값(확장자X)
			jsp로 요총 : 해당 jsp로 가기위한 상대경로 -->
		<form action="JoinProgram" method="post">
		ID : <input type="text" name="id"><br>
		PW : <input type="text" name="pw"><br>
		NAME : <input type="text" name="name"><br>
        <input type="submit" value="회원가입"><br>
        </form>
</fieldset>
</body>
</html>

GET 메서드:
GET 메서드를 사용하면 폼 데이터가 URL의 일부로 노출됩니다.
URL에 데이터가 노출되므로 데이터는 브라우저의 주소 표시줄에 표시됩니다.
주로 데이터를 서버에 요청하는 데 사용되며, 데이터가 노출되어도 상관없는 경우에 유용합니다.
데이터가 URL에 노출되기 때문에 보안에 취약할 수 있습니다.

POST 메서드:
POST 메서드는 폼 데이터를 HTTP 요청 본문에 포함시킵니다.
데이터는 URL에 노출되지 않으므로 상대적으로 더 안전합니다.
주로 데이터를 서버에 전송하고 데이터가 노출되지 않아야 할 때 사용됩니다. 예를 들어, 로그인 정보나 회원가입 데이터와 같이 민감한 정보를 보낼 때 유용합니다.
이 코드에서는 method 속성을 "post"로 설정했으므로, 회원가입 데이터는 HTTP 요청 본문에 포함되고 URL에 노출되지 않습니다. 이렇게 함으로써 민감한 데이터를 안전하게 서버로 보낼 수 있습니다. 때때로 GET 메서드는 데이터를 검색하는 용도로 사용되고, POST 메서드는 데이터를 서버로 보내는 용도로 사용됩니다.

회원가입 프로그램

package Controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import Model.MemberDAO;
import Model.MemberDTO;

@WebServlet("/JoinProgram")
public class JoinProgram extends HttpServlet {
   protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      //post 방식 디코딩
      request.setCharacterEncoding("UTF-8");

      System.out.println("[JoinProgram]");
      
      
      String id = request.getParameter("id");
      String pw = request.getParameter("pw");
      String name = request.getParameter("name");

      System.out.println(id);      
      System.out.println(pw);      
      System.out.println(name);   
      
      // DTO(data Transfer object) 묶기
      MemberDTO dto =  new MemberDTO (id, pw, name);      
      // 회원가입 기능이 있는 join 메소드 호출
      int row = new MemberDAO().join(dto);
      // MemberDAO dao = new MemberDAO();
      // dao.join(dto); 이 두줄을 한줄로 줄인것
   
      // 성공 실패 여부 확인
      // 성공 -> Login.jsp
      // 실패 -> Main.jsp
      String moveURL;
      if (row >0 ) {
         System.out.println("회원가입 성공");
         moveURL = "./Login.jsp";
      }else {
         System.out.println("회원가입 실패");
         moveURL = "./Main.jsp";
      }
      response.sendRedirect(moveURL);
   
   }
   
   

}

로그인 프로그램

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
	fieldset{
		display:inline;
	}
</style>
</head>
<body>
<fieldset>
	<legend aling="center">로그인</legend>
	<form action="loginProgram" method="post">
		ID : <input type="text" name="id"><br>
		PW : <input type="password" name="pw"><br>
        <input type="submit" value="로그인"><br>
		
	</form>
</fieldset>
</body>
</html>

MemberDAO

package Model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class MemberDAO {
	
	// DAO(Data Access Object) : DB에 접근하는 객체
	Connection conn = null;
	PreparedStatement  psmt = null;
	ResultSet rs = null;
	
	// DB연결 메소드
	public void db_conn() {

		try {
			// 1. ojdbc6.jar 라이브러리 불러오기
			// C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib
			// webapp -WEB-INF-lib 폴더에 넣기
			
			// 2. OracleDriver class 불러오기
			// OracleDriver : Java와 DB 사이에 통로를 만들어주는 역할
			Class.forName("oracle.jdbc.driver.OracleDriver");
			
			// 3. DB에 접속하기 위한 카드키 설정(주소, 계정, 비번)
			String url = "jdbc:oracle:thin:@localhost:1521:xe";
			String user = "service";
			String pw = "12345";
			
			// 4. DB에 접속 -> 접속 성송 시 Connection 객체로 반환
			conn = DriverManager.getConnection(url, user, pw);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// DB연결 종료 메소드
	public void db_close() {
		try {
			if(psmt != null) psmt.close();
			if(conn != null) conn.close();
			if(rs != null) rs.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 회원가입 메소드
	public int join(MemberDTO dto) {
		int row = 0;
		try {
			db_conn();
			
			// 5. SQL 쿼리 작성 -> ? : 바인드 변수
			// 바인드 변수를 쓰는 이유 : 성능향상을 위해서(soft parsing)
			String sql = "insert into Member1 values(?,?,?)";
			
			// 6. SQL문장을 DB에 전달 -> 전달 성공시 PrepareStatement 객체로 반환
			psmt = conn.prepareStatement(sql);
			
			// 7. 바인드변수 값 채우기
			// psmt.set자료형(물음표의 순서, 넣을 값)
			psmt.setString(1, dto.getId());
			psmt.setString(2, dto.getPw());
			psmt.setString(3, dto.getName());
			
			// 8. 실행
			// executeUpdate : DB에 변화가 생겼을 때, select구문을 제외한 모든 구문
			// executeQuery : DB에 질의할 때, select구문
			// int로 return하는 이유 : 몇개의 행이 변화되었는지 알려주는 것!
			row = psmt.executeUpdate();
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally { // 무조건 열려있으면 닫으라는뜻
			db_close();
		} return row;
		
	}

	public MemberDTO login(MemberDTO dto) {
		MemberDTO login_dto = null;
		try {
			// 1. DB연결 메소드 호출
			db_conn();
			
			// 2. 쿼리문 작성
			String sql = "select * from member1 where id=? and pw=?";
			
			// 3. SQL문 DB에 전달 -> PrepareState객체 생성(psmt)
			psmt = conn.prepareStatement(sql);
			
			// 4. 받아온 id와 pw를 SQL문에 세팅
			psmt.setString(1, dto.getId());
			psmt.setString(2, dto.getPw());
			
			// 5. 실행(execueQuery 메소드 사용 -> ResultSet 객체 반환)
			rs = psmt.executeQuery();
			
			if(rs.next()) {
				
				String id = rs.getString(1);
				String pw = rs.getNString("pw");
				String name = rs.getString(3);
				
				login_dto = new MemberDTO(id, pw, name);
			}
			
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
			
			// 6. DB연결 종료 메소드 호출
			db_close();
		}
		
		return login_dto;

	}

}

MemberDAO 클래스:

이 클래스는 데이터베이스에 접근하는 역할을 합니다. 데이터베이스는 정보를 저장하는 특별한 장소라고 생각할 수 있어요.
이 클래스는 데이터베이스에 접근하고 데이터를 처리하는 역할을 합니다. 이것은 Data Access Object (DAO) 패턴을 따릅니다.

필드 (멤버 변수):
conn, psmt, rs: 데이터베이스와 통신하고 정보를 저장하는 도구들이에요.

db_conn() 메소드:
이 메소드는 데이터베이스에 연결하기 위한 준비 작업을 수행해요.
데이터베이스에 연결할 때 필요한 정보를 설정하고 실제 연결을 수행합니다.

db_close() 메소드:
이 메소드는 데이터베이스 연결을 닫는 작업을 합니다. 데이터베이스 연결을 마치고 사용한 도구들을 정리합니다.

join(MemberDTO dto) 메소드:
이 메소드는 사용자가 입력한 회원 정보를 데이터베이스에 저장합니다.
사용자가 입력한 아이디, 비밀번호, 이름을 데이터베이스에 저장하는 SQL 쿼리를 실행합니다.

login(MemberDTO dto) 메소드:
이 메소드는 사용자가 로그인할 때 입력한 정보를 확인하는 데 사용됩니다.
사용자가 입력한 아이디와 비밀번호를 데이터베이스에 있는 정보와 비교하여, 일치하면 로그인할 수 있도록 정보를 반환합니다.

데이터베이스 연결 및 쿼리 실행 단계:
데이터베이스 연결 설정 (URL, 사용자 이름, 비밀번호)을 구성하고 데이터베이스와 연결합니다.
SQL 쿼리문을 작성하고 실행하기 위해 필요한 작업을 수행합니다.
실행한 결과를 처리하여 데이터를 읽고 쓰고, 필요한 경우 데이터를 객체로 변환하여 반환합니다.
이 클래스는 데이터베이스와 상호작용하여 회원 정보를 저장하고 로그인 확인을 하는 데 사용됩니다.

데이터베이스 연결 및 쿼리 실행 단계:
데이터베이스에 연결하기 위해 Oracle JDBC 드라이버를 로드하고, 데이터베이스 연결 정보를 설정합니다.
db_conn() 메소드로 데이터베이스에 연결합니다.
SQL 쿼리문을 작성하고 PreparedStatement 객체로 컴파일합니다.
바인드 변수(물음표)를 사용하여 SQL 쿼리에 데이터를 동적으로 제공합니다.
SQL 쿼리를 실행하여 데이터베이스에서 결과를 가져오거나 업데이트합니다.
ResultSet 객체를 사용하여 쿼리 결과를 처리하고 필요한 정보를 추출합니다.
모든 작업을 마친 후 db_close() 메소드로 데이터베이스 연결을 닫습니다.
이 클래스는 데이터베이스와 상호작용하여 회원 관리와 인증을 수행하는 데 사용됩니다.
물론, 더 간단한 설명을 드리겠습니다.

if(rs.next())는 데이터베이스에서 정보를 찾았을 때, 그 정보를 가져오기 위한 체크입니다. 만약 rs라는 통로를 통해 다음 정보가 있는 경우, 즉 로그인 정보가 데이터베이스에 있다면 (예: 사용자 이름과 비밀번호가 일치하는 경우), if 문 안의 코드를 실행합니다. 이것은 로그인 정보를 확인하는데 사용됩니다.
getStringgetNString 메소드는 JDBC(Java Database Connectivity)에서 데이터베이스에서 문자열 값을 가져오는 데 사용되는 메소드입니다. 그러나 이 둘 사이에는 미묘한 차이가 있습니다:

  1. getString(): 이 메소드는 모든 데이터베이스 열 유형에서 문자열 값을 가져올 때 사용됩니다. 숫자, 날짜, 시간 등 모든 유형의 데이터를 문자열로 변환하여 반환합니다. 그러므로 데이터 형식에 관계없이 사용할 수 있습니다.

    String stringValue = resultSet.getString("column_name");
  2. getNString(): 이 메소드는 Unicode 문자열 값을 가져오는 데 사용됩니다. 주로 NCHAR, NVARCHAR, NCLOB와 같은 Unicode 문자열을 저장하는 데이터베이스 열에서 사용됩니다. 이 메소드는 문자 인코딩에 관계없이 문자열 값을 그대로 반환합니다.

    String unicodeValue = resultSet.getNString("unicode_column");

일반적으로 문자열 데이터를 다룰 때는 getString을 사용하면 됩니다. 그러나 데이터베이스에서 Unicode 문자열을 다루는 경우에는 getNString을 사용하여 문자열 값의 일관성을 유지할 수 있습니다.

요약하면, getString은 모든 문자열 유형에 사용되고, getNString은 Unicode 문자열을 다룰 때 사용됩니다.

MemberDTO

package Model;

public class MemberDTO {
	
	// DTO(Data Transfer Object) : 데이터 전달 객체(데이터를 담는 가방)
	//  테이블 형태 그대로 생성하는것이 일반적
	
	// 필드
	private String id;
	private String pw;
	private String name;
	
	// 메소드
	// 생성자 메소드 : 객체를 초기화하기위한 메소드
	
	// MemberDTO dto = new MemberDTO(id, pw, name);
	// 로그인을 위한 생성자 메소드
	public MemberDTO(String id, String pw, String name) {
		this.id = id;
		this.pw = pw;
		this.name = name;
		
		
	}
	public MemberDTO(String id, String pw) {
		this.id = id;
		this.pw = pw;
	}
	
		
	
	// Getter
	public String getId() {
		return id;
	}

	public String getPw( ) {
		return pw;
	}
	
	public String getName() {
		return name;
	}
}

이 클래스는 데이터를 저장하는 "가방" 또는 "통"과 같은 역할을 합니다. 데이터베이스 테이블의 각 행(레코드)에 대한 정보를 저장하는 데 사용됩니다.
제공된 코드는 Java 언어로 작성된 데이터 전달 객체(Data Transfer Object, DTO) 클래스인 MemberDTO를 나타냅니다. DTO 클래스는 데이터를 저장하고 전달하기 위한 목적으로 사용됩니다. 아래는 코드의 각 부분에 대한 설명입니다
필드 (멤버 변수) 정의:
id, pw, name: 이것들은 데이터를 저장하는 곳이에요. id는 아이디, pw는 비밀번호, name은 이름을 저장합니다.
생성자 메소드:객체를 만들 때 필요한 정보를 전달하고, 그 정보로 객체를 초기화합니다.
MemberDTO(String id, String pw, String name): 아이디, 비밀번호, 이름을 받아서 객체를 만들 때 사용하는 생성자에요.
MemberDTO(String id, String pw): 아이디와 비밀번호만 받아서 객체를 만들 때 사용하는 다른 생성자에요.
Getter 메소드:

이 메소드들은 클래스 외부에서 필드 값을 가져올 때 사용해요.
getId(): 아이디 값을 반환해줘.
getPw(): 비밀번호 값을 반환해줘.
getName(): 이름 값을 반환해줘.

이 클래스는 주로 회원 정보를 저장하고 전달하는 데 사용됩니다. 예를 들어, 회원의 아이디, 비밀번호, 이름과 같은 정보를 이 클래스의 객체에 저장한 후, 다른 부분에서 이 정보를 사용할 수 있습니다.

login success

<%@page import="Model.MemberDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<style>
	fieldset{
		display:inline;
	}
</style>
</head>
<body>
<h1>로그인 성공!</h1>	
<% 	//String name = request.getParameter("name");
	//out.print(name);
	MemberDTO login_dto = (MemberDTO)request.getAttribute("login_dto");
	String name = login_dto.getName();
%>

<%=name %>님 환영합니다


</body>
</html>

MemberDTO login_dto = (MemberDTO)request.getAttribute("login_dto");는 request 객체에서 "login_dto" 속성을 가져와 MemberDTO 객체로 형변환합니다. 이것은 로그인 정보를 가져올 때 사용됩니다.
String name = login_dto.getName();은 login_dto 객체에서 이름을 가져와 name 변수에 저장합니다.
MemberDTO login_dto = (MemberDTO)request.getAttribute("login_dto");는 JSP 페이지에서 사용자의 로그인 정보를 가져오는 부분입니다. 이 코드를 자세히 설명하겠습니다.

  1. request 객체: request는 웹 애플리케이션에서 클라이언트로부터 서버로 데이터를 전달하는 데 사용되는 객체입니다. 웹 브라우저에서 웹 서버로 요청(request)을 보낼 때, 이 요청에 관련된 데이터는 request 객체에 담겨 전달됩니다.

  2. getAttribute("login_dto"): getAttribute() 메서드는 request 객체에서 지정된 이름("login_dto"라고 여기서)의 속성(attribute)을 가져오는 데 사용됩니다.

  3. (MemberDTO) 형변환: getAttribute() 메서드로 가져온 속성은 일반적으로 Object 타입으로 반환됩니다. 그러나 우리는 login_dtoMemberDTO 객체로 사용하고 싶으므로 이것을 MemberDTO 타입으로 명시적으로 형변환합니다. 이것은 가져온 객체를 MemberDTO 객체로 변환하는 과정입니다.

결과적으로 이 코드는 "login_dto"라는 이름으로 저장된 객체를 MemberDTO 타입으로 가져와서 login_dto 변수에 할당합니다. 이 객체에는 로그인한 사용자의 정보가 포함되어 있을 것입니다. 이 정보를 나중에 JSP 페이지에서 사용하여 사용자의 이름 등을 표시할 수 있습니다.
MemberDTO login_dto = (MemberDTO)request.getAttribute("login_dto");는 다음과 같이 이해할 수 있습니다:
이 코드는 로그인한 사용자의 이름을 받아오는 명령이에요. 그 이름을 나중에 사용하기 편하게 상자에 넣는 거죠.
MemberDTO login_dto = (MemberDTO)request.getAttribute("login_dto");는 웹 페이지에서 로그인한 사용자의 정보를 가져오는 명령입니다. 이 정보를 login_dto라는 상자에 담아둡니다. 그러면 이제 login_dto 상자 안에 사용자의 정보가 들어 있어서 웹 페이지에서 그 정보를 사용할 수 있게 됩니다.
웹 페이지에서 로그인 정보를 가져오려고 할 때, request라는 통로를 사용합니다.
이 통로에서 "login_dto"라고 이름표를 붙인 정보를 찾아냅니다.
이 정보를 MemberDTO라는 형태로 가져와서 login_dto라는 상자에 넣습니다.
이제 login_dto 상자 안에는 사용자의 로그인 정보가 들어 있어, 그 정보를 사용할 수 있습니다.
MemberDTO login_dto = (MemberDTO)request.getAttribute("login_dto");는 웹 페이지에서 로그인한 사용자의 정보를 가져오는 명령입니다. 이 정보를 login_dto라는 상자에 담아둡니다. 그러면 이제 login_dto 상자 안에 사용자의 정보가 들어 있어서 웹 페이지에서 그 정보를 사용할 수 있게 됩니다.

loginFail

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<style>
	fieldset{
		display:inline;
	}
</style>
</head>
<body>
<fieldset>
로그인실패
	<form action="loginProgram" method="post">
		
        <a href="./Main.jsp">메인</a>
        <a href="./Login.jsp">로그인</a>
		
	</form>

</fieldset>

	
</body>
</html>
profile
갓벽한 개발자

0개의 댓글