서버프로그램 jstl 3~5일차

2026. 3. 9. 21:47대우개발원 수업 내용/서버프로그램

반응형

JSTL - core태그 – 흐름 제어용
<c:choose> : 조건문
- c:if문의 경우 else기능을 제공하지 않는다.
그러므로 else 기능을 하기 위해서는 c:if를 여러 개 나열할 수밖에 없는데
이때 choose를 사용하면 여러 조건을 보다 간결하게 처리할 수 있다

 

<c:choose>
    <c:when test=“조건식1”> 조건식1이 참일 경우 실행할 영역 </c:when>
    <c:when test=“조건식2”> 조건식2이 참일 경우 실행할 영역 </c:when>
    <c:when test=“조건식3”> 조건식3이 참일 경우 실행할 영역 </c:when>
    <c:otherwise> 모든 조건이 만족하지 않을 때 실행 영역 </c:otherwise>
</c:choose>

11_fruitSelect.jsp, 11_fruitSelectForm.jsp

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:choose>
		<c:when test="${param.fruit == 1}">
			<span style="color: red;">사과</span>
		</c:when>
		<c:when test="${param.fruit == 2}">
			<span style="color: green;">메론</span>
		</c:when>
		<c:when test="${param.fruit == 3}">
			<span style="color: blue;">바나나</span>
		</c:when>
	</c:choose>
</body>
</html>
<%@ 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>
<body>
	<form action="fruitSelect.jsp">
		<label for="fruit">과일을 선택하세요</label><br> 
		<select id="fruit" name="fruit">
			<option value="1">사과</option>
			<option value="2">메론</option>
			<option value="3">바나나</option>
		</select> <input type="submit" value="전송">
	</form>
</body>
</html>

 

jstl core태그

for each 태그 : 배열, 컬렉션등의 집합체에 저장된 값을 순차적으로 처리할 때 사용하는 반복문이다. (향상된 for문과 유사)

 

<c:forEach var=“원소 하나를 저장할 변수” items=“반복처리할 집합체”>
	반복할 코드
</c: forEach >
더보기

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:forEach var="cnt" begin="1" end="10" varStatus="status">
		${cnt} <c:if test="${not status.last}">,	</c:if>
	</c:forEach>
	<table border="1" style="width: 100%; text-align: center;">
		<tr>
			<th>index</th>
			<td>count</td>
			<td>cnt</td>
		</tr>
		<c:forEach var="cnt"	begin="1" end="10" varStatus="status" step="2">
			<tr>
				<td>${status.index}</td>
				<td>${status.count}</td>
				<td>${cnt}</td>
			</tr>
		</c:forEach>
	</table>
</body>
</html>

 


JSTL - core태그 – 흐름 제어용
<c:forTokens> : 반복문
- c: forTokens 문의 경우 문자열을 구분자로 쪼개고 각각 쪼개진 문자열 하나하나의 집합체로
서 순차적으로 반복해서 사용하는 반복문이다.

<c:forTokens var=“토큰을 저장할 변수” items=“토큰으로 나눌 문자열” delims=“구분자”>
	반복할 코드
</c:forTokens>

- 예제 13_ forTokens.jsp

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:forEach var="cnt" begin="1" end="10" varStatus="status">
		${cnt} <c:if test="${not status.last}">,	</c:if>
	</c:forEach>
	<table border="1" style="width: 100%; text-align: center;">
		<tr>
			<th>index</th>
			<td>count</td>
			<td>cnt</td>
		</tr>
		<c:forEach var="cnt"	begin="1" end="10" varStatus="status" step="2">
			<tr>
				<td>${status.index}</td>
				<td>${status.count}</td>
				<td>${cnt}</td>
			</tr>
		</c:forEach>
	</table>
	<br>
	<br>
	<c:forTokens var="city" items="서울.인천, 대구.부산" delims=",">
		${city} <br>
		</c:forTokens>
</body>
</html>

 


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:forEach var="cnt" begin="1" end="10" varStatus="status">
		${cnt} <c:if test="${not status.last}">,	</c:if>
	</c:forEach>
	<table border="1" style="width: 100%; text-align: center;">
		<tr>
			<th>index</th>
			<td>count</td>
			<td>cnt</td>
		</tr>
		<c:forEach var="cnt"	begin="1" end="10" varStatus="status" step="2">
			<tr>
				<td>${status.index}</td>
				<td>${status.count}</td>
				<td>${cnt}</td>
			</tr>
		</c:forEach>
	</table>
	<br>
	<br>
	<c:forTokens var="city" items="서울.인천, 대구.부산" delims=",.">
		${city} <br>
		</c:forTokens>
</body>
</html>

JSTL - core태그 – 페이지 제어
- c:url 문의 경우 URL을 생성해서 적절한 위치에 사용할 수 있다

<c:url var=“저장할 변수” value=“URL” scope=“변수를 저장할 영역>
</c:url>

 

 

 

 

 

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:import url="http://localhost:8080/jstlweb/fruitSelectForm.jsp" var="data"></c:import>
	${data}
	</body>
</html>

 

더보기

url=""로 페이지 이동

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:url value="/img/mio.png" var="data"></c:url>
		<h3>${data}</h3>
		<img src="${data}" width="150" height="150">
</body>
</html>

JSTL - core태그 – 페이지 제어
- c:redirect 문의 경우 지정한 페이지로 이동할 때 사용한다.
- response.sendRedirect와 같다

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:import url="http://localhost:8080/jstlweb/fruitSelectForm.jsp" var="data"></c:import>
	
	<%-- ${data}	
	<c:redirect url="Url.jsp"></c:redirect>--%>	
		<c:redirect url="Url.jsp"></c:redirect>

		
