본문 바로가기
JSP

[View업그레이드] 커스텀 태그

by amoomar 2022. 3. 7.
반응형

 

포스팅의 목차는 다음과 같다.

1. 커스텀 태그
   1) 커스텀태그란?
   2) 태그의 구조와 tagib지시어
   3) 커스텀 태그 사용 방법

2. 태그 파일 기반 방법
   1) 사용 방법
   2) 예제

3. 태그 핸들러 클래스 기반 방법
   1) 핸들러클래스 생성
   2) 태그라이브러리기술자 생성
   3) 실습

4. 커스텀 태그를 활용한 로그인 로직 분리

 

 


 

 

 

1. 커스텀 태그

 

1) 커스텀태그란?

커스텀 태그는 새롭게 정의한 나만의 태그라고 할 수 있다. 사실 JSTL도 잘 만들어져 널리 사용되는 커스텀태그의 일종이라고 볼 수 있는것이다.

 


커스텀 태그의 역할 및 기능은 다음과 같다.

  • 로직을 캡슐화 할 수 있게 된다. 즉, 화면(view)으로부터 로직을 분리할 수 있으므로 view를 view답게 할 수 있다.
  • MVC분리가 발생하면서, 유지보수가 용이해진다.
  • 로그인/로그아웃 | 회원/비회원 | 댓글, 대댓글의 체크 로직이 들어간 공간에 많이 사용된다.
  • 로직을 분리할 수 있기는 하나 필수는 아니다. view 작업자가 로직을 충분히 사용할 수 있다면 굳이 사용되지 않는다.

 

html은 브라우저에 의해 해석이 되므로 커스텀 태그가 사용이 어렵지만, jsp파일은 해석(컴파일)-> 서블릿 형태로 진행된다. 즉 html과 다르게 브라우저로 전달되기 전, 서블릿컨테이너(톰캣)에서 먼저 해석되기 때문에 커스텀 태그를 사용할 수 있게 된다.

 


 

2) 태그의 구조와 taglib지시어

 

① 태그의 구조

태그는 태그명, 태그바디, 속성으로 구성되어있다. 이때 속성은 필수가 아닌 선택 구성요소이다.

 

<h1 style="color: pink">안녕?</h1>

예시가 위와 같다고 했을때, 
h1은 태그명, "안녕?"은 태그 바디, style은 속성으로 각각 해당된다.

 


② taglib지시어

태그라이브러리 지시어는 일반적으로 아래와 같이 사용되는 경우가 많다.

<%@ taglib prefix="" uri="" %>

 

prefix는 커스텀태그를 불러오기 위한 속성이다. 이 속성으로 인해 커스텀 태그의 속성 생성시 중복에 대해 신경쓰지 않아도 된다.

 

uri는 커스텀 태그에 대한 설정파일의 위치를 기술하는 속성이다.

 


 

3) 커스텀 태그 사용 방법

 

태그파일 기반으로 개발하는 방법과 태그 핸들러 클래스 기반으로 개발하는 방법, 총 두가지로 구분된다.

 

구분 특징
태그파일기반 1) 상대적으로 간단한 로직, 기능으로 구성되어있다.
2) 단일 프로젝트에서 사용할때 사용된다.
태그핸들러클래스 기반 1) 여러개의 프로젝트에서 사용할때(재사용)
2) 배포, 공개하여 사용할 목적이다.
3) 상대적으로 복잡하고 어려운 로직과 기능으로
   구성되어있다.

 

taglib지시어를 사용할때,

파일 기반의 경우에는 uri대신 tagdir 속성으로 파일의 위치를 기술한다.

 

 

즉, 핸들러클래스기반의 커스텀 태그나 JSTL같은 경우는 파일의 위치를 uri로 기술하고, 파일기반의 커스텀태그는 파일의 위치를 tagdir속성으로 기술한다는 의미이다.

 

 

 


 

2. 태그 파일 기반 방법

 

1) 사용 방법

 

① tag파일 생성

WEB-INF파일 내에 tag파일을 모아둘 폴더를 먼저 생성한 후, 그 폴더 내부에 tag파일을 생성하는 방식으로 진행된다.

 

NEW에서 검색을 통해 쉽게 찾을 수 있다.

 

 

파일 생성 경로

 


 

② taglib지시어 선언

JSTP과 마찬가지로, 커스텀태그를 사용할 jsp페이지에는 taglib지시어가 반드시 선언되어야한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="ham" tagdir="/WEB-INF/tags"%>

tagdir에 입력된 경로에 있는 tag파일을 prefix에 입력된 이름으로 불러올 수 있게 된다. 폴더의 이름까지만 기재한다.

 


 

③ body-content속성

tag파일을 처음 생성하면 최상단에 페이지지시어로  아래와같은 기본 설정만 진행되어있다.

<%@ tag language="java" pageEncoding="UTF-8"%> //body-content="scriptless"가 디폴트

 

