SlideShare ist ein Scribd-Unternehmen logo
1 von 4
Downloaden Sie, um offline zu lesen
Technology & Developer 설계 차원의 단순성 Spring 2011 64 65 Spring 2011 설계 차원의 단순성 Technology & Developer 
out.close(); 
} 
} 
기본 생성자(default constructor)를 포함해야 한다는 것 이외에 주입된 
클래스에 대한 특정한 요구 사항은 없다. 
public class Hello { 
public String helloWorld(){ 
return “Hello World”; 
} 
} 
이에서 제시된 예제가 실행되도록 하기 위해서는 다음과 같은 컨텐츠를 
포함하고 있는 빈 상태의 beans.xml deployment descriptor도 필요할 
것이다: <beans></beans>. WEB-INF 폴더 내에 이러한 구성 파일이 있 
는 경우, CDI 기능이 활성화된다. 
Hello 클래스는 POJO이며, EJB가 아니라는 점을 유념해야 한다. 이는 
선언되거나 구성될 필요가 없으며 @Inject 어노테이션은 적절한 생성과 
라이프사이클 관리가 이루어지도록 한다. 실제 운영 환경에서는 POJO를 
서블릿에 주입하는 경우는 극히 드물다. 아마도 UI 프레임워크(JSF 2와 
같은)를 허용하거나 REST(Representational State Transfer)를 통해 
서비스를 보여주는 방법을 선호할 것이다. 이와 같은 경우, CDI를 사용하 
는 것이 훨씬 유용하다. 
예를 들어, 데이터베이스 내에 메시지 문자열을 저장하는 간단한 
MessageMe 애플리케이션을 생각해 보겠다. JSF 2 마크업(Markup) 
은 inputText와 commandButton 등 2개의 컴포넌트로 구성되어 있다. 
리스팅 2에서와 같이 inputText는 속성 메시지를 포함한 이름 색인을 가 
진 클래스에 대한 value-bound 함수이며, 따라서 컨텐츠 속성을 가지고 
있다. commandButtons의 action 속성은 이름 색인을 가진 backing 
bean의 save 메소드에 바인딩된다. 
코드 리스팅 2: index.xhtml: CDI 내부 빈에 값 바인딩 
<h:body> 
<h:form> 
Content:<h:inputText value=”#{index.message.content}”/> 
<br/> 
<h:commandButton value=”Save” action=”#{index.save}”/> 
</h:form> 
2006년 발표된 Java Platform, Enterprise Edition (Java EE) 5은 엔 
터프라이즈 애플리케이션 개발을 단순화하는데 크게 기여했다. 2009년 
출시된 Java EE 6은 설계 및 아키텍처 작업을 더욱 쉽게 수행할 수 있 
도록 했다. Java EE 6는 소규모의 상황적 애플리케이션(Situational 
applications)을 그 어떤 오버헤드 없이 신속하게 개발하는 데 적합한 옵 
션이다. 이 글에서는 개발자들이 효율적이고 단순하며 손쉽게 유지 관리 
할 수 있는 애플리케이션을 개발할 수 있도록 돕는 여러 다양한 Java EE 6 
아키텍처와 설계 접근 방식에 대해 설명한다. 
Java EE 6는 Java EE의 이름으로 함께 릴리즈 된 일련의 독립 API로 구 
성되어 있다. 이들 API는 독립적이지만, 놀라울 만큼 서로 긴밀하게 연 
동된다. 하나의 애플리케이션에서 오직 JavaServer Faces (JSF) 2.0만 
을 이용할 수 있거나, 트랜잭션 서비스를 위해 Enterprise JavaBeans 
(EJB) 3.1을 이용할 수 있거나, 아니면 Java Persistence API (JPA) 2.0 
과 Bean Validation 모델을 채용한 CDI(Contexts and Dependency 
Injection)를 이용하여 트랜잭션을 이행할 수 있다. 
상용 Java EE 6 API를 실용적으로 혼용하여 애플리케이션 내 트랜잭션, 
스레딩(Threading), 스로틀링(Throttling) 또는 모니터링 등과 같은 인프 
라 서비스를 구현해야 하는 필요성을 완전히 제거할 수 있다. 오버헤드와 
복잡성을 최소화하고 커스텀 코드를 이용해서 모든 기본적인 요소들을 새 
로 개발할 필요가 없도록 하는 최적 API 하위 집합을 선택하는 것은 결코 
쉽지 않다. 일반적으로, 대안을 찾기 위해 검토 범위를 확대하기 전에 기존 
Java SE 및 Java EE 서비스를 사용하기 위해 모든 노력을 해야 한다. 
CDI: 표준 글루(glue) 
Java EE 6이 출시되면서 처음 소개된 CDI는Java EE 6 규격의 여러 파트 
를 위한 글루 기능을 수행하고 POJO (Plain Old Java Object) 빈의 라 
이프사이클을 관리하며 DI(Dependency Injection)를 위한 type-safe 
메커니즘을 사용한다. CDI는 또한, 이벤트, 인터셉터(Interceptor), 데 
코레이터(Decorators), 표준화된 확장 조건(Standardized extension 
points), 서비스 프로바이더 인터페이스(Service provider interface) 등 
과 같은 많은 강력한 기능을 선보였다. 
CDI자체가 새로운 개념이며 통합레이어 역활을 하도록 설계되었기 때 
문에 이전의 기술들과 일부 중복된다. 비록 EJB 3.1 injection 또는 JSF 
managed bean을 직접 사용할 수 있지만, 가능한 CDI를 사용하는 것을 
고려해야 한다. CDI는 더욱 강력할 뿐만 아니라, 단일 API를 이용함으로 
써 애플리케이션을 단순화할 수 있다. 
CDI는 어노테이션(Annotation)을 이용하여 DI(Dependency Injection) 
을 수행한다. 가장 중요한 어노테이션은 javax.inject.Inject이다. 리스 
팅 1에 있는 예제는 이 어노테이션이 POJO를 서블릿에 주입하는 데 사 
용되는 방법을 보여주고 있다. 수행해야 하는 작업은 필드를 선언하고 @ 
Inject 어노테이션을 다는 것뿐이다. 이 코드가 실행되면 컨테이너는 비즈 
니스 메소드가 실행되기 전에 @Inject 어노테이션이 달린 필드를 자동으 
로 초기화한다. 
코드 리스팅 1: @Inject으로 서블릿에 POJO 주입 
@WebServlet(name=”HelloWorldService”, urlPatterns={“/ 
HelloWorldService”}) 
public class HelloWorldHTTPService extends HttpServlet { 
@Inject 
private Hello hello; 
@Override 
protected void doGet (Ht tpServletRequest request , 
HttpServletResponse response) 
throws ServletException, IOException { 
PrintWriter out = response.getWriter(); 
out.println(hello.helloWorld()); 
out.flush(); 
</h:body> 
리스팅 3은 요청 처리를 위한 @RequestScoped를 이용해 request-scoped 
CDI 빈으로서 구현된 backing bean을 보여준다. JSF 2 
managed bean (@ManagedBean 어노테이션)을 사용할 수 있지만, 
CDI도 그만큼 강력하다. 또한, CDI를 사용하면, 모든 애플리케이션 레이 
어 전반에 걸쳐 단일 글루 API를 적용하여 어디에서나 아키텍처를 단순화 
할 수 있다. 
코드 리스팅 3: 주입된 EJB을 포함한 CDI backing bean 
package com.abien.messageme.presentation; 
import com.abien.messageme.business.messaging.boundary. 
Messaging; 
import com.abien.messageme.business.messaging.entity. 
Message; 
import javax.enterprise.context.RequestScoped; 
import javax.inject.Inject; 
import javax.inject.Named; 
@Named 
@RequestScoped 
public class Index { 
@Inject 
Messaging ms; 
private Message message = new Message(); 
public Message getMessage() { 
return message; 
} 
public void save(){ 
ms.store(message); 
} 
} 
어노테이션 @Named (JSR 330 규격에 명시되고 Guice and Spring 
에 구현된 바와 같이)은 색인 backing bean을 모든 EL(expression 
language) 마크업 형태로 나타낼 수 있도록 한다. 이는 JSF 2 내 backing 
bean의 이름은 클래스 이름에서 추출한다는“CoC(Convention over 
Configuration)” 원칙을 따른다. 첫 글자에 대문자를 사용하지 않는다. 
Message 클래스는 리스팅 4에서와 같이 JPA 2 엔티티로 구현된다. 
설계 차원의 단순성 : 
새로운 Java EE 6 기능을 활용하여 
단순하고 유지 관리하기 쉬운 애플리케이션 개발 
저자 - Adam Bien 
감수 - 이창제 Architect, OFM APAC Solutions & Technology Architects
Technology & Developer 설계 차원의 단순성 Spring 2011 66 67 Spring 2011 설계 차원의 단순성 Technology & Developer 
코드 리스팅 4: Bean Validation으로 검증된 JPA 2 엔티티 
package com.abien.messageme.business.messaging.entity; 
@Entity 
public class Message { 
@Id 
@GeneratedValue 
private Long id; 
@Size(min=2,max=140) 
private String content; 
public Message(String content) { 
this.content = content; 
} 
public Message() { /*required by JPA */} 
public String getContent() { 
return content; 
} 
public void setContent(String content) { 
this.content = content; 
} 
public Long getId() { 
return id; 
} 
} 
이 예제의 다음 클래스는 Messaging 클래스로서 EJB 3.1 세션 빈 
(Session bean)으로 구현되었다. 이 클래스는 “CDI everywhere” 규 
칙의 실제적인 예외를 보여주고 있다. EJB는 트랜잭션, 풀링(Pooling), 
Java Management Extensions (JMX) 모니터링 및 비동기식 실행 등 
과 같은 많은 기능을 단지 @Stateless 어노테이션 하나만으로 제공할 수 
있다. 향후의 Java EE 릴리스에서는 이들 aspect들이 EJB에서 추출되 
고 CDI에서도 이용할 수 있게 될 것이다. 하지만, Java EE 6에서는 비즈 
니스 컴포넌트의 바운더리(Boundary) 또는 퍼사드(Facade) 들이 무상 
태 세션 빈(Stateless session bean)으로서 가장 효과적으로 구현된다. 
리스팅 5의 @Asynchronous 어노테이션은 특히 흥미롭다. 이 어노테이 
션은 메소드가 비동기이면서도 트랜젝션을 지원하는 메소드 실행을 지원 
하며, 오직 EJB용으로만 이용할 수 있다. Messaging EJB 는@EJB가 아 
닌 @Inject를 이용하여 주입된다는 점을 유념하라. 실제 업무에서 두 어노 
테이션 모두 적용되며 거의 차이가 없다. @Inject의 사용이 약간 더 강력하 
며 상속(inheritance)을 지원한다. 반면, @EJB 어노테이션은 오직 EJB에 
서만 실행된다. 
코드 리스팅 5: EJB 세션 빈으로서 구현된 바운더리 
package com.abien.messageme.business.messaging.boundary; 
import com.abien.messageme.business.messaging.control. 
MessageStore; 
import com.abien.messageme.business.messaging.entity. 
Message; 
import javax.ejb.Asynchronous; 
import javax.ejb.Stateless; 
import javax.inject.Inject; 
@Stateless 
public class Messaging { 
@Inject 
MessageStore messageStore; 
@Asynchronous 
public void store(Message message){ 
messageStore.store(message); 
} 
} 
리스팅 6의 MessageStore 클래스는 EntityManager에 대한 액세스를 
캡슐화한 DAO(Data Access Object)이다. 
코드 리스팅 6: 컨트롤 레이어의 CDI 빈 
package com.abien.messageme.business.messaging.control; 
import com.abien.messageme.business.messaging.entity. 
Message; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
public class MessageStore { 
@PersistenceContext 
EntityManager em; 
public void store(Message message){ 
em.persist(message); 
} 
} 
ECB: 실용적인 SoC(Separation of Concern) 
위에서 설명한 애플리케이션의 패키징을 검토한다면, 별도의 바운더리, 
컨트롤 및 엔티티 패키지를 확인하게 될 것이다. 이 패키징 접근 방식은 
ECB(Entity Control Boundary) 패턴의 구현이다. 바운더리 레이어는 퍼 
사드이며, 컨트롤 레이어는 프로세스 – 및 엔티티 – 독립적인 로직의 구 
현을 담당한다. 그리고 엔티티 레이어는 많은 도메인 객체를 포함하고 있 
다. 
Java EE 6과 특히 JPA 2, CDI, 및 EJB를 이용할 수 있음에 따라 모든 3개 
레이어의 구현은 빈 상태의 델리케이트(Delegate) 코드로 이어질 수 있 
다. 예를 들어 많은 CRUD 기반 유스 케이스는 다수의 엔티티에 액세스하 
는 퍼사드의 기능을 수행하는 단일 바운더리를 이용해서 매우 효율적으로 
구현될 수 있다. 
하지만, ECB 패턴 내 개념과 컴포넌트 내부 패키지 간의 직접적인 1대1 관 
계가 여전히 효율적일 수 있다. 패키지가 계속해서 분리되어 있는 경우, 패 
키지 간의 종속성을 측정하는 데 정적 분석 툴이 보다 쉽게 사용될 수 있 
다. 뿐만 아니라, OSGi와 Jigsaw 등과 같은 프레임워크는 별도의 패키지 
가 존재한다는 사실을 토대로 공용 API를 나타낸다. 
Java EE 6에서 바운더리는 항상 EJB를 인식한다. 컨트롤 레이어는 CDI 
또는 EJB 중 하나를 포함할 수 있으며 엔티티 레이어는 JPA 2 엔티티 또 
는 transient, unmanaged 엔티티를 포함할 수 있다. 컨트롤 레이어 내 
에서 CDI나 EJB 중 어떤 것을 사용할 것인지에 대한 결정을 반드시 사 
전에 내릴 필요는 없다. CDI에서 시작하고 진행하면서 @Stateless 어노 
테이션을 사용하여 EJB로 변환할 수 있다. @RequiresNew로 후속 트 
랜잭션을 시작해야 할 때, 메소드를 비동기식으로 실행해야 할 때, 또는 
SessionContext.setRollbackOnly()를 호출하여 현재의 트랜잭션을 롤 
백시켜야 할 때 등 몇몇 경우에는 EJB를 사용해야 한다. 
반면, CDI는 레거시 코드를 통합하거나 Strategy, Factory 또는 
Observer 소프트웨어 설계 패턴을 구현하는 경우에 더욱 적합하다. 이들 
기능 모두는 이미 기본 내장되어 있으며 따라서, Java SE의 기능을 이용 
하는 경우보다 코드 수를 크게 줄일 수 있다. 
ECB 패턴을 이용하여 애플리케이션을 개발하는 경우, ECB 레이어링은 
반복적으로 전개해야 하며 하향식(Top-down)으로 강제되어서는 안된 
다. 영속성 (Entity) 레이어에서 시작하고 단위 테스트(Unit testing)를 수 
행한 다음 바운더리 레이어를 구현해야 한다. 단위 테스트를 개발하기 위 
해 EntityManager와 관련 트랜잭션을 수작업으로 생성하고 관리해야 한 
다(리스팅 7 참조). 
코드 리스팅 7: 단독형 JPA 단위 테스트 
package com.abien.messageme.business.messaging.entity; 
import javax.persistence.*; 
import org.junit.Test; 
@Test 
public void mappingSmokeTest() { 
EntityManagerFactory emf = Persistence.createEntityManage 
rFactory(“test”); 
EntityManager em = emf.createEntityManager(); 
EntityTransaction tx = em.getTransaction(); 
tx.begin(); 
em.persist(new Message(“duke”)); 
tx.commit(); 
} 
persistence.xml 파일도 단독 실행을 처리하도록 수정되어야 한다. 특 
히, 트랜잭션 유형을 RESOURCE_LOCAL로 변경해야 하며 JDBC 커넥션 
(Datasource 대신)은 리스팅 8에서와 같이 명시적으로 구성되어야 한다. 
코드 리스팅 8: 독립형 JPA 단위 테스트를 위한 persistence.xml 
<persistence> 
<persistence-unit name=”test” transaction-type=”RESOURCE_ 
LOCAL”> 
<provider>org.eclipse.persistence.jpa.PersistenceProvider</ 
provider> 
<class>com.abien.messageme.business.messaging.entity. 
Message</class> 
<exclude-unlisted-classes>true</exclude-unlisted-classes> 
<properties> 
< p r o p e r t y n a m e = ” j a v a x . p e r s i s t e n c e . j d b c . u r l ” 
value=”jdbc:derby: 
./sample;create=true”/> 
<property name=”javax.persistence.jdbc.password” 
value=”app”/> 
<property name=”javax.persistence.jdbc.driver” value=”org. 
apache.derby 
.jdbc.EmbeddedDriver”/>
Technology & Developer 설계 차원의 단순성 Spring 2011 68 69 Spring 2011 설계 차원의 단순성 Technology & Developer 
<property name=”javax.persistence.jdbc.user” value=”app”/> 
<property name=”eclipselink.ddl-generation” value=”drop-and- 
create-tables”/> 
</properties> 
</persistence-unit> 
</Persistence> 
컨트롤 레이어를 개발할 때, 그 컨텐츠가 엔터티 및 바운더리 레이어 리 
팩토링(Refactoring)의 산물이 되어야 한다는 점을 유념해야한다. 쿼리 
(Queries), 알고리즘(Algorithms) 또는 검증 등과 같이 바운더리 레이어 
의 재사용 가능하고 응집력이 없는(Noncohesive)는 컨트롤 레이어의 
CDI managed bean으로 추출되어야 한다. 
ECB 패턴의 사용 
ECB 패턴의 주요 목적은 비즈니스 및 프레젠테이션 로직 간의 명확한 구 
분을 제공한다는 것이다. 정의에 따라 바운더리는 프레젠테이션 로직에 
서 독립되어야 한다. 실제 아키텍처에서 많은 절충이 이루어지고 있지만, 
비즈니스와 UI 기술 간의 명확한 구분이 이루어져야 한다. 실제로, UI 로 
직은 비즈니스 로직보다 더욱 자주 변경되는 경향이 있다. 웹 클라이언트 
(JSF 2 등), 리치 클라이언트(Swing 또는 Eclipse RCP 등) 그리고 REST 
등에 의해 동시에 액세스될 수 있는 비즈니스 로직을 생성하는 것이 일반 
적이다. 
JSF 2의 경우, CDI는 컨트롤러(Controller) 또는 프레젠터(Presenter)를 
구현하기 위한 가장 쉬운 옵션이다. CDI managed bean은 EL을 통해 JSF 
2에 직접 바운딩될 수 있으며 바운더리(EJB 3.1)는 프레젠터로 직접 주입 
될 수 있다. 프레젠터(또는 컨트롤러)는 @Stereotype 어노테이션으로 직 
접 포착될 수 있다. 이는 매크로처럼 실행되며 그 안에 CDI 어노테이션을 
배치하고 이 어노테이션으로 확장할 수 있다. 스테레오타입(Stereotype) 
은 @Stereotype으로 표시되는 표준 Java 어노테이션이다. 
@Named 
@RequestScoped 
@Stereotype 
@Retention(RUNTIME) 
@Target(TYPE) 
public @interface Presenter {} 
커스텀 스테레오타입(custom stereotype)은 매크로와 마찬가지로 @ 
Messaging boundary; 
@Inject 
IndexView indexView; 
public void save(){ 
boundary.store(indexView 
.getMessage()); 
} 
} 
바운더리와 뷰가 IndexPresenter에 주입되기 때문에 쉽게 mocking 할 
수 있다. 단위 테스트 환경에서 두 필드는 mock을 이용해 설정되지만, 실 
제 운영 환경에서는 컨테이너가 주입을 실행하고 실제 종속성을 설정하게 
된다. 단위 테스트와 IndexPresenter가 동일한 패키지 내에 있기 때문에 
기본 visible 필드는 직접 설정할 수 있다. public setter를 포함한 private 
필드가 사용될 수 있지만, 대개의 경우 packagewide 필드로 충분하며 
코드 사이즈를 줄일 수 있다. 
리스팅 9는 IndexView는 물론, 바운더리 Messaging 클래스를 
mocking화 함으로써 프레젠테이션 로직을 테스트하는 방법을 보여준다. 
IndexPresenter.save() 메소드를 호출하는 이 테스트는 메소드 스토어 
를 단 한 번 호출하고, IndexView에 의해 Message-Instance가 반환되 
면 성공적이다. 호출을 검증한다는 것은 mock를 Mockito.verify() 메소 
드로 보낸다는 것을 의미한다. IndexView는 JSF 렌더링과 상호 작용하 
지 않고도 반환 값을 가공하도록 모의화에서 제외된다. 
코드 리스팅 9: IndexPresenter테스트—모의화에서 제외된 뷰 및 바운 
더리 이용 
package com.abien.messageme.presentation; 
//...other imports 
import org.junit.Before; 
import org.junit.Test; 
import static org.mockito.Mockito.*; 
public class IndexPresenterTest { 
private IndexPresenter cut; 
@Before 
public void initialize(){ 
this.cut = new IndexPresenter(); 
} 
Named 및 @RequestScoped 대신 적용될 수 있다. 그러면, 프레젠터 패 
턴을 식별하는 모든 CDI 어노테이션을 대체할 수 있다. 
@Presenter 
public class Index { 
// 
} 
프레젠터의 목적은 프레젠테이션 로직을 구현하는 것이다. 프레젠터의 구 
조는 뷰와 긴밀히 결합되어 있으며 이 뷰 내 JSF 컴포넌트의 상태 내에서 
프레젠터 내부의 속성으로 매핑될 수 있다. 속성은 값(값 바인딩으로)이나 
컴포넌트 인스턴스 그 자체(컴포넌트 바인딩으로) 중 하나가 될 수 있다. 
때때로 뷰와 프레젠터 간에 1대1 관계가 있는 경우도 있다. 이 프레젠터는 
뷰의 데이터는 물론, 모든 프렌젠테이션 로직을 포함하고 있다. 바운더리 
를 프레젠터에 주입하기 위해서는 @Inject 어노테이션을 사용해야 한다. 
프레젠테이션 로직의 수가 프레젠터 내부에서 증가하고 있기 때문에 코 
드를 유지하고 테스트하는 것이 더욱 어려워질 수 있다. CDI를 통해 단 
일 프레젠터를 매우 손쉽게 분리된 데이터 및 프레젠테이션 로직 파트 
로 분산시킬 수 있다. 예를 들어, 아래 코드는 save 메소드를 새로 만든 
IndexPresenter 빈으로 옮겨 앞에 나온 예제에서 backing bean을 리 
팩토링하는 방법을 보여주고 있다. 프레젠터 어노테이션은 중복되고 @ 
View으로 이름이 변경되며, 이 빈은 IndexView로 이름이 변경된다. 
@View 
public class IndexView { 
private Message message = new Message(); 
public Message getMessage() { 
return message; 
} 
} 
IndexPresenter 빈은 이전 @Presenter 어노테이션을 가져온다. 아래 
코드에서 볼 수 있듯이, 이 사례에서 IndexPresenter 빈의 유일한 목적 
은 프레젠테이션 로직을 구현하는 것이다. 
@Presenter 
public class IndexPresenter { 
@Inject 
@Test 
public void save() { 
this.cut.boundary = mock(Messaging.class); 
this.cut.indexView = mock(IndexView.class); 
Message expected = new Message(“duke”); 
whe n ( t h i s . c u t . i n d e x Vi e w. g e t M e s s a g e ( ) ) . 
thenReturn(expected); 
cut.save(); 
verify(this.cut.boundary,times(1)).store(expected); 
} 
} 
메시징 바운더리는 다른 이유로 즉, 예상 메소드가 실제로 호출되었는지 
를 검증하기 위해 모의화에서 제외된다. 
public void save(){ 
boundary.store(indexView 
.getMessage()); 
} 
JSF 2 프레젠테이션의 설계는 리치 Swing 애플리케이션의 설계 
와 유사하다. Model-View-Controller와 같은 공통의 패턴과 그 개 
선—Supervising Controller 및 Passive View—은 JSF 2에도 적용될 
수 있다. JSF와 리치 클라이언트 기술 간의 가장 중요한 차이점은 뷰가 
렌더링되는 방법이다. Swing에서 개발자들은 Java로 뷰를 구현하지만, 
JSF 2에서 개발자들은 XHTML 마크업을 사용한다. JSF 2에서 컨포넌트 
의 값은 해당 클래스에 직접 바인딩될 수 있지만, Swing에서는 대개 뷰 자 
체 내에 또는 모델에 저장된다. 
CRUD와 같은 데이터 중심의 유스 케이스를 구현하려는 경우, 
Supervising Controller가 Passive View보다 나은 옵션이다. 
Supervising Controller 패턴에서 단일 패키팅 빈(IndexView)은 프레 
젠테이션 로직과 뷰 상태 모두를 관리하는 책임을 맡고 있다. 더욱 복잡한 
유스 케이스에서는 Passive View 변수가 보다 적합할 것이다. Passive 
View 패턴에서는 backing bean이 뷰 및 프레젠테이션 로직으로 분산되 
며 프레젠테이션 로직은 IndexView에서 IndexPresenter로 추출된다. 
CDI는 프레젠테이션 레이어의 구현에 가장 적합하다. 기본 내장된 공통 
관심 사항(Cross-cutting concerns, 여기에는 트랜잭션, 동시성, 비동기 
식 실행 모니터링 및 스로틀링 등이 해당 됨) 때문에 비즈니스 로직의 바운 
더리가 EJB로서 실체화된다. 비즈니스 컴포넌트는 EJB 또는 CDI로 실체
71 Spring 2011 시뮬레이션을 통한 성능 증명 Technology & Developer 
화될 수 있다. 일반적으로 CDI에서 시작하고, 시간이 지난 후, 특수한 케 
이스의 managed bean을 EJB로 대체할 수 있다. CDI-EJB-CDI (CEC) 
패턴은 Java EE 6을 위한 가장 단순하고 가장 실용적인 옵션이다. 
인터페이스를 유용하게 만드는 방법 
EJB 3.0 (Java EE 5에서)는 bean 클래스를 위한 별도의 인터페이스 
를 요구했다. 네이밍 충돌을 방지하기 위해 개발자들은 종종 XyzLocal/ 
XyzRemote 및 XyzBean와 같이 체계적으로 규정된 명명 규칙을 사용해 
야 했다. Java EE 6에서 EJB 및CDI를 위한 인터페이스는 이제 옵션이 되 
었다. Public EJB 또는 CDI 메소드는 이제 그 어떤 기능의 손실도 없이 
“no interface” 뷰를 보여줄 수 있다. 
새로운 기능은 다시한번 인터페이스를 중요하게 만들었다. 이전 릴리스에 
서 강제적이면서도 막연하게 인터페이스를 사용했던 것과는 달리, Java 
EE 6 의 인터페이스는 Strategy 패턴의 구현, Public API의 구현 또는 엄 
격한 모듈 분리(코드를 보다 분명하게 나타낼 수 있도록 함)를 위해 사용 
될 수 있다. 인터페이스는 시스템의 “Protected variations”를 나타내고 
클래스 간의 직접적인 종속성은 변경될 가능성이 낮은 코드를 위해 사용 
될 수 있다. 
인터페이스 없이 개발을 시작해서 필요에 따라서 이를 적용할 수 있다. 이 
와 같은 접근 방식은 Java EE 5에서와 근본적으로 차이가 있다. 2003년 
부터 나온 Java 2 Platform, Enterprise Edition (J2EE)에 비해 Java EE 
6 코드는 여러 레이어, 간접 지정(Indirections) 및 추상화 등이 제거됨에 
따라 훨씬 단순하다. J2EE와 달리, Java EE 6는 플랫폼에 대한 종속성 없 
이 주석이 붙은 클래스로 구성되어 있다. 이와 같은 접근 방식은 인프라에 
서 비즈니스 로직을 분리해야 하는 필요성을 없애고 대부분의 J2EE 패턴 
과 모범 사례를 불필요하게 만든다. Java EE 6에서는 프레젠테이션 및 비 
즈니스 로직으로 단순한 사례를 해결할 수 있다. EntityManager는 이미 
충분히 훌륭한 주요 영속성의 추상화 기능을 제공하기 때문에 추가 간접 
지정 기능은 전혀 필요하지 않다. 
쉽게 유지 관리할 수 있는 Java EE 6 애플리케이션은 YAGNI (You Ain’t 
Gonna Need It), DRY (Don’t Repeat Yourself), 그리고KISS (Keep It 
Simple, Stupid) 원칙에 따라 작성된다. 설계 패턴과 모범 사례는 하향식 
(Top-down)이 아니라 상향식(Bottom-up)으로 도입된다. 이와 같은 패 
턴은 언제나 플랫폼의 한계가 아니라, 기능 및 비 기능 요구 사항에 의해 
주도된다. 이러한 접근 방식은 Java EE 6과 이전 J2EE 릴리스 간의 가장 
큰 차이점을 나타낸다. J2EE에서는 J2EE 플랫폼 종속성에 따라 많은 설 
계 의사 결정이 사전에 이루어졌다. 
반대로, Java EE 6 개발 프로세스는 기능에 초점을 맞추고 있다. 
1. 비즈니스 문제를 직접 해결하는 단순한 코드 작성 
2. 단위 테스트로 비즈니스 로직 검증 
3. 종속성 단절 및 리팩토링으로 설계 향상 
4. 애플리케이션에 대한 스트레스 테스트 
5. 다시 1로 되돌아가기 
설계 및 아키텍처는 일반적인 아키텍처 차원의 모범 사례가 아니라 구체 
적인 요구 사항에 따라 이루어진다. 지속적으로(적어도 1주일에 한번) 애 
플리케이션에 대한 스트레스 테스트를 수행함으로써, 확실한 사실(Hard 
fact)을 이용하여 단순한 설계에 대한 타당성을 보다 손쉽게 입증하고 스 
트레스가 가해졌을 때 시스템의 작동에 대한 정보를 확보할 수 있다. 
시뮬레이션을 통한 성능 증명 : 
저자 - Arup Nanda 
감수자 - 김상엽 
SQL Performance Analyzer에서 Oracle Exadata 시뮬레이션 기능을 
이용한 Oracle Exadata환경에서 실행되는 애플리케이션의 성능 예측 
데이터베이스 시장의 ‘혁신적 파괴자’로 최근 등장한 Oracle Exadata 
는 그 유형에 관계없이 애플리케이션 성능을 향상시키고 있다. 하지만, 
Oracle Exadata로의 마이그레이션을 고려하고 있는 사람들이 가장 궁 
금해 하는 것은 아마도 ‘기존 데이터베이스에서 실행 중인 애플리케이 
션들이 Oracle Exadata에서 적절하게 실행되느냐’하는 것이다. 실제 
로 Oracle Exadata로 마이그레이션을 하기 전에 그 해답을 확인할 수 
있는 방법은 없을까? Oracle Database 11g Release 2에서는 Oracle 
Exadata 어플라이언스에 실제로 투자하기 전에 Oracle Exadata에서 
데이터베이스 작업을 시뮬레이션 및 측정할 수 있도록 지원하는 새로운 
기능이 추가되었다. 이 글에서는 이 시뮬레이션 기능을 사용해 Oracle 
Exadata에서 실행 중인 애플리케이션의 성능을 예측할 수 있는 방법에 
대해 알아보겠다. 
시뮬레이션을 위한 토대 
Oracle Database 11g Release 1은 Oracle Real Application Testing 
스위트의 구성 요소인 SQL Performance Analyzer를 새롭게 도입 
했다(Oracle Magazine 2008년 3월/4월호 “Performing Through 
Changes” 참조). 이 툴을 사용하면 모든 데이터베이스에서 SQL명령문 
을 포착하고, 이를 새로운 환경에서 재현(replay)함으로써 잠재적 문제를 
규명하고 새로운 대상 환경에서의 동작 상황을 예측할 수 있다. 
대상 환경은 인덱스, materialized view 등이 더 많거나 적을 수 있고, 기 
반구조가 다르거나, 다른 세션 매개변수 환경에서 운용되는 등 현재 운영 
중인 환경과 구조적으로 다를 수 있다. Oracle Database 11g Release 
2에서는 Oracle Exadata의 기능을 시뮬레이션할 수 있도록 SQL 
Performance Analyzer의 범위가 확장되었다. 
강력한 성능의 원천 
Oracle Exadata가 이렇게 뛰어난 성능을 발휘할 수 있는 비결 중 하나는 
바로 Oracle Exadata 스토리지가 위치한 스토리지 셀 내 인텔리전스로 
서, 이는 성능에 가장 큰 영향을 미치고 있다. 스토리지 셀은 저장된 데이 
터의 패턴을 알고 있기 때문에 모든 데이터가 아니라 연관성 있는 데이터 
만 지능적으로 반환할 수 있다. 아래 간단한 쿼리를 통해 이를 살펴볼 수 
있다. 
select sum(order_qty) 
from sales 
where cust_id = 1000 
기존 Oracle Database에서는 이미 메모리에 데이터 올라와 있는 경우가 
아니라면 SALES 테이블부터 모든 블록을 버퍼 캐시(시스템 글로벌 영역 
에 위치)로 가져오도록 서버 프로세스가 명령어를 실행한다. 그 다음, 세 
션은 CUST_ID = 1000인 행을 찾기 위해 누적된 데이터를 검사한다. 값 
이 일치하는 행들이 서버 프로세스의 프로그램 글로벌 영역으로 복사되 
고 또 다른 열인 ORDER_QTY의 합계가 계산된 후, 마지막으로 결과가 사 
용자에게 반환된다. 테이블은 10억 개까지 행을 가질 수 있고 CUST_ID = 
1000인 행 수는 100개에 불과한 경우에도 일치하는 행을 찾으려면 데이터 
베이스가 10억 개의 행을 모두 가져와서 검색해야 한다. I/O 서브시스템은 
여전히 테이블의 모든 블록을 서버 프로세스로 반환해야 한다. 이 경우, 스 
토리지는 데이터 구조에 대한 상황을 알지 못하기 때문에 관련 있는 데이 
터와 나머지 데이터를 구별할 수 없다. 
Oracle Real Application Clusters (Oracle RAC) 시스템에서도 또 다 
른 문제가 있다. 병렬 쿼리 슬레이브가 여러 인스턴스 상에 분리되어 있 
을 수 있다. 이들은 수집한 데이터를 대조를 위해 다른 인스턴스의 query 
coordinator로 인터커넥트를 통해 전송하기 때문에 인터커넥트 하드웨 
어가 이와 같은 트래픽으로 포화 상태가 된다. 뿐만 아니라, 인터커넥트를 
통해 블록을 전송하는 프로세스는 CPU를 사용하는 데다 래치(Latch)를 
필요로 하기 때문에 더 많은 CPU 사이클이 요구된다. 따라서, 스토리지 
시스템으로부터의 블록에 대한 요구가 클수록 CPU 및 I/O와 인터커넥트 
Technology & Developer 설계 차원의 단순성 Spring 2011 70 
저자 : Adam Bien (blog.adam-bien.com)은 Java Champion으로서 컨설턴트, 강사, 소프트웨어 아키 
텍트 겸 개발자로 활동하고 있으며 Real World Java EE Patterns: Rethinking Best Practices (lulu. 
com, 2009). 등과 같은 Java 전문 서적을 집필한 저자이기도 하다. 그는 Oracle Magazine의 2010년 올 
해의 Java 개발자(Java Developer of the Year)로 선정되었다.

Weitere ähnliche Inhalte

Andere mochten auch

CF Korea Meetup - Gemfire on PCF
CF Korea Meetup - Gemfire on PCF CF Korea Meetup - Gemfire on PCF
CF Korea Meetup - Gemfire on PCF Jay Lee
 
Our community design project
Our community design projectOur community design project
Our community design projectmaynelindsay
 
Jada 2003-vernillo-24 s-33s
Jada 2003-vernillo-24 s-33sJada 2003-vernillo-24 s-33s
Jada 2003-vernillo-24 s-33sMabel Salas
 
Java 8 & Beyond
Java 8 & BeyondJava 8 & Beyond
Java 8 & BeyondJay Lee
 
Java EE7
Java EE7Java EE7
Java EE7Jay Lee
 

Andere mochten auch (6)

CF Korea Meetup - Gemfire on PCF
CF Korea Meetup - Gemfire on PCF CF Korea Meetup - Gemfire on PCF
CF Korea Meetup - Gemfire on PCF
 
Our community design project
Our community design projectOur community design project
Our community design project
 
Jada 2003-vernillo-24 s-33s
Jada 2003-vernillo-24 s-33sJada 2003-vernillo-24 s-33s
Jada 2003-vernillo-24 s-33s
 
Java 8 & Beyond
Java 8 & BeyondJava 8 & Beyond
Java 8 & Beyond
 
Java EE7
Java EE7Java EE7
Java EE7
 
La7836
La7836La7836
La7836
 

Ähnlich wie JavaEE6 - 설계 차원의 단순성

11장 시스템
11장 시스템11장 시스템
11장 시스템kidoki
 
스프링 스터디 1장
스프링 스터디 1장스프링 스터디 1장
스프링 스터디 1장Seongchan Kang
 
[오픈소스컨설팅]Spring 3.1 Core
[오픈소스컨설팅]Spring 3.1 Core [오픈소스컨설팅]Spring 3.1 Core
[오픈소스컨설팅]Spring 3.1 Core Ji-Woong Choi
 
자바9 특징 (Java9 Features)
자바9 특징 (Java9 Features)자바9 특징 (Java9 Features)
자바9 특징 (Java9 Features)Chang-Hwan Han
 
자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)
자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)
자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)DK Lee
 