</body>
</html>

 

 

 

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:url value="/img/mio.png" var="data"></c:url>
		<h3>${data}</h3>
		<img src="${data}" width="150" height="150">
</body>
</html>

JSTL - core태그 – 기타
- c:out 문은 출력을 위한 태그이다.
- 표현식이나 표현언어와 동일한 역할을 하기 때문에 표현언어보다 자주 사용되지 않는다.
< c:out value=“출력할 값” [defalut=“기본값”] / >

 

JSTL - core태그 – 기타
- c:catch 문은 예외 처리을 위한 태그이다.
- 예외가 발생하면 잡아내는 역할을 한다.

<c:catch var=“발생한 예외가 저장될 변수” >
예외가 발생할 가능성이 있는 코드
</c:catch>

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<c:import url="http://localhost:8080/jstlweb/fruitSelectForm.jsp" var="data"></c:import>
	
	<%-- ${data}	
	<c:redirect url="Url.jsp"></c:redirect>--%>	
	
	<c:set var="age" value="30" scope="page"></c:set>
		나이 :<c:out value="${age }">10</c:out>
	
	<br>
	<c:remove var="age" scope="page"></c:remove>
	나이 : <c:out value="${age}">10</c:out>
		<br>
		<c:catch var="errmsg">
	예외 발생 전<br>
				<%= 1 / 0 %> <br>
	예외 발생 후<br>
				 </c:catch>
				 <c:out value="${errmsg}">></c:out>
</body>
</html>

JSTL - fmt 태그: <fmt:formatNumber>

기본 사용

  • <fmt:formatNumber value="1234567.89" />
    → 1,234,567.89
    (기본적으로 3자리마다 콤마를 붙여 출력)
  • <fmt:formatNumber value="1234567.89" groupingUsed="false" />
    → 1234567.89
    (그룹핑을 사용하지 않음, 즉 콤마 없이 출력)

출력 유형 지정

  • <fmt:formatNumber value="0.5" type="percent" />
    → 50%
    (소수 값을 백분율로 변환)
  • <fmt:formatNumber value="10000" type="currency" />
    → ₩10,000
    (기본 로케일의 통화 기호 사용, 한국 로케일이면 원화 기호)
  • <fmt:formatNumber value="10000" type="currency" currencySymbol="$" />
    → $10,000
    (통화 기호를 직접 지정)

패턴 지정

  • 패턴은 #,0, . 기호로 표기
    • 0 → 빈자리를 0으로 채움
    • # → 빈자리를 공백으로 둠

예시:

  • <fmt:formatNumber value="1234567.8912345" pattern="#,#00.0#" />
    → 1,234,567.89
    (소수점 이하 두 자리까지 표시, 세 번째 자리에서 반올림)
  • <fmt:formatNumber value="1234567.8" pattern="#,#00.0#" />
    → 1,234,567.8
    (소수점 이하 한 자리만 표시)
  • <fmt:formatNumber value="1234567.89" pattern=".000" />
    → 1,234,567.890
    (소수점 이하 세 자리까지 강제로 출력, 부족한 자리는 0으로 채움)

추가 

  • <fmt:formatNumber>는 JSTL의 국제화(i18n) 지원 태그 중 하나로, 숫자 출력 형식을 로케일에 맞게 제어할 수 있다.
  • type 속성으로 number, percent, currency를 지정할 수 있으며, pattern을 통해 세밀한 출력 형식을 직접 정의할 수 있다.
  • groupingUsed 속성은 천 단위 구분 기호(콤마) 사용 여부를 제어
  • currencySymbol 속성을 사용하면 로케일 기본 통화 기호 대신 원하는 기호를 출력할 수 있다.

JSTL - fmt 태그: <fmt:formatDate>

기본 사용

  • <c:set var="now" value="<%=new java.util.Date()%>" />
    → 현재 날짜 객체 생성
  • <fmt:formatDate value="${now}" />
    → 2020.12.31
    (기본적으로 날짜만 출력)
  • <fmt:formatDate value="${now}" type="time" />
    → 오전 8:12:45
    (시간만 출력)
  • <fmt:formatDate value="${now}" type="both" />
    → 2020.12.31 오전 8:12:45
    (날짜와 시간 모두 출력)
  • <fmt:formatDate value="${now}" pattern="yyyy년 MM월 dd일 hh시 mm분 ss초" />
    → 2020년 12월 31일 8시 12분 45초
    (사용자가 지정한 패턴에 따라 출력)

JSTL - fmt 태그: <fmt:setTimeZone> / <fmt:timeZone>

  • <fmt:setTimeZone>
    특정 지역의 타임존을 전체 페이지에 적용하는 태그.
    예: <fmt:setTimeZone value="Asia/Seoul" />
  • <fmt:timeZone>
    특정 영역에만 타임존을 적용하는 태그.
    예:→ 지정된 블록 안에서만 해당 타임존 적용.
  • <fmt:timeZone value="Asia/New_York"> <fmt:formatDate value="${now}" type="both" /> </fmt:timeZone>

• 예제 19_jstllFmt.jsp


JSTL - fmt 태그: <fmt:setLocale>

  • 다국적 페이지에서 국가별 화폐, 날짜 표기법 등을 자동으로 적용하기 위해 사용.
  • 로케일 값만 바꾸면 해당 국가/언어에 맞는 형식으로 출력됨.
  • 예: <fmt:setLocale value="ko_KR" />
    • ko → 한국어 언어 코드
    • KR → 한국 국가 코드
  •  예제 20_jstlFmt.jsp

