본문 바로가기
미니프로젝트

간단한 홈페이지 만들어보기

by Dodledd 2024. 3. 28.

이제 우리가 배운 것들을 이용해서 간단한 홈페이지를 만들어보려 합니다.

 

MVC구조로 진행할 예정입니다.

 

이 홈페이지의 목적은 배웠던 것을 복습하여 전체적인 흐름을 파악하고 완전히 내 것으로 만들어 자유자재로 다룰 수 있게끔 하는 게 목적입니다.

 

톰 캣 서버와 이클립스를 사용하며 html, css는 VSCode를 사용합니다.

 

시작은 서버 세팅인데 이전 포스팅에서 자세히 다뤘기 때문에 넘어가서 DB와 연결부터 시작하겠습니다.

 

DB연결은 이전 JDBC에서도 다뤘기 때문에 간단히 설명하고 넘어가면 db, driver 폴더에 따로 prop 파일을 만들어놓고 그 안에 DB아이디와 경로를 설정해놓습니다. 또 ojdbc6.jar 파일을 라이브러리에 추가해주는 것도 잊으면 안됩니다.

driver = oracle.jdbc.driver.OracleDriver
url = jdbc:oracle:thin:@localhost:1521:xe
username=SERVER
password=SERVER

 

서버와 DB 세팅이 끝났다면 시작은 클라이언트가 처음 접속했을 때 보여지는 시작페이지(index.html나 jsp 등) 을 만들어 놓습니다.

 

이번 index파일에는 직접 작성하지않고 공용으로 사용되는 (제일 상단에 있는 메뉴바 같은) 것을 따로 jsp로 만들어서

include시켜보겠습니다.

 

index.jsp (웰컴파일)

 <%@ include file="views/common/menubar.jsp" %>

그럼 이제 menubar.jsp를 보겠습니다..

 

먼저 link와 j쿼리, 부트스트랩을 위한 준비입니다.

<!-- Latest compiled and minified CSS -->
 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">

 <!-- jQuery library -->
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
 <!-- Popper JS -->
 <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>

 <!-- Latest compiled JavaScript -->
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>

head안에 복붙하면 되는 편리한 CDN방식입니다.

 

또 코드의 재사용을 높이기 위해 제일 위에 import를 해주도록하겠습니다.

import="com.kh.member.model.vo.Member"%>
<%
	String contextPath = request.getContextPath();

    Member loginUser = (Member)session.getAttribute("loginUser");
    // 로그인 시도 전 menubar.jsp로딩시 : null
    // 로그인 성공 후 menubar.jsp로딩시 : 로그인 성공한 회원의 정보
    
    String alertMsg = (String)session.getAttribute("alertMsg");
    //서비스 요청 전 : null
    //서비스 요청 후 : alert띄워줄 메세지 문구
%>

또 loginUser는 세션에서 값을 가지고 돌아오는 친구이고, aelrtMsg도 자주사용하는 것이기 때문에 (성공,실패 등) 위에 써주었습니다.

 

이제 body 영역입니다.

<body>
	<% if(alertMsg != null){ %>
		<script>
			alert("<%=alertMsg%>");
		</script>
		<% session.removeAttribute("alertMsg"); %>
	<% } %>
    <h1 align="center">Welcome KH World</h1>
    <div class="login-area">
        <% if(loginUser == null) { %>
            <!-- 로그인 전 -->
            <form action="<%=contextPath %>/login.me" method="POST">
                <table>
                    <tr>
                        <th>아이디</th>
                        <td><input type="text" name="userId" required></td>
                    </tr>
                    <tr>
                        <th>비밀번호</th>
                        <td><input type="password" name="userPwd" required></td>
                    </tr>
                    <tr>
                        <th colspan="2">
                            <input type="submit" value="로그인">
                            <input type="button" value="회원가입" onclick="enrollPage();">
                        </th>
                    </tr>
                </table>
                <script>
                    function enrollPage(){
						//location.href = "<%=contextPath%>/views/member/memberEnrollForm.jsp";
                    	//웹 애플리케이션의 디렉토리 구조가 url에 노출되면 보안에 취약
						
                    	location.href = "<%=contextPath%>/enrollForm.me";
                    	//단순한 페이지 요청도 servlet을 거쳐갈 것(즉, url에는 서블릿 맵핑값만 나타나도록)
                    }
                </script>
            </form>
        <% } else { %>
            <!-- 로그인 후 -->
            <div>
                <b><%=loginUser.getUserName()%>님</b>의 방문을 환영합니다<br><br>
                <div align="center">
                    <a href="<%=contextPath%>/myPage.me">마이페이지</a>
                    <a href="<%=contextPath%>/logout.me">로그아웃</a>
                </div>
            </div>
        <% } %>
    </div>

    <br clear="both"><br>

    <div class="nav-area" align="center">
        <div class="menu"><a href="<%=contextPath %>">HOME</a></div>
        <div class="menu"><a href="<%=contextPath %>/list.no">공지사항</a></div>
        <div class="menu"><a href="">일반게시판</a></div>
        <div class="menu"><a href="">사진게시판</a></div>
    </div>

    