Spring3 발표자료 - 김연수
Spring3 발표자료 - 김연수Spring3 발표자료 - 김연수
Spring3 발표자료 - 김연수Yeon Soo Kim
 
Implementing_AOP_in_Spring_SYS4U
Implementing_AOP_in_Spring_SYS4UImplementing_AOP_in_Spring_SYS4U
Implementing_AOP_in_Spring_SYS4Usys4u
 
All about JDBC Performance Tuning_Wh apm
All about JDBC Performance Tuning_Wh apmAll about JDBC Performance Tuning_Wh apm
All about JDBC Performance Tuning_Wh apm엑셈
 
[Uws] enterprise application architecture, msa, java9, spring 소개
[Uws] enterprise application architecture, msa, java9, spring 소개[Uws] enterprise application architecture, msa, java9, spring 소개
[Uws] enterprise application architecture, msa, java9, spring 소개HYUN-JOO LEE
 
C Language II
C Language IIC Language II
C Language IISuho Kwon
 
Introduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&CIntroduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&Csys4u
 
[스프링 스터디 1일차] 템플릿
[스프링 스터디 1일차] 템플릿[스프링 스터디 1일차] 템플릿
[스프링 스터디 1일차] 템플릿AnselmKim
 
Spring vs. spring boot
Spring vs. spring bootSpring vs. spring boot
Spring vs. spring bootChloeChoi23
 