JSTL - fmt 태그: <fmt:requestEncoding>

  • POST 방식으로 넘어온 데이터가 깨지지 않도록 인코딩을 지정하는 태그.
  • 기존 request.setCharacterEncoding("UTF-8") 메소드와 동일한 역할.
  • 예: <fmt:requestEncoding value="UTF-8" />
    → UTF-8 인코딩을 적용해 한글 깨짐 방지.

• 예제 21_info.jsp, 21_jstlFmt.jsp, 22_info.jsp, 22_jstlFmt.jsp 


추가 설명

  • <fmt:formatDate>는 날짜와 시간을 다양한 형식으로 출력할 수 있으며,
    type 속성(date, time, both)과 pattern 속성을 통해 세밀하게 제어할 수 있다
  • <fmt:setTimeZone>와 <fmt:timeZone>는 국제화(i18n)에서 중요한 역할을 하며,
    서버 기본 시간대와 다른 지역의 시간을 표시할 때 유용힘
  • <fmt:setLocale>는 언어와 국가 코드에 따라 자동으로 날짜, 숫자, 통화 형식을 바꿔주므로
    다국어 웹사이트 제작에 필수적
  • <fmt:requestEncoding>는 인코딩 문제를 해결해 사용자 입력 데이터가 깨지지 않도록 보장

 

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<pre>
	
		<c:set var="now" value="<%= new java.util.Date() %>"> </c:set>
		\%{now> : ${now}
		now : ${now}
		
		date : <fmt:formatDate value="${now}" type="date"/>
		time : <fmt:formatDate value="${now}" type="time"/>
		both : <fmt:formatDate value="${now}" type="both"/>
		
		default :
		<fmt:formatDate value="${now}" type="both" dateStyle="default" timeStyle="default"></fmt:formatDate>		
		medium :
		<fmt:formatDate value="${now}" type="both" dateStyle="medium" timeStyle="medium"></fmt:formatDate>
		long :
		<fmt:formatDate value="${now}" type="both" dateStyle="long" timeStyle="long"></fmt:formatDate>
		full :
		<fmt:formatDate value="${now}" type="both" dateStyle="full" timeStyle="full"></fmt:formatDate>
		pattern="yyyy년 MM월 dd일 hh시 mm분 ss초" :
		<fmt:formatDate value="${now}" pattern="yyyy년 MM월 dd일 hh시 mm분 ss초"></fmt:formatDate>
	
	</pre>

</body>
</html>

실습 : jstlExam.jsp JSTL과 EL 종합 예제

코드 해설

1. <c:set>과 <c:out>

<c:set var="product1" value="<h2>애풀 아이폰 </h2>" />
<c:set var="product2" value="삼성 갤럭시 노트" />
  • c:set은 변수를 설정하는 태그
  • product1에는 HTML 태그가 포함된 문자열이 들어 있고, product2에는 단순 문자열이 들어 있다
<c:out value="${product1}" default="Not registerd" escapeXml="true" />
  • c:out은 EL로 지정한 값을 출력
  • escapeXml="true" → HTML 태그를 이스케이프 처리해서 <h2>가 실제로는 태그로 해석되지 않고 문자열로 출력
  • default 속성은 값이 없을 때 기본값을 출력

2. 배열 출력 (forEach)

<ul>
  <c:forEach var="num" varStatus="i" items="${intArray}">
    <li>${i.index} : ${num}</li>
  </c:forEach>
</ul>
  • c:forEach는 반복문 태그
  • items 속성으로 배열이나 리스트를 받아 반복함.
  • varStatus="i"를 지정하면 반복 상태 객체를 사용할 수 있다.
    • i.index → 0부터 시작하는 인덱스
    • i.count → 1부터 시작하는 반복 횟수

※ 현재 intArray는 주석 처리되어 있어서 실제 실행 시에는 값이 없을 수 있다


3. 조건문 (if)

<c:set var="checkout" value="true" />
<c:if test="${checkout}">
  <p>주문 제품: ${product2}</p>
</c:if>
<c:if test="${!checkout}">
  <p>체크아웃 상태가 아님!!</p>
</c:if>
  • c:if는 조건문 태그
  • checkout이 true일 때는 주문 제품을 출력, false일 때는 다른 메시지를 출력
<c:if test="${!empty product2}">
  <p><b>${product2} 이미 추가됨 !!.</b></p>
</c:if>
  • empty는 값이 비어있는지 확인하는 EL 연산자
  • product2가 비어있지 않으면 메시지를 출력

4. choose / when / otherwise

<c:choose>
  <c:when test="${checkout}">
    <p>주문 제품: ${product2}</p>
  </c:when>
  <c:otherwise>
    <p>체크아웃 상태가 아님!!</p>
  </c:otherwise>
</c:choose>
  • c:choose는 switch-case와 유사한 구조
  • c:when은 조건이 참일 때 실행, c:otherwise는 모든 조건이 거짓일 때 실행

5. forTokens

<c:forTokens var="city" items="Seoul/Tokyo/New York/Toronto" delims="/" varStatus="i">
  <c:if test="${i.first}"> 도시목록 :</c:if>
  ${city}
  <c:if test="${!i.last}">,</c:if>
</c:forTokens>
  • c:forTokens는 문자열을 특정 구분자(delims)로 나누어 반복
  • items="Seoul/Tokyo/New York/Toronto" → /로 구분된 문자열을 도시 이름으로 분리
  • i.first → 첫 번째 반복인지 확인
  • i.last → 마지막 반복인지 확인
  • 결과: 도시목록 : Seoul, Tokyo, New York, Toronto

전체 흐름

  1. 변수 설정과 출력: c:set, c:out으로 값 저장 및 출력.
  2. 배열 반복 출력: c:forEach로 리스트나 배열을 순회.
  3. 조건문 처리: c:if로 단일 조건 분기.
  4. 다중 조건 분기: c:choose, c:when, c:otherwise로 여러 경우 처리.
  5. 문자열 토큰화: c:forTokens로 문자열을 구분자로 나누어 반복 출력.

즉, 이 JSP는 JSTL Core 태그의 기본적인 데이터 설정, 출력, 조건문, 반복문, 문자열 처리 기능을

한 페이지에서 종합적으로 보여주는 예제

 

 

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSTL 종합 예제</title>
</head>
<body>
	<h2>JSTL 종합 예제</h2>
	
	<hr>
	
	<h3>set, out</h3>
	<c:set var="product1" value="<h2>애풀 아이폰 </h2>" />
	<c:set var="product2" value="삼성 갤럭시 노트" />
	<%-- <c:set var="intArray" value="${1,2,3,4,5} /> --%>
	
	<p>
		product1(jst1):
		<c:out value="${product1}" default="Not registerd"
			escapeXml="true" />
	</p>
	<p>product1(el):${product1}</p>
	<p>intArray[2]: ${intArray[2]}</p>
	
	<h3>forEach : 배열 출력</h3>
	<ul>
		<c:forEach var="num" varStatus="i" items="${intArray}">
			<li>${i.index} : ${num} </li>
			</c:forEach>
	</ul>
	<hr>
	
	<h3>if</h3>
	<c:set var="checkout" value="true" />
	<c:if test="${checkout}">
		<p>주문 제품: ${product2}</p>
	</c:if>
	<c:if test="${!checkout }">
		<p>체크아웃 상태가 아님!!</p>
		</c:if>
		
		<c:if test="${!empty product2}">
		<p>
			<b>${ product2} 이미 추가됨 !!.</b>
		</p>
		</c:if>
		<hr>
		
		<h3>choose, when, otherwise</h3>
		<c:choose>
			<c:when test="${checkout}">
			<p>주문 제품: ${product2 }</p>
			</c:when>
			<c:otherwise>
			<p>체크아웃 상태가 아님!!</p>
			</c:otherwise>
			</c:choose>
			<hr>
			
			<h3>forTokens</h3>
			<c:forTokens var="city" items="Seoul/Tokyo/New York/Toronto"
				delims="/" varStatus="i">
					<c:if test="${i.first}"> 도시목록 :</c:if>
			${city}
			<c:if test="${!i.last }">,</c:if>
			</c:forTokens>
</body>
</html>

maven

자바 빌드 도구

  • Ant: 가장 오래된 자바 빌드 도구
  • Maven: 2004년 아파치 프로젝트로 등장
    • 이후 오랜 기간 자바 빌드 도구의 표준으로 자리잡음
    • 특히 스프링 프레임워크 개발에서 기본 빌드 도구로 활용됨
  • Gradle: 2012년 등장
    • 유연하고 복잡한 처리를 쉽게 하기 위해 만들어짐
    • 안드로이드 앱 개발의 기본 빌드 도구
  • 현재는 Maven과 Gradle이 대표적인 빌드 도구로 사용됨

Maven과 Gradle 비교

  • 설정 방식
    • Maven: pom.xml 파일에 XML 구조로 작성 → 프로젝트가 커질수록 길어지고 가독성 저하
    • Gradle: Groovy 기반 언어로 작성 → 짧고 간결하게 표현 가능
  • 다중 프로젝트
    • Maven: 설정을 다른 모듈에서 사용하려면 상속 필요
    • Gradle: 설정 주입 방식을 사용 → 다중 프로젝트에 적합

개발 환경

  • 안드로이드 프로젝트 → 기본적으로 Gradle 사용
  • 스프링 프레임워크 기반 프로젝트 → Maven 또는 Gradle 선택 가능
  • IDE 친화성
    • Eclipse → Maven에 친화적
    • IntelliJ → Gradle에 친화적

빌드 도구의 주요 목적

  1. 컴파일/실행 설정과 라이브러리 설정
  2. 라이브러리 관리
    • 핵심 라이브러리만 설정 파일에 등록하면, 해당 라이브러리가 필요로 하는 다른 라이브러리는 자동으로 함께 설치됨

리포지터리

  • 라이브러리를 통합 보관하는 저장소
  • 설정 파일을 참고해 글로벌 저장소에서 로컬 저장소로 다운로드 후 프로젝트에 복사하여 사용
  • 로컬 저장소에 라이브러리가 있으면 인터넷 다운로드 없이 바로 사용 가능
  • 필요 시 기업 내부에서 자체 저장소를 운영하여 필요한 라이브러리만 관리 가능


디자인 패턴 (Design Pattern)

  • 처음에는 건축학적 관점에서 출발한 개념
  • 1994년 GoF의 Design Patterns: Elements of Reusable Object-Oriented Software를 통해 소프트웨어 설계에서 공통적으로 발생하는 문제에 대한 재사용 가능한 솔루션으로 제시됨
  • GoF 디자인 패턴은 생성, 구조, 행동, 동시실행 등의 문제에 대해 여러 패턴을 제시
  • UML 클래스 다이어그램을 이용해 구조를 표현

UML (Unified Modeling Language)

  • 객체지향 설계와 구현을 지원하기 위해 만들어진 모델링 언어
  • 시스템 분석, 설계에 필요한 내용을 여러 다이어그램 형태로 정의한 규격

디자인 패턴은 문제 해결을 위한 재사용 가능한 설계 방법론

UML은 이를 시각적으로 표현하는 표준 언어

 


추상 팩토리 (Abstract Factory) 패턴

  • 추상(Abstract): 자바의 추상 클래스(abstract class)처럼 구체적인 구현을 하위 객체에 위임하는 모델
  • 팩토리(Factory): 디자인 패턴에서 객체를 생성하는 역할을 의미
  • 추상 팩토리: 객체 생성 과정을 별도로 구현하면서, 관련된 구체적인 구현은 하위 클래스에서 담당하도록 하는 설계 모델

추상 팩토리 패턴의 UML 클래스 다이어그램

  • 객체 생성 문제를 해결하기 위한 디자인 패턴
  • 여러 관련 객체들을 일관성 있게 생성할 수 있도록 추상화된 인터페이스를 제공
  • 구체적인 객체 생성은 하위 클래스(Concrete Factory)가 담당
  • 클라이언트는 추상 팩토리 인터페이스를 통해 객체를 생성하므로, 구체적인 클래스에 의존하지 않고 유연한 구조를 가질 수 있음

객체 생성 로직을 캡슐화하여 클라이언트가 구체적인 클래스에 의존하지 않도록 하는 구조를 제공하는 디자인 패턴


MVC 패턴 (Model-View-Controller)

  • 약어: Model-View-Controller
  • 기원: GUI(Graphical User Interface) 기반 애플리케이션 개발에 사용된 디자인 패턴
  • 현재 활용: 백엔드 기반 웹 애플리케이션 개발의 기본 모델
    • 모바일 앱 및 프런트엔드 웹 애플리케이션 개발에서는 MVP(Model-View-Presenter), MVVM(Model-View-ViewModel) 같은 변형 패턴도 널리 사용됨
  • 목적: 화면(View)과 데이터 처리(Model)를 분리하여 코드 간 종속성을 줄이는 것
  • 효과: 구성 요소 간 역할을 명확히 하여 코드 분리와 협업을 용이하게 함

애플리케이션을 Model, View, Controller로 나누어 책임을 분리하는 구조로, 유지보수성과

확장성을 높이는 데 핵심적인 역할을 함


모델 (Model)

  • 데이터 처리 영역을 담당
  • 일반적으로 다음과 같은 구성 요소를 포함
    • DAO (Data Access Object): 데이터베이스와 연동을 위한 클래스
    • DO (Data Object, 엔티티 클래스): 데이터 구조를 표현하는 클래스
  • 특징
    • 뷰(View)나 컨트롤러(Controller)에 독립적인 구조
    • 데이터베이스 처리를 필요로 하는 여러 애플리케이션에서 공유 가능
    • 웹 애플리케이션뿐 아니라 일반 애플리케이션에서도 활용 가능

모델(Model)은 애플리케이션의 데이터와 그 처리 로직을 담당하는 핵심 영역으로,

다른 구성 요소와 독립적으로 동작하며 재사용성이 높다


뷰 (View)

  • 역할: 화면 구성을 담당하는 영역
  • 특징
    • 주어진 데이터를 출력하는 용도로만 사용하는 것이 바람직함
    • 뷰에서 데이터를 직접 가져오는 방식은 권장하지 않음
  • 구현 방식
    • 뷰 템플릿 엔진을 사용하여 구현
    • JSP 역시 뷰 템플릿 엔진 중 하나
  • 표현 기술
    • HTML, EL, JSTL 등을 활용해 컨트롤러로부터 전달받은 데이터를 출력
    • HTML, CSS 등을 통해 화면을 디자인
  • 독립성
    • 뷰는 기본적으로 모델(Model), 컨트롤러(Controller)와 종속성이 없도록 구현해야 함

뷰(View)는 사용자에게 보여지는 화면을 담당하며, 컨트롤러가 전달한 데이터를 출력하는 독립적인 영역으로,

데이터 처리나 로직은 포함하지 않고 화면 표현에만 집중


컨트롤러 (Controller)

  • MVC 패턴의 핵심으로 모든 사용자 요청의 중심에 위치
  • 사용자 요청 처리 흐름
    • 사용자 요청은 특정 뷰(View)에 직접 전달되지 않고 반드시 컨트롤러를 거침
    • 컨트롤러는 요청에 따라 모델(Model)을 통해 데이터베이스와 연동하여 데이터를 처리
    • 처리된 데이터를 뷰(View)에 전달
  • 데이터 전달 방식
    • 뷰로 전달하기 위해 데이터가 들어 있는 DO 객체 또는 List<DO> 형태를 request에 저장한 후 포워딩
  • 특징
    • 특정 뷰를 지정해야 하므로 뷰와 종속 관계가 발생
    • 프로젝트 규모가 커질수록 컨트롤러의 복잡성이 증가하여 관리가 어려워질 수 있음

즉, 컨트롤러(Controller)는 사용자 요청을 받아 모델과 연동해 데이터를 처리하고, 그 결과를 뷰에 전달하는 중심 역할을 담당


컨트롤러의 구현

  • JSP, 서블릿 모두 가능
  • JSP
    • 간단한 기능을 구현할 때 유리
  • 서블릿
    • 규모 확장에 적합
    • 향후 스프링 프레임워크로의 확장에도 유리
  • 특징
    • 컨트롤러는 사용자 요청을 받아 처리하고, 필요한 경우 모델과 연동하여 데이터를 가져온 뒤 뷰로 전달
    • 따라서 컨트롤러를 호출해야 전체 MVC 흐름이 진행됨

컨트롤러는 MVC 패턴의 중심에서 사용자 요청을 받아 처리하는 역할을 하며,

구현 방식에 따라 단순한 JSP 기반 처리부터 대규모 서블릿 기반 확장까지 가능하다


컨트롤러를 구성하는 방법

① 사용자 요청마다 컨트롤러를 만들기
② 특정 모듈 단위로 하나의 컨트롤러 안에서 여러 요청 단위를 구분해 처리하기
③ 프런트 컨트롤러를 따로 두어 모든 요청을 하나의 컨트롤러로 모은 다음 요청에 따라 구현 컨트롤러를 호출하기



서블릿 컨트롤러 설계

클라이언트 요청 처리

컨트롤러의 기본 기능 세 가지

  1. 클라이언트 요청 처리
  2. 입력값 핸들링
  3. 뷰(View) 이동

① 클라이언트 요청 처리

  • 클라이언트 요청을 단일 컨트롤러에서 처리할지, 개별 컨트롤러에서 처리할지 결정해야 함
  • 서블릿은 URL 요청을 GET, POST 등의 HTTP 메서드를 통해 처리하는 구조
  • 하나의 서블릿에서 여러 URL 패턴을 처리할 수 있음
  • 하지만 URL에 따라 서로 다른 처리 로직을 구현하는 데 한계가 있음

클라이언트 요청 처리 단계에서는 요청을 어떻게 분배하고 관리할지 결정하는 것이 핵심

서블릿 기반 구조에서는 URL 매핑 방식에 따라 단일 처리와 개별 처리 전략을 선택.


사용자의 요청을 구분해 하나의 서블릿에서 처리하기 위한 두 가지 방법
1) URL의 파라미터 이용
2) 프런트 컨트롤러 구현

 

