해보자고

PBL4 - 코드 분석 본문

웹 프로그래밍

PBL4 - 코드 분석

초코맛동산 2023. 9. 14. 02:09

 

분석 코드)

https://github.com/orgs/PaaS-TA/repositories?q=edu&type=all&language=&sort= 

 

K-PaaS

K-PaaS Official Repository. K-PaaS has 189 repositories available. Follow their code on GitHub.

github.com

 

참고 영상)

https://www.youtube.com/watch?v=_SqykCMmbCA&list=PL-AoIAa-OgNlAYCjLnUSLWkEKk4qgxOSH&index=20 


 

1) edu-msa-ui

 

 

1)

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<jsp:forward page="/boardList"/> // /boardList로 이동 
// <jsp:forward> 액션태그: 하나의 JSP 페이지에서 다른 JSP페이지로 요청 처리를 전달

=> 그냥 boardList로 이동하는 jsp로 첫 시작하는 jsp가 아닐까..(web.xml을 참고)

 

 

2) font 파일은 정말 폰트 (생략)

 

3) images 파일은 정말 이모티콘 (생략)

 

4) 

- jquery란? : HTML의 요소들을 쉽게 조작하고 편리하게 사용할 수 있게 만든 라이브러리로 Javascript를 미리 작성해둔 것이다. Javascript로도 모든 기능을 구현할 수는 있지만, 코드가 복잡하고, 브라우저 간 호환성 문제 등도 고려해야해 JQuery라는 라이브러리가 등장하게 되었다고 한다. 

- JQuery는 Javascript와 다른 소프트웨어가 아니라 미리 작성된 Javascript 코드로 전문 개발자들이 짜둔 코드를 잘 가져와서 사용하는 것으로, 사용하기 전에  꼭 "import 임포트" 해야한다고 한다. 

출처: https://jjungslife.tistory.com/40

 

제이쿼리란? JQuery 사용하는 방법

제이쿼리란? JQuery 사용하는 방법 JQuery란? : HTML의 요소들을 쉽게 조작하고 편리하게 사용할 수 있게 만든 라이브러리로 Javascript를 미리 작성해둔 것이다. Javascript로도 모든 기능을 구현할 수는

jjungslife.tistory.com

- 해당 코드는 내용 분석X. jquery 라이브러리를 사용할 수 있도록 하는 그냥 파일. 

 

5) 

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c"      uri="http://java.sun.com/jsp/jstl/core"%> // JSTL 사용을 위해 taglib 지시자로 선언. core 라이브러리 사용.
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> // JSP 스프링 태그 라이브러리 사용을 위한 지시문 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> // DOCTYPE html은 브라우저에게 HTML 버전 및 웹브라우저 내용을 잘 출력할 수 있게 도와주는 역할을 하며, HTML 문서가 XHTML 1.0 Transitional 버전으로 작성되었다.
<html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko"> // <html> 태그 안에 있는 xmlns=http://www.w3.org/1999/xhtml" 속성이 네임 스페이스 부분이며, 옆에 있는 lang="ko" xml:lang="ko" 는 '언어는 한국어이다'라는 뜻. xhtml에서는 네임스페이스가 꼭 필요함. 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="<c:url value='/css/egovframework/sample.css'/>" /> // "/css/egovframework/sample.css" 경로의 스타일 시트를 현재 웹 페이지에 적용하도록 지시
<title>Basic Sample</title> // Basic Sample이라는 이름의 문서 제목 명시
</head>

<body>
    <table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0">
        <tr>
            <td width="100%" height="100%" align="center" valign="middle" style="padding-top: 150px;"><table border="0" cellspacing="0" cellpadding="0">
                    <tr>
                        <td class="<spring:message code='image.errorBg' />"> // <spring:message>를 사용하여 메시지 코드 'image.errorBg'에 해당하는 메시지를 검색하고 그 값을 class 속성에 설정 (이해를 위한 링크: https://pangtrue.tistory.com/134)
                            <span style="font-family: Tahoma; font-weight: bold; color: #000000; line-height: 150%; width: 440px; height: 70px;"></span>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</body>
</html>

=> 잘 꾸며진 에러메시지를 class 속성에 설정하는 코드 

+) 6) 에러페이지에 location에 이 코드로 이동하는 듯... 

