WAS/WAS수업

#52. DB 테이블 설계, JSP/Servlet 회원(로그아웃, 회원가입)

열하나요 2023. 9. 13. 09:47

52-1. DB설계

1. 정규화

함수종속성 x -> y : x는 결정자 y는 종속자(x는 Primary Key)

완전/부분 함수적 종속성(pk가 복합키일 경우)

- 부분 함수적 종속성 : y가 x의 전체가 아닌 일부분에도 함수적으로 종속됨

- 완전 함수적 종속성 : y가 x의 전체에 대해서만 함수적으로 종속

 

1정규화 : 모든 컬럼의 데이터가 원자값으로 이루어져야 한다.

 

2정규화 : 1정규화를 만족하고, 부분함수적 종속을 제거해서 완전함수적 종속 상태로 만드는 것

 

3정규화 : 2정규화를 만족하고, 이행적 함수종속을 제거하는 것

 

=> 정규화 시, INSERT, UPDATE, DELETE 비용이 줄어들 수 있지만,

SELECT 비용이 증가할 수 있다. ( JOIN이 많아짐 )

 

2. 테이블과 테이블간의 관계

1:1관계 - 식별관계 : 참조하는 컬럼을 다시 pk로 사용하는 경우

1:N관계 - 비 식별관계 : 참조하는 컬럼을 식별자(pk)로 사용하지 않는 경우

* 대부분의 경우 1:N관계로 만들어진다.

N:M관계 - 1:N, M: 1 관계로 풀어서 설계해야 함. 중간 테이블 필요.

* 찜하기, 좋아요, 구독하기, 장바구니 등

 

3. 테이블 설계

ERD cloud 사용

 

52-2. JSP

로그아웃

1. 로그아웃하면 보낼 경로(절대경로) 설정

menubar.jsp

<a href="/jsp/logout.me">로그아웃</a>

 

2. Controller 생성 (Mapping값 logout.me)

LogoutController.java(Servlet)

POST방식도 doGet메소드에 작성

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 로그아웃 요청에 대한 처리 => session을 만료시킨다(== 무효화한다)
		// 무효화메소드 == invalidate() => session에서 제공하는 메소드
		HttpSession session = request.getSession();
		session.invalidate(); // 다날림
		// 응답데이터 => sendRedirect방식
		// index가 보여지게끔 => localhost:8001/jsp
		// response.sendRedirect("/jsp");
		
		// request.getContextPath()
		// System.out.println(request.getContextPath());
		response.sendRedirect(request.getContextPath());
	}

request.getContextPath() ==> tomcat Server의 Path

 

3. Path값 변수 처리 후, 절대경로 바꿔주기

menubar.jsp

String contextPath = request.getContextPath();

<!-- <a href="/jsp/logout.me">로그아웃</a> -->
<a href="<%= contextPath %>/logout.me">로그아웃</a>

<!-- <form action="/jsp/login.me" method="post"> -->
<form action="<%= contextPath %>/login.me" method="post">

 

------------------------------------------------------------------------------

 

52-3. 회원가입

 

include는 내 하위 폴더에 있는 모든 jsp나 html에 있는 변수들을 쓸 수 있음. => Path경로/매핑값

1. 회원가입 페이지 만들기

memberEnrollForm.jsp

 

VS Code에서 jsp가 저장된 폴더를 불러와 화면 만들고 저장하면 Eclipse와 연동됨

<%@ include file="../common/menubar.jsp" %>
<!--  ../ : 상위폴더로 이동(view폴더로 이동) -->

<!-- include는 내 하위 폴더에 있는 모든 jsp나 html에 있는 변수들을 쓸 수 있음. => Path경로/매핑값 -->
<form id="enroll-form" action="<%= contextPath %>/insert.me" method="post">

http://localhost:8001/jsp/views/member/memberEnrollForm.jsp

http://ip주소:port번호(톰캣)/Server Path(식별값) /(WebContent) 폴더경로

 

 

2. 회원가입 버튼을 누르면 만들어둔 회원가입 페이지로 이동

menubar.jsp

<button type="button" onclick="enrollPage();">회원가입</button>

<script>
    function enrollPage(){
        // 페이지 이동
        // localhost:8001/jsp/views/member.memberEnrollForm.jsp
        // location.href = "<%= contextPath %>/views/member/memberEnrollForm.jsp";
        // 웹 어플리케이션의 디렉토리 구조가 url에 노출됨 => 보안에 취약

        // 단순한 정적인 페이지 요청이라고 하더라도 Servlet을 거쳐서 화면을 띄어줄 것!
        // => url에 서블릿 매핑값만 노출되게끔
        // localhost:8001/jsp/매핑값
        location.href = '<%= contextPath %>/enrollForm.me';

    }
</script>

 

3. menubar에서 부른 페이지 생성