URL의 파라미터 이용
 URL에 action과 같이 별도의 파라미터를 두어 요청을 구분함
• member: 서블릿 URL 매핑값
• action: 요청을 구분하기 위한 파라미터
 요청에는 회원 정보, 로그인 아이디 등의 사용자 데이터가 추가로 포함됨
 GET, POST 방식이 모두 가능함
 컨트롤러에서는 action 값을 비교하여 별도의 메서드 구현 등의 방식으로 처리함
 비교적 간단한 방법이지만 action 파라미터의 구조가 변경되며 관련된 HTML, JSP, 컨트롤러의 수정이 필요하다는
단점이 있음

 

URL의 파라미터 이용의 실제 구현: 분기문 사용


 프런트 컨트롤러 구현(1)
 모든 요청의 진입점이 되는 컨트롤러가 있고 여기서 서브 컨트롤러를 호출하는 구조
 좀 더 복잡한 구조를 체계적으로 처리할 수 있음
 프런트 컨트롤러 패턴으로 정립되어 있어 여러 구현에 응용되는 디자인 패턴임
 모든 요청을 하나로 모으는 방법이 필요하며, 일반적으로는 서블릿 매핑의 구조적인 특징을 활용함
• /member: 회원 관리 웹 애플리케이션 콘텍스트 혹은 서비스 구분 경로
• *.do: 서블릿 URL 매핑값으로 모든 요청은 하나의 서블릿을 호출함
 컨트롤러에서는 .do 앞의 요청 이름(create, login)으로 구분하여 별도의 메서드 혹은 서브클래스를 통해 실행함

 

 프런트 컨트롤러 구현의 장점
 요청에 대한 파라미터 없이 명확한 이름(전 예시의 create, login)으로 요청할 수 있음
 요청에 대한 URL 관리가 필요 없음


 프런트 컨트롤러 구현의 단점
 전체 시스템이 세부 시스템이 분리되어 있는 경우: 콘텍스트를 분리하는 것은 세션 관리 등에 부담이 갈 수 있음
