Category: Programming

Java BookMark

Maven 저장소 URL 변경하기

Maven 3 을 쓰다보면  Update나 Build 시에 Maven은 어딘서가 의존성 패키지를 다운받는다. 다운받은 파일을 어디에 저장할 것인가 를 지정하는것이 localRepository 이다.

문제는 어딘가에서 받아오는 저장소 URL 이 간혹 접속이 불가할 경우가 문제가 된다. 나 같은 경우에 일하고 있는 사무실 환경에서는 어찌된 영문인지 Maven이 패키지를 제대로 가지고 오지 못하고 있었다. 원인은 “Connection Time Out” 으로서 “https://repo.maven.apache.org/maven2” 에 접속이 되지 않아 발생 했다. 자세히 보니 https 로 접속이 안되는 문제였다.

이와같이 접속이 불가능 할 경우에는 Maven 저장소 URL 을 바꿀 필요가 있다.

pom.xml 에서 바꾸기

일차적인 방법으로는 프로젝트의 pom.xml 파일에서 저장소 위치를 지정하는 것이다. 먼저 저장소 위치가 어떻게 되는지 알수가 있다. 그것은 Eclipse 에서 pom.xml 을 열면 편집영역 하단에 “Effective POM” 탭이 보인다. 여기서 중간쯤에 보면 다음과 같은 저장소 URL 이 보인다.

Maven 3 에서 기본 세팅된 저장소 URL 을 살펴 볼수 있다.

아니면 pom..xml 이 있는 프로젝트 디렉토리에서 다음과 같은 명령어로 Effective POM 상태를 출력해 볼 수 있다.

이제 기본적인 저장소 URL 을 알았으니 이것을 바꿔보자. pom.xml 탭을 클릭해 다음과 같이 바꿔보자.

이렇게 하면 Maven의 기본 저장소 URL을 변경이 된다.

Maven settings.xml 설정 파일에서 바꾸기

만일 프로젝트가 아주 많이 있다면 일일이 프로젝트마다 앞에 방법대로 pom.xml 을 수정한다는 것이 바보같은 짓이된다. 이럴때에는 Maven의 설정 파일인 settings.xml 에서 설정 해주면 된다.

다음과 같이 설정 해준다.

이렇게 변경 후 저장하고 Eclipse 를 재시작하면 모든 프로젝트에 Effective POM 을 보면 저장소 위치가 변경된 것을 확인할 수 있다.

Maven 다중 모듈 프로젝트 구성

STS Eclipse를 이용하면 손쉽게 Spring MVC 프로젝트를 구성할 수 있다. Spring MVC 프로젝트에는 Java 파일과 Web Content 파일을 모두 포함한다. 이를 Dynamic Content, Static Content 등로 구분하기도 한다.

문제는 이렇게 하나의 프로젝트에 모든 것을 담을 경우에 다음과 같은 문제가 발생할 수 있다.

  • 분리 배포가 불가능 하다. 요즘에는 WAS 앞에 Web 서버를 따로 두어 Static Content 를 서비스 하는 아키텍쳐가 많은데 하나의 프로젝트에 모든 것을 담게 되면 분리 배포가 어렵다.

단 하나의 큰 문제인데 이 문제를 가볍게 여길 수 없다. 실제 프로젝트를 할때에 이것을 간과해 나중에 아주 힘들어지는 경우가 허다 하다.

그래서 Spring MVC 기반의 프로젝트를 할때에는 Dynamic Content, Static Content를 분리해 진행하는 것이 좋은데, Maven 에서는 이를 ‘다중 모듈 프로젝트 구성’ 이라는 기능으로 제공하고 있다.

Root 프로젝트 생성

다중 모듈 프로젝트를 생성하는 첫번째는 Root 프로젝트 생성이다. 이름에서도 알수 있듯이 이 모든 모듈 프로젝트에 뿌리가 되는 프로젝트를 말한다.

이는 ‘Maven Project’ 를 통해서 생성 할 수 있다.

Maven Project 생성
Maven Project 생성

위와같이 Maven Project를 통해서 생성할때 한가지 주의해야 하는 것이 있는데, Pakaging 형태를 pom으로 해야만 한다. Root 프로젝트는 하위 프로젝트에 기반을 제공하는 것으로 별도 was 배포용 패키지를 만들지 않는다.