</body>

여기서 자세히 봐야할 것은 form 태그의 action과 a태그의 href입니다.

이곳의 주소가 한 글자라도 틀릴경우 연결이 되지 않기 때문에 주의해야합니다.

 

(코드 일부)

<form action="<%=contextPath %>/login.me" method="POST">
<a href="<%=contextPath%>/myPage.me">마이페이지</a>
<a href="<%=contextPath%>/logout.me">로그아웃</a>

그럼 contextPath는 뭘까?

웹 애플리케이션에 대한 요청이 들어오면, 웹 서버는 ContextPath를 확인하고 해당 요청을 적절한 웹 애플리케이션으로 라우팅 합니다. ContextPath는 웹 서버의 설정에 따라 변경될 수 있습니다. 보통 web.xml 파일에서 설정 가능합니다.

 

먼저 form action에 로그인 페이지로 이동해보겠습니다.

로그인 버튼을 누르면 

<form action="<%=contextPath %>/login.me" method="POST">

 

 

경로의 login.me가 있는 servlet을 찾아가게 되며  login.me는 다른 이름으로 loginController로 존재하고 있습니다.

package com.kh.member.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
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 javax.servlet.http.HttpSession;

import com.kh.member.model.vo.Member;
import com.kh.member.service.MemberService;

/**
 * Servlet implementation class loginController
 */
@WebServlet("/login.me")
public class loginController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public loginController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1) 전달값에 한글이 있을 경우 인코딩 처리(POST일 경우)
		request.setCharacterEncoding("UTF-8");
		
		//2) 요청시 전달값 추출해서 변수 또는 객체에 기록하기
		String userId = request.getParameter("userId");
		String userPwd = request.getParameter("userPwd");
		
		//3) 요청하기(db에 sql문 활용해서 조회해줘)
		//service클래스에 담당 메소드 호출
		Member loginUser = new MemberService().loginMember(userId, userPwd);
		
		
		/**
		 * 응답페이지에 전달할 값이 있을 경우 어딘가에는 담아야한다. (담을 수 있는 영역)
		 * 1) apllication : 여기에 담긴 데이터는 웹 애플리케이션 전역에서 다 꺼내서 쓸 수 있음
		 * 2) session : 여기에 담긴 데이터는 직접 지우기 전까지, 세션이 만료(서버가 멈추거나, 브라우저 종료)되기 전까지
		 * 				어떤 jsp든, 어떤 servlet이건 꺼내서 사용할 수 있다.
		 * 3) request : 해당 영역에 담긴 데이터는 현재 이 request객체를 "포워딩한 응답 jsp에서만" 꺼내 쓸 수 있다.
		 * 4) page: 해당 jsp에서담고 해당 jsp에서만 사용할 수 있다.
		 * 
		 * 공통적으로 데이터를 담고자한다면 특정객체.setAttribute("키", 벨류)
		 * 			데이터를 꺼내고자 한다면 특정객체.getAttribute("키")
		 * 			데이터를 지우고자 한다면 특정객체.removeAttribute("키")
		 */
		
		//4) 처리된 결과를 가지고 사용자가 보게될 응답뷰를 지정해서 포워딩 또는 url 재요청
		if(loginUser==null) {
			//조회결과 없음 => 로그인 실패 => 에러문구가 보여지는 에러페이지로 포워딩
			request.setAttribute("errorMsg", "로그인에 실패하였습니다.");
			
			//응답페이지에게 위임
			RequestDispatcher view = request.getRequestDispatcher("views/common/errorPage.jsp");
			
			view.forward(request, response);
			
			
		}else {
			//조회결과 있음 => 로그인 성공!!
			//로그인한 회원정보(loginUser)를 session 영역에 담기(왜? 여기저기서 다 가져다 쓸 수 있도록)
			//Servlet에서는 session영역에 접근하고자 한다면 우선 세션객체를 얻어야한다.
			HttpSession session = request.getSession();
			session.setAttribute("loginUser", loginUser);
			
			//1. 포워딩방식 => 해당방식은 url이 변경되지 않는다. => 우리는 localhost:8001/kh/라는 기존에 메인 url이 있는데
			// 해당 방식으로 화면 응답시 url은 http://localhost:8001/kh/login.me가 나타난다. 
			// 실제 화면은 localhost:8001/kh/의 응답화면이 나타난다.
			//
			
			//2. url재요청 방식
			//기존에 해당 페이지를 응답하는 url이 존재한다면 사용가능
			// 응답페이지 => index.jsp페이지 (jsp url 재요청)
			
			response.sendRedirect(request.getContextPath());
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {	
		doGet(request, response);
	}

}