• 예) 네이버와 같은 포털 형태
 단일 콘텍스트에 경로로 구분하는 경우: 프런트 컨트롤러에서 모든 요청을 조건문과 메서드 구현만으로 처리하기
에는 컨트롤러 클래스가 비대해짐
 → 규모가 어느 수준 이상이 되면 경로에 따라 서브 컨트롤러로 포워딩하는 처리가 필요함

 

 서브 컨트롤러 구현하기
 URL 요청을 분석해 사용자 요청을 구분하는 작업이 우선적으로 필요함
 메서드를 이용해 사용자 요청을 분리해서 처리함
• switch(혹은 if ) 문을 사용하는 구조는 기능 추가 또는 변경이 필요할 때 조건문도 함께 관리해야 하는 문제가 있음


서브 컨트롤러 구현하기
 Command 패턴을 사용하면 switch(혹은 if) 구조 없이해당 요청에 맞는 특정 컨트롤러가 실행되도록 구현할 수 있음

 

 서브 컨트롤러를 운영하는 프런트 컨트롤러를 설계하기
 먼저 서브 컨트롤러의 규격을 정의한 인터페이스가 필요함
 다음으로 필요한 서브 컨트롤러를 구현함
• 앞의 다중 요청 처리 서블릿을 서브 컨트롤러 규격에 맞게 수정함
• 기본적으로는 단일 기능을 수행하며 서브 URL 경로를 추가로 구분해 메서드 단위로 여러 요청을 처리하도록 구현하는 것
도 가능함

 