Root Project 에 pom Packaging
Root Project 에 pom Packaging

이렇게 하면 Root Project가 생성이 된다.

이 상태를 그대로 두고 Static Content를 위한 하위 프로젝트를 먼저 생성한다.

하위 프로젝트 생성(Static Content)

Static Content 를 위한 하위 프로젝트는 오로지 CSS, Java Script, Images 만을 위한 것이여서 Spring Mvc 샘플 프로젝트를 만들 필요는 없다. 간단하게 Maven Module 로 제작하면 된다.

앞에서 생성한 Root Project 에서 마우스 오른쪽 버튼을 눌러 Maven Module 생성하기를 시작한다. 그리고 다음과 같이 ‘maven-archetype-webapp’ 를 선택해준다.

Maven 으로 webapp 생성
Maven 으로 webapp 생성

이렇게 하면 Root Project 밑에 디렉토리로 하위 프로젝트가 위치하는게 보이고 이와 별도로 이클립스에 프로젝트로도 보인다.

Root 와 Static 프로젝트 모습
Root 와 Static 프로젝트 모습

Static 프로젝트에 pom.xml 를 보면 Root 프로젝트와 연결된 설정이 보인다.

이제 Static 의 디렉토리 구조를 바꾼다. 이는 이전에 글을 참고 하면 잘 나와 있는데 여기서는 WebContent 디렉토리만 인식시켜주면 되기 때문에 pom.xml 에 설정해주고 파일을 옮기면 된다.

그리고 Static 파일을 위한 디렉토리를 생성한 다음에 가짜 파일을 하나 만든다.

Static 파일을 위한 CSS, JS, Images 디렉토리 생성
Static 파일을 위한 CSS, JS, Images 디렉토리 생성

이렇게 한 후에 Build 를 하면 WebContent 이하 디렉토리 내용이 war 파일로 작성되어 진다. war 파일이긴하지만 Static만 있으면 되기 때문에 이 Static 파일만 담기도록 해보자. pom.xml 을 다음과 같이 수정 한다.

** 위와같이 설정해도 원하는데로 동작하지 않습니다. 아신다면 덧글 남겨 주시면 고맙겠습니다. **

이렇게 한 후에 SystemVLabs-Static 에 빌드를 하면 WebContent 디렉토리에 내용들이 war로 만들어진다. 또, RootProject 에서 빌드를 하면 하위 모듈로등록된 SystemVLabs-Static 도 빌드가 되면 정상적으로 프로젝트가 세팅된 것이다.

하위 프로젝트 생성(Dynamic Content)

이제 Dynamic Content 를 위한 하위 모듈 프로젝트를 생성해야 한다. 이는 여러 방법이 존재하는데, 내가 보기에 가장 손쉬운 방법을 설명하고자 한다.

먼저 STS Eclipse 의 Spring MVC 샘플 프로젝트를 생성한다. 그러면 기존의 RootProject와는 별도로 프로젝트가 생길 것이다.

Spring5 샘플 프로젝트
Spring5 샘플 프로젝트

이제 이것을 export 를 해주는데, File System 으로 export 를 한다.

Export를 File System 으로 한다.
Export를 File System 으로 한다.

대상 디렉토리는 RootProject 로 지정한다.

Spring5의 RootProject 로 Export
Spring5의 RootProject 로 Export

이렇게 한 후에 RootProject 를 ReFresh 하면 방금 Export 한 Spring5 디렉토리가 보인다.

이제 기존의 Spring5 프로젝트는 디스크에서 삭제도 체크해  삭제한다. 그리고 이제 프로젝트를 Import 한다.

Existing Project into Workspace
Existing Project into Workspace

“Existing Projects into Workspace” 를 선책하고 Next,

Export된 Spring5 디렉토리 지정
Export된 Spring5 디렉토리 지정

이렇게 하면 RootProject 하위가 아닌 독립된 프로젝트로 나타난다.

마지막으로 RootProject 의 pom.xml 에 방금 등록한 하위 모듈 프로젝트로 등록해 준다.

그리고 새로 등록한 하위 모듈 프로젝트의 pom.xml 에는 parent 모듈을 등록해 준다.

이렇게 함으로써 Dynamic Content 를 하위 모듈 프로젝트 등록은 다 된 것이다.

 