Better Scalable Flexible Soa Platform 0.8.0
Better Scalable Flexible Soa Platform 0.8.0Better Scalable Flexible Soa Platform 0.8.0
Better Scalable Flexible Soa Platform 0.8.0Kidong Lee
 
테스터도 알아야 할 웹 개발(테스트 교육 3장 1절 부분발췌)
테스터도 알아야 할 웹 개발(테스트 교육 3장 1절 부분발췌)테스터도 알아야 할 웹 개발(테스트 교육 3장 1절 부분발췌)
테스터도 알아야 할 웹 개발(테스트 교육 3장 1절 부분발췌)SangIn Choung
 
Java8 - Oracle Korea Magazine
Java8 - Oracle Korea MagazineJava8 - Oracle Korea Magazine
Java8 - Oracle Korea MagazineJay Lee
 
Sql 중심 코드 탈피 발표자료
Sql 중심 코드 탈피 발표자료Sql 중심 코드 탈피 발표자료
Sql 중심 코드 탈피 발표자료ssuser776e2d
 
Spring Boot + React + Gradle in VSCode
Spring Boot + React + Gradle in VSCodeSpring Boot + React + Gradle in VSCode
Spring Boot + React + Gradle in VSCodedpTablo
 
[H3 2012] Bridge over troubled water : make plug-in for Appspresso
[H3 2012] Bridge over troubled water : make plug-in for Appspresso[H3 2012] Bridge over troubled water : make plug-in for Appspresso
[H3 2012] Bridge over troubled water : make plug-in for AppspressoKTH, 케이티하이텔
 