입력값 핸들링
② 입력값 핸들링
 서블릿에서 클라이언트의 입력값을 처리하려면 request.getParameter( )를 이용해야 함
 파라미터가 한두 개라면 문제없겠지만 회원 가입과 같이 여러 정보가 전달되는 경우 모든 값을
request.getParameter( )로 받는 것은 문제가 됨
 또한 DAO 클래스와 연동을 위해서는 입력값을 Member 객체로 만든 후에 전달해야 하므로 기본적으로
다음과 같은 코드 구현이 필요함

 JSP에서는 useBean 액션을 통해 입력값을 Member 객체로 쉽게 만들 수 있었음
 서블릿에서는 그런 기능이 제공되지 않기 때문에 별도의 라이브러리를 사용해야 함
 대표적으로 Apache Commons BeanUtils가 쓰임

 

뷰 이동
③ 뷰 이동
 컨트롤러에서 사용자 요청을 처리한 다음에는 적절한 뷰로 이동할 수 있어야 함
 뷰에서 보여줄 데이터를 포함해서 이동해야 하는 경우와 그렇지 않은 경우로 나뉨
 데이터를 포함하지 않는 경우
 사용자 요청 처리 후 별도의 데이터를 포함하지 않는다면 해당 페이지로 리디렉션Redirection할 수 있음
 JSP, 서블릿 모두 response.sendRedirect( )를 사용함

 

