본문 바로가기
Web Development/Spring Legacy

[Spring / Legacy / JSTL / JSP] Custom Tag를 이용해 JSP에서 사용할 사용자 함수 구현하기(feat. tld파일 작성법)

by 감자맹고우 2023. 2. 28.
728x90
반응형

Spring Legacy 프로젝트에서는 JSP를 템플릿 엔진으로 흔히 사용하는데, 이 때 서버단에서 받아온 데이터를 활용하기 위해 EL과 JSTL을 사용한다. 주로 사용되는 것이 core와 functions로 각각 c와 fn으로 prefix를 등록해 <c:if>, <fn:length()> 등을 활용해 데이터를 보여준다.

 

그런데 가끔 Java에서 제공하는 함수를 JSP에서도 사용하고 싶은데, JSTL에서는 제공되지 않아 아쉬운 경우가 있곤 했다. 예를 들어 Java Collection 중 List는 contains 함수를 제공하는데 JSTL에서는 제공되지 않기 때문에 <c:forEach>를 활용해 반복문을 돌려서 찾는 식으로 처리하기도 했다.

 

그러다 문득, model1방식으로는 Java 코드를 직접 JSP에 작성했는데, 어떤 방법이 있지 않을까하는 생각이 떠올랐다. 그래서 찾다보니 Custom Tag라는 기능을 알게 되었고 JSTL도 Custom Tag의 일종이라는 것을 알게 되었다.

그렇게 Custom Tag를 구현하는 방법을 찾게 되었는데, 대부분 오래된 자료들이다보니 현재 프로젝트 상태에 맞는 방법을 찾기가 힘들었다. 그러나 다행히도 시행착오 끝에 구현이 되었기에 그 방법을 공유하고자 한다.

 

 

[ 해결 방법 ]

 

1. JSP 버전 확인

 

일단 JSP 버전을 확인해야 한다. 확인하는 방법은 구글링을 통해서 간단히 찾을 수 있는데, 이미 구현해놓은 프로젝트의 JSP 파일에 아래의 코드를 추가하면 된다.

<%= JspFactory.getDefaultFactory().getEngineInfo().getSpecificationVersion() %>

 

이렇게하고 서버를 실행시켜 해당 코드를 작성해 둔 JSP 페이지 화면이나, 개발자 도구를 활용해서 출력부분을 보면 JSP 버전을 확인할 수 있다.

본인의 경우에는 개발자 도구를 활용하여 2.3 버전임을 확인할 수 있었다.

 

 

2. Java Class 작성

 

이제 본격적으로 기능을 구현해볼텐데, 먼저 원하는 함수를 Java Class로 작성해야 한다. 예시로는 위에서 설명했던 List의 contains 메소드를 JSP에서 쓸 수 있도록 구현하려고 한다.

 

package com.example.custom;

import java.util.List;

public class CustomFunctions {
    public static boolean contains(List<Object> list, Object o) {
        return list.contains(o);
    }
}

 

Class명은 임의로 작성하면 되고, 기억만 하면 된다. 여기서는 구글링을 하면서 봤던 CustomFunctions 로 클래스명을 지정했다. 그리고 contains 메소드를 이미 Java에서 구현되어 있는 List Collection의 contains 메소드를 활용하여 작성해주었다.

 

 

3. tld 파일 작성

 

tld 파일에 대해서는 구글링을 통해 자세히 알 수 있지만, 간략하게 Tag Library Descriptor의 약자로 JSP에서 사용되는 태그들에 대한 설정 파일이라고 설명한다.

 

그래서 작성한 Java Class를 JSP의 태그로써 사용하려면 이 파일에서 설정을 해주어야 한다.

이 때, tld 파일의 JSP Tag Library 버전을 JSP 버전과 호환되도록 맞춰주어야 하는데, 이를 위해 앞에서 JSP 버전을 확인했다.

문제는 JSP가 2.3 버전인데 JSP Tag Library는 2.3버전이 없다. 숫자가 일치하는 버전이 있으면 덜 헷갈리겠지만, 어쨌든 최신 버전이라 생각해 가장 마지막으로 뜨는 버전인 2.1버전으로 작성했는데 다행히 잘 동작했다.

 

tld 파일의 경로는 WEB-INF 폴더 아래에만 설정하면 된다. WEB-INF의 하위 폴더를 생성하고 그 안에 두어도 되고 WEB-INF 바로 하위에 파일을 생성해도 된다. 추후에 사용할 JSP에서 경로만 맞게 지정해주면 된다.

 

 