Ähnlich wie JavaEE6 - 설계 차원의 단순성 (20)

11장 시스템
11장 시스템11장 시스템
11장 시스템
 
스프링 스터디 1장
스프링 스터디 1장스프링 스터디 1장
스프링 스터디 1장
 
[오픈소스컨설팅]Spring 3.1 Core
[오픈소스컨설팅]Spring 3.1 Core [오픈소스컨설팅]Spring 3.1 Core
[오픈소스컨설팅]Spring 3.1 Core
 
자바9 특징 (Java9 Features)
자바9 특징 (Java9 Features)자바9 특징 (Java9 Features)
자바9 특징 (Java9 Features)
 
자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)
자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)
자바 웹 개발 시작하기 (5주차 : 스프링 프래임워크)
 
J2 Ee
J2 EeJ2 Ee
J2 Ee
 
Spring3 발표자료 - 김연수
Spring3 발표자료 - 김연수Spring3 발표자료 - 김연수
Spring3 발표자료 - 김연수
 
Implementing_AOP_in_Spring_SYS4U
Implementing_AOP_in_Spring_SYS4UImplementing_AOP_in_Spring_SYS4U
Implementing_AOP_in_Spring_SYS4U
 
All about JDBC Performance Tuning_Wh apm
All about JDBC Performance Tuning_Wh apmAll about JDBC Performance Tuning_Wh apm
All about JDBC Performance Tuning_Wh apm
 