데이터를 포함하는 경우
 request scope object에 속성으로 데이터를 넣은 후 원하는 페이지로 포워딩함
 데이터 활용 목적에 따라 session 또는 application을 사용할 수도 있으며 여러 데이터를 포함하는 것도 가능함

 


컨트롤러 기초 예제: 계산기 구현
• 컨트롤러 동작 원리와 구현 방법을 배우기 위해 단순한 구조의 컨트롤러를 구현해봄
• 기본적으로 MVC 구조를 따름
• 구현했던 Calculator 클래스를 컨트롤러와 모델 영역으로 구분하고 결과를 보여줌
① 뷰 구현: calcForm.html, calcResult.jsp
② 모델 구현: Calculator.java
③ 컨트롤러 구현: CalcController.java

 

더보기
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>계산기-컨트롤러</title>
</head>
<body>
    <h1>계산기-컨트롤러</h1>
    <form action="/jstlweb/calccontrol" method="get">
        <input type="text" name="n1" size="10">
        <select name="op">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        

        <input type="text" name="n2">
        <button type="submit">실행</button>
    </form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>계산기-컨트롤러</title>
</head>
<body>
<h2>계산 결과-컨트롤러</h2>
<hr>
결과: ${result}
</body>
</html>
package mvc;

public class Calculator {
	private int n1;
	private int n2;
	private String op;
	
	public int getN1() {
		return n1;
	}
	public void setN1(int n1) {
		this.n1 = n1;
	}
	public int getN2() {
		return n2;
	}
	public void setN2(int n2) {
		this.n2 = n2;
	}
	public String getOp() {
		return op;
	}
	public void setOp(String op) {
		this.op = op;
	}
	
	public long calc() {
		long result= 0;
		switch(op) {
			case "+" :result = n1+n2;break;
			case "-" :result = n1-n2;break;
			case "/" :result = n1/n2;break;
			case "*" :result = n1*n2;break;
		}
		return result;
	}
}
package mvc;

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;


@WebServlet("/calccontrol")
public class CalcController extends HttpServlet {
	private static final long serialVersionUID = 1L;


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int n1 = Integer.parseInt(request.getParameter("n1"));
		int n2 = Integer.parseInt(request.getParameter("n2"));
		
		long result = 0;
		
		switch(request.getParameter("op")) {
			case "+" :result = n1+n2;break;
			case "-" :result = n1-n2;break;
			case "/" :result = n1/n2;break;
			case "*" :result = n1*n2;break;
		}
		request.setAttribute("result", result);
		getServletContext().getRequestDispatcher("/mvc/calcResult.jsp")
		.forward(request, response);
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

고급 컨트롤러 서블릿 구현
• 여러 요청을 하나의 컨트롤러에서 처리하는 구조를 구현함
• 기본적으로 MVC 구조를 따름
• 전체 상품 목록을 보여주고 상품을 선택하면 세부 정보를 보여주도록 구현함
① 뷰 구현: productList.jsp, productInfo.jsp
② 모델 구현: Product.java, ProductService.java
③ 컨트롤러 구현: ProductController.java

 

더보기

form이 없기떄문에 doget과 dopost는 사용 안함

 


JDBC의 개념
 JDBC의 구조
 JDBC API: 응용 프로그램에서는 자바에 기본적으로 포함된 JDBC API를 사용해 프로그램 코드를 작성함
 JDBC 드라이버(JDBC API 구현 클래스): 실제 데이터베이스 연결은 각 데이터베이스 회사가 제공하는 JDBC 드라이
버를 이용함
 SQL 문으로 데이터를 조작하는 형태로 동작함

 

JDBC 드라이버
 자바 인터페이스로 정의된 일종의 규격이기 때문에 실제 구현된 클래스가 없으면 동작하지 않음
 이때 실제 구현된 클래스를 JDBC 드라이버라고 부르며 라이브러리와 같은 개념임
 JDBC API를 사용하는 프로그램을 개발하거나 실행하는 과정에 해당 라이브러리가 반드시 필요함
• Maven 기반으로 프로젝트를 변경했기 때문에 다른 라이브러리와 마찬가지로 pom.xml에 의존성을 추가하면 자동으로 프
로젝트에서 참조됨
 JDBC 드라이버는 보통 데이터베이스를 만드는 회사에서 직접 배포함


JDBC 프로그래밍

 1단계: JDBC 드라이버 로드
 먼저 해당 데이터베이스의 JDBC 드라이버를 로드해야 함

 

 JDBC 드라이버를 로드하는 방법
① jdbc.drivers라는 시스템 환경 변수에 등록된 내용으로 하는 방법
② Class.forName( ) 메서드를 이용해서 직접 해당 클래스를 로드하는 방법
 대부분의 경우 다음 코드와 같이 Class.forName( ) 메서드를 사용함

Class.forName(“oracle.jdbc.driver.OracleDriver”)