- tld 파일 작성법 -

 

(1) tld 파일의 작성법은 아래의 잘 작성된 다른 블로거님의 블로그 글을 참고하여 작성할 수 있다. 특히 여기서는 1.2버전과 2.0버전을 다루고 있어서 JSP 이전 버전을 사용한다면 더욱 참고하기 좋을 것 같다.

 

 

[서블릿/JSP] TLD(Tag Library Descriptor)란? tld 파일 작성 방법

연관글 [서블릿/JSP] JSP 커스텀 태그란? JSP 2.0 SimpleTagSupport를 이용한 태그 작성 방법[서블릿/JSP] JSP 1.2 버전 커스텀 태그 만들기 TLD(Tag Library Descriptor)란 Tag Library Descriptor 줄여서 tld란 JSP에서 사용

dololak.tistory.com

 

(2) 위와 같이 하기가 번거롭다면 그냥 빈 파일을 생성하고 아래의 코드를 작성해 직접 만들어주어도 좋다. xml 파일을 작성하는 것처럼 생각하면 된다.

 

<%-- custom-functions.tld 파일(이 줄은 작성 X, 주석임) -->

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd ">
  <tlib-version>2.1</tlib-version>
  <short-name>custom-functions</short-name>
  <function>
  	<name>contains</name>
  	<function-class>com.example.custom.CustomFunctions</function-class>
  	<function-signature>boolean contains(java.util.List, java.lang.Object)</function-signature>
  </function>
</taglib>

 

내용을 요약하면, 우선 web-jsptaglibrary 2.1버전을 taglib 루트 엘리먼트에 설정해준다.

그렇게 하면 기본적으로 tlib-version과 short-name 태그를 설정해주어야 하는데, tlib-version은 taglib 버전을 그대로 적어주었고, short-name은 tld 파일명과 동일하게 임의로 작성해주었다.

(해당 내용은 구글링 결과를 참고해 단순 작성했기에 명확히 알고서 기재한 것은 아니다)

이제, 여기서 function 태그를 추가하여 만들어둔 Java Class 메소드를 연동시켜준다.

 

function 태그에도 여러가지 작성할 수 있는 태그 들이 있는데 여기서는 3가지를 각각 작성해주면 된다.

name은 JSP에서 사용할 메소드 명칭, function-class는 작성해둔 Java Class의 패키지가 포함된 전체 경로, function-signature는 해당 Java Class에 작성한 메소드를 형식에 맞게 쓴 것이다.

 

이렇게 하면 tld파일은 다 작성한 것인데, 원래는 tld 파일의 존재를 인식시킬 수 있도록 web.xml에 등록해야 했지만 버전이 높아지면서 이 부분은 이제 생략해도 되는 것 같다.

 

반응형

 

4. 이제 JSP에서 쓰면 됩니다

 

이제 작성한 메소드를 JSP에서 쓰면 된다.

 

<%-- JSP -->
<%-- JSTL -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%-- CUSTOM -->
<%@ taglib uri="/WEB-INF/custom-functions.tld" prefix="cfn" %>

<c:forEach var="student" items="${studentList}">
    <c:if test="${fn:length(subjectList) gt 0}">
        <c:forEach var="subject" items="${subjectList}">
            <c:if test="${cfn:contains(student.applicationSubjectIdList, subject.id)}">
                <p>${subject.name}</p>
            </c:if>
        </c:forEach>
    </c:if>
</c:forEach>

 

JSTL과 유사하게 uri 경로만 잘 지정해서 사용하면 된다.

위의 코드는 예시 코드로 작성해본 것인데, 학생 목록과 과목 목록을 각각 서버단에서 studentList와 subjectList로 받은 경우, 학생들의 수강신청과목에 있는 과목명을 중복을 고려하지 않고 출력하도록 작성한다면 이렇게 작성할 수 있을 것 같다.

 

이렇게 하면, 사용하고 싶은 Java 메소드를 JSP에서도 마음대로 사용할 수 있다!

 

 

🤞 도움이 되셨기를 바랍니다. 한 번의 클릭과 댓글은 어딘가의 누군가에게 진실로 큰 힘이 됩니다. 🐱‍🏍

 

728x90
반응형

댓글