- 사용된  태그:

구분 JSP 태그 용도
지시자 <%@     %> 페이지 속성 지정

- JSTL: (출처ㅣ https://atoz-develop.tistory.com/entry/JSP-JSTL-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95-%EC%A3%BC%EC%9A%94-%ED%83%9C%EA%B7%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC)

<%@ taglib prefix="접두사" uri="URI" %>      <--  선언 예시

- uri : 태그 라이브러리의 네임 스페이스 URI 식별자

- prefix : JSTL 태그를 사용할때 태그 이름 앞에 붙일 접두사

- JSTL 지시어: JSP 기능을 좀더 확장할 수 있는 개념으로 사용자 정의 태그를 사용할 수 있다. 

+) 사용 방법에 대한 추가적인 티스토리(https://itjy2.tistory.com/225)

 

- JSP 스프링 태그 라이브러리: 스프링 MVC 패턴을 이용해 애플리케이션을 개발할 때 JSP의 구현을 용이하게 하는 것이 목적. 다양한 종류 존재. 

출처:&nbsp;https://blog.naver.com/aservmz/222225560205

 

<meta> 문서의 설명, 저자, 키워드 등 지정
<link> 일반적으로 외부 CSS 파일 연결시 사용.
<title> 문서의 제목 지정
<script> 자바스크립트와 같은 클라이언트 사이드 스크립트(client-side scripts)를 정의할 때 사용

-> 이들은 <head> 요소 안의 요소들

 

6)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>egov.sample</display-name>

// 필터 : 클라이언트(브라우저)가 서버로 요청을 보내올때 요청이 서블릿으로 전달되기 전, 후에 필터링하기 위한 기술
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/</url-pattern>
	</filter-mapping>
    
	<filter>
		<filter-name>HTMLTagFilter</filter-name>
		<filter-class>egovframework.rte.ptl.mvc.filter.HTMLTagFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>HTMLTagFilter</filter-name>
		<url-pattern>/</url-pattern>
	</filter-mapping>
// 필터 끝
    

// 서블릿 환경 정보 설정
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:egovframework/spring/context-*.xml</param-value>
	</context-param>
// 서블릿 환경 정보 설정 끝
 
// 리스너 : 어떠한 이벤트가 발생하면 호출되어 처리하는 객체.
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
// 리스너 끝

// 서블릿 설정
	<servlet>
		<servlet-name>action</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/config/egovframework/springmvc/dispatcher-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
    
	<servlet-mapping>
		<servlet-name>action</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
// 서블릿 설정 끝

// 시작 페이지 설정 
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
// 시작 페이지 설정 끝

// 서블릿 보안 시작
	<login-config>
		<auth-method>BASIC</auth-method>
	</login-config>
// 서블릿 보안 끝
    
// 에러페이지 설정
	<error-page>
		<exception-type>java.lang.Throwable</exception-type>
		<location>/common/error.jsp</location>
	</error-page>
	<error-page>
		<error-code>404</error-code>
		<location>/common/error.jsp</location>
	</error-page>
	<error-page>
		<error-code>500</error-code>
		<location>/common/error.jsp</location>
	</error-page>
// 에러 페이지 끝
    
</web-app>

 

- web.xml: 서블릿 맵핑 방법, 인증이 필요한 URL 등의 정보 확인. 모든 web application은 반드시 하나의 web.xml 파일이 존재해야하며 WEB-INF폴더 아래에 있다. web.xml 파일의 설정은 web application 시작시 메모리에 로딩된다. 
훨씬 자세한 설명) https://hipdizzy.tistory.com/61

 

web.xml이란 무엇인가?

*광고 클릭은 제게 큰 힘이됩니다! Web.xml 스프링 웹프로그래밍이나 서블릿위주인 웹프로그래밍을 하다보면 web.xml 을 만지는 일들이 있다. 그렇다면 도대체 web.xml이 무엇일까? web.xml에서 서블릿

hipdizzy.tistory.com

- (1): 

- 추가 도움 사이트 및 출처 (https://llnote.tistory.com/753)

 

 

7)

