IBM Korea Skip to main content
       IBM 홈    |  제품 & 서비스  |  고객지원 & 다운로드  |  회원가입  

EJB best practices : 엔터티 빈 보호
Session Facade 패턴으로 데이터를 안전하게 관리하기

Level: Intermediate

Brett McLaughlin
작가/편집자, O'Reilly and Associates
2002년 10월

Column icon엔터티 빈을 웹 티어(tier)에게 직접 노출하지 않고 애플리케이션에 사용자들이 액세스 할 수 있도록 하려면? 하지만 이것은 애플리케이션에 보안 위협을 가져올 수 있다. Brett McLaughlin은 엔터티 빈에는 안전하고 전체 애플리케이션에는 효율적인 솔루션을 제안한다.

Enterprise JavaBeans 기술은 세 개의 핵심 빈(bean) 유형- 세션(session), 메시지 구동(message-driven), 엔터티(entity)-으로 나뉘어진다. 그리고, 빈(bean)은 비지니스 객체로서 작동하는 것과 데이터 객체로서 작동하는 것으로 나뉠 수 있다. 세션 빈과 메시지 중심 빈은 비지니스 객체이다. 엔터티 빈은 데이터 객체이다. 대부분 비지니스 객체들은 웹 티어에게 노출되어야 한다. 비지니스 객체는 데이터 스토어를 다루는데 데이터 객체를 사용할 수 있기 때문이다. 하지만 어떤 경우는 사용자들이 데이터 객체에 직접 액세스해서 조작할 필요도 있다. 다시 말해서 엔터티 빈을 웹 티어에게 노출해야함을 의미한다. 이것은 애플리케이션을 보안 위협 속에 노출하는 것이고 가끔 코드가 깨지는 경우도 생긴다.

노출의 위험
엔터티 빈은 데이터베이스의 기반 구조에 대해 많은 것을 드러내고 있다. 각 빈은 데이터베이스의 각 필드마다 액세서(accessor)와 뮤테이터(mutator) 메소드를 포함하고 있고 메소드 이름들은 보통 필드이름과 정렬되기 때문에 엔터티 빈에서 전체 데이터베이스 구조를 검색할 수 있다. 한 개의 애플리케이션에서는 그다지 큰 일은 아니지만 빈들은 다른 네트워크상에서 다른 애플리케이션에 종종 노출된다. 애플리케이션들이 다중 네트워크를 통해 연결되어 있는 웹 서비스 시스템에서는 특히 그렇다.

노출된 빈: 실행 예제
Movie라는 엔터티 빈을 생각해보자. 이 빈의 메소드는 getTitle(), getDirector(), getActors().이다. 빈의 원격 인터페이스를 노출했기 때문에 여러분의 애플리케이션과 여러 클라이언트 애플리케이션 모두 getDirector() 메소드를 포함하는 코드를 작성했다. 하지만 애플리케이션이 진화하면서 다중 director를 가진 movie를 수용할 수 있어야 한다는 것이 명확해 졌다. 데이터베이스는 변하고 getDirector() 메소드는 getDirectors()가 되었다. 메소드가 복수형이고 단일 객체가 아닌 리스트를 리턴하도록 코딩되었다. 결과적으로 오래된 메소드를 사용하는 모든 모드는 깨어지고 여러분의 애플리케이션 코드는 재작성되어야 한다.

데이터베이스 구조를 알려지지 않은 애플리케이션에 드러낼 경우에 나타나는 분명한 위험 뿐만아니라 데이터 구조가 변경될 때 어떤일이 발생할 것인가에 대해서도 생각해야 한다. 엔터티 빈은 데이터 구조와 밀접하게 묶여있기 때문에 데이터베이스 테이블의 칼럼이 변경되거나 새로운 칼럼이 추가될 때 엔터티 빈도 종종 변한다. 엔터티 빈을 애플리케이션 레이어에 노출함으로서 메소드 이름을 사용할 수 있도록 하고 이러한 메소드 이름들은 새로운 애플리케이션 코드에 추가된다. 심각한 코드 오류는 엔터티 빈이 변경되거나 진화할 때 발생할 수 있다.

Session Facade 패턴
다행히, 엔터티 빈을 웹 티어에게 노출하지 않고 데이터 객체로 사용자 액세스를 가능하게 하는 디자인 패턴이 있다. Session Facade 패턴은 엔터티 빈과 애플리케이션 클라이언트 사이에 세션 빈을 놓는다. 이것은 다른 엔터티로의 액세스를 관리하기 때문에 이러한 방식으로 세션 빈을 사용할 때 매니저로서 간주된다.

세션 빈은 비지니스 로직과 애플리케이션 로직간의 인터페이스로 작동하도록 설계되었다. 실행 예제의 경우 로직은 매우 간단하다. 하나의 기반 엔터티 빈을 호출하는 것이다. 실제 시나리오에서는 세션 빈이 데이터 타당성검사, 보안, 기타 비지니스 함수를 관리하도록 해야한다. 세션 빈에서 엔터티 빈을 래핑함으로서 엔터티 빈 코드를 손상시키지 않고 필요한 비지니스 함수에 액세스 할 수 있다.

실행 예제를 분석하기위해서 MovieManager를 호출하는 세션빈을 만들어야한다. MovieManager 빈은 오래된 메소드인 getDirector()와 새로운 메소드인 getDirectors()를 포함하게 된다. 새로운 메소드가 추가될 때 엔터티 빈을 통해 "프록시화(proxied)" 된다. 첫 번째 메소드는 이 엔터티 빈에서는 더이상 사능하지 않기 때문에 세션 빈은 이를 숨기기 위해 헬퍼 메소드를 사용한다.(Listing 1):

