액션 태그
액션(Action) 태그란 JSP에서 객체 생성과 공유, 페이지 이동과 전달, 태그 파일 작성 등에 필요한 기능을 제공하는 일종의 커스컴 태그다. 표준 액션이라고도 불리며 커스텀 태그 기반이지만 별도의 taglib 지시어 사용 없이 jsp 접두어를 사용한다.
액션 태그는 JSP에서 프로그램적인 요소를 많이 구현하거나 컨트롤러로 활용할 때 유용하다. 이러한 기능은 기본적으로 서블릿에서도 가능하지만 개발자가 직접 코드를 구현하여 처리해야 한다. 반면 액션 태그는 JSP 파일에서 커스텀 태그의 구조적인 특징을 살려 HTML 형태로 프로그램 요소를 처리할 수 있기 때문에 간편하다는 장점이 있다.
요즘과 같이 JSP의 역할이 축소된 상황에서는 액션 태그의 실무 활용이 권장되지 않는다. 그럼에도 아래 내용 정도는 알아두는 것이 좋다. 다음 표는 주로 사용되는 액션 태그를 보여준다.
주요 액션 태그
액션 태그 | 설명 |
jsp:forward | request와 reponse 객체를 포함해 다른 페이지로 포워드함 |
jsp:include | 다른 페이지의 실행 결과를 포함시킴 |
jsp:useBean | 자바 빈즈 객체를 생성하거나 불러옴 |
jsp:setProperty | 자바 빈즈 객체의 속성(멤버 변수)에 값을 할당함 |
jsp:getProperty | 자바 빈즈 객체의 속성값을 출력함 |
jsp:param | include, forward 액션 사용 시 파라미터 값을 수정하거나 추가함 |
자바 빈
객체지향 프로그래밍의 핵심 콘셉트는 컴포넌트 모델로, 프로그램 모듈화를 위해 컴포넌트를 사용한다. 따라서 컨테이너 기반으로 운영되는 시스템에서는 여러 객체를 활용하기 위하여 단순 하면서도 정형화된 구조를 통해 동일한 방식으로 객체를 다루는 방법을 제공할 수 있어야 한다.
자바 빈(Java Bean)은 자바의 재활용 가능한 컴포넌트 모델을 말하는 것으로, 웹 개발에만 국한된 개념이 아니며 POJO라고 하는 단순한 구조를 가진다. POJO(Plain Old Java Object)란 특정 기술이나 프레임워크에 종속하지 않고 기본 생성자와 멤버 변수에 대한 getter/setter 메서드를 제공하고 직렬화할 수 있는 자바 클래스를 의미한다.
예를 들어 데이터베이스의 테이블 구조와 연동되어 데이터를 표현하기 위한 클래스를 엔티티 클래스 혹은 DO(Data Object)라고 하는데 기본적으로 테이블 칼럼에 해당하는 private 멤버 변수와 getter/setter 메서드로 구성할 수 있다.
자바 빈 구조의 특징
- 인자가 없는 생성자(기본 생성자)로 구성된다.
- 파일 혹은 네트워크를 통해 객체를 주고받을 수 있는 직렬화 구조가 가능하다.
- getter, setter 메서드를 통해 멤버 변수(속성)에 접근한다.
Java 직렬화(Serialization) : 자바 시스템 내부에서 사용되는 Object 또는 Data를 외부의 자바 시스템에서도 사용할 수 있도록 byte 형태로 데이터를 변환하는 기술
자바 빈 클래스
다음은 회원 관리를 위한 Member 클래스를 자바 빈 구조로 만든 것이다.
class Member { // 클래스 선언
private int id;
private String name;
private String email;
...
public void setId(int id) { // setter 메서드 선언
this.id = id
}
public int getId() { // getter 메서드 선언
return id;
}
...
}
getter/setter 메서드의 이름은 'get/set + 대문자로 시작되는 변수명'의 형태를 사용한다. 기본적으로 인자를 받아 현재 멤버 변수에 값을 대입하거나 현재 값을 리턴하는 구조다. 물론 메서드 내에서 추가적으로 필요한 기능을 구현할 수 있으며 이러한 구조는 객체지향에서 캡슐화의 한 형태이기도 하다.
예를 들어 쇼핑몰 회사가 있고 쇼핑몰 회사에 결제 시스템을 제공하는 회사가 있다고 할때 주문 상품의 '최종 결제 금액'은 '일반 가격'에서 회원 등급에 따른 할인'을 적용해야 하는 경우도 있고 내부적으로 '포인트'를 적립하는 과정이 있을 수도 있다. 이때 '회원 등급별 할인 조건' 또는 '내부 포인트 적립' 구조 등을 결제 회사에 알려줄 필요 없이 setTotalPrice() 메서드와 같은 최종 결제 금액 메서드만 호출하도록 제공할 수 있는 것이다. 즉 setTotalPrice() 메서드 안에서 회원 등급 관련 부분 혹은 포인트 관련 부분을 처리하면 관련 정보를 외부에 노출하지 않아도 된다.
스프링 빈
스프링 프레임워크의 경우에도 컨테이너 기반으로 객체의 생성과 소멸 등을 관리하게 되는데 이러한 객체를 스프링 빈(Spring Bean)이라고 한다. 이러한 객체는 컨테이너를 통해 공유하거나 참조할 수 있다.
useBean 액션
JSP에서 자바 빈 객체를 생성하거나 참조하기 위한 액션이다. 매우 유용하지만 JSP를 단순히 뷰 역할로만 사용한다면 사용할 일이 없다.
기본적인 동작 방식
- useBean을 이용해 만든 객체의 범위는 지정하는 속성인 scope에 주어진 id의 객체가 있는지 확인한다.
- 객체가 없다면 새로 객체를 생성하고 해당 scope에 저장한다.
기본 구문과 사용 예
<jsp:useBean id="instanceName" scope="page | request | session | application"
class="packageName.className" type="packageName.className"
beanName="packageName.className" >
</jsp:useBean>
- id: 자바 빈을 특정 scope에 저장하거나 가져올 때 사용하는 이름이며, 현재 페이지에서는 해당 인스턴스를 참조하기 위한 변수명이 된다.
- scope: 해당 클래스 타입의 객체를 저장하거나 가지고 오는 범위로 내장객체의 일부다.
- class: 생성하거나 참조하려는 객체의 클래스명이며 반드시 패키지명까지 명시해야 한다. 추상 클래스나 인터페이스는 사용할 수 없다.
- type: 특정 타입의 클래스를 명시할 때 사용한다. 추상 클래스나 인터페이스, 일반 클래스가 될 수 있으며 class 속성의 클래스에서 상속 혹은 구현이 이루어져야 한다.
- beabName: type과 beabName 사용을 통해 class 속성을 대체할 수 있다.
scope는 서블릿의 scope object와 동일하며 현재 JSP 페이지를 참조하는 page가 추가되어 있다. 클래스 타입도 동일하고 생성 시점과 유효 범위, 제공 메서드 등도 모두 같다.
useBean의 활용
HTML 폼에서 입력한 값을 자바 객체로 연동할 때 useBean을 주로 활용한다. 예를 들어 회원 가입 페이지에서 아이디, 이름, 전화번호, 주소 등 여러 정보를 입력하고 가입하는 경우에 입력값을 받아 Member 객체에 넣고 이를 데이터베이스에 저장하기 위한 메서드 호출에 인자로 전달해야 한다.
이때 useBean 액션을 사용하면 다음 코드와 같이 간단한 처리가 가능하다.
<jsp:useBean id="m" class="com.my.Member" />
<jsp:setProperty name="m" property="*" />
<%
MemberDAO dao = new MemberDAO();
dao.insertDB(m);
%>
- page scope로 새로운 Member 클래스 인스턴스를 생성한 후 m이라는 이름으로 속성에 저장한다.
- setProperty는 HTML <form> 태그의 name 속성값을 해당 객체의 setter 메서드를 이용해 저장한다.
- property 속성에는 멤버 변수명 혹은 *을 사용해 전체 변수를 한 번에 지정할 수 있다.
서블릿으로 처리하기
물론 서블릿으로 회원 가입 처리를 구현할 수 있다. 하지만 모든 값을 개발자가 직접 읽어와 객체에 할당해야 하기 때문에 불편하다. 서블릿 코드로 위 코드 내용을 구현하면 다음과 같다.
doGet(...) {
Member m = new Member();
m.setId("testuser");
m.setName("테스트 사용자");
m.setEmail("test@test.com");
...
dao.insertDB(m);
}
이와 같이 불편한 부분은 Apache Commons BeanUtils 라이브러리로 해결이 가능하다. 서블릿에서 BeanUtils를 사용한 코드는 다음과 같다.
doGet(...) {
Member m = new Member();
BeanUtils.populate(m, request, getParameterMap());
...
dao.insertDB(m);
}
include, forward 액션
include, forward 액션은 다른 JSP 파일을 현재 페이지에 포함하거나 전달하는 액션이다. 단순히 페이지를 포함하거나 이동하는 기능 외에 <jsp:param> 액션을 통해 파라미터값을 수정하거나 추가하는 것이 가능하다는 특징이 있다.
include 액션
include 액션은 include 지시어와 마찬가지로 다른 페이지를 포함한다는 점에서 동일하지만 처리 과정에서 차이가 있다. include 지시어에서는 include된 파일 구조를 모두 포함해 하나의 파일로 컴파일한 다음 처리했다. 반면 include 액션은 include된 파일을 각각 호출해 처리된 결과만 포함해 보여주는 형식이다.
만약 'main.jsp'에서 'header.jsp'를 포함한다고 할 때 include 지시어는 두 파일을 합쳐 'main_jsp.java'로 만든 다음 서블릿 형태로 등록한다. 하지만 include 액션의 경우 'main_jsp.java'와 'header_jsp.java'의 파일을 각각 컴파일하고 서블릿 형태로 등록하게 된다.
다음 예제 코드는 include 액션을 사용하여 'main.jsp'에 'header.jsp'를 포함시킨 경우로, 'main.jsp'를 호출하면 'header.jsp'의 실행 결과가 포함되어 출력된다.
// main.jsp
<jsp:include page='header.jsp'>
<jsp:param name="title" value="My Homepage" />
</jsp:include>
// header.jsp
<h2><%= request.getParameter("title") %></h2>
- 'main.jsp'에서 'header.jsp'를 include할 때 <jsp:param>에서 title을 통해 My Homepage라는 값을 전달한다. 그리고 'header.jsp'는 <h2> 부분에서 전달받은 제목을 출력하는 형태가 된다.
내부적인 과정이지만 'main.jsp'에서 'header.jsp'를 호출할 때의 URL 구조는 header.jsp?title=My Homepage와 같다.
forward 액션
forward 액션은 클라이언트 요청을 다른 페이지로 전환하는 액션으로 리디렉션(response.sendRedirect())과 기능적으로 유사하다. 클라이언트 요청과 다른 새로운 페이지로(혹은 서블릿)로 이동하는 점은 두 방법이 동일하다고 할 수 있지만 내부적으로는 차이가 있다.
리디렉션은 서버가 클라이언트에게 새로운 페이지로 다시 접속하도록 응답을 보내고, 응답을 받은 클라이언트가 다시 새로운 페이지로 접속하는 방식이다. 하지만 forward 액션은 클라이언트가 새롭게 접속하는 것이 아니라 서버에서 내부적으로 새로운 페이지로 이동하고 그 페이지의 내용을 클라이언트에게 응답으로 전달한다.
단순한 페이지 이동이 필요한 경우라면 리디렉션이 적합하다. 하지만 최초 request를 유지하거나 request의 setAttribute()로 속성값을 저장한 경우에 이를 유지하면서 페이지를 이동하려면 forward 액션을 사용해야 한다. include 액션과 마찬가지로 파라미터의 추가가 가능하다.
// main.jsp
<jsp:forward page='result.jsp'>
<jsp:param name="title" value="My Homepage" />
</jsp:forward>
// result.jsp
<h2><%= request.getParameter("title") %></h2>
JSP를 뷰로 사용하는 경우 forward 액션을 사용할 일은 없으며 주로 서블릿 컨트롤러에서 request.getRequestDispatcher("서블릿 혹은 jsp 경로").forward()와 같이 사용하게 된다.
'Programming > Web' 카테고리의 다른 글
[Web] JSTL(JSP Standard Tag Library) (0) | 2022.10.22 |
---|---|
[Web] 커스텀 태그와 EL (0) | 2022.10.22 |
[Web] 템플릿 데이터와 스크립트 요소(<%! %>, <%= %>, <% %>) (0) | 2022.10.20 |
[Web] JSP의 개요(JSP의 장단점, page지시어, include지시어, taglib지시어) (0) | 2022.10.20 |
[Web] 페이지 이동과 정보 공유(Cookie, Session, Scope Object) (0) | 2022.10.20 |