Tomcat plugin 을 이용한 배포.

만일 WAS 서버를 Tomcat 을 이용해 개발을 하고 있다면 Maven tomcat7 플러그인을 이용해서 배포를 할 수 있다. 참고로 이클립스의 tomcat add-on 과는 다른 것이다. 이것은 Tomcat 에서 제공하는 Manager 기능을 이용한 것이다.

그리고 이 문서의 내용은 Tomcat 8 버전에서도 이용 가능 하다.

Tomcat 설정

Tomcat 의 Manager 기능을 이용하는 것이여서 Tomcat Manager 설정을 먼저 해줘야 한다. 아시겠지만 Manager 접근을 위해서는 인증 설정을 해줘야 하는데 이 인증은 Tomcat 의 ㅊCATALINA_HOME/conf/tomcat-users.xml 파일을 다음과 같이 설정 해준다.

Tomcat 방화벽 설정

앞서 설정을 한다고 해도 원격에서 Manager 접속은 불가능 하다. 왜냐하면 Tomcat 자체에 Manager 접속을 로컬호스트만 허용하도록 되어 있기 때문이다. 이것은 “CATALINA_HOME/webapps/manager/META-INF/context.xml” 파일에 설정되어 있다.

위 설정을 보면 ‘192.168.96.2,192.168.96.3’ 두개의 원격아이피가 허용되어 있다.

이 설정은 매우 중요하다. 모든 설정이 정상인데도 배포 실패가 나온다면 이 설정을 잘 살펴봐냐 한다.

Maven 설정(pom.xml)

이제 pom.xml 설정을 해야 한다. Maven 에서는 Tomcat Manager 에 원격 접속해 배포할수 있도록 도와주는 플러그인을 제공하는데 그 설정은 다음과 같다.

package tomcat7:[deploy|undeploy|redeploy]

tomcat7 maven 플러그인은 위 주제와 같이 사용하면 된다. Maven Build 시에 위 내용을 입력하면 설정한 Manager URL 로 배포 파일을 업로드 해주는데 이때 업로드 되는 파일 이름은 path 설정 이름으로 된다.

스프링 디렉토리 구조 재정의하기

이클립스(Eclipse)에서 STS 를 설치하면 아주 간단하게 Spring MVC 샘플 프로젝트를 생성할 수 있다. 이 샘플 프로젝트의 디렉토리는 다음과 같다.

Directory Structure of Spring MVC
Directory Structure of Spring MVC

엄밀히 말하면 사실 이 디렉토리 구조는 Maven 이 관리 한다. Maven 에서는 기본적으로 Java 소스 디렉토리, Resource 디렉토리, webapp 디렉토리를 위와  같이 정의해 놓고 있다. STS 의 Spring MVC 샘플 프로젝트도 Maven을 기반으로 만들어 졌기 때문에 위와 같은 디렉토리 구조를 가진다.

하지만 한국에서는 다음과 같은 디렉토리 구조를 주로  사용한다.

완성된 디렉토리 구조
완성된 디렉토리 구조

webapp 의 루트(root) 디렉토리를 WebContent 로 바꾸고 스프링의 설정 파일인 root-context.xml, servlet-context.xml 를 Resource 디렉토리의 config 디렉토리 아래로 옮겨준다.

이러한 구조로 바꾸기 위해서는 Maven 설정을 만줘져야 하는데, 이클립스를 이용하면 손쉽게 위와같은 구조로 변경할 수 있다.

WebContent 디렉토리 생성

webapp 디렉토리를 WebContent 로 바꾸기 위해서는 먼저 디렉토리를 만들어야 한다. 이클립스에서 프로젝트 아이콘에서 오른쪽 버튼을 클릭해서 WebContent 를 만들어 준다.

생성이 되었다면 이제 기존의 webapp 디렉토리 아래에 모든 디렉토리와 파일을 WebContent 디렉토리로 옮겨준다. 그리고 webapp 디렉토리를 삭제해 준다.

webapp 파일 옮기기
webapp 파일 옮기기

이렇게 옮겨 놓고 보면 pom.xml 파일이 오류가 난다. 오류의 내용은 다음과 같다.

Maven 에서 정해진 위치에 있어야 할 web.xml 이 없기 때문에 나오는 오류다. 따라서 Maven 에서 web.xml 디렉토리 위치를 바꿔 주면 되는데 먼저 pom.xml 에 maven-war-plugin 를 추가해 준다.

