Java Application 개발을 하면서 처음부터 완벽하게 만든 다는 것은 능력자 가 아닌 이상 흔하지 않다. 잠재적인 결함이 있을 수 있고, 필수 값 체크를 못했다면 친숙한 Exception 인 NullPointerException 을 만나게 된다. 최근에 경험했던 일 이다.


Java String.split(String regex) 사용 시 '|' 파싱 이 안되는 경우 (http://blog.whitelife.co.kr/222)


배열에서 파싱 할때 split("|") 라고 작성 했을 때 Escape 처리를 해줘야 동작 한다. FindBugs 는 기본적으로 발생 하는 결함을 확인하고 Report 해준다. 이외에 분석 도구는 Checkstyle, cobertura, PMD 등 이 있다.


Eclipse 도 Problems Report 를 해준다. 무심결에 지나치기 보다 잠깐 이라도 보고 넘어가자.


FindBugs: http://findbugs.sourceforge.net/


Maven, Eclipse Plugin 형태로 제공 된다. Eclipse 기준으로 진행 하겠다.



Help > Eclipse Marketplace 클릭 한후 Find 에 FindBugs 라고 검색 한다. Install 버튼을 클릭 하자.



친절하게 가이드를 해준다. Next 를 계속 하자. 설치 도중 Security Warning 가 나오면 OK 하자.



완료 되었다면 재 시작 한다. Window > Show View 에 FindBugs 폴더가 추가 되는대 Bug Explorer 를 클릭 한다.



하단에 출력 창이 추가 됬을 것 이다.


Project Explorer 에서 마우스 오른쪽 클릭을 하면 FindBugs 라는 메뉴가 있다. 하위 메뉴도 FindBugs 를 클릭 한다.



결함이 있다면 Report 된다. 자세한 내용을 알고 싶다면 + 아이콘 클릭 후 하위 에 있는 값을 클릭 해보거나, 마우스 오른쪽 클릭 Show Bug Info 화면으로 이동하여 참고 하자.


FindBugs 는 강제적으로 해야 하는 것이 아닌, 선택 적이다. 프로그래밍도 습관이 중요 하다고 생각 한다. 당장 +1분, +5분, +10분 투자 하는게 아깝다고 하는 것 보다, 조금씩 투자 하다 보면, -60분, -120분, -180분 보상 받을 것 이다. 치명적인 결함이 줄어드므로...


기본적으로 배포 하는 방법에 대해서는 앞서 설명 하였다.


Tomcat War Deploy 하기 (http://blog.whitelife.co.kr/240)


이해가 안되는 경우 위 글을 참고하기 바란다.


항상 Java Web Application 을 Build 하여 전체 배포를 할 수는 없다. 고객의 추가 요구 사항에 따라 프로그램 소스는 얼마든지 수정 될 수 있다.


JSP 파일만 수정되면 Restart 가 생략이 가능 하지만, 그 이외의 파일이라면 반드시 수행해야 한다.


  • server.xml
<Host name="localhost"  appBase="/home/users/parkmc/webapps"
    unpackWARs="false" autoDeploy="true" deployOnStartup="false">

<!-- SingleSignOn valve, share authentication between web applications
     Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->

<!-- Access log processes all example.
     Documentation at: /docs/config/valve.html
     Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       prefix="localhost_access_log." suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>


War 압축된 상태가 아닌, Context 경로에 직접 파일로 배포 하는 경우에는 unpackWARs="false" 로 설정 해야 한다. 기본적인 경로는 /ROOT 이다. 개별 적으로 추가가 필요하다면, Context 를 추가 한다.


/ROOT
    /META-INF
    /WEB-INF
        /classes
        web.xml


위의 폴더 구조에 따라 배포를 진행 한다. 파일 복사가 끝났다면, /bin/startup.sh 를 하여 서버를 시작 하자.


프로젝트가 마무리 되고, 실제 서비스 적용 할 때 두 가지 방법으로 나뉜다.


  1. WEB Server, WAS(Web Application Server)
  2. WAS(Web Application Server)

첫 번째 방법은 정적 요소인 Image, Css, Javascript 파일은 WEB Server 에서 응답 하고, 프로그래밍 요소가 들어간 요청 에 대해서는 역 프록시(Reverse Proxying) 하여 WAS 로 요청을 전달 한다. Business Logic 처리 후 결과를 응답 한다.
두 번째 방법은 WAS 에서 정적 요소와, 프로그래밍 요소가 들어간 요청을 받고 응답 한다.


보통 관리자 페이지는 내부 네트워크에 있는 PC 만 접근이 되야 한다. WAS 만 사용 하는 경우에는 프로그래밍 적으로 제한해야 하지만, WEB Server 사용 시 서버 설정으로 제한 할 수 있다.


  • /httpd/conf/httpd-vhosts.conf
<Location "/admin">
    Order mutual-failure
    Allow from 192.168.0.1
</Location>

ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
ProxyPreserveHost On


Directory 와는 다르게 Location 은 Url 기준 이다. 속성 값에 해당 주소를 설정 한다.


Order Value Description
1 deny, allow deny, allow 지시자 검사
2 allow, deny allow, deny 지시자 검사
3 mutual-failure 모든 접속을 거부 Allow from Ip 만 허용


allow 는 허용 되는 Ip 이고, deny 는 반대 되는 개념 이다.


참고 사이트


많이 사용되는 예외 처리 기법 중 ExceptionResolver 의 일종인 SimpleMappingExceptionResolver 를 사용하여 Exception 종류 별로 특정 페이지로 이동 할 수 있게 하는 방법 이 있다.



Controller 의 기능만 사용해서 개발 한다면 Spring MVC 의 범위 안에서 Exception 을 해결 할 수 있기 때문에 크게 문제가 되지 않는다. 실제 개발 하는 부분은 Execute Business Logic 가 전부 이기 때문 이다.


회사에서 Spring MVC 라이브러리를 바탕으로 하여 만들어 지는 프레임워크는 Handler Mapping, Handler Adapter, View Resolver 의 확장이 대부분 이며, 예외 처리는 직접 고려해야 한다.


Business Logic 을 처리 하고 난 후 사용자에게 제공 되는 화면이 요구사항에 따라 달라질 수 있고, 잦을 수도 있다. 이에 대응 하기 위해서 View 를 확장 한다.


  1. AbstractExcelView 를 사용하여 Excel 연동 하기 (http://blog.whitelife.co.kr/197)
  2. AbstractView 사용하여 Ajax 처리 하기 (http://blog.whitelife.co.kr/208)
  3. AbstractView 사용하여 파일 다운로드 처리 하기 (http://blog.whitelife.co.kr/211)

AbstractView 를 사용해서 작업한 내용의 글 이다. 필요한 경우 참고 하자.


View 를 확장 했기 때문에 ExceptionResolver 가 예외 처리를 할 수 없다. 시점 이 그 이후 이기 때문 이다. 추가 적인 예외 처리가 필요 한대 WAS(Web Application Server) 에서 제공 하는 기능을 사용 해야 한다.


실제 서비스 중에 알파벳이 난무 하는 화면이 보여진 다면, 문제가 심각할 것 이다. 디버깅을 해서 보완을 하더라도, 그 시간동안은 대체 하는 화면이 필요 하다.


<error-page>
    <error-code>400</error-code>
    <location>/WEB-INF/view/error/badrequest.jsp</location>
</error-page>
<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/view/error/notfound.jsp</location>
</error-page>
<error-page>
    <error-code>414</error-code>
    <location>/WEB-INF/view/error/requesturitoolong.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/WEB-INF/view/error/internalservererror.jsp</location>
</error-page>


web.xml 에 추가 하자. 보통 /WEB-INF/web.xml 에 파일이 있다.


error-page

description
400 (잘못된 요청): 서버가 요청의 구문을 인식하지 못했다.
404 (찾을 수 없음): 서버가 요청한 페이지를 찾을 수 없다. 예를 들어 서버에 존재하지 않는 페이지에 대한 요청이 있을 경우 서버는 이 코드를 제공한다.
414 (요청 URI가 너무 긺): 요청 URI(일반적으로 URL)가 너무 길어 서버가 처리할 수 없다.
500 (내부 서버 오류): 서버에 오류가 발생하여 요청을 수행할 수 없다.


Http Status Code 에 따라 보여질 화면을 설정 한다.


강제로 에러를 발생해서 확인 해 보면 의도하는 화면이 표현 될 것 이다.


요구사항에 대한 기능은 정상적으로 동작 하기 때문에, 별거 아니라고 생각하고 지나칠 수 있다. 신경 써서 마무리 한다면 완성도 가 높은 프로젝트를 경험 할 수 있을 것 이다.


참고 사이트


Java Web Application 개발은 대부분 Eclipse 를 사용 해서 개발 한다. 소스 파일 작성은 확실히 편리 하다. 하지만 Tomcat 을 사용 할때 문제점 이 있다.


1. Class 파일의 로딩 지연 현상

개발 진행 중에 Start, Stop, reStart 를 하루에도 몇십번? 씩은 하고 있다. 서버가 Start 될 때 이런 문구를 발견 하게 된다. ClassNotFoundException, NoClassDefFoundError 확인 하기 위해 파일을 찾아 본다. 실제로 Class 가 있고, Build 도 되어 있다. 결국 Clean Tomcat Work Directory 를 하고 난 후에야 해결이 된다.



2. Java Library 충돌

최근에 프로젝트를 진행 하면서 경험한 부분 이다. dom4j 라이브러리를 사용 하는대 2가지 버전이 Dependency 되어 있었다. Eclipse Tomcat 사용 할 때는 정상적으로 동작 한다. 하지만 Maven Build 하여 서버에 적용 하면 아니러니 하게도 ClassCastException 이 발생 한다. 흔히 Local 개발 환경에서는 정상 동작 하는대 실제 서비스를 적용 하는 환경에서 발생 하는 에러의 일부분은 이와 같은 사례 이다.


mvn dependency:tree


라이브러리를 사용할 때 의존성에 대한 검사를 하는 습관을 갖게 되면 라이브러리 간에 충돌은 줄일 수 있다.


위 두가지 사례를 들었다. Eclipse 에서도 배포가 가능 하겠지만, 개발 환경이 항상 Eclipse 를 사용 하고 있을 수는 없을 것이다. Maven 은 직접 소스를 build 해서 war 로 만들 수 있다. 개발자가 불편을 감안 하고 직접 Tomcat 에 deploy 하여 실제 서비스 환경과 비슷한 환경에서 테스트를 진행 할 수 있고, 좀 더 편리한 환경에서 테스트를 하고 싶다면, Tomcat Plugin 을 사용하면 된다.


<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>tomcat-maven-plugin</artifactId>
    <version>1.1</version>
    <configuration>
        <mode>war</mode>
        <port>8080</port>
        <path>/</path>
        <charset>UTF-8</charset>
        <uriEncoding>UTF-8</uriEncoding>
    </configuration>
</plugin>


pom.xml 에 추가 하자.


mvn clean tomcat:run


packing 이 war 로 선언 되어 있다면, war 로 Build 한 후 서버가 시작 될 것이다.


D:\Project\workspace\whitelife>mvn clean tomcat:run -Denv=local
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building whitelife web application
[INFO]    task-segment: [clean, tomcat:run]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting directory D:\Project\workspace\whitelife\target
[INFO] Preparing tomcat:run
[debug] execute contextualize
[INFO] [resources:resources {execution: default-resources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 28 resources
[INFO] Copying 5 resources
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 80 source files to D:\Project\workspace\whitelife\target\classes
[INFO] [tomcat:run {execution: default-cli}]
[INFO] Running war on http://localhost:8080/
[INFO] Creating Tomcat server configuration at D:\Project\workspace\whitelife\target\tomcat
2014. 11. 7 오전 11:29:16 org.apache.catalina.startup.Embedded start
정보: Starting tomcat server
2014. 11. 7 오전 11:29:16 org.apache.catalina.core.StandardEngine start
정보: Starting Servlet Engine: Apache Tomcat/6.0.29
2014. 11. 7 오전 11:29:16 org.apache.catalina.core.ApplicationContext log
정보: Initializing Spring root WebApplicationContext
2014-11-07 11:29:16,934  INFO ContextLoader - Root WebApplicationContext: initialization started


http://localhost:8080/ 에 접속 하여 확인 해보자.


위 방법을 사용 하면서 Eclipse 는 본연의 모습을 찾아 가는 것 같고, Maven 은 Project 에 대한 매니저 역할을 하는 것 같아 보인다.


개발자 마다 개인의 스타일이 있고, 편한 방법이 있다. 정답은 없지만, 본인이 편리하게 사용할 수 있는 방법으로 개발 하면 될 것이다.


파일 업로드 기능을 개발한 경험들은 많을 것 이다. 보통 서버에서 파일 크기 확인을 해서, 실패 응답을 내려주기도 했지만, 요청 전에 직접 확인이 가능 하다.


<input type="file" name="sample" />


정보를 직접 확인 해보자.


$(document).on('change', 'input[type=file]', function() {
    console.log($(this)[0].files[0].size);
    console.log($(this)[0].files[0].name);
});


기본 객체가 Array 로 되어 있어 확인하기 까지 시간을 많이 소비 했다. 평소에 연락을 자주 하고 지내는 전산실 공장장 지단로보트님이 방법을 알려주셨다. Script 에 위 내용을 추가 하고 파일을 업로드 해보자. 확인이 가능 할 것이다.


Web Application View 는 보통 Html 을 사용한다. Dom 객체를 필요에 따라 생성 할때 유용한 라이브러리를 소개 한다.



사용을 위해서 jquery.tmpl.js, jquery.tmplPlus.js 파일을 /js 폴더에 추가 하자.


<script id="sampleData" type="text/x-jQuery-tmpl">
    <tr>
        <td>{{= sample1}}</td>
        <td>{{= sample2}}</td>
    </tr>
</script>


실제 동적으로 추가할 Template을 작성 한다. 위 내용을 참고 한다.


Template 작성이 완료 되었다면, 실제 코드를 작성 하자.


$('#sampleData').tmpl([{ sample1: 1, sample2: 2 }]).appendTo('body');


Template 객체를 불러 온 후 tmpl(data) 함수를 사용하여 값을 바인딩 한다. 그 후 원하는 부분에 appendTo(target) 하여 적용 하면 된다.


직접 문자열로 생성하여 개발 하거나 객체화하여 추가 할 수 있지만, Template 를 사용하면 개발이 유연해지는 모습을 볼 수 있기 때문에, 시간도 단축 된다. 라이브러리 사용이 가능한 환경이라면 적용 해 보자.


부팅 할 때 shift 버튼을 누른 상태로 하면, GRUB 메뉴 화면이 출력 된다. root 계정으로 부팅을 위해서는 파라미터 값을 수정해야 한다.


Ubuntu, with Linux 3.13.0-32-generic (recovery mode) 메뉴로 커서를 이동 하고, e 키를 눌러 보자.


부팅 할때 필요한 값들이 설정되어 있는 페이지에서 값을 수정 하자.


linux /vmlinuz-3.13.0-32-generic root=/dev/mapper/dev--vg-root ro recovery nomodeset


해당 라인을 찾아서 아래와 같이 수정 한다.


linux /vmlinuz-3.13.0-32-generic root=/dev/mapper/dev--vg-root rw init=/bin/bash


F10 키를 눌러서 부팅 한다.


root@(none):/# 


해당 문구가 나오면 부팅이 완료 된 것이다.


root@(none):/# sudo passwd root


비밀번호를 수정 한 후 재 부팅 하자.


참고 사이트


+ Recent posts