이때, body-content속성을 통해 태그바디의 사용에 대해 정의를 내릴 수 있게 된다. 

속성값은 아래에 정리된 바와 같다.

 

속성값 내용
scriptless 태그바디를 쓸 수 있다.
ex) <태그명>태그바디</태그명>
empty 태그바디를 쓸 수 없다.
ex) <태그명/>
tagdependent 다른 태그바디가 들어올 수 있다.
ex) <태그명><다른태그/></태그명>

 

 


 

현재까지 내용의 사용 예시는 다음과 같다.

 

test.tag

<%@ tag language="java" pageEncoding="UTF-8" body-content="empty"%>

태그파일 기반 커스텀 태그

NewFile.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="ham" tagdir="/WEB-INF/tags"%>    
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1><ham:test/></h1>

</body>
</html>

출력화면

 

 

아래로는 tag파일로 java파일의 내용을 불러오는 것, 커스텀 태그에 속성을 부여하는 것, 커스텀태그의 태그바디 내용을  tag파일로 가져오는 것에 대한 내용이 정리되어있다.

 


④ attribute

attribute를 활용하여 커스텀태그에 속성을 부여할 수 있다.

<%@ attribute name="" %> name에 입력한 이름으로 속성을 불러낼 수 있게 된다.

 

사용 예시는 다음과 같다.

 

tag파일

<%@ tag language="java" pageEncoding="UTF-8"%>

<%@ attribute name="border" %>
<%@ attribute name="bgcolor" %>

<!-- java파일의 변수에 접근, 그 변수를 id라고 부를 것. -->
<!-- test패키지에 Test라는 이름으로 저장된 class는 String배열을 가지고 있다. -->
<jsp:useBean id="datas" class="test.Test"/>

<table border="${border}" bgcolor="${bgcolor}">
	<%
		for(String v: datas.getDatas()){
			out.println("<tr><td>"+v+"</td></tr>");
		}
	%>
</table>

jsp파일

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="ham" tagdir="/WEB-INF/tags"%>    
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<ham:data border="2" bgcolor="lightblue">상품목록</ham:data>

</body>
</html>

 

출력화면

 


 

 

⑤ doBody

이 태그를 활용하여 jsp파일의 태그바디의 내용을 tag파일로 불러올 수 있다. 자세한 내용은 아래 예시를 통해 확인할 수 있다.

tag파일의 아래의 문장 선언
<h1><jsp:doBody/></h1>

jsp파일의 상황 : 불필요한 부분 생략
<%@ taglib prefix="ham" tagdir="/WEB-INF/tags"%>    
<ham:data border="2" bgcolor="lightblue">상품목록</ham:data>

즉, 커스텀태그바디 내부의 "상품 목록"이 <h1>태그바디에 감싸진 것과 동일하다

 

 

 


 

2) 예제

print라는 커스텀태그바디에 글을 작성하면 <h1>사이즈로 출력되며, 또한 CSS속성을 적용할 수 있도록 할 것

 

print.tag

<%@ tag language="java" pageEncoding="UTF-8"%>

<%@ attribute name="st" %>

<h1 style="${st}"><jsp:doBody/></h1>
<!-- 내 커스텀 태그에서 앞으로 style속성을 줄 수 있는 명령어는 앞으로 st라고 부를거야 -->

<!-- style="background-color: ${st}" -->
<!-- 내 커스텀 태그에서 앞으로 style속성 중 배경색을 줄 수 있는 명령어는 앞으로 st라고 부를거야 -->

 

NewFile.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="ham" tagdir="/WEB-INF/tags"%>    
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<ham:print st="background-color: blue; color: white;">뭐야</ham:print>

</body>
</html>

 

출력화면

 

 


 

3. 태그 핸들러 클래스 기반 방법

*핸들러클래스(.java)와 태그라이브러리기술자(.xml)을 가져야한다*

 

 

1) 핸들러클래스 생성

일반 클래스를 생성하고, SimpleTagSupport를 상속하여 핸들러클래스로 전환할 수 있다. 파일의 경로는 아래와 같다.

 

주석을 통해 내용의 파악이 가능하다.

package test;

import java.io.IOException;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class TestHandler extends SimpleTagSupport{
	
	//태그의 시작부분을 만나면 호출되는 메서드를 오버라이딩!
	public void doTag() throws IOException {
		//out내장객체 사용을 위한 선언
		JspWriter out=getJspContext().getOut();
		out.println("태그 핸들러 클래스 기반 커스텀 태그");
	}
}

 


 

2) 태그라이브러리기술자 생성

우선 xml파일을 생성해야하는데 아래와 같은 순서로 진행된다.

 

 

1. WEB-INF폴더 하위에 tld폴더를 생성한다

 

 

2. xml파일을 생성한다

 

※이때 finish를 누르지 않고 next버튼으로 단계별 진행을 거쳐야한다※

 

 

3. 파일 생성시 확장자를 .tld로 기술하는 것이 좋다

 