member > controller > MemberEnrollFormController.java(Servlet)

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 회원가입 양식 띄어주기
		// 서블릿에서 화면 응답을 해주는 방법이 두 가지
		// 1. RequestDispatcher객체를 이용하는 방법(forwarding)
		// 2. sendRedirect(url재요청 방식)
		
		RequestDispatcher view = request.getRequestDispatcher("views/member/memberEnrollForm.jsp");
		view.forward(request, response);
	}

 

동적인 이벤트 발생 시 문제 => JavaScript에서 문제 발생 => F12 console창 열어서 확인

404 Error => 메시지를 읽어볼 것 => 매핑값 오타 / 경로 오타 / 파일명 오타

 

 

4. 사용자가 회원가입 진행 시 입력한 값을 다루어줄 Controller 생성

MemberinsertController.java(Servlet)

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// POST
		// 1) 인코딩 설정
		request.setCharacterEncoding("UTF-8");
		
		// 회원가입이란? 
		// 2) request객체로부터 요청 시 전달값 뽑기
		String userId = request.getParameter("userId"); // "필수입력"
		String userPwd = request.getParameter("userPwd"); // "필수입력"
		String userName = request.getParameter("userName"); // "필수입력"
		String phone = request.getParameter("phone");
		String email = request.getParameter("email");
		String address = request.getParameter("address"); // 빈문자열이 들어갈 수 있음
		String[] interestArr = request.getParameterValues("interest"); // null / ["소개팅", "아프기"]
		
		// 소개팅, 아프기
		// String.join("구분자", 배열명)
		String interest = "";
		if(interestArr != null) {
			interest = String.join(",", interestArr);
		}
		
		// 데이터 가공 String 배열에 담던가, String형 list에 담던가, Member객체에 담던가
		// 3) Member 객체에 담기(setter메소드이용)
		Member m = new Member();
		m.setUserId(userId);
		m.setUserPwd(userPwd);
		m.setUserName(userName);
		m.setPhone(phone);
		m.setEmail(email);
		m.setAddress(address);
		m.setInterest(interest);
		
		// 4) 요청처리(Service단 메소드 호출)
		int result = new MemberService().insertMember(m);
		
	}

 

5. Controller가 호출한 Service 메소드 만들어주기

MemberService.java

	public int inserMember(Member m) {
		
		Connection conn = JDBCTemplate.getConnection();
		
		int result = new MemberDao().insertMember(conn, m);
		// 성공했다면 1 / 실패했으면 0
		
		if(result > 0) {
			JDBCTemplate.commit(conn);
		} else {
			JDBCTemplate.rollback(conn);
		}
		
		JDBCTemplate.close(conn);
		
		return result;
	}

 

6. Service가 호출한 DAO 메소드 만들어주기

MemberDao.java

	public int insertMemeber(Connection conn, Member m) {
		
		// INSERT문 => 처리된 행의 개수 
		int result = 0;
		PreparedStatement pstmt = null;
		String sql = prop.getProperty("insertMember");
		
		try {
			// pstmt 객체 생성(SQL문 미리 전달)
			pstmt = conn.prepareStatement(sql);
			
			// 위치홀더 채우기
			pstmt.setString(1, m.getUserId());
			pstmt.setString(2, m.getUserPwd());
			pstmt.setString(3, m.getUserName());
			pstmt.setString(4, m.getPhone());
			pstmt.setString(5, m.getEmail());
			pstmt.setString(6, m.getAddress());
			pstmt.setString(7, m.getInterest());
			
			// SQL문 실행 및 결과받기
			// insert / update / delete => pstmt.executeUpdate();
			result = pstmt.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCTemplate.close(pstmt);
		}
		// 결과 반환
		return result;
	}

 

7. Controller에서 Service에서 가져온 결과값으로 응답화면 지정

MemberinsertController.java

		// 데이터 가공 String 배열에 담던가, String형 list에 담던가, Member객체에 담던가
		// 3) Member 객체에 담기(setter메소드이용)
		Member m = new Member();
		m.setUserId(userId);
		m.setUserPwd(userPwd);
		m.setUserName(userName);
		m.setPhone(phone);
		m.setEmail(email);
		m.setAddress(address);
		m.setInterest(interest);
		
		// 4) 요청처리(Service단 메소드 호출)
		int result = new MemberService().insertMember(m);
		
		// 5) 처리결과를 가지고 사용자가 보게 될 응답화면 지정
		if(result > 0) { // 성공 => /jsp를 요청(index.jsp) => url재요청방식(sendRedirect)
			HttpSession session = request.getSession();  // 원래 기획회의때 이런것까지 정해줘야함.. session으로 보낼건지 request로 보낼건지..
			session.setAttribute("alertMsg", "회원가입에 성공했습니다.");
			response.sendRedirect(request.getContextPath());
		} else { // 실패 => 에러페이지로 포워딩
			request.setAttribute("errorMsg", "회원가입에 실패했습니다.");			
			RequestDispatcher view = request.getRequestDispatcher("views/common/errorPage.jsp");
			view.forward(request, response);
		}