요즘 여러 회사의 채용공고들을 살펴보고 있는데, 느낀 점이 아직은 Spring Boot보다는 Spring Framework가 많이 사용되고, Thymeleaf 보다는 JSP가 많이 사용된다는 점이었다.
그래서 가만히 생각을 해보니, 회사에서 Thymeleaf만 사용하다보니 JSP를 전부 까먹었다는 사실을 알아냈다.
언제 jsp를 사용하게 될 지 모르므로, jsp의 사용법을 간단하게 기재해서 저장해놓고자 한다.
JSP
Java Server Pages (JSP)는 웹 개발을 위해 사용되는 자바의 기술이다. HTML과 Java를 결합해서 사용할 수 있는데, 서버에서 실행해서 생성된 결과를 html로 사용자에게 전달한다. 동적인 웹 페이지를 만들때 사용된다.
JSP를 사용함에 있어 장점과 단점은 아래와 같다.
- 코드와 디자인의 분리가 가능하다.
- 커스텀 태그, JSTL 및 EL을 통해 재사용 가능한 컴포넌트를 제공한다.
- MVC 패턴을 적용하기 좋아 개발과 유지보수에 용이하다.
- JSP 페이지는 첫 요청시 컴파일되어야 하기에 상대적으로 비효율적이고 느리다.
- JSP 페이지의 Java 코드는 오류를 찾고 디버깅하기 어렵다.
JSP 예제
이전에 작성했던 Thymeleaf 포스팅처럼 JSP에서의 코드를 간단하게 적어놓고자 한다.
우선 언제나 그랬듯 프로젝트부터 생성하고 시작한다. jsp 사용법만 만들 것이기에 Spring Web과 Lombok만 추가했다.
프로젝트가 생성됐으면 우선 pom.xml 파일에 아래 디펜던시를 추가한다. 템플릿 엔진인 JSP를 사용하기 위한 라이브러리이다.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
추가 완료 후 메이븐을 이용해 프로젝트를 업데이트한다.
- 프로젝트 우클릭 > Maven > Update Project
프로젝트가 갱신되었다면 /src/main/밑에 webapp 폴더와, 그 밑에 WEB-INF 폴더를 생성한다.
webapp 폴더는 스프링에서 웹의 root 폴더이며, WEB-INF는 J2EE 사양에 따라 정의된 표준 폴더 구조라고 한다.
참고 : https://7942yongdae.tistory.com/115
추가가 되었다면 이제 Thymeleaf 때처럼 jsp 파일의 위치와 확장자명을 application.properties에 추가해준다.
spring.mvc.view.prefix=classpath:/WEB-INF/
spring.mvc.view.suffix=.jsp
이제 테스트를 위한 Controller 클래스와, JSP 파일을 생성하자.
컨트롤러 클래스는 간단하게 작성한다. 일반 String, List, Map을 jsp에 반환하는 클래스이다.
package com.mwlee.jsp.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class CommonController {
@GetMapping("/")
public String mainPage(Model model) {
String stringObj = "hello world";
List<String> listObj = new ArrayList<>();
listObj.add("hello");
listObj.add("world");
Map<Integer, String> mapObj = new HashMap<>();
mapObj.put(1, "hello");
mapObj.put(2, "world");
// jsp에 데이터 반환
model.addAttribute("stringObj", stringObj);
model.addAttribute("listObj", listObj);
model.addAttribute("mapObj", mapObj);
// jsp 반환
return "main";
}
}
다음으로 데이터를 표출할 JSP를 작성한다.
우선 JSP는 가장 상단에 아래와 같은 설정이 입력되어 있어야 한다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 아래부터는 사용하는 태그에 따라 동적으로 추가 -->
<!-- c 태그 사용 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- fn 태그 사용 -->
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!-- x 태그 사용 -->
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<!-- fmt 태그 사용 -->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!-- sql 태그 사용 -->
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
그리고 String을 다루는 부분은 아래와 같이 작성한다.
<h2>String Data: </h2>
<c:if test="${not empty stringObj}">
${stringObj}
<!-- 이렇게도 가능하다. -->
<c:out value="${stringObj}"/>
</c:if>
List는 forEach를 사용해서 하나씩 뽑아낸다.
<h2>List Data: </h2>
<c:if test="${not empty listObj}">
<c:forEach var="item" items="${listObj}">
${item}<br/>
</c:forEach>
</c:if>
마지막으로 Map도 마찬가지로 forEach를 사용해서 하나씩 뽑아내고, key와 value로 구분해서 사용한다.
<h2>Map Data: </h2>
<c:if test="${not empty mapObj}">
<c:forEach var="entry" items="${mapObj}">
${entry.key} : ${entry.value}<br/>
</c:forEach>
</c:if>
Java에서 전달한 변수를 반드시 HTML 내에서만 사용하란 법은 없다. 분명 JavaScript에서 사용될 일이 존재할 텐데, Java에서 전달한 변수는 아래와 같이 JavaScript에서 사용할 수 있다.
<script type="text/javascript">
// String
var stringObj = "${stringObj}";
var stringObj2 = '<c:out value="${stringObj}"/>'
// List
var listObj = []; // 혹은 new Array()
<c:if test="${not empty listObj}">
<c:forEach var="item" items="${listObj}">
listObj.push("${item}");
</c:forEach>
</c:if>
// Map
var mapObj = new Map();
<c:forEach var="entry" items="${mapObj}" varStatus="loop">
mapObj.set("${entry.key}", "${entry.value}")
</c:forEach>
// 이렇게도 사용 가능. 단 이 때는 object로 생성됨.
var mapObj2 = {
<c:forEach var="entry" items="${mapObj}" varStatus="loop">
"${entry.key}": "${entry.value}"<c:if test="${!loop.last}">,</c:if>
</c:forEach>
};
console.log(stringObj);
console.log(listObj)
console.log(listObj[0]);
console.log(mapObj);
console.log(mapObj.get('a'));
console.log(mapObj2);
</script>
최종 jsp 파일은 아래와 같다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- c 태그 사용 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- fn 태그 사용 -->
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
<head>
<title>jsp 연습</title>
</head>
<body>
<h2>String Data: </h2>
<c:if test="${not empty stringObj}">
${stringObj}
<!-- 이렇게도 가능하다. -->
<c:out value="${stringObj}"/>
</c:if>
<h2>List Data: </h2>
<c:if test="${not empty listObj}">
<c:forEach var="item" items="${listObj}">
${item}<br/>
</c:forEach>
</c:if>
<h2>Map Data: </h2>
<c:if test="${not empty mapObj}">
<c:forEach var="entry" items="${mapObj}">
${entry.key} : ${entry.value}<br/>
</c:forEach>
</c:if>
<script type="text/javascript">
// String
var stringObj = "${stringObj}";
var stringObj2 = '<c:out value="${stringObj}"/>'
// List
var listObj = []; // 혹은 new Array()
<c:if test="${not empty listObj}">
<c:forEach var="item" items="${listObj}">
listObj.push("${item}");
</c:forEach>
</c:if>
// Map
var mapObj = new Map();
<c:forEach var="entry" items="${mapObj}" varStatus="loop">
mapObj.set("${entry.key}", "${entry.value}")
</c:forEach>
// 이렇게도 사용 가능. 단 이 때는 object로 생성됨.
var mapObj2 = {
<c:forEach var="entry" items="${mapObj}" varStatus="loop">
"${entry.key}": "${entry.value}"<c:if test="${!loop.last}">,</c:if>
</c:forEach>
};
console.log(stringObj);
console.log(listObj)
console.log(listObj[0]);
console.log(mapObj);
console.log(mapObj.get('a'));
console.log(mapObj2);
</script>
</body>
</html>
마지막으로 c 태그 사용법을 기재하며 포스팅을 마무리한다.
태그 | 설명 | 사용 |
c:set | 변수 선언 | <c:set var="변수명" value="값" property="자바 객체" scope="범위/> *공유범위는 page, request, session, application |
c:remove | 변수 제거 | <c:remove var="변수명" scope="범위"/> |
c:out | 변수 출력 | <c:out var="변수명" default="기본값 지정" excapeXML="true|false"/> *excapeXML은 >, < 등을 %lt;, %gt; 등으로 변경하는 유무이다. |
c:catch | 예외처리 | <c:catch var="에러 메시지로 "> 에러 발생 가능성이 있는 로직 수행 </c:catch> |
c:if | 조건문 (else 없음에 유의) | <c:if test="조건" var="변수명" scope="변수범위> </c:if> |
c:choose | 조건문 (switch) | <c:choose> <c:when test="조건"> ... </c:when> <c:when test="조건"> ... </c:when> <c:otherwise> ... </c:otherwise> </c:choose> |
c:when | ||
c:otherwise | ||
c:forEach | 반복문 | <c:forEach var="변수" items="데이터 내 아이템명" begin="시작값" end="종료 값" step="증가 값" varStatus="반복 상태 변수"> </c:forEach> |
c:forTokens | 구분자로 분할하는 반복문 | <c:forTokens var="변수" items="데이터 내 아이템명" delims="구분자" begin="시작값" end="종료 값" step="증가 값" varStatus="반복 상태 변수"> </c:forEach> |
c:url | url | <c:url var="변수" value="이동할 URL" scope="범위/> |
c:param | 파라미터 추가 | <c:param name="파라미터명" value="값"/> |
c:import | 페이지 첨부 | <c:import url="첨부 URL"/> |
c:redirecrt | 리다이렉트 | <c:redirect url="이동할 URL"/> |
'실습 > 리눅스 서버 + 스프링 부트' 카테고리의 다른 글
[SPRING JPA] N+1 문제 (0) | 2023.07.04 |
---|---|
Spring Boot + Mybatis (0) | 2023.07.02 |
OAuth2.0 + Spring Boot (Google, Kakao, Naver 연동) (2) | 2023.07.01 |
application 파일에서 자료구조(list, map) 사용법 (1) | 2023.05.28 |
application.yml 적용법 (0) | 2023.01.15 |