[Uws] enterprise application architecture, msa, java9, spring 소개
[Uws] enterprise application architecture, msa, java9, spring 소개[Uws] enterprise application architecture, msa, java9, spring 소개
[Uws] enterprise application architecture, msa, java9, spring 소개
 
C Language II
C Language IIC Language II
C Language II
 
Introduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&CIntroduction to Fork Join Framework_SYS4U I&C
Introduction to Fork Join Framework_SYS4U I&C
 
[스프링 스터디 1일차] 템플릿
[스프링 스터디 1일차] 템플릿[스프링 스터디 1일차] 템플릿
[스프링 스터디 1일차] 템플릿
 
Spring vs. spring boot
Spring vs. spring bootSpring vs. spring boot
Spring vs. spring boot
 
Better Scalable Flexible Soa Platform 0.8.0
Better Scalable Flexible Soa Platform 0.8.0Better Scalable Flexible Soa Platform 0.8.0
Better Scalable Flexible Soa Platform 0.8.0
 
테스터도 알아야 할 웹 개발(테스트 교육 3장 1절 부분발췌)
테스터도 알아야 할 웹 개발(테스트 교육 3장 1절 부분발췌)테스터도 알아야 할 웹 개발(테스트 교육 3장 1절 부분발췌)
테스터도 알아야 할 웹 개발(테스트 교육 3장 1절 부분발췌)
 
Java8 - Oracle Korea Magazine
Java8 - Oracle Korea MagazineJava8 - Oracle Korea Magazine
Java8 - Oracle Korea Magazine
 
Sql 중심 코드 탈피 발표자료
Sql 중심 코드 탈피 발표자료Sql 중심 코드 탈피 발표자료
Sql 중심 코드 탈피 발표자료
 
Spring Boot + React + Gradle in VSCode
Spring Boot + React + Gradle in VSCodeSpring Boot + React + Gradle in VSCode
Spring Boot + React + Gradle in VSCode
 
[H3 2012] Bridge over troubled water : make plug-in for Appspresso
[H3 2012] Bridge over troubled water : make plug-in for Appspresso[H3 2012] Bridge over troubled water : make plug-in for Appspresso
[H3 2012] Bridge over troubled water : make plug-in for Appspresso
 

Mehr von Jay Lee

Spring on Kubernetes
Spring on KubernetesSpring on Kubernetes
Spring on KubernetesJay Lee
 
Knative And Pivotal Function As a Service
Knative And Pivotal Function As a ServiceKnative And Pivotal Function As a Service
Knative And Pivotal Function As a ServiceJay Lee
 
Knative and Riff
Knative and RiffKnative and Riff
Knative and RiffJay Lee
 
Spring5 New Features
Spring5 New FeaturesSpring5 New Features
Spring5 New FeaturesJay Lee
 
Reactive Microservice And Spring5
Reactive Microservice And Spring5Reactive Microservice And Spring5
Reactive Microservice And Spring5Jay Lee
 
CF Korea Meetup - Spring Cloud Services
CF Korea Meetup - Spring Cloud ServicesCF Korea Meetup - Spring Cloud Services
CF Korea Meetup - Spring Cloud ServicesJay Lee
 
SpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
SpringCamp 2016 - Apache Geode 와 Spring Data GemfireSpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
SpringCamp 2016 - Apache Geode 와 Spring Data GemfireJay Lee
 

Mehr von Jay Lee (7)

Spring on Kubernetes
Spring on KubernetesSpring on Kubernetes
Spring on Kubernetes
 
Knative And Pivotal Function As a Service
Knative And Pivotal Function As a ServiceKnative And Pivotal Function As a Service
Knative And Pivotal Function As a Service
 
Knative and Riff
Knative and RiffKnative and Riff
Knative and Riff
 
Spring5 New Features
Spring5 New FeaturesSpring5 New Features
Spring5 New Features
 
Reactive Microservice And Spring5
Reactive Microservice And Spring5Reactive Microservice And Spring5
Reactive Microservice And Spring5
 
CF Korea Meetup - Spring Cloud Services
CF Korea Meetup - Spring Cloud ServicesCF Korea Meetup - Spring Cloud Services
CF Korea Meetup - Spring Cloud Services
 
SpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
SpringCamp 2016 - Apache Geode 와 Spring Data GemfireSpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
SpringCamp 2016 - Apache Geode 와 Spring Data Gemfire
 

