Struts Framework

2008. 4. 22. 21:20Software Development/OSGi & Eclipse

STRUTS Framework

[개발 이슈]

■ Time to Market에 맞춘 신속한 개발
■ 개발 중에도 변화하는 요구 사항을 만족
■ 개발 비용의 절감
■ 개발 후 관리 비용의 절감 및 관리의 용이
■ 서비스 및 시스템의 운영 시간 증대
■ 견고한 시스템의 개발
■ 향후, 다른 서비스 개발에 활용 가능한 개발
■ 새로운 기술의 적용

[STRUTS Framework 기본 방향]

1. 단순

- 코드의 중복 및 복잡성을 제거함으로써 심플한 코드의 개발을 가능하게 한다.
- 프레임워크가 가진 설계 구조와 의도가 자연스럽게 적용되어, 아키텍처를 따르는 좋은 설계를 유지하도록 돕는다.

2. 품질

- 프레임워크의 설계 원칙에 충실해야 한다. (디자인 품질)
- 이해하기 쉽고 코드를 분석할 수 있어야 한다. (코드 품질)
- 안정적인 성능을 제공해야 한다. (프레임워크 품질)

3. 확장성

- 기능별 프레임워크의 확장 기능을 활용해서 커스터마이징 할 수 있어야 한다.
- 프레임워크나 기술에 어느 정도 종속적인가를 파악 후 유연한 구조를 제공받을 수 있어야 한다.

4. 생산성

- 단순성을 바탕으로 생산성을 보장해야 한다.
- 파트간 협업이 쉽도록 하여 생산성을 보장해야 한다.(UI, 비즈니스, 퍼시스턴스 계층 분리)

[What is Struts?]

1. Craig McClanahan에 의해 개발
2. Apache Software Foundation Project
3. 오픈 소스 웹 애플리케이션 프레임워크
   - XML 기반의 컨트롤러 서블릿.
   - End-to-End J2EE 어플리케이션 프레임워크 아님.
4. MVC 패턴 기반
5. 타 프레임워크와 연동 가능
   - Velocity, iBatis, Hibernate, XSLT, Spring, Expresso, ADF ….
6. 웹 애플리케이션 개발 시 Common problems 해결
   - common infrastructure service 제공
7. 중, 대형 규모의 웹 애플리케이션 개발에 적합.

[MVC (Model-View-Controller)]

1. 변경. MVC는 변경을 관리하는 디자인 패턴이다.
2. 비즈니스 로직 및 데이터와 인터페이스를 분리한다.
3. 다음 세 가지 범주로 나누어서 싱글 모듈 방식으로 문제를 해결한다.
   모델(Model)
   모델에는 애플리케이션 기능의 핵심이 포함된다. 이 모델은 애플리케이션의 상태를 캡슐화 한다.
   모델(model)은 뷰나 컨트롤러를 볼 수 없다.
   뷰(View)
   뷰는 모델의 표현이라고 할 수 있다. 애플리케이션의 외양이다. 뷰는 모델 게터(getter)에 액세스 할 수 있지만
   세터(setter)에 대해서는 모른다. 컨트롤러를 볼 수 없다. 뷰는 모델이 변경될 때 공지를 받는다.
   컨트롤러(Controller)
   컨트롤러는 사용자 인풋에 반응을 한다. 모델을 구현하여 설정한다.

[모델1 개발 방식]