이클립스로 코드 확인

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Micro Service Architecture Board</title> // 탭창에 title 제목 뜨는 것 확인.
<script src="/js/jquery-3.6.0.min.js"></script> // jQuery를 로드하는 데 사용되며, 이 라이브러리는 /js/jquery-3.6.0.min.js 경로에 위치한 파일로부터 가져옴.
<script> 
$(document).ready(function(){
	$('#selectBtn').click(function(){ // 'electBtn' id를 가진 요소(일반적으로 버튼)를 클릭할 때 실행될 함수를 정의.
		$('#page').val("1"); // 클릭 이벤트가 발생하면 id가 'page'인 요소의 값을 1로 설정하고,
		$.fn.search(); //  $.fn.search();를 호출하여 함수(검색)을 수행합니다. <- search() 메서드가 뭔지 해당 코드에서는 안 나와있기에,, 이름으로 일단 추측^^
	});
// 코드 11 ~ 15 (1)    
    
	
	$('#writeBtn').click(function(){
		location.href = 'boardDetail';
	}); // 'writeBtn' id를 가진 요소(버튼)를 클릭하면 'boardDetail' 페이지로 이동
	
	$('#btnJoin').click(function(){
		location.href = 'user/join';
	}); // 'btnJoin' id를 가진 요소(버튼)를 클릭하면 'user/join' 페이지로 이동
	
	$('#btnLogin').click(function(){
		location.href = 'user/login';
	}); // 위 코드의 스니핏과 기능은 같음. 
	
	$('#btnLogout').click(function(){
		location.href = 'user/logout';
	}); // 위 코드의 스니핏과 기능은 같음. 

	$('#list').children('tr').click(function(){ // 'list' id를 가진 요소의 자식 중 'tr' 요소(테이블 행)를 클릭하면
		location.href = 'boardDetail?boardSeq=' + $(this).attr("boardSeq"); // 현재 클릭한 테이블 행($(this))의 "boardSeq" 속성 값을 가져와 URL을 생성하고, 이 URL로 페이지를 이동. (2)
	}); 
	$.fn.drawPagination(); // drawPagination 함수를 호출 (아마 페이지네이션을 그리는 역할로 추측) 
}); 

$.fn.drawPagination = function() { // 페이지네이션 함수
	var page = $('#page').val(); // 변수 page에 id가 page인 값 가져옴.
	var lastPage = Math.ceil($('#count').val() / $('#pagePerCount').val()); // 전체 아이템 수를 한 페이지당 표시할 아이템 수로 나누고 그 결과를 올림하여 마지막 페이지 번호를 계산
	var startPage = 1;
	
	
	if(page > 2) {
		startPage = page - 2;
	}
	
	var html = "<span class=\"firstPage\">&laquo;</span>"; //"firstPage"라는 클래스 이름을 통해 CSS 스타일링이나 JavaScript 이벤트 처리에 사용. "&laquo;"는 HTML 엔터티로서 "«" 문자.
    // => 첫 페이지로 이동하며 <<는 아마 이전 버튼일 듯. 
	for(var i = startPage ; i < startPage + 5 && i <= lastPage; i++) { //  현재 페이지 주변에 표시할 페이지 번호를 생성하는 반복문. startPage부터 시작하여 5개의 페이지 번호를 생성하며, lastPage를 넘어가지 않도록 조건을 설정
		html += "<span class=\"numberPage " + (i==page?"selected":"") + "\">" + i + "</span>"; // 각 페이지 번호를 생성. 현재 페이지와 i 값이 같다면 "selected" 클래스가 추가 (아,, 잘 모르겠어요)
	}
	html += "<span class=\"lastPage\">&raquo;</span>"; //마지막 페이지로 이동하는 버튼을 나타내는 HTML 문자열을 생성. "&raquo;" 문자열은 "다음 페이지"를 나타내는 아이콘 또는 버튼으로 사용
	
	$('.pagination').html(html); // 페이징 컴포넌트가 웹 페이지에 나타남.
	$('.pagination').children('.numberPage').click(function(){ //"pagination"인 요소의 자식 요소 중에서 클래스가 "numberPage"인 요소를 클릭할 때 실행되는 함수를 정의
		$('#page').val($(this).text()); // 클릭된 페이지 번호를 숨겨진 input 요소(#page)의 값으로 설정
		$.fn.search();
	});
	$('.pagination').children('.firstPage').click(function(){ // "pagination"인 요소의 자식 요소 중에서 클래스가 "firstPage"인 요소를 클릭할 때 실행되는 함수를 정의
		$('#page').val("1"); //page value를 1로 설정 (첫 페이지로 가겠다~)
		$.fn.search();
	});
	$('.pagination').children('.lastPage').click(function(){ // 위와 코드 구조는 같음
		$('#page').val(lastPage);
		$.fn.search();
	});
	
	if(page > lastPage) { // page > lastPage 이면 page의 값을 1로 설정함. (첫 번째 페이지로~)
		$('#page').val("1");
		$.fn.search();
	}
}
$.fn.search = function() {
	$.ajax({
	    url:'./boardJSON',
        type:'get',
        data:$('#search').serialize(),
	    success:function(data){
	    	var result = data.resultData;
	    	$('#countText').text(result.boardCount);
	    	$('#count').val(result.boardCount);
	    	
	    	var tableList = "";
	    	if(result.boardCount > 0) {
	    		var list = result.boardList;
		    	for(var i=0;i<list.length;i++) {
		    		tableList += "<tr boardSeq=\"" + list[i].boardSeq + "\">";
		    		tableList += "<td class=\"center\">" + list[i].boardNo +  "</td>";
		    		tableList += "<td>" + list[i].boardTitle + "</td>";
		    		tableList += "<td class=\"center\">" + list[i].writeUserName + "</td>";
		    		tableList += "<td class=\"center\">" + list[i].createDt + "</td>";
		    		tableList += "</tr>";
		    	}
			} else {
				tableList = "<tr>"
					+ "<td class=\"center\" colspan=\"4\">게시물이 존재하지 않습니다.</td>"
					+ "</tr>";
			}
	    	
	    	$('#list').html(tableList);
	    	
	    	$('#list').children('tr').click(function(){
	    		location.href = 'boardDetail?boardSeq=' + $(this).attr("boardSeq");
	    	});
	    	$.fn.drawPagination();
	    }
	});
}
</script>
<style type="text/css">
html, body {
	margin: 0;
	padding: 0;
	height: 100%;
}

