넷빈즈 6.8로 자바 EE 6 시작하기 |
 |


지난 칼럼에서 자바 EE 6의 맛을 살짝 보았는데, 제대로 지원하는 IDE가 없어 구체적인 예를 보여주기 쉽지 않았다. 마침 넷빈즈(NetBeans) 차기 버전인 6.8의 첫 번째 마일스톤이 나와 자바 EE 6를 지원하게 되어 소개해보려 한다.
준비
넷빈즈 6.8은 자바 EE 6를 지원하는 버전이어서 출시 일정도 자바 EE 6 서버인 글래스피시(GlassFish) V3와 맞물려 있다. 따라서 원래는 9월 말로 예정됐는데 자바 EE 6가 JSR-299 Contexts and Dependency Injection for Java EE와 JSR-330 Dependency Injection for Java를 합쳐서 넣기로 해 11월로 최종안 발표가 연기되어 글래스피시 V3와 같이 11월로 밀린 상태다(이와 관련해서는 다음 칼럼에서 상세히 다루기를 희망한다). 하지만 현재 자바 EE 6 프리뷰 수준의 기술을 사용하는 데에는 첫 번째 마일스톤으로도 부족함이 없으므로 넷빈즈 6.8 M1을 아래 링크를 통해 받자.
http://bits.netbeans.org/netbeans/6.8/m1/
노파심에 일러두면, 자바 EE 6는 자바 SE 6를 요구하므로 넷빈즈 설치 전에 자신의 JDK 버전을 확인하여 요구사항에 맞게 해두자. 넷빈즈 6.8을 설치하면 자동으로 글래스피시 V3 최근 버전을 설치하므로 따로 서버를 설치할 필요는 없다.
프로젝트 생성
넷빈즈를 실행한 다음 New » New Project를 선택하면 다음과 같은 화면이 나온다.
위의 그림과 같이 Java Web » Web Application을 선택한다.
다음 화면에서 Project Name은 microblog(그렇다. 마이크로블로그를 만들 작정이다)로 하고 Next 버튼을 눌러 넘어간다. 다음 화면을 보면 Server는 GlassFish v3 Domain, Java EE Version은 Java EE 6 Web으로 되어있을 것이다. Context Path가 /microblog로 되어 있는 것도 확인해두자. 다음으로 넘어가 Frameworks 선택 화면에서 JavaServer Faces를 선택하고 Finish 버튼을 눌러 마친다.
microblog라는 프로젝트가 생성됐으면 이 상태에서 한번 실행해 보자. Run » Run Main Project를 선택하면(간단히 F6 키를 눌러도 된다), 먼저 자바 DB가 뜨고, 글래스피시 서버가 뜬 다음 microblog 프로젝트를 빌드한 후 배포하고 나서 http://localhost:8080/microblog/를 자동으로 연다.
설계
마이크로블로그라고는 해도 트위터나 미투데이를 보면 그리 간단한 시스템이 아니다. 따라서 microblog 웹 애플리케이션은 다음과 같아야 한다.
- 글 하나를 나타내는 Post라는 엔티티 모델이 있고,
- 이것을 웹 사용자 인터페이스(JSF 사용)와 웹 REST 인터페이스(JAX-RS)로 접근할 수 있게 한다.
본격적인 프로그램 작성에 앞서 설정할 것이 하나 있다. 넷빈즈 6.8에는 Deploy on Save라는 기능이 있는데, 쉽게 말해 애플리케이션을 구성하는 파일이 변경되면 자동으로 배포하는 것이다. 전과는 달리 배포가 매우 빨라 편리하긴 한데, 간혹 설정을 완전히 초기화하지 못해 배포 후 애플리케이션이 정상 작동을 하지 않는 경우가 있다. microblog 프로젝트의 Properties에서 Run 카테고리를 선택하여 Deploy on Save 옵션을 끄자.
엔티티 모델
File » New File을 선택하면 나오는 화면에서 Categories는 Persistence를 선택하고 File Types는 Entity Class를 선택한 다음 Next 버튼을 누른다. 다음 화면에서 Class Name은 PostEntity로, Package는 microblog로 한다. 아직 퍼시스턴스 유닛을 생성한 적이 없다면 Create Persistence Unit 버튼을 눌러 퍼시스턴스 유닛을 생성해야 하는데, 이때 나오는 팝업 창에서 Data Source를 jdbc/sample로 선택하고 Table Generation Strategy는 Drop and Create로 한 다음 Create 버튼을 눌러 생성한다. 이 작업을 마친 다음 Finish 버튼을 눌러 완료한다.
생성된 PostEntity 클래스를 열어 글 하나의 본문에 해당하는 body 필드를 추가한다. 먼저 다음과 같이 body 필드 선언을 id 필드 선언 바로 밑으로 넣고, body를 선택한 다음 컨텍스트 메뉴의 Refactor » Encapsulate Fields를 선택하여 게터와 세터를 생성한다.
@Column
private String body;
|
최종 코드는 다음과 같다.
Listing 1. 최종 코드
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package microblog;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
*
* @author ias
*/
@Entity
public class PostEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String body;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof PostEntity)) {
return false;
}
PostEntity other = (PostEntity) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "microblog.PostEntity[id=" + id + "]";
}
/**
* @return the body
*/
public String getBody() {
return body;
}
/**
* @param body the body to set
*/
public void setBody(String body) {
this.body = body;
}
}
|
 |