1. 싱글 페이지 방식을 사용한 결과

   ■ 무거운 HTML-자바 커플링(coupling)
   JSP 파일을 코딩하는 사람은 페이지 디자이너와 자바 개발자여야 한다. 그렇지 않을 경우 끔찍한 자바 코드가 되거나 엉망이 된 페이지가 나올 수 있다.

   ■ 자바와 JavaScript 오염

   페이지가 커지면서 몇 개의 JavaScript를 구현하게 된다. JavaScript가 페이지에 나타나면 이 스크립트는 자바 코드와 혼돈이 된다. 대표적인 예로 클라이언트측 JavaScript를 사용하여 email 필드를 검사하는 경우이다.

   ■ 삽입된 플로우 로직

   이 애플리케이션의 전체 흐름을 이해하려면 모든 페이지를 봐야 한다. 100 페이지나 되는 웹 사이트의 스파게티 로직(spaghetti logic)을 상상해 보라.

   ■ 디버깅 문제점

   HTML 태그, 자바 코드, JavaScript 코드가 모두 한 페이지에 있으면 디버깅 하기도 어렵다.

   ■ 강결합

   비즈니스 로직 또는 데이터를 변경하려면 여기에 개입된 모든 페이지를 다 변경해야 한다는 의미가 된다.

   ■ 미학

   시각적으로 큰 페이지에서 이런 식의 코딩은 난잡해보인다. Microsoft ASP를 개발 할 때 1000 라인 페이지를 늘상 보았다. 심지어 신택스 컬러링(syntax coloring)으로도 읽고 이해하기 힘들었다.


[모델2 개발 방식]

- 장점 : 유지보수 비용이 적다, JSP 소트코드와 디자인의 분리.
- 단점 : 배우기 어렵다, 개발속도가 모델1에 비해 느리다.
- 적용범례 : 장기개발, 적정한 개발 인력, 변경의 유동성.

[Struts 프레임워크]

서블릿과 JSP를 사용하는 Model-View-Controller 구현인 Struts를 소개한다.
Struts로 웹 프로젝트의 변경을 관리한다.
Struts로 시스템을 구현하지 않더라도 Struts를 이해한다면 서블릿과 JSP 구현에 많은 도움을 받을 수 있다.

1. 재사용 성이 부족했던 많은 부분들을 재사용이 가능하게 미리 만들어 놓은 프레임워크.
2. JSP와 Action 클래스 사이의 매핑을 소스가 아닌 XML을 이용하며 새로운 Action 클래스가 추가될 경우, 소스의 수정 없이 XML 파일에 JSP와 Action 클래스를 매핑해준다.
3. Command (ActionServlet)와 Model (Action & ActionForm)의 관계


■ ActionServlet 클래스

Struts Controller는 이벤트를 클래스에 매핑하는 서블릿이다. 그리고 컨트롤러는 설정 파일을 사용하기 때문에 값을 코딩 할 필요가 없다. 삶은 변했지만 상황은 똑같다.
ActionServlet은 MVC 구현의 Command 부분이고 Framework의 핵심이다. ActionServlet (Command)은 Action, ActionForm ,ActionForward를 만들어서 사용한다. struts-config.xml 파일은 Command를 설정한다. 웹 프로젝트를 만드는 동안 Action과 ActionForm은 특정 문제 공간을 해결하기 위해 확장된다. struts-config.xml 파일은  ActionServlet에게 확장 클래스를 사용하는 방법에 대해 알려준다. 이 방식은 여러 가지 장점이 있다.

   1) 이 애플리케이션의 전체적인 논리적 흐름은 계층적 텍스트 파일에 존재한다.
      큰 애플리케이션의 경우 보고 이해하기가 더 쉽다.
   2) 페이지 디자이너는 애플리케이션의 흐름을 이해하기 위해 자바 코드를 모두 다 볼 필요가 없다.
   3) 자바 개발자는 흐름을 변경할 때 코드를 재 컴파일 하지 않아도 된다.

명령어 기능은 ActionServlet를 확장하여 추가할 수 있다.

#요약#

 1. 모든 Http 요청을 받아서 해당 Module의 RequestProcessor에게 전달.
 2. Configuration XML을 통해서 메타 데이터 Lookup.(web.xml, struts-config.xml, validation.xml …)

■ RequestProcessor

- 하나의 애플리케이션 모듈당 하나의  인스턴스 생성됨.
- Locale과 Content Type 처리.
- 자동으로 Rquest 파라미터로 Java Beans(Form class)를 populate함.
- URI에 해당하는 Action class 실행.

■ ActionForm 클래스