그리고 이클립스에 설정으 바꿔 줍니다. 프로젝트이름에서 마오스 오른쪽 클릭 후에 ‘Properties -> Deployment Assembly’ 를 보면 /src/main/webapp 이 보인다. 이것을 삭제하고 WebContent 를 추가해준다.

WebContent 를 위한 이클립스 설정
WebContent 를 위한 이클립스 설정

이렇게 한 후에 pom.xml 파일의 오류가 사라지는것을 볼 수 있다. 만일 그렇지 않다면 Maven Update 를 한번 해준다.

이제 Maven 을 이용해서 프로젝트를 빌드 해본다. 성공적으로 빌드가 됐다면 다음과 같이 나온다.

webapp 디렉토리 변경후에 빌드 성공한 디렉토리 구조
webapp 디렉토리 변경후에 빌드 성공한 디렉토리 구조

Spring 설정을 WebContent 와 분리

WebContent 이름에서 보이듯이 이 디렉토리는 Web 관련 파일들만 모아놓기위한 것이다. Web 관련 파일이라면 CSS, JS, Images, JSP 로 대표되는 Web Frontend 파일을 말한다. 하지만 자세히 보면 Spring 에 관련된 파일 들도 있어서 이것을 Resource 디렉토리로 옮겨 놓는게 적절해 보인다.

먼저 src/main/resources 디렉토리에 ‘spring’ 이름의 디렉토리를 생성해준다. 디렉토리를 생성했는데 패키지 아이콘이 나온다면 ‘Build Path’ 에서 Exclude 해주면 된다. 그리고 spring-root.xml, spring-context.xml 두개의 파일을 모두 resources/spring 으로 옮겨주고 기존의 WEB-INF/spring 디렉토리는 삭제해준다.

Spring 설정파일 옮기기
Spring 설정파일 옮기기

Web.xml 파일에서 spring 설정 파일의 경로를 변경해 준다.

그리고 pom.xml 파일을 다음과 같이 변경해 준다.

 

이렇게 디렉토리를 변경하는 이유는 앞에서 잠깐 언급했지만 Web 컨텐츠와 Spring 설정파일들을 분리하는데 있다. 또, 이렇게 함으로써 자바 관련 파일과 Web 컨텐츠 파일을 손쉽게 분리해서 배포할 수 있게 된다.

web.xml 스키마 예제 헤더

web.xml 스키마 헤더 예제는 버전별로 다음과 같다.

Servlet 2.5

Servlet 3.0

Servlet 3.1

Servlet 4.0

 

참고: IBM Knowledge Center

Windows JDK 1.8 Portable

최근에(2017년 11월) JAVA 9 가 발표 되었다. 이와 관련해서 이미 JAVA 9로 많은 소프트웨어가 포팅되고 배포되고 있다. 대표적으로 자바 개발 도구인 이클립스의 경우 최신버전은 JAVA 9 에서 매우 잘 동작 한다.

하지만 여전히 많은 소프트웨어가 JAVA 8 을 필요로 한다. 한 시스템에서 JDK 를 두가지 버전을 설치하는게 썩 좋아보이지 않다. 시스템에서 JAVA 9 를 메인으로 하고 JAVA 8은 포터블하게 설치해서 사용하면 얼마나 좋을까?

이 문서는 Windows 에 JDK 1.8 을 포터블 제작에 대한 것이다.

환경

  • Windows 10 64bit
  • JDK 1.8 u152
  • 7-zip 64bit

JDK 1.8 의 포터블 제작을 위한 환경은 위와 같다. 압축 프로그램이면 아무거나 다 되는거 아니냐 하겠지만 7-Zip 을 권장 한다.

압축 해제

다운받은 JDK 1.8 u152 설치 파일을(exe) 오른쪽 클릭한 후에 압축 해제한다.

JDK 1.8 u152 압축해제

압축을 해제하고 나후 디렉토리를 펼치면 위와같이 나온다.

tools.zip 파일

포터블 JDK 의 핵심은 바로 tools.zip 이다. 이 파일에는 java 의 실행파일, 라이브러리 파일등이 들어 있다. 문제는 이 파일이 안보이는데, JAVA_CAB10 디렉토리에 111 파일이 보인다. 이 파일을 압축 해제한다.