div.header {
	margin: 0;
	padding: 0;
	height: 15%;
}

div.body {
	margin: 0;
	padding: 0;
	height: 70%;
	margin: 0% 15%;
	/* 	background-color: #EEEEEE; */
}

div.footer {
	margin: 0;
	padding: 0;
	height: 15%;
}

table {
	margin: 0;
	padding: 0;
	border: 0px;
    border-collapse: collapse;
	width: 100%;
	border-top: solid 2px;
	border-bottom: solid 2px;
}

table thead {
	height: 30px;
	border-top: solid 1px;
	border-bottom: solid 1px #404040;
}

table tbody tr {
	border-bottom: solid 1px #DDDDDD;
	height: 30px;
}

.searchArea {
	text-align: right;
	padding: 3px;
}

/* 페이징 디자인 시작 */
.pagination {
	width: 100%;
	text-align: center;
	margin: 1% 0;
}

.pagination span {
	color: black;
	padding: 4px 8px;
	cursor: pointer;
	text-decoration: none;
}

.pagination .selected {
	font-weight: bold !important;
}
/* 페이징 디자인 종료 */

/* selectbox 디자인 시작*/
select {

    -webkit-appearance: none;  /* 네이티브 외형 감추기 */
    -moz-appearance: none;
    appearance: none;
    
    width: 70px; /* 원하는 너비설정 */
    padding: .3em .5em; /* 여백으로 높이 설정 */
    font-family: inherit;  /* 폰트 상속 */
    background: url('/images/select_icon.jpg') no-repeat 95% 50%; /* 네이티브 화살표를 커스텀 화살표로 대체 */
    border: 1px solid #999;
    border-radius: 0px; /* iOS 둥근모서리 제거 */
    -webkit-appearance: none; /* 네이티브 외형 감추기 */
    -moz-appearance: none;
    appearance: none;
    
}

/* IE 10, 11의 네이티브 화살표 숨기기 */
select::-ms-expand {
    display: none;
}
/* selectbox 디자인 종료*/