servlet으로 만들었기 때문에 웹 통신에서 중요한 httpservlet을 자동 상속하고 경로를 잡아줍니다.

 

사용법과 구조는 간단합니다. 사용자가 form에 입력한 값을 제출하면 HTTP에 parameter을 타고 옵니다.

그럼 parameter가 값을 가지고 있으니 우리가 꺼낼 땐 request.getParameters("이름") 으로 꺼내어 변수에 저장해 서버 영역에서 사용할 수 있게 만들어줍니다.(데이터 가공이니 controller의 영역과도 일치함)

우리는 서버에서 값을 사용할 수 있게 저장했으니 그 다음부터는 그냥 JDBC와 정확히 일치합니다.

솔직히 말하자면 Dao에서 조금 다르지만 어렵지 않기때문에 잘 외우고 이해했다면 문제 없습니다.

 

그럼 controller -> service -> dao -> DB 로 값을 전송하여 dao가 DB와 통신하고 값의 비교를 한 후 그 결과를 가지고

역순인 DB -> Dao -> service -> controller를 타고 다시 돌아오게 됩니다.

그럼 controller에서 돌아온 값을가지고 로그인의 성공, 실패 여부를 판단하면 됩니다.

 

여기서 특이한 점은 로그인 실패 시 화면을 다른 jsp 파일에게 위임하는 것 입니다.

RequestDispatcher view = request.getRequestDispatcher("views/common/errorPage.jsp");

이런식으로 경로안에 jsp 파일을 만들어놓고 호출하면 코드의 재사용성을 높일 수 있습니다.

 

지금은 결과를 들고와서 그 결과에 따른 응답페이지를 뿌려주지만

 

만약 DB에서 값 ( 조회하거나 수졍된 값을 다시 보여줘야 할 때 등) 이럴 땐 어떻게 할까요?

바로 request 객체의 속성(attribute)을 사용합니다. 값을 controller(servlet)까지 들고 오는 것은 똑같습니다.

그럼 여기서 응답페이지인 jsp에 값을 전달해주기 위해  취미로 예를 들면

request.setAttribute("hobby", strHobby); 로 속성을 집어넣으면,

JSP에서 <% String strHobby = (String)request.getAttribute("hobby"); %>로 strHobby의 값을 인식할 수 있게 됩니다.

) 정확히는 전달받은 것?

또 arrtibute에 들어갔다가 나온 것은 타입이 object로 변해있기 때문에 다운캐스팅 해주는 것도 잊지말아야 합니다.

 

 

 

 

미니홈페이지 만드는 포스팅은 여기까지 해야할 듯 싶습니다... 이제 팀원들과 세미프로젝트를 시작해서 여기에 힘을 쏟고 그 과정을 포스팅하려고 합니다.

'미니프로젝트' 카테고리의 다른 글

[초미니프로젝트] 3일차  (0) 2024.03.04
[초미니프로젝트] 2일차  (0) 2024.03.03
[초미니프로젝트] 1일차  (0) 2024.03.02