|
웹 UI(User Interface)
PostEntity를 외부 시스템에 노출하는 첫 번째 방법은 사람이 웹 브라우저를 통해 사용할 수 있는 웹 UI다. File » New File 메뉴에서 Categories는 Persistence, File Types는 JSF Pages from Entity Classes를 선택하고 Next 버튼을 누른다. 다음 화면에서 Available Entity Classes 안에 있는 microblog.PostEntity를 선택하여 Add 버튼을 누르고 Next 버튼을 누른다. 마지막 화면에서 JSF Pages Folder에 posts를 넣은 다음 Finish 버튼으로 완료한다.
프로젝트를 실행하면 앞서 프로젝트 생성 직후의 화면과 다르게 Show All PostEntity Items라는 링크가 나온다. 이 링크를 누르면 PostEntity에 대해 CRUD를 할 수 있는 페이지가 나온다. New PostEntity 링크를 눌러 Body 텍스트 필드에 아무것이나 입력한 다음 Create 링크를 누르면 생성된 결과 목록이 출력된다.
꽤 간단한 기능이지만, 그 뒤로는 상당한 양의 코드가 생성됐음을 프로젝트의 아티팩트 변화로 알 수 있다. 먼저 Source Packages에 PostEntity 말고도 PostEntityController, PostEntityConverter, PostEntityFacade가 생성되었고, microblog.util 패키지가 아예 새로 생겨 관련 유틸리티 클래스들이 들어가 있다. Web Pages에는 postEntity 디렉터리 안에 Detail, Edit, List, New JSP 파일이 생성되었고, CRUD 처리를 위한 CSS와 자바스크립트가 그 상위에 jsfcrud라는 이름으로 담겨 있다.
마치 레일즈의 스캐폴드(scaffold)를 보는 듯한데, 이렇게 엔티티가 사용자와 연결되며, 그 사이를 세션 퍼사드(PostEntityFacade) - 컨버터(PostEntityConverter) - 컨트롤러(PostEntityController) - JSF 페이지가 잇고 있다. 여기서 컨버터는 자바 오브젝트를 웹 프로토콜에서 처리할 수 있도록 직렬화•직렬화해제하는 일을 한다. JSF는 단순히 페이지 처리 기술이 아니라, 이렇듯 MVC 구조를 구현하는 프레임워크라 할 수 있다.
웹 RI(REST interface)
JSF와 마찬가지로 JAX-RS도 엔티티 클래스로부터 생성이 가능하다. File » New File에서 Web Services 카테고리로 RESTful Web Services from Entity Classes를 선택한 다음 Next 버튼을 누르면, JSF의 경우와 아주 비슷한 엔티티 빈 선택 화면이 나오며 Add한 다음 Next를 누르면 생성될 코드에 대한 개요를 보여준다. Finish 버튼을 눌러 완료한 다음 프로젝트를 실행한다.
이번에는 화면 변화는 없으며, 대신 microblog 프로젝트 뷰에 RESTful Web Services라는 항목이 생겨 거기에 PostEntitesResource와 PostEntityResource가 있음을 볼 수 있다. (배포를 하면 이전 데이터가 모두 지워지므로) 이것들을 테스트하기 전에 웹 UI로 데이터를 먼저 채워 넣자. 그런 다음 PostEntitiesResource를 선택하여 컨텍스트 메뉴로 Test Resource Uri를 선택하면 해당 URI로 브라우저가 열리면서 XML 파일이 보인다(사파리의 경우 XML이 바로 나오지 않아 소스 보기로 확인한다). 결과는 대략 다음과 같이 나온다.
«?xml version="1.0" encoding="UTF-8" standalone="yes"?»
«postEntities uri="http://localhost:8080/microblog/resources/postEntities/"»
«postEntity uri="http://localhost:8080/microblog/resources/postEntities/1/"»«body»test«/body»«id»1«/id»«/postEntity»
«postEntity uri="http://localhost:8080/microblog/resources/postEntities/2/"»«body»한글«/body»«id»2«/id»«/postEntity»
«/postEntities»
|
더불어 http://localhost:8080/microblog/resources/postEntities/1/을 브라우저로 열면 목록이 아닌 항목이 나온다.
«?xml version="1.0" encoding="UTF-8" standalone="yes"?»
«postEntity uri="http://localhost:8080/microblog/resources/postEntities/1"»«body»test«/body»«id»1«/id»«/postEntity»
|
각 리소스를 프로젝트 뷰에서 펼쳐보면, 부가 정보가 나오는데 HTTP 메서드를 보면 다음과 같은 것이 가능하다.
- 복수(plural) URI인 http://localhost:8080/microblog/resources/postEntities/에는 GET과 POST 메서드가 가능하며
- 단수(singular) URI인 http://localhost:8080/microblog/resources/postEntities/id에는 GET, PUT, DELETE 메서드가 가능하다.
생성된 클래스들은 SF와 구조가 흡사하다. service 패키지에는 리소스 게이트웨이 역할인 PostEntitiesResource와 PostEntityResource, 그리고 PostEntity를 관리하는 PersistenceService가 있다. converter 패키지에는 URI와 엔티티를 연결하는 유틸리티인 UriResolver와 각 엔티티의 자바 오브젝트와 XML간의 변환을 맡는 PostEntitiesConverter와 PostEntityConverter가 있다. 정리하면 엔티티 - 퍼시스턴스 서비스 - 컨버터 - 리소스의 형태가 된다.
더 나은 미래
레일즈만큼이나 간단하게 하나의 엔티티를 웹 UI와 RI로 노출하는 웹 애플리케이션을 만들어 보았다. 엔티티 빈과 세션 빈을 따로 EJB 모듈로 만들지 않고도 웹 애플리케이션 안에서 편하게 쓸 수 있는 EJB 3.1 Lite도 시나브로 쓰였다. 하지만 자동 코드 생성에 많이 의지한 탓에 간결한 형태를 지니지 못한 것이 눈에 띈다. 좀 더 이상적인 형태로 한다면 다음과 같은 형태 정도를 구상해볼 만하다.
독자 여러분들의 도전을 바라며, 다음 칼럼에서 더 논의해보면 좋겠다.
PostEntity(엔티티) - PostEntityFacade(세션) - (JSF 또는 JAX-RS의) (컨버터 - 컨트롤러) - JSF 페이지
|
이 문서 북마킹 하기
[지난 developerWorks Column 보기]
|