ActionForm은 웹 애플리케이션의 세션 상태를 관리한다. ActionForm은 각각의 인풋 형식 모델에 대해 하위 클래스로
분류된 추상 클래스이다. 내가 인풋 형식 모델(input form model)을 언급한다면 ActionForm이 HTML 형식에 의해 설정 및 업데이트 되는 일반적인 데이터 개념을 나타내는 것을 의미한다. 예를 들어, HTML 형식에 의해 설정 UserActionForm을 가질 수 있다.

   1) Struts는 UserActionForm의 존재 여부를 확인한다. 없을 경우, 이 클래스의 인스턴스를 만든다.
   2) Struts는 HttpServletRequest의 상응하는 필드를 사용하여 UserActionForm의 상태를 설정한다.
      request.getParameter()호출이 더 이상 필요 없다. 예를 들어, Struts 프레임웍은 요청 스트림에서 fname을
      취해서 UserActionForm.setFname()을 호출한다.
   3) Struts 프레임웍은 UserAction으로 전달하기 전에 UserActionForm의 상태를 업데이트 한다.
   4) Action 클래스로 전달하기 전에 Struts는 UserActionForm에 validation() 메소드를 호출하여 상태 밸리데이션을 수행한다.
      주의: 이 방법이 언제나 옳은 것은 아니다. 다른 페이지나 비즈니스 객체에서 UserActionForm을 사용하는 방법도 있다. 이때 밸리데이션은 달라진다. 상태에 대한 밸리데이션은 UserAction 보다 낫다.
   5) UserActionForm은 세션 레벨에서 관리될 수 있다.

■ Action 클래스

Action 클래스는 비즈니스 로직 주위에 있는 래퍼이다. Action 클래스의 목적은 HttpServletRequest를 비즈니스 로직으로 변환하는 것이다. Action을 사용하려면 process() 메소드를 하위 클래스로 분류하여 process() 메소드를 겹쳐 쓴다.
ActionServlet(Command)은 매개변수화 된 클래스들을 perform() 메소드를 사용하여 ActionForm으로 전달한다. 더 이상 request.getParameter() 호출은 없다. 이벤트가 여기에 올 때 까지 인풋 형식 데이터(HTML 형식 데이터)는 요청 스트림 밖에서 이미 변환되어 ActionForm 클래스로 들어간다.

#요약#

 1. 프리젠테이션과 비즈니스 티어 간의 bridge 역할 수행.
 2. 애플리케이션 당 하나의 인스턴스.
 3. org.apache.struts.action.Action 클래스 상속하고 execute 메소드를 구현.
 4. 처리 결과에 따른 Page Flow 기능 수행.(ActionForward 리턴)

■ ‘Pre-Built’Action 클래스

ForwardAction, DispatchAction, LookupDispathcAction, IncludeAction, SwitchAction

■ Action 클래스 다이어그램

■ Action 시퀀스 다이어그램

[Struts MVC 구현]

Struts는 협업 클래스이자, 서블릿이며, 재사용 가능한 MVC투 디자인을 구성하는 JSP 태그이다.
이 정의에는 다음과 같은 뜻이 내포된다. Struts는 라이브러리가 아닌 프레임워크이지만, Struts에는 확장 태그
라이브러리와 프레임워크와 독립적으로 작동하는 유틸리티 클래스도 포함되어 있다.

■ Struts 개요

   1) 클라이언트 브라우저(Client browser)
      클라이언트 브라우저에서 온 HTTP 요청은 이벤트를 만든다. 웹 컨테이너는 HTTP 응답을 보낸다.
   2) 컨트롤러(Controller)
      컨트롤러는 브라우저에서 요청을 받아서, 그 요청을 어디로 보낼지를 결정한다. 컨트롤러는 서블릿으로서 구현된 명령어 디자인 패턴이다. struts-config.xml 파일은 컨트롤러를 설정한다.
   3) 비즈니스 로직(Business logic)
      비즈니스 로직은 모델의 상태를 업데이트하고 애플리케이션의 흐름을 제어한다. 이 작동은 실제 비즈니스 로직에 대한 씬(thin) 래퍼로서 Action 클래스로 수행된다.
   4) 모델 상태(Model state)
      모델은 애플리케이션의 상태를 보여준다. 비즈니스 객체들은 애플리케이션 상태를 업데이트 한다. ActionForm 빈은 세션 또는 요청 레벨에 모델의 상태를 나타낸다. JSP 파일은 JSP 태그를 사용하여 ActionForm 빈에서 온 정보를 읽는다.
   5) 뷰(View)
      뷰는 JSP 파일이다. 흐름 로직, 비즈니스 로직, 모델 정보가 전혀 없는 그저 태그일 뿐이다. 바로 이 태그가
      Struts를 다른 프레임워크와 차별되는 요소이다.