JavaEE6 - 설계 차원의 단순성

  • 1. Technology & Developer 설계 차원의 단순성 Spring 2011 64 65 Spring 2011 설계 차원의 단순성 Technology & Developer out.close(); } } 기본 생성자(default constructor)를 포함해야 한다는 것 이외에 주입된 클래스에 대한 특정한 요구 사항은 없다. public class Hello { public String helloWorld(){ return “Hello World”; } } 이에서 제시된 예제가 실행되도록 하기 위해서는 다음과 같은 컨텐츠를 포함하고 있는 빈 상태의 beans.xml deployment descriptor도 필요할 것이다: <beans></beans>. WEB-INF 폴더 내에 이러한 구성 파일이 있 는 경우, CDI 기능이 활성화된다. Hello 클래스는 POJO이며, EJB가 아니라는 점을 유념해야 한다. 이는 선언되거나 구성될 필요가 없으며 @Inject 어노테이션은 적절한 생성과 라이프사이클 관리가 이루어지도록 한다. 실제 운영 환경에서는 POJO를 서블릿에 주입하는 경우는 극히 드물다. 아마도 UI 프레임워크(JSF 2와 같은)를 허용하거나 REST(Representational State Transfer)를 통해 서비스를 보여주는 방법을 선호할 것이다. 이와 같은 경우, CDI를 사용하 는 것이 훨씬 유용하다. 예를 들어, 데이터베이스 내에 메시지 문자열을 저장하는 간단한 MessageMe 애플리케이션을 생각해 보겠다. JSF 2 마크업(Markup) 은 inputText와 commandButton 등 2개의 컴포넌트로 구성되어 있다. 리스팅 2에서와 같이 inputText는 속성 메시지를 포함한 이름 색인을 가 진 클래스에 대한 value-bound 함수이며, 따라서 컨텐츠 속성을 가지고 있다. commandButtons의 action 속성은 이름 색인을 가진 backing bean의 save 메소드에 바인딩된다. 코드 리스팅 2: index.xhtml: CDI 내부 빈에 값 바인딩 <h:body> <h:form> Content:<h:inputText value=”#{index.message.content}”/> <br/> <h:commandButton value=”Save” action=”#{index.save}”/> </h:form> 2006년 발표된 Java Platform, Enterprise Edition (Java EE) 5은 엔 터프라이즈 애플리케이션 개발을 단순화하는데 크게 기여했다. 2009년 출시된 Java EE 6은 설계 및 아키텍처 작업을 더욱 쉽게 수행할 수 있 도록 했다. Java EE 6는 소규모의 상황적 애플리케이션(Situational applications)을 그 어떤 오버헤드 없이 신속하게 개발하는 데 적합한 옵 션이다. 이 글에서는 개발자들이 효율적이고 단순하며 손쉽게 유지 관리 할 수 있는 애플리케이션을 개발할 수 있도록 돕는 여러 다양한 Java EE 6 아키텍처와 설계 접근 방식에 대해 설명한다. Java EE 6는 Java EE의 이름으로 함께 릴리즈 된 일련의 독립 API로 구 성되어 있다. 이들 API는 독립적이지만, 놀라울 만큼 서로 긴밀하게 연 동된다. 하나의 애플리케이션에서 오직 JavaServer Faces (JSF) 2.0만 을 이용할 수 있거나, 트랜잭션 서비스를 위해 Enterprise JavaBeans (EJB) 3.1을 이용할 수 있거나, 아니면 Java Persistence API (JPA) 2.0 과 Bean Validation 모델을 채용한 CDI(Contexts and Dependency Injection)를 이용하여 트랜잭션을 이행할 수 있다. 상용 Java EE 6 API를 실용적으로 혼용하여 애플리케이션 내 트랜잭션, 스레딩(Threading), 스로틀링(Throttling) 또는 모니터링 등과 같은 인프 라 서비스를 구현해야 하는 필요성을 완전히 제거할 수 있다. 오버헤드와 복잡성을 최소화하고 커스텀 코드를 이용해서 모든 기본적인 요소들을 새 로 개발할 필요가 없도록 하는 최적 API 하위 집합을 선택하는 것은 결코 쉽지 않다. 일반적으로, 대안을 찾기 위해 검토 범위를 확대하기 전에 기존 Java SE 및 Java EE 서비스를 사용하기 위해 모든 노력을 해야 한다. CDI: 표준 글루(glue) Java EE 6이 출시되면서 처음 소개된 CDI는Java EE 6 규격의 여러 파트 를 위한 글루 기능을 수행하고 POJO (Plain Old Java Object) 빈의 라 이프사이클을 관리하며 DI(Dependency Injection)를 위한 type-safe 메커니즘을 사용한다. CDI는 또한, 이벤트, 인터셉터(Interceptor), 데 코레이터(Decorators), 표준화된 확장 조건(Standardized extension points), 서비스 프로바이더 인터페이스(Service provider interface) 등 과 같은 많은 강력한 기능을 선보였다. CDI자체가 새로운 개념이며 통합레이어 역활을 하도록 설계되었기 때 문에 이전의 기술들과 일부 중복된다. 비록 EJB 3.1 injection 또는 JSF managed bean을 직접 사용할 수 있지만, 가능한 CDI를 사용하는 것을 고려해야 한다. CDI는 더욱 강력할 뿐만 아니라, 단일 API를 이용함으로 써 애플리케이션을 단순화할 수 있다. CDI는 어노테이션(Annotation)을 이용하여 DI(Dependency Injection) 을 수행한다. 가장 중요한 어노테이션은 javax.inject.Inject이다. 리스 팅 1에 있는 예제는 이 어노테이션이 POJO를 서블릿에 주입하는 데 사 용되는 방법을 보여주고 있다. 수행해야 하는 작업은 필드를 선언하고 @ Inject 어노테이션을 다는 것뿐이다. 이 코드가 실행되면 컨테이너는 비즈 니스 메소드가 실행되기 전에 @Inject 어노테이션이 달린 필드를 자동으 로 초기화한다. 코드 리스팅 1: @Inject으로 서블릿에 POJO 주입 @WebServlet(name=”HelloWorldService”, urlPatterns={“/ HelloWorldService”}) public class HelloWorldHTTPService extends HttpServlet { @Inject private Hello hello; @Override protected void doGet (Ht tpServletRequest request , HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); out.println(hello.helloWorld()); out.flush(); </h:body> 리스팅 3은 요청 처리를 위한 @RequestScoped를 이용해 request-scoped CDI 빈으로서 구현된 backing bean을 보여준다. JSF 2 managed bean (@ManagedBean 어노테이션)을 사용할 수 있지만, CDI도 그만큼 강력하다. 또한, CDI를 사용하면, 모든 애플리케이션 레이 어 전반에 걸쳐 단일 글루 API를 적용하여 어디에서나 아키텍처를 단순화 할 수 있다. 코드 리스팅 3: 주입된 EJB을 포함한 CDI backing bean package com.abien.messageme.presentation; import com.abien.messageme.business.messaging.boundary. Messaging; import com.abien.messageme.business.messaging.entity. Message; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; @Named @RequestScoped public class Index { @Inject Messaging ms; private Message message = new Message(); public Message getMessage() { return message; } public void save(){ ms.store(message); } } 어노테이션 @Named (JSR 330 규격에 명시되고 Guice and Spring 에 구현된 바와 같이)은 색인 backing bean을 모든 EL(expression language) 마크업 형태로 나타낼 수 있도록 한다. 이는 JSF 2 내 backing bean의 이름은 클래스 이름에서 추출한다는“CoC(Convention over Configuration)” 원칙을 따른다. 첫 글자에 대문자를 사용하지 않는다. Message 클래스는 리스팅 4에서와 같이 JPA 2 엔티티로 구현된다. 설계 차원의 단순성 : 새로운 Java EE 6 기능을 활용하여 단순하고 유지 관리하기 쉬운 애플리케이션 개발 저자 - Adam Bien 감수 - 이창제 Architect, OFM APAC Solutions & Technology Architects
  • 2. Technology & Developer 설계 차원의 단순성 Spring 2011 66 67 Spring 2011 설계 차원의 단순성 Technology & Developer 코드 리스팅 4: Bean Validation으로 검증된 JPA 2 엔티티 package com.abien.messageme.business.messaging.entity; @Entity public class Message { @Id @GeneratedValue private Long id; @Size(min=2,max=140) private String content; public Message(String content) { this.content = content; } public Message() { /*required by JPA */} public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Long getId() { return id; } } 이 예제의 다음 클래스는 Messaging 클래스로서 EJB 3.1 세션 빈 (Session bean)으로 구현되었다. 이 클래스는 “CDI everywhere” 규 칙의 실제적인 예외를 보여주고 있다. EJB는 트랜잭션, 풀링(Pooling), Java Management Extensions (JMX) 모니터링 및 비동기식 실행 등 과 같은 많은 기능을 단지 @Stateless 어노테이션 하나만으로 제공할 수 있다. 향후의 Java EE 릴리스에서는 이들 aspect들이 EJB에서 추출되 고 CDI에서도 이용할 수 있게 될 것이다. 하지만, Java EE 6에서는 비즈 니스 컴포넌트의 바운더리(Boundary) 또는 퍼사드(Facade) 들이 무상 태 세션 빈(Stateless session bean)으로서 가장 효과적으로 구현된다. 리스팅 5의 @Asynchronous 어노테이션은 특히 흥미롭다. 이 어노테이 션은 메소드가 비동기이면서도 트랜젝션을 지원하는 메소드 실행을 지원 하며, 오직 EJB용으로만 이용할 수 있다. Messaging EJB 는@EJB가 아 닌 @Inject를 이용하여 주입된다는 점을 유념하라. 실제 업무에서 두 어노 테이션 모두 적용되며 거의 차이가 없다. @Inject의 사용이 약간 더 강력하 며 상속(inheritance)을 지원한다. 반면, @EJB 어노테이션은 오직 EJB에 서만 실행된다. 코드 리스팅 5: EJB 세션 빈으로서 구현된 바운더리 package com.abien.messageme.business.messaging.boundary; import com.abien.messageme.business.messaging.control. MessageStore; import com.abien.messageme.business.messaging.entity. Message; import javax.ejb.Asynchronous; import javax.ejb.Stateless; import javax.inject.Inject; @Stateless public class Messaging { @Inject MessageStore messageStore; @Asynchronous public void store(Message message){ messageStore.store(message); } } 리스팅 6의 MessageStore 클래스는 EntityManager에 대한 액세스를 캡슐화한 DAO(Data Access Object)이다. 코드 리스팅 6: 컨트롤 레이어의 CDI 빈 package com.abien.messageme.business.messaging.control; import com.abien.messageme.business.messaging.entity. Message; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; public class MessageStore { @PersistenceContext EntityManager em; public void store(Message message){ em.persist(message); } } ECB: 실용적인 SoC(Separation of Concern) 위에서 설명한 애플리케이션의 패키징을 검토한다면, 별도의 바운더리, 컨트롤 및 엔티티 패키지를 확인하게 될 것이다. 이 패키징 접근 방식은 ECB(Entity Control Boundary) 패턴의 구현이다. 바운더리 레이어는 퍼 사드이며, 컨트롤 레이어는 프로세스 – 및 엔티티 – 독립적인 로직의 구 현을 담당한다. 그리고 엔티티 레이어는 많은 도메인 객체를 포함하고 있 다. Java EE 6과 특히 JPA 2, CDI, 및 EJB를 이용할 수 있음에 따라 모든 3개 레이어의 구현은 빈 상태의 델리케이트(Delegate) 코드로 이어질 수 있 다. 예를 들어 많은 CRUD 기반 유스 케이스는 다수의 엔티티에 액세스하 는 퍼사드의 기능을 수행하는 단일 바운더리를 이용해서 매우 효율적으로 구현될 수 있다. 하지만, ECB 패턴 내 개념과 컴포넌트 내부 패키지 간의 직접적인 1대1 관 계가 여전히 효율적일 수 있다. 패키지가 계속해서 분리되어 있는 경우, 패 키지 간의 종속성을 측정하는 데 정적 분석 툴이 보다 쉽게 사용될 수 있 다. 뿐만 아니라, OSGi와 Jigsaw 등과 같은 프레임워크는 별도의 패키지 가 존재한다는 사실을 토대로 공용 API를 나타낸다. Java EE 6에서 바운더리는 항상 EJB를 인식한다. 컨트롤 레이어는 CDI 또는 EJB 중 하나를 포함할 수 있으며 엔티티 레이어는 JPA 2 엔티티 또 는 transient, unmanaged 엔티티를 포함할 수 있다. 컨트롤 레이어 내 에서 CDI나 EJB 중 어떤 것을 사용할 것인지에 대한 결정을 반드시 사 전에 내릴 필요는 없다. CDI에서 시작하고 진행하면서 @Stateless 어노 테이션을 사용하여 EJB로 변환할 수 있다. @RequiresNew로 후속 트 랜잭션을 시작해야 할 때, 메소드를 비동기식으로 실행해야 할 때, 또는 SessionContext.setRollbackOnly()를 호출하여 현재의 트랜잭션을 롤 백시켜야 할 때 등 몇몇 경우에는 EJB를 사용해야 한다. 반면, CDI는 레거시 코드를 통합하거나 Strategy, Factory 또는 Observer 소프트웨어 설계 패턴을 구현하는 경우에 더욱 적합하다. 이들 기능 모두는 이미 기본 내장되어 있으며 따라서, Java SE의 기능을 이용 하는 경우보다 코드 수를 크게 줄일 수 있다. ECB 패턴을 이용하여 애플리케이션을 개발하는 경우, ECB 레이어링은 반복적으로 전개해야 하며 하향식(Top-down)으로 강제되어서는 안된 다. 영속성 (Entity) 레이어에서 시작하고 단위 테스트(Unit testing)를 수 행한 다음 바운더리 레이어를 구현해야 한다. 단위 테스트를 개발하기 위 해 EntityManager와 관련 트랜잭션을 수작업으로 생성하고 관리해야 한 다(리스팅 7 참조). 코드 리스팅 7: 단독형 JPA 단위 테스트 package com.abien.messageme.business.messaging.entity; import javax.persistence.*; import org.junit.Test; @Test public void mappingSmokeTest() { EntityManagerFactory emf = Persistence.createEntityManage rFactory(“test”); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); em.persist(new Message(“duke”)); tx.commit(); } persistence.xml 파일도 단독 실행을 처리하도록 수정되어야 한다. 특 히, 트랜잭션 유형을 RESOURCE_LOCAL로 변경해야 하며 JDBC 커넥션 (Datasource 대신)은 리스팅 8에서와 같이 명시적으로 구성되어야 한다. 코드 리스팅 8: 독립형 JPA 단위 테스트를 위한 persistence.xml <persistence> <persistence-unit name=”test” transaction-type=”RESOURCE_ LOCAL”> <provider>org.eclipse.persistence.jpa.PersistenceProvider</ provider> <class>com.abien.messageme.business.messaging.entity. Message</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> < p r o p e r t y n a m e = ” j a v a x . p e r s i s t e n c e . j d b c . u r l ” value=”jdbc:derby: ./sample;create=true”/> <property name=”javax.persistence.jdbc.password” value=”app”/> <property name=”javax.persistence.jdbc.driver” value=”org. apache.derby .jdbc.EmbeddedDriver”/>
  • 3. Technology & Developer 설계 차원의 단순성 Spring 2011 68 69 Spring 2011 설계 차원의 단순성 Technology & Developer <property name=”javax.persistence.jdbc.user” value=”app”/> <property name=”eclipselink.ddl-generation” value=”drop-and- create-tables”/> </properties> </persistence-unit> </Persistence> 컨트롤 레이어를 개발할 때, 그 컨텐츠가 엔터티 및 바운더리 레이어 리 팩토링(Refactoring)의 산물이 되어야 한다는 점을 유념해야한다. 쿼리 (Queries), 알고리즘(Algorithms) 또는 검증 등과 같이 바운더리 레이어 의 재사용 가능하고 응집력이 없는(Noncohesive)는 컨트롤 레이어의 CDI managed bean으로 추출되어야 한다. ECB 패턴의 사용 ECB 패턴의 주요 목적은 비즈니스 및 프레젠테이션 로직 간의 명확한 구 분을 제공한다는 것이다. 정의에 따라 바운더리는 프레젠테이션 로직에 서 독립되어야 한다. 실제 아키텍처에서 많은 절충이 이루어지고 있지만, 비즈니스와 UI 기술 간의 명확한 구분이 이루어져야 한다. 실제로, UI 로 직은 비즈니스 로직보다 더욱 자주 변경되는 경향이 있다. 웹 클라이언트 (JSF 2 등), 리치 클라이언트(Swing 또는 Eclipse RCP 등) 그리고 REST 등에 의해 동시에 액세스될 수 있는 비즈니스 로직을 생성하는 것이 일반 적이다. JSF 2의 경우, CDI는 컨트롤러(Controller) 또는 프레젠터(Presenter)를 구현하기 위한 가장 쉬운 옵션이다. CDI managed bean은 EL을 통해 JSF 2에 직접 바운딩될 수 있으며 바운더리(EJB 3.1)는 프레젠터로 직접 주입 될 수 있다. 프레젠터(또는 컨트롤러)는 @Stereotype 어노테이션으로 직 접 포착될 수 있다. 이는 매크로처럼 실행되며 그 안에 CDI 어노테이션을 배치하고 이 어노테이션으로 확장할 수 있다. 스테레오타입(Stereotype) 은 @Stereotype으로 표시되는 표준 Java 어노테이션이다. @Named @RequestScoped @Stereotype @Retention(RUNTIME) @Target(TYPE) public @interface Presenter {} 커스텀 스테레오타입(custom stereotype)은 매크로와 마찬가지로 @ Messaging boundary; @Inject IndexView indexView; public void save(){ boundary.store(indexView .getMessage()); } } 바운더리와 뷰가 IndexPresenter에 주입되기 때문에 쉽게 mocking 할 수 있다. 단위 테스트 환경에서 두 필드는 mock을 이용해 설정되지만, 실 제 운영 환경에서는 컨테이너가 주입을 실행하고 실제 종속성을 설정하게 된다. 단위 테스트와 IndexPresenter가 동일한 패키지 내에 있기 때문에 기본 visible 필드는 직접 설정할 수 있다. public setter를 포함한 private 필드가 사용될 수 있지만, 대개의 경우 packagewide 필드로 충분하며 코드 사이즈를 줄일 수 있다. 리스팅 9는 IndexView는 물론, 바운더리 Messaging 클래스를 mocking화 함으로써 프레젠테이션 로직을 테스트하는 방법을 보여준다. IndexPresenter.save() 메소드를 호출하는 이 테스트는 메소드 스토어 를 단 한 번 호출하고, IndexView에 의해 Message-Instance가 반환되 면 성공적이다. 호출을 검증한다는 것은 mock를 Mockito.verify() 메소 드로 보낸다는 것을 의미한다. IndexView는 JSF 렌더링과 상호 작용하 지 않고도 반환 값을 가공하도록 모의화에서 제외된다. 코드 리스팅 9: IndexPresenter테스트—모의화에서 제외된 뷰 및 바운 더리 이용 package com.abien.messageme.presentation; //...other imports import org.junit.Before; import org.junit.Test; import static org.mockito.Mockito.*; public class IndexPresenterTest { private IndexPresenter cut; @Before public void initialize(){ this.cut = new IndexPresenter(); } Named 및 @RequestScoped 대신 적용될 수 있다. 그러면, 프레젠터 패 턴을 식별하는 모든 CDI 어노테이션을 대체할 수 있다. @Presenter public class Index { // } 프레젠터의 목적은 프레젠테이션 로직을 구현하는 것이다. 프레젠터의 구 조는 뷰와 긴밀히 결합되어 있으며 이 뷰 내 JSF 컴포넌트의 상태 내에서 프레젠터 내부의 속성으로 매핑될 수 있다. 속성은 값(값 바인딩으로)이나 컴포넌트 인스턴스 그 자체(컴포넌트 바인딩으로) 중 하나가 될 수 있다. 때때로 뷰와 프레젠터 간에 1대1 관계가 있는 경우도 있다. 이 프레젠터는 뷰의 데이터는 물론, 모든 프렌젠테이션 로직을 포함하고 있다. 바운더리 를 프레젠터에 주입하기 위해서는 @Inject 어노테이션을 사용해야 한다. 프레젠테이션 로직의 수가 프레젠터 내부에서 증가하고 있기 때문에 코 드를 유지하고 테스트하는 것이 더욱 어려워질 수 있다. CDI를 통해 단 일 프레젠터를 매우 손쉽게 분리된 데이터 및 프레젠테이션 로직 파트 로 분산시킬 수 있다. 예를 들어, 아래 코드는 save 메소드를 새로 만든 IndexPresenter 빈으로 옮겨 앞에 나온 예제에서 backing bean을 리 팩토링하는 방법을 보여주고 있다. 프레젠터 어노테이션은 중복되고 @ View으로 이름이 변경되며, 이 빈은 IndexView로 이름이 변경된다. @View public class IndexView { private Message message = new Message(); public Message getMessage() { return message; } } IndexPresenter 빈은 이전 @Presenter 어노테이션을 가져온다. 아래 코드에서 볼 수 있듯이, 이 사례에서 IndexPresenter 빈의 유일한 목적 은 프레젠테이션 로직을 구현하는 것이다. @Presenter public class IndexPresenter { @Inject @Test public void save() { this.cut.boundary = mock(Messaging.class); this.cut.indexView = mock(IndexView.class); Message expected = new Message(“duke”); whe n ( t h i s . c u t . i n d e x Vi e w. g e t M e s s a g e ( ) ) . thenReturn(expected); cut.save(); verify(this.cut.boundary,times(1)).store(expected); } } 메시징 바운더리는 다른 이유로 즉, 예상 메소드가 실제로 호출되었는지 를 검증하기 위해 모의화에서 제외된다. public void save(){ boundary.store(indexView .getMessage()); } JSF 2 프레젠테이션의 설계는 리치 Swing 애플리케이션의 설계 와 유사하다. Model-View-Controller와 같은 공통의 패턴과 그 개 선—Supervising Controller 및 Passive View—은 JSF 2에도 적용될 수 있다. JSF와 리치 클라이언트 기술 간의 가장 중요한 차이점은 뷰가 렌더링되는 방법이다. Swing에서 개발자들은 Java로 뷰를 구현하지만, JSF 2에서 개발자들은 XHTML 마크업을 사용한다. JSF 2에서 컨포넌트 의 값은 해당 클래스에 직접 바인딩될 수 있지만, Swing에서는 대개 뷰 자 체 내에 또는 모델에 저장된다. CRUD와 같은 데이터 중심의 유스 케이스를 구현하려는 경우, Supervising Controller가 Passive View보다 나은 옵션이다. Supervising Controller 패턴에서 단일 패키팅 빈(IndexView)은 프레 젠테이션 로직과 뷰 상태 모두를 관리하는 책임을 맡고 있다. 더욱 복잡한 유스 케이스에서는 Passive View 변수가 보다 적합할 것이다. Passive View 패턴에서는 backing bean이 뷰 및 프레젠테이션 로직으로 분산되 며 프레젠테이션 로직은 IndexView에서 IndexPresenter로 추출된다. CDI는 프레젠테이션 레이어의 구현에 가장 적합하다. 기본 내장된 공통 관심 사항(Cross-cutting concerns, 여기에는 트랜잭션, 동시성, 비동기 식 실행 모니터링 및 스로틀링 등이 해당 됨) 때문에 비즈니스 로직의 바운 더리가 EJB로서 실체화된다. 비즈니스 컴포넌트는 EJB 또는 CDI로 실체
  • 4. 71 Spring 2011 시뮬레이션을 통한 성능 증명 Technology & Developer 화될 수 있다. 일반적으로 CDI에서 시작하고, 시간이 지난 후, 특수한 케 이스의 managed bean을 EJB로 대체할 수 있다. CDI-EJB-CDI (CEC) 패턴은 Java EE 6을 위한 가장 단순하고 가장 실용적인 옵션이다. 인터페이스를 유용하게 만드는 방법 EJB 3.0 (Java EE 5에서)는 bean 클래스를 위한 별도의 인터페이스 를 요구했다. 네이밍 충돌을 방지하기 위해 개발자들은 종종 XyzLocal/ XyzRemote 및 XyzBean와 같이 체계적으로 규정된 명명 규칙을 사용해 야 했다. Java EE 6에서 EJB 및CDI를 위한 인터페이스는 이제 옵션이 되 었다. Public EJB 또는 CDI 메소드는 이제 그 어떤 기능의 손실도 없이 “no interface” 뷰를 보여줄 수 있다. 새로운 기능은 다시한번 인터페이스를 중요하게 만들었다. 이전 릴리스에 서 강제적이면서도 막연하게 인터페이스를 사용했던 것과는 달리, Java EE 6 의 인터페이스는 Strategy 패턴의 구현, Public API의 구현 또는 엄 격한 모듈 분리(코드를 보다 분명하게 나타낼 수 있도록 함)를 위해 사용 될 수 있다. 인터페이스는 시스템의 “Protected variations”를 나타내고 클래스 간의 직접적인 종속성은 변경될 가능성이 낮은 코드를 위해 사용 될 수 있다. 인터페이스 없이 개발을 시작해서 필요에 따라서 이를 적용할 수 있다. 이 와 같은 접근 방식은 Java EE 5에서와 근본적으로 차이가 있다. 2003년 부터 나온 Java 2 Platform, Enterprise Edition (J2EE)에 비해 Java EE 6 코드는 여러 레이어, 간접 지정(Indirections) 및 추상화 등이 제거됨에 따라 훨씬 단순하다. J2EE와 달리, Java EE 6는 플랫폼에 대한 종속성 없 이 주석이 붙은 클래스로 구성되어 있다. 이와 같은 접근 방식은 인프라에 서 비즈니스 로직을 분리해야 하는 필요성을 없애고 대부분의 J2EE 패턴 과 모범 사례를 불필요하게 만든다. Java EE 6에서는 프레젠테이션 및 비 즈니스 로직으로 단순한 사례를 해결할 수 있다. EntityManager는 이미 충분히 훌륭한 주요 영속성의 추상화 기능을 제공하기 때문에 추가 간접 지정 기능은 전혀 필요하지 않다. 쉽게 유지 관리할 수 있는 Java EE 6 애플리케이션은 YAGNI (You Ain’t Gonna Need It), DRY (Don’t Repeat Yourself), 그리고KISS (Keep It Simple, Stupid) 원칙에 따라 작성된다. 설계 패턴과 모범 사례는 하향식 (Top-down)이 아니라 상향식(Bottom-up)으로 도입된다. 이와 같은 패 턴은 언제나 플랫폼의 한계가 아니라, 기능 및 비 기능 요구 사항에 의해 주도된다. 이러한 접근 방식은 Java EE 6과 이전 J2EE 릴리스 간의 가장 큰 차이점을 나타낸다. J2EE에서는 J2EE 플랫폼 종속성에 따라 많은 설 계 의사 결정이 사전에 이루어졌다. 반대로, Java EE 6 개발 프로세스는 기능에 초점을 맞추고 있다. 1. 비즈니스 문제를 직접 해결하는 단순한 코드 작성 2. 단위 테스트로 비즈니스 로직 검증 3. 종속성 단절 및 리팩토링으로 설계 향상 4. 애플리케이션에 대한 스트레스 테스트 5. 다시 1로 되돌아가기 설계 및 아키텍처는 일반적인 아키텍처 차원의 모범 사례가 아니라 구체 적인 요구 사항에 따라 이루어진다. 지속적으로(적어도 1주일에 한번) 애 플리케이션에 대한 스트레스 테스트를 수행함으로써, 확실한 사실(Hard fact)을 이용하여 단순한 설계에 대한 타당성을 보다 손쉽게 입증하고 스 트레스가 가해졌을 때 시스템의 작동에 대한 정보를 확보할 수 있다. 시뮬레이션을 통한 성능 증명 : 저자 - Arup Nanda 감수자 - 김상엽 SQL Performance Analyzer에서 Oracle Exadata 시뮬레이션 기능을 이용한 Oracle Exadata환경에서 실행되는 애플리케이션의 성능 예측 데이터베이스 시장의 ‘혁신적 파괴자’로 최근 등장한 Oracle Exadata 는 그 유형에 관계없이 애플리케이션 성능을 향상시키고 있다. 하지만, Oracle Exadata로의 마이그레이션을 고려하고 있는 사람들이 가장 궁 금해 하는 것은 아마도 ‘기존 데이터베이스에서 실행 중인 애플리케이 션들이 Oracle Exadata에서 적절하게 실행되느냐’하는 것이다. 실제 로 Oracle Exadata로 마이그레이션을 하기 전에 그 해답을 확인할 수 있는 방법은 없을까? Oracle Database 11g Release 2에서는 Oracle Exadata 어플라이언스에 실제로 투자하기 전에 Oracle Exadata에서 데이터베이스 작업을 시뮬레이션 및 측정할 수 있도록 지원하는 새로운 기능이 추가되었다. 이 글에서는 이 시뮬레이션 기능을 사용해 Oracle Exadata에서 실행 중인 애플리케이션의 성능을 예측할 수 있는 방법에 대해 알아보겠다. 시뮬레이션을 위한 토대 Oracle Database 11g Release 1은 Oracle Real Application Testing 스위트의 구성 요소인 SQL Performance Analyzer를 새롭게 도입 했다(Oracle Magazine 2008년 3월/4월호 “Performing Through Changes” 참조). 이 툴을 사용하면 모든 데이터베이스에서 SQL명령문 을 포착하고, 이를 새로운 환경에서 재현(replay)함으로써 잠재적 문제를 규명하고 새로운 대상 환경에서의 동작 상황을 예측할 수 있다. 대상 환경은 인덱스, materialized view 등이 더 많거나 적을 수 있고, 기 반구조가 다르거나, 다른 세션 매개변수 환경에서 운용되는 등 현재 운영 중인 환경과 구조적으로 다를 수 있다. Oracle Database 11g Release 2에서는 Oracle Exadata의 기능을 시뮬레이션할 수 있도록 SQL Performance Analyzer의 범위가 확장되었다. 강력한 성능의 원천 Oracle Exadata가 이렇게 뛰어난 성능을 발휘할 수 있는 비결 중 하나는 바로 Oracle Exadata 스토리지가 위치한 스토리지 셀 내 인텔리전스로 서, 이는 성능에 가장 큰 영향을 미치고 있다. 스토리지 셀은 저장된 데이 터의 패턴을 알고 있기 때문에 모든 데이터가 아니라 연관성 있는 데이터 만 지능적으로 반환할 수 있다. 아래 간단한 쿼리를 통해 이를 살펴볼 수 있다. select sum(order_qty) from sales where cust_id = 1000 기존 Oracle Database에서는 이미 메모리에 데이터 올라와 있는 경우가 아니라면 SALES 테이블부터 모든 블록을 버퍼 캐시(시스템 글로벌 영역 에 위치)로 가져오도록 서버 프로세스가 명령어를 실행한다. 그 다음, 세 션은 CUST_ID = 1000인 행을 찾기 위해 누적된 데이터를 검사한다. 값 이 일치하는 행들이 서버 프로세스의 프로그램 글로벌 영역으로 복사되 고 또 다른 열인 ORDER_QTY의 합계가 계산된 후, 마지막으로 결과가 사 용자에게 반환된다. 테이블은 10억 개까지 행을 가질 수 있고 CUST_ID = 1000인 행 수는 100개에 불과한 경우에도 일치하는 행을 찾으려면 데이터 베이스가 10억 개의 행을 모두 가져와서 검색해야 한다. I/O 서브시스템은 여전히 테이블의 모든 블록을 서버 프로세스로 반환해야 한다. 이 경우, 스 토리지는 데이터 구조에 대한 상황을 알지 못하기 때문에 관련 있는 데이 터와 나머지 데이터를 구별할 수 없다. Oracle Real Application Clusters (Oracle RAC) 시스템에서도 또 다 른 문제가 있다. 병렬 쿼리 슬레이브가 여러 인스턴스 상에 분리되어 있 을 수 있다. 이들은 수집한 데이터를 대조를 위해 다른 인스턴스의 query coordinator로 인터커넥트를 통해 전송하기 때문에 인터커넥트 하드웨 어가 이와 같은 트래픽으로 포화 상태가 된다. 뿐만 아니라, 인터커넥트를 통해 블록을 전송하는 프로세스는 CPU를 사용하는 데다 래치(Latch)를 필요로 하기 때문에 더 많은 CPU 사이클이 요구된다. 따라서, 스토리지 시스템으로부터의 블록에 대한 요구가 클수록 CPU 및 I/O와 인터커넥트 Technology & Developer 설계 차원의 단순성 Spring 2011 70 저자 : Adam Bien (blog.adam-bien.com)은 Java Champion으로서 컨설턴트, 강사, 소프트웨어 아키 텍트 겸 개발자로 활동하고 있으며 Real World Java EE Patterns: Rethinking Best Practices (lulu. com, 2009). 등과 같은 Java 전문 서적을 집필한 저자이기도 하다. 그는 Oracle Magazine의 2010년 올 해의 Java 개발자(Java Developer of the Year)로 선정되었다.