tools.zip

위 파일을 압축 해제하면 드디어 익숙해 보이는 파일들이 보인다.

tools.zip 압축해제

문제는 이걸 그대로 사용할 수가 없다는 것이다. 이 안에 많은 파일들이 *.pack 인채다.  cmd 창에서 tools.zip 압축해제한 디렉토리로 이동한 후에 다음과 같이 해준다.

그러면 다음과 같이 pack 파일이 jar 파일로 변경된다.

pack 파일을 jar로 변환.

src.zip 파일

JDK 1.8 의 소스 파일인데, 이는 다음과 같이 110 파일을 압축 해제하면 된다.

src.zip 파일

src.zip 파일을 tools.zip 압축 해제했던 디렉토리에 넣어준다.

COPYRIGHT 파일

JDK 에 COPYRIGHT 파일이 있어야 한다. 이는 다음과 같은 디렉토리에 112 파일을 압축해제하면 나온다.

JDK 1.8 COPYRIGHT 파일

압축해제해 나온 COPYRIGHT 파일을 tools.zip 압축해제한 디렉토리에 넣는다.

JDK 1.8 Portable

tools.zip 압축해제하고 pack 파일을 jar 로 전환하고 src.zip, COPYRIGHT 파일을 작성해 tools 압축해제한 디렉토리로 옮겨놨다.

이제 이 tools 디렉토리를 JDK 1.8 로 바꾸고 적당한 디렉토리로 옮겨서 사용하면 된다.

JDK 1.8 Portable

 

참고

  • https://portableapps.com/node/53015
  • https://techtavern.wordpress.com/2014/03/25/portable-java-8-sdk-on-windows/

 

아주 심플한 자바 웹 애플리케이션

이중화 시스템을 구축하면 WAS 서버의 헬스 체킹을 하기 위한 웹애플리케이션 페이지가 필요할 때가 있다. AWS ELB 가 대표적으로 ELB 뒤에 WAS 서버가 있을 경우에 HTTP를 이용한 헬스 체킹을 위해 웹애플리케이션의 페이지가 필요하게 된다.

보통은 Product 웹프로그램에 AWS ELB 헬스체킹을 위한 페이지를 넣을 수도 있지만 별도의 웹애플리케이션을 작성하는게 더 좋다.

이 문서는 이러한 환경에서 헬스체킹을 위한 아주 심플한 자바 웹 애플리케이션을 작성하는 법에 대해서 기술 한다.

디렉토리 구조

기본적으로 웹 애플리케이션의 기본 디렉토리는 다음과 같다.

  • META-INF/MANIFEST.MF
  • index.jsp
  • WEB-INF/web.xml

위 디렉토리와 파일을  jar 를 이용해서 war 파일로 압축해 배포하면 된다. 이때 Context Root 는 war 파일 이름이 된다.

META-INF/MANIFEST.MF

위 파일은 war 파일의 정보를 기재하는 것으로 다음과 같다.

index.jsp

위 파일은 다들 알다 시피 html, jsp 문법을 쓸수 있는 파일이다. 그냥 OK 글자 하나만으로도 된다.

web.xml

이 파일은 웹애플리케이션 동작에 대해 설정하는 파일이다. 다음과 같다.

그냥 index.jsp 파일에 대해서만 설정 하면 된다.

healthcheck.war 만들기

위에서 기술한 디렉토리에서 다음과 같이 입력해 war 파일을 만든다.

이렇게 하면 war 파일이 나온다.

그리고 이것을 WAS 서버에 배포하고 브라우저에서 ‘http://server:8080/healthcheck/index.jsp’ 를 호출하면 OK 가 나온다.

AWS ELB 에서 HealthCheck 설정에서 port 는 8080, URL 은 /healthcheck/index.jsp 를 기재하면 WAS 에 대한 헬스체크를 HTTP를 통해서 할 수 있게 된다.

 

 

 

 

 

 

Java 8 람다 표현식

이 글은 다음의 Youtube 강의 내용을 요약 정리한 것입니다.

  • Java 8 Lambda Basics – Java Brains

왜 람다(Lambda) 인가?

  • 함수형 프로그램이 가능하다.
  • 읽기 쉽고 간결한 코드
  • API 나 라이브러리 사용이 좀 더 쉽다.
  • 패러럴 프로그래밍이 가능하다.