/* input 디자인 시작*/
input[type=text] {
    -webkit-appearance: none;  /* 네이티브 외형 감추기 */
    -moz-appearance: none;
    appearance: none;
    
    width: 150px; /* 원하는 너비설정 */
    padding: .3em .5em; /* 여백으로 높이 설정 */
    font-family: inherit;  /* 폰트 상속 */
    border: 1px solid #999;
    border-radius: 0px; /* iOS 둥근모서리 제거 */
    -webkit-appearance: none; /* 네이티브 외형 감추기 */
    -moz-appearance: none;
    appearance: none;
}
/* input 디자인 시작*/

.button {
    -webkit-appearance: none;  /* 네이티브 외형 감추기 */
    -moz-appearance: none;
    appearance: none;
    font-family: inherit;  /* 폰트 상속 */
    font-size: 0.85em;
    border: 1px solid #999;
    padding: .3em .5em; /* 여백으로 높이 설정 */
    border-radius: 0px; /* iOS 둥근모서리 제거 */
    -webkit-appearance: none; /* 네이티브 외형 감추기 */
    -moz-appearance: none;
    appearance: none;
	background-color: #EEEEEE;
	cursor: pointer;
}

.left {
	text-align: left;
}
.right {
	text-align: right;
}
.center {
	text-align: center;
}
</style>

</head>
<body>
	<div class="header" style="text-align: right; padding: 3px;">
		<c:if test="${session.session_id.value eq null}">
			<span id="btnJoin" style="float:left;" class="button">회원가입</span>
			<span id="btnLogin" style="float:left;" class="button">로그인</span>
		</c:if>
		<c:if test="${session.session_id.value ne null}">
			<span id="btnLogout" style="float:left;" class="button">로그아웃</span>
		</c:if>
 	</div>
	<div class="body">
		<article>
			<form id="search"  action="javascript:return false;">
				<div class="right"><span>총 <span id="countText">${resultData.boardCount}</span>건 조회되었습니다.</span></div>
				<input type="hidden" id="count" value="${resultData.boardCount}">
				<input type="hidden" id="page" name="page" value="${resultData.page}">
				<input type="hidden" id="pagePerCount" name="pagePerCount" value="${resultData.pagePerCount}">
				<table>
					<thead>
						<tr>
							<th style="width:10%;">번호</th>
							<th style="width:60%;">제목</th>
							<th style="width:10%;">작성자</th>
							<th style="width:20%;">작성일</th>
						</tr>
					</thead>
					<tbody id="list">
						<c:choose>
							<c:when test="${resultData.boardCount eq '0'}">
								<tr>
									<td class="center" colspan="4">게시물이 존재하지 않습니다.</td>
								</tr>
							</c:when>
							<c:otherwise>
								<c:forEach var="row" items="${resultData.boardList}" varStatus="status">
									<tr boardSeq="${row.boardSeq}">
										<td class="center">${row.boardNo}</td>
										<td>${row.boardTitle}</td>
										<td class="center">${row.writeUserName}</td>
										<td class="center">${row.createDt}</td>
									</tr>
								</c:forEach>
							</c:otherwise>
						</c:choose>
					</tbody>
				</table>
				<div class="searchArea">
					<select name="searchType">
						<option value="boardTitle">제목</option>
						<option value="boardText">내용</option>
						<option value="writeUserName">작성자</option>
					</select>
					<input type="text" name="searchValue" onKeypress="javascript:if(event.keyCode==13) {$.fn.search();}"/>
					<span id="selectBtn" class="button">검색</span>
					<c:if test="${session.session_id.value ne null}">
						<span id="writeBtn" class="button">등록</span>
					</c:if>
				</div>
				<div id="pagination" class="pagination" page=""></div>
			</form>
		</article>
	</div>
	<div class="footer"></div>
</body>
</html>

 

(1)

- jQuery를 사용한 모든 웹페이지는 다음 코드로 시작함. 

<script>
$(document).ready(function(){ // 문서가 준비되면 매개변수로 넣은 콜백 함수를 실행하라는 의미

});
</script>

 

(2)

- 예를 들어, 클릭한 테이블 행의 "boardSeq" 값이 123이라면, 최종적으로 "boardDetail?boardSeq=123"로 이동. 특정 게시물의 상세 정보 페이지로 이동하는 것으로 보임. 

 

- 페이지네이션: 

출처: https://yonghwankim-dev.tistory.com/578

 

8)

 

 

 

코드 77부터 다시 분석 시작