주: Action 클래스는 애플리케이션의 로직이 아닌 흐름을 제어해야 한다. 개별 패키지나 EJB에 비즈니스 로직을 배치함으로서 유연성과 재사용성의 혜택을 누릴 수 있다.

Action 클래스를 Adapter 디자인 패턴으로서 생각할 수 있다. Action의 목적은 "클래스의 인터페이스를 클라이언트가 기대하는 또 따른 인터페이스로 변환하는 것이다. 어댑터는 클래스가 함께 작동할 수 있도록 한다." (Design Patterns - Elements of Reusable OO Software (Gof) 발췌).
이 경우 클라이언트는 특정 비즈니스 인터페이스에 대해 모르는 ActionServlet이다. 따라서 Struts는 자신이 이해하는 비즈니스 인터페이스인 Action을 제공한다. Action을 확장함으로써 비즈니스 인터페이스가 Struts 비즈니스 인터페이스와 호환되도록 한다. (Action은 인터페이스가 아니라 클래스이다. Action은 인터페이스로 시작하여 시간이 지나면서 클래스로 변한다. 어떤 것도 완전한 것은 없다.)

■ Error 클래스
ActionError는 개별 에러 메시지를 캡슐화 한다. ActionErrors는 ActionError 클래스의 컨테이너이며 View가 태그를 사용하여 액세스 할 수 있다.

■ ActionMapping 클래스
인커밍 이벤트는 일반적으로 HTTP 요청의 형태를 띈다. 서블릿 Container는 HttpServletRequest로 변한다. Controller는 인커밍 이벤트를 보고 요청을 Action 클래스로 보낸다. struts-config.xml은 Controller가 어떤 Action 클래스를 호출할 지를 결정한다. struts-config.xml 설정 정보는 ActionMapping으로 변환된다. 이것은 ActionMapping(‘s’에 주의)의 컨테이너에 놓이게 된다.
ActionMapping에는 특정 이벤트를 특정 Actions로 매핑하는 방법이 포함된다. ActionServlet (Command)는
ActionMapping을 perform() 메소드를 통해 Action 클래스로 전달한다.
이로서 Action은 흐름을 제어하는 정보에 액세스 할 수 있다.

■ ActionMappings
ActionMappings는 ActionMapping 객체들의 모음이다.

■ ActionMappings

ActionMappings는 ActionMapping 객체들의 모음이다.


[Struts Use Case]



[Action 예제]



[웹 애플리캐이션의 web.xml 설정]

<?xml version="1.0" encoding="UTF-8"?>
<web-app>   
 <servlet>       
  <servlet-name>action</servlet-name>       
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>       
  <init-param>           
   <param-name>config</param-name>           
   <param-value>/WEB-INF/struts-config.xml</param-value>       
  </init-param>       
                                  :
                                 중략
                                  :
  <load-on-startup>1</load-on-startup>   
 </servlet>   
 <servlet-mapping>       
  <servlet-name>action</servlet-name>       
  <url-pattern>*.do</url-pattern>   
 </servlet-mapping>
</web-app>

ActionServlet에는 여러 개의 초기 인자를 전달할 수 있다. 그 중 유독 눈에 띄는 부분은 struts-config.xml을 초기 인자로 전달 한다는 것이다. 이 의미는 만약 struts-config.xml이외에 다른 이름으로 스트럿츠 설정 파일을 사용하고 싶다면 web.xml에서 변경해 주면 다. 또 하나 다른 점은 태그를 사용한다는 것이다. 이 태그의 의미는 애플리케이션이 시작할 때 ActionServlet의 init() 메소드를 호출하여 초기화를 진행 하겠다는 뜻이다.
이 과정을 통하여 struts-config.xml의 모든 정보가 객체로 변환되어 메모리에 저장 되었다가 이후에 재 사용된다. 마지막으로 확장자는 *.do로 사용하겠다는 정보를 명시하고있다.