람다는 함수 자체를 값으롤 할당할 수 있는 Inline 함수처럼 표현된다.

 

람다 표현식(Lambda Expressions)

자바에서 메소드로 불리우는 함수 표현식은 대략 다음과 같은 형식을 갖는다.

Inline Values

위 예제는 Inline Values 가 무엇인지 보여준다. 별다른 객체, 메소드의 도움이 바로 할당하는 형식이 바로 Inline Values 라고 보면 된다.

그렇다면 코드 블럭(Code Block) 자체를 인라인으로 할당 할 수 있지 않을까? 다음과 같이 말이다.

실제로 JavaScript 에서는 Inline 함수라고 해서 존재한다. 다음과 같은 형식을 갖는다.

Java 8 에서의 람다 표현식은 JavaScript 에서의 인라인 표기와 유사하다.

HelloWorld 람다

HelloWorld 를 통해서 람다 표현식을 익혀보자.

전형적인 HelloWorld 코드다. 이것을 람다 표현식으로 어떻게 바꿀까? 먼저 메소드 자체를 Inline Value 할당하듯이 가상의 변수에 할당해보자. 다음과 같이.

public 은 접근제한자라고 해서 protected, private 등이 있다. 변수에 할당하는 행위에서 있어서 이러한 접근제한자는 의미가 없다. OOP 에서는 객체의 변수를 직접 받는것이 아니라 메소드를 통해서 할당 받는데, 람다 표현식에서는 Inline Value 로 직접 할당하는 방식이기 때문에 무의미하다. 지우자!

코드를 다시보면 perform  이라는 함수 이름이 존재한다. 하지만 코드 블럭자체를 왼쪽 변수에 할당하고 그러한 코드 블럭은 왼쪽 aBlockOfCode 를 호출함으로써 동작하게 될터이다. 따라서 perform 이라는 함수 자체를 지칭하는 이름은 불 필요하다. 이는 앞서본 JavaScript 의 인라인함수 표현식에서처럼 할당되는 함수의 이름이 없는것과 같다. 지우자!

void 는 리턴타입을 말한다. 아무런 리턴도 없다는 의미이기도 하다. Java 8 컴파일러는 똑똑하다. 람다 표현식에서 리턴타입을 명시하지 않더라도 컴파일러가 알아서 해준다. 지우자!

다 됐다. Java 8 에서 람다 표현식에서는 ->  를 이용한다. 다음이 Java 8의 람다 표현식의 완성이다.

이게 정상적인 코드라구? 그렇다. Java 8 에 도입된 람다표현식이다. 정확하게 잘 동작한다. 위를 좀 더 간결하게 바꿔 쓸수도 있다.

 

람다(Lambda) 예제.

다음을 람다 표현식으로 바꿔보자.

Inline 변수 할당이기 때문에 객체 접근제한자는 필요가 없다. public 삭제..

Inline 변수 할당이기 때문에 double 이라는 함수자체이 이름도 필요가 없다. double 삭제.. 그러면 다음과 같은 형태만 남는다.

자바 컴파일러는 매우 똑똑하다. 리턴타입을 추론해 맞춰준다. 먼저 인자 타입이 int 형이라 결과도 나름대로 int 형일것으로 추정하기도 하고 리턴 되는 계산을 하면서 리턴타입을 추론하기도한다. 별도로 리턴타입을 정의해줄 필요가 없다. int 리턴타입 삭제…

그렇게 하고 나면 다음과 같이 람다 표현식을 쓸수 있게 된다.

람다 표현식이다. 하지만 이를 좀 더 줄이면 다음과 같이 쓸 수 있다.

한줄로 다 작성할 수가 있다면 {} 블럭을 사용할 필요가 없고 {} 없는 경우에 return 을 쓰지 않아도 된다.

모든 람다가 {} 이 필요 없는 것은 아니다. 다음과 같이 블럭내에 로직이 들어갈 경우에 {} 블럭과 return 이 필요하다.

문자열 길이를 알아내고자 한다면 어떻게 람다 표현식을 쓸 수 있나? 다음과 같다.

물론, 앞에서 처럼 뭔가 로직을 넣어야 한다면 {} 감싸고 return 을 해주면 된다.