본문 바로가기

프로그래밍(TA, AA)/JVM 언어

[자바성능] 디자인패턴과 애플리케이션 성능 관계

디자인패턴과 애플리케이션 성능 관계


디자인 패턴도 성능과 연관이 있을 수 있습니다. 개발자 한명이 처음 개발할 때에는 MVC, JSP 모델1,2 어느것을 쓰더라도 성능은 별 차이가 나지 않습니다. 하지만 그 개발자가 프로젝트에서 철수하거나, 여섯 달 뒤 관련 시스템을 수정하면 어떻게 될까요?


Model1 방식의 JSP 화면에서 다수의 메소드를 호출하는 구조의 페이지가 있다고 가정합시다. 그 소스의 상단에서 호출된 메소드를 중복해서 사용하는 것이 있다면 그부분을 중복을 제거함으로써 성능을 개선할 수 있습니다. HTML과 혼재되어 있는 3,000 라인이 넘는 JSP 소스에서 중복되는 호출이 없다고 보장할 수 있을까요? 아무도 그러한 중복 호출이 없다고 장담할 수 없습니다. 결국 시스템 중 성능 목표에 도달하지 못한 몇몇 화면은 직접 jsp에 중복되는 호출이 없는지를 일일이 조사하여 수정해야 합니다.


최근은 화면제어로직을 브라우저단에서 해결하는 것이 대세입니다. javascript에 컨트롤 로직을 담는 것인데요. 이 때 브라우저단 엔진 스펙에 의해서도 성능이 영향을 받겠지요. 브라우저 엔진 스펙 및 성능에 대한 포스팅도 나중에 해보려고 합니다.


patter [명사] : a model, guide or set of instructions for making something

                   (무엇인가를 만들기 위한 모델이나 가이드, 설명의 집합)


시스템을 만들기 위해서 전체 중 일부 의미 있는 클래스들을 묶은 각각의 집합을 디자인 패턴이라고 생각하면 됩니다. 이러한 반복되는 의미 있는 집합을 정의하고 이름을 지정해서, 누가 이야기하더라도 동일한 의미의 패턴이 되도록 만들어 놓은 것입니다.


[Design Patterns: Elements of Reusable Object-Oriented Software] 라는 책에 최초로 객체지향에 맞는 디자인 패턴을 정리해 놓았습니다. 다음 그림은 J2EE 코어 패턴 입니다.





초록색은 프레젠테이션 티어이고, 보라색은 비즈니스티어, 주황색은 인터그레이션 티어입니다. 위로 갈수록 화면에 가깝고, 아래로 갈수록 데이터베이스에 가까워 집니다.


Intercepting Filter 패턴 : 요청 타입에 따라 다른 처리를 하기위한 패턴

Front Controller 패턴 : 요청 전후에 처리하기 위한 컨트롤러를 지정하는 패턴

View Helper 패턴 : 프레젠테이션 로직과 상관없는 비즈니스 로직을 헬퍼로 지정하는 패턴

Composite View 패턴 : 최소 단위의 하위 컴포넌트를 분리하여 화면을 구성하는 패턴

Service to Worker 패턴 : Front Controller와 View Helper 사이에 디스패처를 두어 조합하는 패턴

Dispatcher to Worker 패턴 : Front Controller와 View Helper로 디스패처 컴포넌트를 형성합니다. 뷰 처리가 종료될 때까지 다른 활동을 지연한다는 점이 Service to Worker 패턴과 다른 점.

Business Delegate 패턴 :  비즈니스 서비스 접근을 캡슐화하는 패턴.

Service Locator 패턴 : (성능에 영향) 서비스와 컴포넌트 검색을 쉽게하는 패턴

Session Facade 패턴 :  비즈니스 티어 컴포넌트를 캡슐화하고, 원격 클라이언트에서 접근할 수 있는 서비스를 제공하는 패턴.

Composite Entity 패턴 : 로컬 엔티티 빈과 POJO를 이용하여 큰 단위의 엔티티 객체를 구현하는 패턴.

Transfer Object 패턴 : (성능에 영향) 일명 Value Object 패턴이라고 많이 알려져 있습니다. 데이터를 전송하기 위한 객체에 대한 패턴.

  - 하나의 객체에 결과값을 담아올 수 있어 두번 세번씩 요청을 하는 일이 발생하는 것 감소

Transfer Object Assembler 패턴 : 하나의 Transfer Object로 모든 데이터를 처리할 수 없으므로, 여러 Transfer Object를 조합하거나 변형한 객체를 생성하여 사용하는 패턴.

Value List Handler 패턴 : 데이터 조회를 처리하고, 결과를 임시 저장하며, 결과 집합을 검색하여 요한 항목을 선택하는 역할을 수행.

Data Access Object 패턴 :  일명 DAO라고 많이 알려져 있습니다. DB에 접근을 전담하는 클래스를 추상화하고 캡슐화

Service Activator 패턴 :  비동기적 호출을 처리하기 위한 패턴.



Service Locator 패턴 예제입니다.

 package com.perf.pattern;

import java.util.*;
import javax.naming.*;
import java.rmi.RemoteException;
import javax.ejb.*;
import javax.rmi.PortableRemoteObject;
public class ServiceLocator {
private InitialContext ic;
private Map cache;
private static ServiceLocator me;
static {
me = new ServiceLocator();
}
private ServiceLocator() {
cache = Collections.synchronizedMap(new HashMap());
}
public InitialContext getInitialContext() throws Exception {
try {
if (ic == null) {
ic = new InitialContext();
}
} catch (Exception e) {
throw e;
}
return ic;
}
public static ServiceLocator getInstance() {
return me;
}
public EJBLocalHome getLocalHome(String jndiHomeName) throws Exception {
EJBLocalHome home = null;
try {
if (cache.containsKey(jndiHomeName)) {
home = (EJBLocalHome)cache.get(jndiHomeName);
} else {
home = (EJBLocalHome)getInitialContext().lookup(jndiHomeName);
cache.put(jndiHomeName, home);
}
} catch (NamingException ne) {
throw new Exception(ne.getMessage());
} catch () {
throw new Exception(e.getMessage());
}
return home;
}
}

Service Locator 패턴은 가장 빈번히 사용되는 EJB Home 객체나 DB의 Datasource를 찾을때 소용되는 응답 속도를 감소시키기 위해서 사용 됩니다. cache 라는 Map 객체에 home 객체를 찾은 결과를 보관하고 있다가, 누군가 그 객체를 필요로 할 때 메모리에서 찾아서 제공하도록 되어 있습니다. 만약 해당 객체가 cache라는 맵에 없으면 메모리에서 찾습니다.


EJB home 객체를 찾거나 Datasource 객체를 찾는 시간은 일반적으로 30ms가 소요됩니다. EJB Remote home을 찾을 때에는 시스템에 따라서 1초가 소요되는 시스템도 있습니다. 하지만 메모리에서 찾으면 0.01ms도 소요되지 않으므로, 100배이상의 성능 향상을 가져올 수도 있습니다.



디자인 패턴과 마찬가지로, 요즘 많이 사용하는 프레임워크를 사용할 때에도 프레임워크를 만든 사람의 사상과 프레임워크의 구조, 기능을 정확히 알고 있어야 제대로 프레임워크를 활용할 수 있습니다. 


J2EE 개발 시, Business Delegate, Session Facade, Data Access Object, Service Locator, Transfer Object 패턴 알아두면 특히 유용합니다.


본 포스팅은 자바 성능을 결정짓는 코딩 습관과 튜닝 이야기 1장을 참고하였습니다.