4. Create file using a DTD or XML Schema file을 선택한다.

 

 

5. Select XML Catalog entry를 선택한 후 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0xsd를 를 클릭한다

 

 

6. 형광펜 표시된 부분이 <no prefix>로 표시되도록 한다.

 

 

7. 탭을 source로 클릭한다

 

 

 


 

3) 실습

 

① 기본실습

 

TestHandler.java

package test;

import java.io.IOException;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class TestHandler extends SimpleTagSupport{
	
	//태그의 시작부분을 만나면 호출되는 메서드를 오버라이딩!
	public void doTag() throws IOException {
		//out내장객체 사용을 위한 선언
		JspWriter out=getJspContext().getOut();
		out.println("태그 핸들러 클래스 기반 커스텀 태그");
	}
}

 

TestHandler.tld

태그 관련 내용 정의

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" 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/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd ">

	<tlib-version>1.0</tlib-version> <!-- 이거 필수야! 없으면 500에러 뜬당 -->
	
	<tag>
		<name>test</name> <!-- 얘를 뭐라고 부를거야? -->
		<tag-class>test.TestHandler</tag-class><!-- 어떤 핸들러클래스랑 연결할거야? -->
		<body-content>empty</body-content><!-- 바디 컨텐츠는 어떻게 할거야? -->
	</tag>

</taglib>

 

NewFile1.jsp

taglib지시어의 속성 중 uri를 활용하여 tld파일의 경로를 기입한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="mytag" uri="/WEB-INF/tld/TestHandler.tld" %>    

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1><mytag:test/></h1>

</body>
</html>

 

 


② 자바파일 불러오기 및 속성적용 실습

 

Test2Handler.java

JspFragment body=getJspBody();로 커스텀태그바디의 내용을 가져오고,

body.invoke(null);로 그 내용을 화면(브라우저)에 띄울 수 있다.

Test test = new Test();는 jsp:useBean에 해당되는 내용이다.

package test;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class Test2Handler extends SimpleTagSupport{
	
	//1. 태그에게 속성을 부여
	private String border;
	private String bgcolor;
	
	public String getBorder() {
		return border;
	}
	public String getBgcolor() {
		return bgcolor;
	}
	public void setBorder(String border) {
		this.border = border;
	}
	public void setBgcolor(String bgcolor) {
		this.bgcolor = bgcolor;
	}
	
	//2. 태그의 시작부분을 만나면 호출되는 메서드, 이때 태그 바디는 있도록 한다.
	//멤버변수를 활용하여 속성을 주고 있다
	public void doTag() throws IOException, JspException {
		//out내장객체 사용을 위한 선언
		JspWriter out=getJspContext().getOut();
		
		JspFragment body=getJspBody();//태그바디를 가져오는 부분
		
		// ※ 바디를 가져오라고 했는데, 만약 바디의 내용없이 닫았다? <h1/> 널포인트익셉션뜸 ※
		// 방지하기위한 if문!
		if(body!=null) {			
			out.println("<h1>");
			body.invoke(null);//화면(브라우저)에 태그바디내용을 작성하는 코드!
			out.println("</h1>");
		}
		
		out.println("<table border="+border+" bgcolor="+bgcolor+">");//어트리뷰트부분
		
		Test test = new Test();//useBean부분
		
		for(String v:test.getDatas()) {
			out.println("<tr><td>"+v+"</td></tr>");
		}
		out.println("</table>");
	}
}

 

Test2Handler.tld

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" 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/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd ">
  <tlib-version>1.0</tlib-version>
  
	<tag>
		<name>test2</name>
		<tag-class>test.Test2Handler</tag-class>
		<body-content>scriptless</body-content>
		
        <!-- 속성이름과 필수여부를 구분 -->
		<attribute>
			<name>border</name><!-- 속성이름 -->
			<required>true</required><!-- 필수여부 -->
		</attribute>
		<attribute>
			<name>bgcolor</name><!-- 속성이름 -->
			<required>true</required><!-- 필수여부 -->
		</attribute>
	
	</tag>

</taglib>

 

NewFile1.jsp

uri로 파일의 위치를 정확히 알려주어야하기때문에 정확하게 작성한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="mytag2" uri="/WEB-INF/tld/Test2Handler.tld" %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<mytag2:test2 bgcolor="pink" border="2">테이블</mytag2:test2>

</body>
</html>

 

출력화면

 

 


 

 

4. 커스텀 태그를 활용한 로그인 로직 분리

이전포스팅에서 다루었던 파일을 그대로 사용하였다. tag파일에서도 JSTL과 EL을 사용할 수 있으며, 좌측에서의 로직을 그대로 가져와 tag파일에 붙여넣고, 좌측에서 커스텀태그를 호출하는 것 만으로 우측의 로직 전부가 수행될 수 있다.

이때 우측 tag파일의 body-content는 "empty"로 설정되어 태그바디가 없도록 하였다.

 

 

 


 

반응형