75-1. 표준 액션 태그
1. index.jsp
<h1>* JSP Action Tag</h1>
<p>
XML기술을 이용해서 JSP문법을 확장 시킬 수 있음
</p>
<h3>1. 표준 액션 태그</h3>
<p>
** 별도의 라이브러리 연동이 필요하지 않음 JSP상에서 곧바로 사용이 가능! <br>
** 태그 앞에 jsp: 이라는 접두어가 붙음
</p>
<a href="views/2_StandardAction/01_include.jsp">01_jsp:include</a>
<br>
<a href="views/2_StandardAction/02_forward.jsp">02_jsp:forward</a>
<br>
2. 01_include.jsp
include해도 파일이 가지고 있는 변수는 사용못함
<%@ 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>
<h3>include</h3>
<p>
또 다른 페이지를 포함하고자 할 때 사용
</p>
<h4>1. 기존의 include지시어를 이용한 방식(정적 include방식 == 컴파일 시 포함되는 형태)</h4>
<%--
<%@ include file="footer.jsp" %>
<br><br>
특징 : include하고 있는 페이지 상에 선언되어 있는 변수를
현재 이 페이지에서도 사용가능함 <br>
include한 페이지의 year 변수 값 : <%= year %> <br><br>
단점이 될 수도 있음
현재 이 페이지에서 동일한 이름의 변수를 선언할 수 없음 <br><br>
<%
//String year = "2222";
%>
--%>
<hr>
<h4>2. JSP표준 액션 태그를 이용한 방식(동적 include 방식 == 런타임 시 포함되는 형태)</h4>
<!-- 반드시 시작태그와 종료태그를 같이 써야한다!!!!!!!!!!!!!!!!!!!!!!!!!!(XML기술이 기반이기 때문에)
단, 시작태그와 종료태그 사이에 넣을 값이 따로 없다면 <시작태그 />로 작성할 수 있음. /없으면 500에러 발생! -->
<jsp:include page="footer.jsp" />
<%--
<jsp:include page="footer.jsp" />
<jsp:include page="footer.jsp" />
<jsp:include page="footer.jsp" />
--%>
<br><br>
특징1 : include하고 있는 페이지에 선언된 변수를 공유하지 않음(즉, 동일한 이름의 변수 선언 가능) <br>
<%
// String year = "2023";
%>
특징2 : 포함 시 include하는 페이지로 값을 전달할 수 있음 <br>
<br>
---- include 테스트 ----
<br>
<!-- 해당 include 액션태그 안에 키 밸류로 값을 넘길 수 있음 => 여는태그와 닫는태그로 된 해당 include에서만 그 키값을 쓸 수 있음 -->
<jsp:include page="footer.jsp">
<jsp:param name="test" value="Hello..?" />
</jsp:include>
<!-- Content영역안에는 절대로 주석을 적지않음!!!!!!!!!!!!!! -->
<br>
<jsp:include page="footer.jsp">
<jsp:param name="test" value="GoodBye" />
</jsp:include>
</body>
</html>
3. footer.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.Date, java.text.SimpleDateFormat" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
// Date 객체 => new Date()하면 오늘날짜
// 오늘날짜 기준으로 년도만 뽑아서 채워넣어야함
// => simpleDateFormat
String year = new SimpleDateFormat("yyyy").format(new Date());
%>
Copyright © 1998-<%= year %> KH Information Educational Institute All Right Reserved
<br>
01_include.jsp로부터 전달받은 test라는 키값의 밸류를 출력 <br>
test : ${ param.test }
</body>
</html>
4. 02_forward.jsp
forward하면 화면은 띄어주지만 주소창은 그대로 남아있음
<%@ 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>
<h1>여기는 02_forward.jsp페이지야!</h1>
<jsp:forward page="footer.jsp" />
<!--
url로는
http://localhost:8001/action/views/2_StandardAction/02_forward.jsp
가 찍혀있음
jsp:forward : 화면을 전환시켜주는 태그
특성상 url은 그대로고 화면만 바꾼다.
-->
</body>
</html>
커스텀 액션 태그
75-2. JSTL core
라이브러리 다운
추가
1. index.jsp
<h3>2. 커스텀 액션 태그</h3>
<a href="views/3_CustomAction/jstl.jsp">JSTL</a>
2. jstl.jsp
<%@ 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>
<h1>JSTL이란?</h1>
<p>
JSP Standard Tag Library의 약자로 JSP에서 사용되는 커스텀 액션 태그 <br>
공통적으로 사용되는 코드들의 집합을 보다 쉽게 사용할 수 있도록 태그화 해서
표준으로 제공하는 라이브러리
</p>
<hr>
<h3>* 라이브러리 다운로드 후 추가 방법</h3>
1) https://tomcar.apache.org/download-taglibs.cgi 접속 <br>
2) Standard-1.2.5 jar Files 4개 다 다운로드 <br>
3) WEB-INF/lib 폴더에 추가 <br>
<h3>* JSTL 선언 방법</h3>
<p>
JSTL을 사용하고자 하는 해당 JSP페이지 상단에 <br>
taglib지시어를 사용해서 선언함 <br><br>
[ 표현법 ] <br>
<% taglib prefix="접두어" uri="사용하고자 하는 파일상의 uri주소" %gt;
</p>
<hr>
<h3>* JSTL 분류</h3>
<h4>1. JSTL Core Library</h4>
<p>
변수와 조건문, 반복문 등의 로직과 관련된 문법을 제공
</p>
<a href="01_core.jsp">core library</a>
</body>
</html>
3. 01_core.jsp
taglib
prefix => <jsp:> 처럼 내가 쓰고싶은 접두사를 고를 수 있음 (대부분 c를 씀)
uri => 꼭이걸씀 외우기 http://java.sun.com/jsp/jstl/core
EL태그를 쓰게 되면 값이 존재하지 않을 때 null이 아닌 빈문자열이 나오므로 null처리를 해줄 필요가 없음
<%@ 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>
<h1>JSTL Core Library</h1>
<h3>1. 변수(속성 == Attribute)</h3>
<pre>
* 변수 선언(<c:set var="변수명" value="리터럴값" scope="스코프영역지정(생략가능)" />)
- 변수를 선언하고 초기값을 대입해주는 기능을 제공
- 더 나아가서 해당 변수를 어떤 scope영역에 담아둘건지 지정 가능함
(생략 시 pageScope에 담김)
=> 즉, 해당 scope영역에 setAttribute라는 메소드를 이용해서 key + value형태로 데이터를 담아둔다라고 생각하면 됨!
=> c:set 을 통해 선언된 변수는 EL구문으로 접근해서 사용 가능(스크립팅 원소로는 접근 불가능)
* 주의사항
- 변수의 타입을 별도로 지정하지 않음
- 반드시 해당 변수에 담아두고자하는 값(value속성에 담긴 리터럴)을 무조건 세팅해야함!!!(초기값을 반드시 넣어야함! 선언과 동시에 초기화!!!)
</pre>
<c:set var="num1" value="10" /><!-- pageScope에 담김 pageContext.setAttribute("num1", "10"); -->
<c:set var="num2" value="20" scope="request" /><!-- requestScope에 담김 request.setAttribute("num2", "20") -->
num1 변수값 : ${ num1 } <br>
num2 변수값 : ${ num2 } <br>
<c:set var="result" value="${ num1 + num2 }" scope="session" /> <!-- sessionScope에 담김 -->
result 변수값 : ${ result } <br>
<!--
변수명만 제시하면 고유범위가 작은 곳에서부터 찾게 됨
: 티가 나지는 않지만 속도가 느려질 수 있음(스코프영역.변수명 권장)
-->
${ pageScope.num1 } <br>
${ requestScope.num2 } <br>
${ sessionScope.result } <br>
requestScope에서 result라는 변수명을 제시할 경우? : ${ requestScope.result } <br><br>
<c:set var="result" scope="request">9999</c:set>
<!-- value속성 말고 시작태그와 종료태그 사이에도 대입할 값을 기술할 수 있음 -->
${ requestScope.result } <br>
${ sessionScope.result } <br>
<hr>
<pre>
* 변수 삭제(<c:remove var="제거하고자하는변수명" scope="스코프영역지정(생략가능)"/>)
- 해당 변수를 scope에서 제거하는 태그
- scope지정 생략 시 모든 scope에서 해당 변수를 다 찾아서 제거함
=> 즉, .removeAttribute("키값"); 메소드를 이용해서 제거하는 것과 동일하게 동작함
</pre>
삭제전 result : ${ result } <br>
1) 특정 scope를 지정해서 삭제 <br>
<c:remove var="result" scope="request" />
request에서 삭제 후 result : ${ result } <br>
2) 모든 scope에서 삭제 <br>
<c:remove var="result" />
모든 scope에서 삭제 후 result : ${ result } <br>
<hr>
<pre>
* 변수 출력(<c:out value="출력하고자하는값" default="기본값(생략가능)" escapeXml="true(기본값, 생략가능)/false" />)
- 데이터를 출력하고자 할 때 사용하는 태그
- default : 기본값, value속성에 출력하고자 하는 값이 없을 경우 대체해서 기본값으로 출력할 내용물을 기술(생략가능)
</pre>
num1을 출력! : <c:out value="${ num1 }" /> <br>
num1을 EL구문으로 출력! : ${ num1 } <br>
<br>
result를 El로 출력 : ${ result }
result를 c:out으로 출력 : <c:out value="${ result }" default="값이 존재하지 않음" /> <br><br>
<!-- escapeXml 테스트 -->
<c:set var="outTest" value="<b>출력테스트</b>" />
escapeXml속성을 생략하고 출력(true) : <c:out value="${ outTest }" /> <br>
escapeXml속성을 false로 지정하고 출력 : <c:out value="${ outTest }" escapeXml="false" />
<!-- escapeXml생략 시 기본값은 true이고, HTML태그가 해석되지 않음(단순한 문자열로 취급) -->
<hr>
<h3>2. 조건문 - if(<c:of test="조건식"> 조건식이 true일 경우 실행할 내용물 </c:if>)</h3>
<pre>
- JAVA의 단일 if문과 비슷한 역할을 하는 태그
- 조건식은 test라는 속성에 작성(******** 조건을 작성할 경우 반드시 !!!!!!!!!!! EL구문으로 작성해야 함 ***********)
</pre>
<%--
기존방식
<% if(조건식) { %>
~~~~~~~~~~~~
<% } %>
--%>
<c:if test="${ num1 gt num2 }">
<b>num1이 num2보다 큽니다.</b>
</c:if>
<c:if test="${ num1 le num2 }">
<b>num1이 num2보다 작거나 같습니다.</b>
</c:if>
<c:set var="str" value="안녕하세요" />
<%--
<% if(str.equals("안녕하세요")) { %>
~~~~~~~~~~
<% } %>
--%>
<c:if test="${ str eq '안녕하세요' }">
<mark>Hello World!</mark>
</c:if>
<br>
<h3>3. 조건문 - choose, when, otherwise</h3>
<pre>
[ 표현법 ]
<c:choose>
<c:when test="조건1"> ~~~~ </c:when>
<c:when test="조건2"> ~~~~ </c:when>
......
<c:otherwise> ~~~~ </c:otherwise> => else 블럭에 해당됨, 또는 switch문의 default
</c:choose>
- JAVA의 if-else if문, switch문과 비슷한 역할을 하는 태그
- 각 조건들은 c:choose의 하위요소로 c:when을 통해서 작성
- otherwise에는 조건을 적어주지 않음
</pre>
<%--
<% if(조건1) { %>
~~~~
<% } else if(조건2) { %>
~~~~
<% } else if(조건3) { %>
~~~~
<% } else { %>
~~~~
<% } %>
--%>
<c:choose>
<c:when test="${ num1 eq 20 }"> <!-- if블럭 -->
<b>안녕하세요</b>
</c:when>
<c:when test="${ num1 eq 10 }"> <!-- else if블럭 -->
<b>반갑습니다</b>
</c:when>
<c:otherwise> <!-- else 블럭 -->
<b>안녕히가세요</b>
</c:otherwise>
</c:choose>
<!-- c:choose태그 안에 when/otherwise말고 다른내용이 들어가선 절대로 안!됨!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<hr>
<h3>4. 반복문 - forEach</h3>
<pre>
[ 표현법 ]
for loop문
<c:forEach var="변수명" begin="초기값" end="끝값" step="증가시킬값(생략 가능)">
반복적으로 실행할 코드
</c:forEach>
=> step생략 시 기본값이 1이다. (step="1")
향상된 for문
<c:forEach var="변수명" items="순차적으로접근할배열또는컬렉션" [varStatus="현재접근된요소의상태값을보관할변수"]>
반복적으로 실행할 코드
</c:forEach>
var속성으로 선언된 변수에 접근하고자 할 때 반드시 EL구문으로 접근해야 함
</pre>
<!-- for loop문 -->
<%--
<% for(int i = 1; i <= 10; 1++) { %>
~~~~
<% } %>
--%>
<c:forEach var="i" begin="1" end="10">
반복 확인 : ${ i } <br>
</c:forEach>
<br>
<c:forEach var="i" begin="1" end="10" step="2">
반복 확인 : ${ i } <br>
</c:forEach>
<br>
<c:forEach var="i" begin="1" end="6">
<h${ i }>태그 안에도 적용이 가능</h${ i }>
</c:forEach>
<br>
<!-- 향상된 for문 -->
<c:set var="colors">
red, orangered, orange, yellow, yellowgreen, greenyellow, green
</c:set> <!-- 마치 배열처럼 사용 가능 -->
colors 값 : ${ colors }
<ul>
<c:forEach var="c" items="${ colors }">
<!-- 태그 안에도 적용 가능! -->
<li style="color:${ c }">${ c }</li>
</c:forEach>
</ul>
<br>
<!-- 응용 -->
<%@ page import="java.util.ArrayList, com.kh.model.vo.Person" %>
<%
// 나는 사실 서블릿
ArrayList<Person> list = new ArrayList();
list.add(new Person("홍길동", 20, "남자"));
list.add(new Person("김길동", 15, "남자"));
list.add(new Person("고길동", 10, "남자"));
request.setAttribute("peopleList", list);
// 여기까지가 원래 페이지가 응답되기 전 서블릿에서 완성되어야 하는 코드
%>
<c:set var="peopleList" value="<%= list %>" scope="request" /> <!-- 출력식 대신 ${ peopleList } 이렇게 해도 됨 -->
<table border="1">
<thead>
<tr>
<th>이름</th>
<th>나이</th>
<th>성별</th>
</tr>
</thead>
<tbody>
<%--
<% if(list.isEmpty()) { %>
조회결과가 없어요~
<% } else { %>
<% for(Person p :list) { %>
<tr>
<td><%= p.getName() %></td>
</tr>
<% } %>
<% } %>
--%>
<c:choose>
<c:when test="${ empty peopleList }">
<td colspan="4">조회결과가 없습니다.</td>
</c:when>
<c:otherwise>
<c:forEach var="p" items="${ requestScope.peopleList }" varStatus="status">
<tr align="center">
<td>${ status.index }</td> <!-- index : 0부터 시작 / count : 1부터 시작 -->
<td>${ p.name }</td>
<td>${ p.age }</td>
<td>${ p.gender }</td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</tbody>
</table>
<hr>
<h3>5. 반복문 - forTokens</h3>
<pre>
[ 표현법 ]
<c:forTokens var="각값을보관할변수명" items="분리시키고자하는문자열" delims="구분자">
반복적으로 실행할 문구(출력만)
</c:forTokens>
- 구분자를 통해서 분리된 각각의 문자열에 순차적으로 접근하면서 반복 수행
- JAVA의 split("구분자") 또는 StringTokenizer와 비슷한 역할
</pre>
<br>
<!-- 테스트할 문자열 변수 만들기 -->
<c:set var="device" value="컴퓨터,휴대폰,TV, 에어컨/냉장고.세탁기" />
<ul>
<c:forTokens var="d" items="${ device }" delims=",./">
<li>${ d }</li>
</c:forTokens>
</ul>
<hr>
<h3>6. 쿼리스트링 관련 태그 - url, param</h3>
<pre>
[ 표현법 ]
<c:url var="변수명" value="요청할url">
<c:param name="키값" value="밸류값" />
<c:param name="키값" value="밸류값" />
...
</c:url>
- url경로를 생성하고 쿼리스트링을 정의할 수 있는 태그
- 넘겨야할 쿼리스트링이 길 경우 사용하면 편하다.
</pre>
<a href="list.do?cPage=1&boardLimit=10&pageLimit=5">기존방식으로 요청</a> <br>
<!-- c:url을 이용 -->
<c:url var="query" value="list.do">
<c:param name="cPage" value="1" />
<c:param name="boardLimit" value="10" />
<c:param name="pageLimit" value="10" />
</c:url>
<!-- 만들어진 요청을 보내겠다! -->
<a href="${ query }">c:url방식으로 요청</a>
</body>
</html>
1~4번은 주구장창 써야함 (5, 6번은 특정상황에 씀)
75-3. fomatting
1. jstl.jsp
<h4>2. JSTL Formatting Library</h4>
<p>
숫자, 날짜 및 시간데이터의 출력 형식을 지정할 때 사용하는 문법을 제공
</p>
<a href="02_formatting.jsp">formatting library</a>
2. 02_formatting.jsp
taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"
<%@ 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>
<h1>1. formatNumber 태그</h1>
<p>
숫자형 데이터와 포맷(형식)을 지정 <br>
- 표현하고자 하는 숫자 데이터의 형식을 통화기호, % 등 원하는 쓰임에 맞게 지정하는 태그 <br><br>
[ 표현법 ]
<fmt:formatNumber value="출력할값" groupingUsed="true/false" type="percent/currency" /> <br>
</p>
<br>
<!-- 테스트할 변수 -->
<c:set var="num1" value="123456789" />
<c:set var="num2" value="0.83952123" />
<c:set var="num3" value="50000" />
<!-- Missing End Tag : 태그를 안닫음 -->
<!-- Unknown Tag : 상단에 라이브러리 선언을 하지 않음(taglib지시어를 작성하지않음) -->
num1의 경우 <br>
그냥 출력 : ${ num1 } <br>
세자리마다 구분하여 출력 : <fmt:formatNumber value="${ num1 }" /> <br>
그냥 출력 : <fmt:formatNumber value="${ num1 }" groupingUsed="false" /> <br><br>
num2의 경우 <br>
percent : <fmt:formatNumber value="${ num2 }" type="percent" /> <br><br>
num3의 경우 <br>
currency : <fmt:formatNumber value="${ num3 }" type="currency" /> <br><br>
<!--
type="currency" : 통화(돈) 단위로 보여짐
현재 사용하고 있는 컴퓨터의 정보에 따라서 단위가 정해짐
+ groupingUsed 속성의 기본값이 true이기 때문에 3자리마다 ,도 찍혀있음
-->
currency $ : <fmt:formatNumber value="${ num3 }" type="currency" currencySymbol="$" />
<!--
currencySymbol : 통가회고 문자의 종류를 지정할 수 있음
-->
<hr>
<h3>2. formatDate 태그</h3>
<p>
날짜 및 시간 데이터의 포맷(형식)을 지정 <br>
단, java.util.Date클래스의 객체를 이용해야만 한다!!!
</p>
<!-- 테스트할 변수 -->
<c:set var="current" value="<%= new java.util.Date() %>" />
current 출력 : ${ current } <br>
<ul>
<li>
현재 날짜 : <fmt:formatDate value="${ current }" type="date" />
<!--
type 속성은 생략가능
기본값은 type="date"
년. 월. 일 출력
-->
</li>
<li>
현재 시간 : <fmt:formatDate value="${ current }" type="time" />
</li>
<li>
현재 날짜 및 시간 : <fmt:formatDate value="${ current }" type="both" />
<!-- type="both" : 날짜와 시간을 둘 다 출력하겠다. -->
</li>
<li>
medium : <fmt:formatDate value="${ current }" type="both" dateStyle="medium" timeStyle="medium" />
<!-- dateStyle, timeStyle이 "medium"일 경우 기본설정, 기본길이 형식 -->
</li>
<li>
long : <fmt:formatDate value="${ current }" type="both" dateStyle="long" timeStyle="long" />
</li>
<li>
full : <fmt:formatDate value="${ current }" type="both" dateStyle="full" timeStyle="full" />
<!-- full : long보다 쪼끔 더 긴 형식 -->
</li>
<li>
short : <fmt:formatDate value="${ current }" type="both" dateStyle="short" timeStyle="short" />
</li>
<li>
customizing : <fmt:formatDate value="${ current }" type="both" pattern="yyyy-MM-dd(E) a HH:mm:ss" />
</li>
</ul>
<!--
yyyy : 4자리년도
MM : 2자리 월수
dd : 2자리 일수
E : 요일
a : 오전 / 오후
HH : 2자리 시간(24시간제)
mm : 2자리 분
ss : 2자리 초
-->
</body>
</html>
75-4. JSTL function library
1. jstl.jsp
<h4>3. JSTL Function Library</h4>
<p>
EL구문안에서 사용할 수 있는 메소드들을 제공
</p>
<a href="03_functions.jsp">functions library</a>
2. 03_functions.jsp
<%@ 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="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>JSTL Functions Library</h1>
<p>
functions 라이브러리는 따로 태그를 제공하는 형태는 아님 <br>
EL구문안에서 메소드를 호출하는 형태로 사용 <br>
주로 문자열과 관련된 메소드들을 제공함 <br>
=> 접두어 : 메소드명(인자값) 형식으로 사용
</p>
<c:set var="str" value="How are you??" />
str : ${ str } <br>
문자열의 길이 : ${ fn:length(str) }글자 <br>
문자열의 길이 : ${ str.length() }글자 <br>
<!-- 참고) 문자열의 길이 뿐만아니라 인자로 List타입을 제시하면 List의 사이즈도 리턴할 수 있음 -->
대문자로 출력 : ${ fn:toUpperCase(str) } <br>
소문자로 출력 : ${ fn:toLowerCase(str) } <br>
are의 시작인덱스 : ${ fn:indexOf(str, "are") }번째 <br>
are의 were로 변환 : ${ fn:replace(str, 'are', 'were') } <br>
</body>
</html>
75-5. Mybatis
Mybatis
WebContent 대신 webapp폴더 생성했음
views폴더를 WEB-INF안에 넣어줌 => 직접 접근이 불가능(포워딩으로 접근가능)
<jsp:forward page="WEB-INF/views/main.jsp" />
taglib을 쓰지 않아도 됨, url이 변경되지 않고 바로 views의 jsp파일로 이동가능
마이바티스란? 영속성 프레임워크
처음 배우는거???? => 공식사이트로 가야지
라이브러리 다운로드~
jar파일을 누르면 git이 나오는데 zip파일을 다운받으면 된다.