 드라이버 로드에 사용되는 oracle.jdbc.driver.OracleDriver 는 ORACLE 데이터베이스의 드라이버 클래스로 이름을
잘못 명시하면 오류 발생함


 2단계: 데이터베이스 연결
 드라이버가 로드되면 해당 데이터베이스의 JDBC 드라이버를 이용해 프로그램을 작성할 수 있는 상태가 된 것을 의
미함
 실제 데이터베이스와 연결하려면 Connection 클래스의 인스턴스가 필요함
 DriverManager.getConnection( ) 메서드를 이용해서 레퍼런스를 가져올 수 있음
 또한 JDBC URL, DB 사용자 아이디/비밀번호가 필요함
 JDBC URL: 데이터베이스에 대한 다양한 정보를 포함함
 JDBC URL 구조

 2단계: 데이터베이스 연결
 Connection 클래스 인스턴스 레퍼런스 얻기
• JDBC 클래스 로딩과 URL이 준비되었으면 실제 데이터베이스와의 연결을 만들기 위한 코드를 작성하기
• DriverManager의 getConnection( ) 메서드를 사용함

Connection conn = DriverManager.getConnection(JDBC_URL, "아이디", "비밀번호");


• JDBC_URL: 해당 데이터베이스에 맞게 미리 정의되어 있는 문자열
• 아이디와 비밀번호: 데이터베이스에 등록된 계정



데이터 베이스 커넥션 풀
• 데이터 베이스에 어떤 쿼리를 실행하기 위해서 가장 우선해야 할 작업 : 연결된 상태
• 이런 연결된 상태를 ‘커넥션’이라고 부른다.
• 그러나 웹 페이지에 접속자가 많아지면 커넥션도 동일한 수 만큼 만들어 주어야 하기 때문에
   서버에 과부하가 걸리게 되고 심한 경우 서버가 다운되는 현상(서버가 폭파 되었다고도 한다)이 발생한다.
• 이런 문제를 해결하기 위해서 나온 기법이 ‘커넥션 풀’이다

 

커넥션 풀(DBCP : Database Connection Pool)은 dbcp 매니저가 미리 연결 수량을 확보하고서 요청이 들어오면 
확보된 연결(커넥션)을 제공하고 처리가 완료되면 다시 연결을 회수해서 재활용하는 방식이다

 



 3단계: Statement 생성
 데이터베이스와 연결을 한번 완료하면 이후 연동부터는 SQL 문을 통해 이루어짐
 이때 문자열로 이루어진 SQL 문을 JDBC에서 처리할 수 있는 객체로 변환해야 하는데, 이때 사용되는 것이 Statement 객체임
 하지만 보통 SQL 문과 데이터를 조합하기 때문에 일반 Statement보다는 Statement를 상속받는
PreparedStatement를 사용하는 것이 좋음
 PreparedStatement
• SQL 문을 미리 만들어두고 변수를 따로 입력하는 방식
• 효율성이나 유지보수 측면에서 유리한 구조임
• 기본적으로 Statement 클래스를 상속받기 때문에 Statement 클래스 메서드를 모두 사용할 수 있음

PreparedStatement pstmt = conn.prepareStatement("insert into test values(?,?)");
// 여기서 values 뒤의 첫 번째 ? → 바인드 변수 1번
// 두 번째 ? → 바인드 변수 2번
pstmt.setString(1, request.getParameter("username")); // 첫 번째 ?에 값 바인딩
pstmt.setString(2, request.getParameter("email"));    // 두 번째 ?에 값 바인딩

=> 이런 방식은 SQL 인젝션을 방지하고 코드 가독성을 높이는 장점

 


4단계: SQL 문 전송
 3단계 과정을 통해 PreparedStatement 객체가 준비되었고 실제 쿼리의 실행은 SQL 문 종류에 따라
executeQuery( ) 혹은 executeUpdate( )를 사용하게 됨
 executeQuery( )
• SELECT 문을 수행할 때 사용함
• 반환값은 ResultSet 클래스 타입으로, 해당 SELECT 문의 결과에 해당하는 데이터에 접근할 수 있는 방법을 제공함
 executeUpdate( )
• INSERT, UPDATE, DELETE와 같은 문을 수행할 때 사용함
• 반환값은 INT 값으로, 처리된 데이터의 수를 반환함

 


 5단계: 결과 받기
 데이터베이스에서 데이터 결과를 받으려면 Statement나 PreparedStatement의 execute Query( )를 사용함
 입력, 수정, 삭제와 달리 데이터를 갖고 오는 경우에는 가져온 결과 데이터를 처리하기 위한 ResultSet 객체가 필요함
 ResultSet은 조회한 결괏값에 순차적으로 접근할 수 있는 커서를 다룰 수 있게 함

ResultSet rs = pstmt.executeQuery();

 


 6단계: 연결 해제
 데이터베이스 사용이 종료되면 기본적으로 연결을 해제해야 함
 데이터베이스는 동시에 여러 연결을 지원하지만 동시 연결 수에 따라 라이선스 비용이 증가하기도 하고, 동시 연결
가능 수가 적은 경우 대기 시간이 길어지는 문제가 발생하기도 함
 따라서 사용이 끝난 데이터베이스와의 연결은 해제해주는 것이 좋으며 하나의 연결에서 발생하는 여러 Statement, 
ResultSet 같은 객체도 종료해주는 것이 좋음.

rs.close();
pstmt.close();
conn.close();

'대우개발원 수업 내용 > 서버프로그램' 카테고리의 다른 글

서버프로그램 2일차  (0) 2026.03.03