[ActionForm]

public class UserForm extends ActionForm {
    // --------------------------------------------------------- Instance Variables
    private String password;
    private String userId;
    private String email;
    private String name;

    public ActionErrors validate(
         ActionMapping mapping,
  HttpServletRequest request) {
        return null;
    }

    public void reset(ActionMapping mapping, HttpServletRequest request) {
  password = null;
  userId = null;
  email = null;
  name = null;
    }
    ……. 중략 ……..

특이할만한 메소드는 validate()와 reset() 메소드이다.
reset() 메소드는 한번의 요청을 처리한 다음 초기화할 속성에 대하여 초기화 작업을 담당하는 메소드이다.
validate() 메소드는 사용자로부터 전달되는 값들의 유효성을 서버측에서 체크하기 위한 메소드이다.
보통의 웹 애플리케이션은 자바 스크립트(Java Script)를 이용하여 클라이언트 측에서 유효성 체크를 많이 한다.
하지만 서버측에서 유효성 체크를 같이 해주는 것이 애플리케이션을 더 좋게 만들 수 있는 기초가 된다.
스트럿츠에서는 클라이언트가 입력한 값이 ActionForm을 상속하는 클래스에 저장된다.
따라서 클라이언트가 입력한 값을 구하기 위하여 request.getParameter("paramName")을 사용할 필요 없이 Form클래스를 이용하여 가능하다.
스트럿츠가 추가된 Form클래스를 인식하도록 하기 위하여 struts-config.xml에 다음과 같이 추가해주어야 한다.

<form-beans>
 <form-bean name="userForm" type=“com.paran.struts.form.UserForm" />       
</form-beans>

[struts-config.xml]

애플리케이션 실행을 위한 메타 데이터 관리
Logical-to-physical 맵핑. (Actions, ActionForms, ActionForwards)
폼 빈 지정, 추상적 페이지 맵핑, 페이지 흐픔, 액션 클래스 지정, 예외처리, 메시지 리소스, 플러그인 지정.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "
http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
  <!-- ========== Form Bean Definitions =================================== -->
  <form-beans>
    <form-bean name="boardForm“ type="net.javajigi.form.BoardForm“ />
    <form-bean name="listForm“ type=“com.paran.form.ListForm“ />
  </form-beans>

  <!-- ========== Global Forward =================================== -->
    <global-forwards>
        <forward name=“logoff” path=“/logoff.do” />
        <forward name=“logon” path=“/logon.jsp” />
    </global-forwards>

<!-- ========== Action Mapping Definitions =================================== -->
   <action-mappings>
    <action
      path="/board_writeForm"
      type=“com.paran.action.BoardWriteFormAction"
      name="boardForm"
      scope="request"
      unknown="false"
      validate="true"
    >
      <forward
        name="write"
        path="/board_write.jsp"
        redirect="false"
      />
    </action>

    <exception key=“expired.password”
               type=“rog.apache.struts.webapp.example.ExpiredPasswordException”
               path=“/changePassword.jsp” />
    </action-mappings>

    <controller
     contentType="text/html;charset=euc-kr"
     debug="3"
     locale="true"
     nocache="true"
     processorClass=“com.paran.processor.MyAppRequestProcessor"/>
    
    <message-resources parameter="net.javajigi.resources.ApplicationResources"/>
</struts-config>

[다중 모듈 지원]

규모(메뉴)에 따라 애플리케이션을 여러 개로 분할하여 관리하면 효율적이다.

[선언적 에러 처리]

전역이나 Action별로 특정 Exception을 처리하는 Exception Handler를 선언적으로 지정할 수 있다.

[유효성(Validation) 확인]

1) 버전 1.1부터 Struts 패키지에 포함됨.
2) XML 파일을 통한 유효성 검증.(validation.xml, validation-rule.xml)
3) 서버 및 클라이언트 사이드 Validation 지원 - java script 자동 생성(클라이언트 사이드)
4) Regular expression 사용
5) 확장 가능한 아키텍처
6) 기본적으로 제공하는 Validation : 숫자 여부(float, int), 자릿수 체크, 신용카드 번호, 이메일 주소