Listing 1. "deprecated" 메소드 숨기기

      public Person getDirector() {
          // We can't call getDirector() any more on the entity bean

          // Call the new method, through this manager
          List directors = getDirectors();

          // Return the first one in the list
          return (Person)directors.item(0);
      }

해결방법
여기에서 설명된 문제 유형에 대한 일반적인 솔루션은 엔터티 빈에 헬퍼(helper) 메소드를 단순히 추가하는 것이다. 하지만 그렇게 했을 때의 결과는 재앙이 될 수도 있다. 엔터티 빈의 모든 메소드가 일년에 단 한번 바뀌더라도 빈은 그 해 연말 까지 두배의 메소드를 얻는다. 메소드가 일년에 한번 이상으로 빠르게 변경한다는 것을 생각한다면 "Band-Aid" 접근방식이 소용없는지가 명백해진다. 엔터티빈이 데이터 객체 처럼 보이지 않고 헬퍼 클래스처럼 보이기 시작할 때 문제가 있다는 것을 알게된다. 반면 세션빈은 정확히 헬퍼 클래스처럼 보인다. 왜냐하면 함수 세션 빈들 중 하나가 수행되도록 설계되었기 때문이다.

Listing 1은 트릭을 수행하고 있다. 오래된 메소드는 숨겨져있기 때문에 이것에 의존하는 모든 애플리케이션 코드는 잘 돌아간다. 또한 속해있는 비지니스 객체안에 이를 위치시켜서 엔터티 빈 밖에서 헬퍼 메소드를 유지한다. 급한 문제를 해결할 때 빈의 클라이언트를 새로운메소드로 옮기거나 헬퍼 메소드가 이동을 핸들하도록 하는 옵션이 있다. 두 방법 중 어떤 것을 채택하더라도 애플리케이션 코드나 클라이언트 코드는 피해를 입지 않는다.

데이터 구조 숨기기
위 솔루션이 변경 관리 문제들을 해결하지만 보안 문제는 사라지지 않는다. 엔터티 빈이 웹 티어에게 노출되지 않도록 보호해야 한다. 몇 가지 간단한 비지니스 로직과 데이터 조작 함수를 세션 빈에 추가하여 애플리케이션 데이터를 숨기고 여기에 포함된 정보를 세련된 방식으로 접근할 수 있다.

예를 들어 애플리케이션이 발전해가면서 사용자들이 다양한 데이터에 개별적으로 액세스하도록 하는 것이 비효율적이라는 것을 알게된다. 정보 유형은 항상 상호적으로 사용되기 때문에 세션빈을 변경하는 것이 유용하다. getDirector()getDirectors() 메소드 대신 세션빈은 새로운 비지니스 로직을 가질 수 있다(Listing 2):

Listing 2. 데이터 구조를 세션 빈으로 숨기기

      public List getCrew(String movieName)
	     throws NamingException, RemoteException {
          List crew = new LinkedList();

          EJBHomeFactory f = EJBHomeFactory.getInstance();
          MovieHome movieHome =
            (MovieHome)f.lookup("java:comp/env/ejb/Movie", MovieHome.class);
          Movie movie = movieHome.findByName(movieName);

          crew.add(movie.getDirectors());
          crew.add(movie.getProducers());
          crew.add(movie.getExecutiveProducers());
          // and so on...

          return crew;
      }

      public List getCast(String movieName)
	     throws NamingException, RemoteException {
          List cast = new LinkedList();

          EJBHomeFactory f = EJBHomeFactory.getInstance();
          MovieHome movieHome =
            (MovieHome)f.lookup("java:comp/env/ejb/Movie", MovieHome.class);
          Movie movie = movieHome.findByName(movieName);

          crew.add(movie.getActors());
          crew.add(movie.getStandIns());
          // and so on...

          return cast;
      }

서로 다른 애플리케이션 티어들을 분리하고 비지니스 로직을 사용하여 데이터 조작을 핸들함으로서 직접적이고 불안한 엔터티 빈으로의 액세스를 방지하고 웹 티어에게도 좋은 메소드를 만들었다. 이 경우 Session Facade는 엔터티 빈과 비지니스 로직 단위에는 래퍼로서 작용하면서 오리지널 데이터를 의미있는 정보로 바꾸었다.

참고자료

목 차:
노출의 위험
Session Facade 패턴
데이터 구조 숨기기
참고 자료
필자 소개
기사에 대한 평가
관련 dW 링크:
EJB best practices series
Rules and Patterns for Session Facades
Best practices in EJB exception handling
Subscribe to the developerWorks newsletter
US 원문 읽기
Also in the Java zone:
Tutorials
Tools and products
Code and components
Articles
필자소개
Photo of Brett McLaughlin Brett McLaughlin은 현재 자바 및 관련 기술을 이용하여 애플리케이션 기반구조 구현을 전문적으로 수행하고 있다. Brett은 Java Apache 프로젝트인 Turbine의 공동 창립자이다.
이 기사에 대하여 어떻게 생각하십니까?

정말 좋다 (5) 좋다 (4) 그저그렇다 (3) 수정보완이 필요하다(2) 형편없다 (1)

  회사소개  |  개인정보 보호정책  |  법률  |  문의