[플러그 인 기능]

StartUp Class를 선언적으로 추가
Ex) Validator, Tiles 플러그인 등 등…

[Struts Commons Libraries]

■ Jakarta Commons 라이브러리 사용

1) commons-beanutils
   Bean 프로퍼티 핸들링
2) commons-collections
   표준 JAVA2 커렉션 클래스의 확장 라이브러리
3) commons-dbcp
   Optional JDBC Connection Pool
4) commons-digester
   XML 파싱
5) commons-fileupload
   Http를 통한 파일 업로드
6) commons-logging
   애플리케이션 logging wrapper
7) commons-pool
   오브젝트 풀링
8) commons-resources
   메시지 리소스 지원
9) commons-validator
   필드 validation

[Struts의 “전과 후”]

■ Struts 장점

   1) JSP 태그 메커니즘 사용
      이 태그 기능은 재사용 가능한 코드를 조장하고 JSP 파일에서 자바 코드를 제거한다.
      이 기능은 JSP 기반 개발툴로 잘 통합된다.
   2) 태그 라이브러리(Tag library)
      재구현이냐, 태그 라이브러리냐? 필요로 하는 것이 라이브러리에 없다면 여러분이 기여하면 된다.
      또한 Struts는 JSP 태그 기술을 배울 수 있는 좋은 토대이다.
   3) 오픈 소스
      코드를 볼 수 있다는 오픈 소스만의 장점이 있다. 보는 눈들이 많은 만큼 코드 리뷰가 확실하다.
   4) Sample MVC 구현
      자신만의 MVC 구현을 만들고 싶다면 Struts가 도움이 된다.
   5) 문제 관리
      분할과 정복(Divide & conquer)은 문제를 해결하고 문제를 관리할 수 있는 좋은 방법이다.

■ Struts 단점

   1) 정확한 추상화 레벨
     Struts는 정확한 레벨의 추상화를 제공하는가? 페이지 디자이너에게 맞는 추상화 레벨은 무엇인가? 좋은 질문이다. 페이지 디자이너가 페이지 개발 시 자바 코드에 액세스 하도록 할 수 있는가? UI 개발 시 자바 코드 액세스를 제한하는 이유가 있다. 가장 중요한 이유는 페이지 디자이너에게 자바를 조금만 제공해도 많은 자바를 사용하기 때문이다. Microsoft ASP 개발이 이를 증명한다. ASP 개발 시 COM 객체를 만들어서 ASP 객체들을 구현한 다음 ASP 스크립트를 작성하여 이를 함께 묶는다. 대신, ASP 개발자들은 ASP 스크립트 때문에 미칠 지경에 이른다. "내가 VBScript로 직접 프로그래밍 할 수 있는 것을 왜 COM 개발자가 이를 구현할 때 까지 기다려야 하나?" 라고 푸념하는 소리가 들린다. Struts는 태그 라이브러리를 통해 JSP 파일에 필요한 자바 코드의 양을 제한한다. Logic Tag는 아웃풋의 조건적 생성을 관리하지만 자바 코드 때문에 UI 개발자가 괴로워하는 것에는 속수무책이다. 어떤 유형의 프레임웍을 사용하든지 전개 및 관리 환경은 이해해야 한다. 물론 어려운 일이다.
   2) 범위 제한
     Struts는 웹 기반 MVC 솔루션으로서 HTML, JSP 파일, 서블릿을 사용하여 구현된다.

[Struts의 미래]

새로운 소프트웨어 개발 시대에 모든 것은 빠르게 변화한다. 5년도 채 못 되어서 Struts는 웹 애플리케이션 개발에
표준으로 자리매김 하고 있다. 기존 Servlet, JSP의 문제점이나 편리성 등을 모두 만족시켰기에 가능하였다.
현재 Struts2.0 버전이 베타 릴리즈 될 만큼 계속적인 진화게 진행 중이다. 향후 Servlet, JSP의 대안이 아닌 J2EE
환경이 보다 확장된 기능까지 지원될지 지켜볼 만 하다.


- 이 종 화 (ingenuity.egloos.com) -

[출처] STRUTS Framework|작성자 메멘토