'2016/12/20'에 해당되는 글 4건

  1. 2016.12.20 라이브러리와 프레임워크에 대해
  2. 2016.12.20 고급 DAO 프로그래밍 (Transaction)
  3. 2016.12.20 트랜잭션 서비스 사용
  4. 2016.12.20 트랜잭션(Transaction)과 2PC(two-phase commit)

라이브러리와 프레임워크에 대해

FRAMEWORK 2016. 12. 20. 17:41

원본 : https://kldp.org/node/124237

일단 모든 소스 코드든 라이브러리든 메모리에 들어가는 정보는, 컴파일러나 인터프리터에게는 호출가능한 모듈일 뿐입니다.

이런 물리적인 계층을 보지말고, 그 위의 논리적인 계층을 봐야합니다.

라이브러리는 톱, 망치, 삽같은 연장입니다.

사람이 들고 썰고, 바꿔들고 내려치고, 다시 바꿔들고 땅을 파는 겁니다.

프레임워크는 차, 비행기, 배같은 탈것입니다.

사람이 타서 엔진 켜고, 기어 넣고, 핸들 돌리고, 운전하거나, 조종하거나 해야합니다.

도구를 쓸 때, 급하면 썰어야 할 곳에 망치를 쳐도 됩니다. 땅 파야할 때 톱으로 땅을 긁어내도 됩니다.

사람은 도구를 선택하는 입장이기 때문에, 어떤 도구를 사용하든 원하는 것을 만들어낼 수 만 있으면 됩니다.

반면에, 탈것은 정해진 곳으로만 다녀야 합니다. 차를 타고 하늘을 날거나, 배를 타고 땅으로 갈 수는 없습니다.

하지만, 그 목적에 맞게 만들어져 있기 때문에, 톱이나 망치를 들고 먼저 탈것을 만들어야 할 필요가 없습니다.

그저 정해진 규칙에 맞춰서 엔진, 기어, 핸들만 잘 돌리면 됩니다.

라이브러리와는 달리 프레임워크는 이미 프로그래밍할 규칙이 정해져 있습니다.

예를 들어, 설정파일로 사용되는 XML에 어떤 태그를 써야 하며, 어떤 함수를 추가적으로 작성해야 하고,

소스 파일을 어느 위치에 넣어야하며, DB와 연동하기 위해 무엇을 써넣어야 하는지 정해져 있습니다.

보통 이런 대부분의 작업은 프레임워크가 하고자 하는 일에 비하면 아주 작은 일이며, 사람은 극히 일부분만 조정함으로써 목적을 달성할 수 있습니다.

만약 프레임워크가 담당하는 부분이 내가 하고자 하는 목적과 다를 경우에는 어떻게 할까요?

그럼 그냥 프레임워크를 잘못쓴겁니다.

더 목적에 가까운 프레임워크를 찾아보면 대부분 있을겁니다.

없거나 구하기 힘들다면, 비슷한 프레임워크를 라이브러리 단계에서 변경해서 다른 프레임워크로 만들면 됩니다.

차를 튜닝한다음, 차를 다시 운전하면 된다는 말이지요.

혹시 프레임워크 없이 그냥 라이브러리로만 만들면 안될까요?

안될 이유가 어딨겠습니까?

그냥 다 다시 만들 능력과 시간과 여유만 있다면 그렇게 해도 되지요.

스스로 만든 프레임워크는 버그도 스스로 잡아야하지만, 남들이 만들어놓은 프레임워크는 쓰는 사람이 많은 만큼 그만큼 수정이나 업데이트도 빠릅니다.

기능이 마음에 안드는 부분이 있다면, 프레임워크를 고치면 됩니다. 처음부터 다 만드는 것보다는 싸게 먹히지요.

내일 당장 지방에서 서울로 출근해야하는데, 혼자서 차를 만들어서 타고 가야한다는 생각을 해보세요.


프레임워크를 선택함에 있어 가장 고려해야 될 것은 내가 아닌 같이 일하는 동료들의 개발 효율과 프로그램을 사용할 고객이 바라는 기능이 우선이 되어야 하지 않을까 한다.


* 추가내용

토비의 스프링3. 1장 오브젝트와 의존관계를 보면 다음과 같은 내용이 있다.

프레임워크는 라이브러리의 다른 이름이 아니다.
프레임워크는 단지 미리 만들어 둔 반제품이나, 확장해서 사용할 수 있도록 준비된 추상 라이브러리의 집합이 아니다.
프레임워크가 어떤 것인지 이해하려면 라이브러리와 프레임워크가 어떻게 다른지 알아야 한다.
라이브러리를 사용하는 애플리케이션 코드는 애플리케이션 흐름을 직접 제어한다. 
단지 동작하는 중에 필요한 기능이 있을 때 능동적으로 라이브러리를 사용할 뿐이다.
반면에 프레임워크는 거꾸로 애플리케이션 코드가 프레임워크에 의해 사용된다.
보통 프레임워크 위에 개발한 클래스를 등록해두고, 프레임워크가 흐름을 주도하는 중에 
개발자가 만든 애플리케이션 코드를 사용하도록 만드는 방식이다.
최근에는 툴킨, 엔진, 라이브러리 등도 유행을 따라서 무작정 프레임워크라고 부르기도 하는데 이는 잘못된 것이다.
프레임워크에는 분명한 제어의 역전 개념이 적용되어 있어야 한다.
애플리케이션 코드는 프레임워크가 짜놓은 틀에서 수동적으로 동작해야 한다.
스프링이 프레임워크라는 것은 이제 쉽게 알 수 있지만 jquery나 ext-js와 같은 것들은 뭐라 정의하기가 매우 고민스러운데 위와 같은 개념을 바탕으로 생각해보면 ext-js의 경우 프레임워크라 부를 수 있을 것이고 jquery의 경우 라이브러리라 부를 수 있을 것이다.


출처 - http://lbass.tistory.com/entry/%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC%EC%99%80-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC%EC%97%90-%EB%8C%80%ED%95%B4

'FRAMEWORK' 카테고리의 다른 글

WAS에서 트랜잭션 처리  (0) 2017.01.04
Oracle Application Development Framework (ADF)  (0) 2016.12.12
Service Data Objects (SDO)  (0) 2016.12.12
Maven 을 이용한 프로젝트 생성 및 활용  (1) 2015.06.05
JNDI, TOMCAT  (0) 2013.11.06
:

고급 DAO 프로그래밍 (Transaction)

DB 2016. 12. 20. 17:35

DAO 구현 기술 

Level: Advanced

Sean C. Sullivan 
소프트웨어 엔지니어
2003년 10월 7일

J2EE 개발자들은 Data Access Object (DAO) 디자인 패턴을 사용하여 저수준의 데이터 액세스 로직과 고급 비즈니스 로직을 분리한다. DAO 패턴을 구현하는 것은 단순히 데이터 액세스 코드를 작성하는 것 이상이다.

지난 18개월 동안, 재능 있는 소프트웨어 엔지니어들과 함께 웹 기반의 공급체인 관리 애플리케이션을 구현했다. 우리가 만든 애플리케이션은 선적 상황, 공급 체인 메트릭스, 창고 재고, 운송장, 프로젝트 관리 데이터, 사용자 프로파일 등의 광범위한 데이터에 접근했다. JDBC API를 사용하여 회사의 다양한 데이터베이스 플랫폼에 연결했고 이 애플리케이션에 DAO 디자인 패턴을 적용했다.

그림 1은 애플리케이션과 데이터 소스의 관계이다:

그림 1. 애플리케이션과 데이터 소스

DAO의 기초
DAO 패턴은 표준 J2EE 디자인 패턴들 중 하나이다. 이 패턴을 사용하여 저수준 데이터 액세스와 고급 비지니스 로직을 분리한다. 전형적인 DAO 구현에는 다음과 같은 요소들이 있다:

  • DAO 팩토리 클래스
  • DAO 인터페이스
  • DAO 인터페이스를 구현하는 구체적 클래스
  • 데이터 전송 객체들(밸류(value) 객체)

구체적인 DAO 클래스에는 특정 데이터 소스로 부터 데이터에 액세스하는데 쓰이는 로직이 포함되어 있다.

트랜잭션 경계설정(demarcation)
DAO는 트랜잭션 객체들이라는 것을 반드시 기억해야 한다. DAO에 의해 수행되는 각각의 작동(데이터 구현, 업데이트, 삭제)은 트랜잭션과 관련있다. 따라서 트랜잭션 경계설정(demarcation) 개념은 매우 중요하다.

트랜잭션 경계설정은 트랜잭션 영역들이 정의 되는 방식이다. J2EE 스팩은 두 가지 모델의 트랜잭션 경계설정을 설명하고 있다. (표 1):

표 1. 트랜잭션 경계설정

선언적(Declarative) 트랜잭션 경계설정프로그램에 입각한(Programmatic) 트랜잭션 경계설정
프로그래머는 EJB 전개 디스크립터를 사용하여 트랜잭션 애트리뷰트를 선언한다.프로그래머는 트랜잭션 로직을 코딩해야한다.
런타임 환경(EJB 컨테이너)은 트랜잭션을 자동으로 관리하기 위해 이 애트리뷰트를 사용한다.이 애플리케이션은 API를 통해 트랜잭션을 제어한다.

프로그램에 입각한(Programmatic) 트랜잭션 경계설정을 중점적으로 설명하겠다.

디자인 고려사항
앞서 언급했지만, DAO는 트랜잭션 객체이다. 전형적인 DAO는 구현, 업데이트, 삭제 같은 트랜잭션 작동을 수행한다. DAO를 설계할 때 다음 사항들을 점검한다:

  • 트랜잭션은 어떻게 시작하는가?
  • 트랜잭션은 어떻게 끝나는가?
  • 트랜잭션 시작을 담당하는 객체는 무엇인가?
  • 트랜잭션 종료를 담당하는 객체는 무엇인가?
  • DAO가 트랜잭션의 시작과 종료를 담당해야 하는가?
  • 이 애플리케이션이 다중의 DAO를 통해 데이터에 액세스해야 하는가?
  • 트랜잭션에 포함될 DAO의 수는?
  • 하나의 DAO가 또 DAO에 대한 메소드를 호출할 수 있는가?

이러한 질문들에 대한 답을 알고있다면 자신의 DAO에 가장 잘 맞는 트랜잭션 경계설정 전략을 선택하는데 도움이 된다. DAO에는 두 가지 주요한 트랜잭션 경계설정 전략이 있다. 하나는 DAO가 트랜잭션의 경계를 설정하도록 하는 것이다. 또 다른 방법은 트랜잭션 경계설정을 DAO의 메소드를 호출하는 객체에 맡기는 것이다. 전자를 선택한다면 DAO 클래스 안에 트랜잭션 코드를 임베딩해야 한다. 후자의 방법을 선택한다면 트랜잭션 경계설정 코드는 DAO 클래스의 외부에 있게 될 것이다. 코드 예제를 보고 이 두 가지 방법을 자세히 보도록 하자.

Listing 1- DAO와 두 개의 데이터 작동;구현 및 업데이트:

Listing 1. DAO 메소드


       public void createWarehouseProfile(WHProfile profile);
       public void updateWarehouseStatus(WHIdentifier id, StatusInfo status);

Listing 2은 간단한 트랜잭션이다. 트랜잭션 경계설정 코드는 DAO 클래스 외부에 있다. 이 예제에서 콜러(caller)가 다중의 DAO 작동들을 이 트랜잭션 내에서 결합하는 방법을 주목해보자.

Listing 2. 콜러(Caller)에 의해 관리되는 트랜잭션


      tx.begin();    // start the transaction
      dao.createWarehouseProfile(profile);
      dao.updateWarehouseStatus(id1, status1);
      dao.updateWarehouseStatus(id2, status2);
      tx.commit();   // end the transaction

이 트랜잭션 경계설정 전략은 단일 트랜잭션에서 다중의 DAO에 액세스 해야하는 애플리케이션에 특별히 어울린다.

JDBC API 또는 Java Transaction API (JTA)를 사용하여 트랜잭션 경계설정을 구현할 수 있다. JDBC 트랜잭션 경계설정은 JTA 보다 단순하다. 하지만 JTA는 보다 유연하다.

JDBC를 이용한 트랜잭션 경계설정
JDBC 트랜잭션은 Connection 객체를 사용하여 제어된다. JDBC Connection 인터페이스(java.sql.Connection)는 두 개의 트랜잭션 모드를 제공한다. (auto-commit과 manual commit). java.sql.Connection은 트랜잭션 제어에 다음의 메소드를 제공한다:

  • public void setAutoCommit(boolean)
  • public boolean getAutoCommit()
  • public void commit()
  • public void rollback()

Listing 3은 JDBC API를 사용하여 트랜잭션의 경계설정을 하는 방법이다:

Listing 3. JDBC API를 이용한 트랜잭션 경계설정


      import java.sql.*;
      import javax.sql.*;

      // ...
      DataSource ds = obtainDataSource();
      Connection conn = ds.getConnection();
      conn.setAutoCommit(false);
      // ...
      pstmt = conn.prepareStatement("UPDATE MOVIES ...");
      pstmt.setString(1, "The Great Escape");
      pstmt.executeUpdate();
      // ...
      conn.commit();
      // ...

JDBC 트랜잭션 경계설정을 이용하면 여러 개의 SQL 문장을 하나의 트랜잭션으로 결합할 수 있다. JDBC 트랜잭션의 단점 중 하나는 트랜잭션 범위가 하나의 데이터베이스 연결로 제한되어 있다는 점이다. JDBC 트랜잭션은 다중 데이터베이스로 확장할 수 없다. 다음에는 JTA를 사용한 트랜잭션 경계설정이다.

JTA 개요
Java Transaction API (JTA)와 Java Transaction Service (JTS)는 J2EE 플랫폼에 분산 트랜잭션 서비스를 제공한다. 분산 트랜잭션에는 트랜잭션 매니저와 한 개 이상의 리소스 매니저가 포함된다. 리소스 매니저는 일종의 영속 데이터스토어이다. 트랜잭션 매니저는 모든 트랜잭션 참여자들 간 통신을 조정하는 역할을 담당한다. 트랜잭션 매니저와 리소스 매니저 관계는 다음과 같다. (그림 2):

그림 2. 트랜잭션 매니저와 리소스 매니저

JTA 트랜잭션은 JDBC 트랜잭션 보다 강력하다. JDBC 트랜잭션이 하나의 데이터베이스 연결로 제한되어 있다면 JTA 트랜잭션은 다중의 참여자들을 가질 수 있다. 다음의 자바 플랫폼 컴포넌트 중 어떤 것이든지 JTA 트랜잭션에 참여할 수 있다:

  • JDBC 커넥션
  • JDO PersistenceManager 객체
  • JMS 큐
  • JMS 토픽
  • Enterprise JavaBeans
  • J2EE Connector Architecture 스팩에 호환하는 리소스 어댑터

JTA를 이용한 트랜잭션 경계설정
JTA로 트랜잭션 경계를 설정하기 위해 애플리케이션은 javax.transaction.UserTransaction 인터페이스에 대한 메소드를 호출한다. Listing 4는 UserTransaction 객체의 전형적인 JNDI이다:

Listing 4. UserTransaction 객체의 JNDI



      import javax.transaction.*;
      import javax.naming.*;
      // ...
      InitialContext ctx = new InitialContext();
      Object txObj = ctx.lookup("java:comp/UserTransaction");
      UserTransaction utx = (UserTransaction) txObj;

애플리케이션 UserTransaction 객체에 대한 레퍼런스를 가진 후에 트랜잭션을 시작한다. (Listing 5):

Listing 5. 트랜잭션 시작



      utx.begin();
      // ...
      DataSource ds = obtainXADataSource();
      Connection conn = ds.getConnection();
      pstmt = conn.prepareStatement("UPDATE MOVIES ...");
      pstmt.setString(1, "Spinal Tap");
      pstmt.executeUpdate();
      // ...
      utx.commit();
      // ...

애플리케이션이 commit()을 호출하면, 트랜잭션 매니저는 2 단계 커밋(two-phase commit) 프로토콜을 사용하여 트랜잭션을 종료한다.

트랜잭션 제어용 JTA 메소드
javax.transaction.UserTransaction 인터페이스는 다음의 트랜잭션 제어 메소드를 제공한다:

  • public void begin()
  • public void commit()
  • public void rollback()
  • public int getStatus()
  • public void setRollbackOnly()
  • public void setTransactionTimeout(int)

JTA 트랜잭션을 시작할 때 이 애플리케이션은 begin()을 호출한다. 트랜잭션을 끝내려면 commit() 또는 rollback()을 호출한다. (참고자료).

JTA와 JDBC 사용하기
개발자들은 DAO 클래스에서 저수준 데이터 작동에 JDBC를 사용하곤 한다. JTA를 이용하여 트랜잭션의 경계를 설정하려면 javax.sql.XADataSourcejavax.sql.XAConnectionjavax.sql.XAResource인터페이스를 구현하는 JDBC 드라이버가 필요하다. 이러한 인터페이스를 구현하는 드라이버는 JTA 트랜잭션에 참여할 수 있게된다. XADataSource 객체는 XAConnection 객체용 팩토리이다. XAConnection는 JTA 트랜잭션에 참여하는 JDBC 커넥션이다.

애플리케이션 서버의 관리 툴을 사용하여 XADataSource를 설정해야 한다. 애플리케이션 서버 문서와 JDBC 드라이버 문서를 참조하라.

J2EE 애플리케이션은 JNDI를 사용하여 데이터 소스를 검색한다. 일단 애플리케이션이 데이터 소스 객체에 대한 레퍼런스를 갖게 되면 이것은 javax.sql.DataSource.getConnection()을 호출하여 데이터베이스로의 커넥션을 획득하게 된다.

XA 커넥션은 비 XA 커넥션과는 다르다. XA 커넥션은 JTA 트랜잭션에 참여하고 있다는 것을 언제나 기억하라. XA 커넥션은 JDBC의 자동 커밋 기능을 지원하지 않는다. 또한 이 애플리케이션은 XA 커넥션 상에서 java.sql.Connection.commit() 또는 java.sql.Connection.rollback()을 호출하지 않는다. 대신 UserTransaction.begin()UserTransaction.commit()UserTransaction.rollback()을 사용한다.

최상의 접근방법 선택하기
JDBC와 JTA를 이용한 트랜잭션 경계설정에 대해 이야기했다. 각 접근방식 대로 장점이 있기 때문에 자신의 애플리케이션에 가장 알맞는 것을 선택해야 한다.

최근 많은 프로젝트에서 우리팀은 JDBC API를 사용하여 DAO 클래스를 구현했다. 이 DAO 클래스는 다음과 같이 요약된다:

  • 트랜잭션 경계설정 코드는 DAO 클래스 안으로 임베딩된다.
  • DAO 클래스는 트랜잭션 경계설정에 JDBC API를 사용한다.
  • 콜러가 트랜잭션 경계를 설정할 방법은 없다.
  • 트랜잭션 범위는 하나의 JDBC Connection으로 제한된다.

JDBC 트랜잭션이 복잡한 엔터프라이즈 애플리케이션에 언제나 적합한 것은 아니다. 트랜잭션이 다중 DAO 또는 다중 데이터페이스로 확장한다면 다음과 같은 구현 전략이 보다 적합하다:

  • 트랜잭션은 JTA로 경계 설정된다.
  • 트랜잭션 경계설정 코드는 DAO와 분리되어 있다.
  • 콜러가 트랜잭션 경계설정을 담당하고 있다.
  • DAO는 글로벌 트랜잭션에 참여한다.

JDBC 접근방법은 간단함이 매력이다. JTA 접근방법은 유연성이 무기이다. 애플리케이션에 따라 구현 방법을 선택해야 한다.

로깅과 DAO
잘 구현된 DAO 클래스는 런타임 작동에 대한 세부사항을 파악하기 위해 로깅(logging)을 사용한다. 예외, 설정 정보, 커넥션 상태, JDBC 드라이버 메타데이터, 쿼리 매개변수 중 어떤 것이든 선택하여 기록해야 한다. 기록은 모든 개발 단계에 유용하다.

로깅 라이브러리 선택하기
많은 개발자들은 단순한 형식의 로깅을 사용한다: System.out.println과 System.err.printlnPrintln 문장은 빠르고 편리하지만 완벽한 로깅 시스템은 제공하지 않는다. 표 2는 자바 플랫폼을 위한 로깅 라이브러리이다:

표 2.자바 플랫폼을 위한 로깅 라이브러리

로깅 라이브러리오픈소스여부URL
java.util.loggingNohttp://java.sun.com/j2se/
Jakarta Log4jYeshttp://jakarta.apache.org/log4j/
Jakarta Commons LoggingYeshttp://jakarta.apache.org/commons/logging.html

java.util.logging은 J2SE 1.4 플랫폼을 위한 표준 API이다. Jakarta Log4j가 더 많은 기능성과 유연성을 제공한다는 것에는 많은 개발자들이 동의하고 있다. java.util.logging의 이점 중 하나는 J2SE 1.3과 J2SE 1.4 플랫폼을 지원한다는 것이다.

Jakarta Commons Logging은 java.util.logging 과의 연결 또는 Jakarta Log4j에 사용될 수 있다. Commons Logging은 로깅 추상 레이어로서 애플리케이션을 기저의 로깅 구현에서 고립시킬 수 있다. Commons Logging을 사용하여 설정 파일을 변경하여 기저의 로깅 구현을 바꿀 수 있다. Commons Logging은 Jakarta Struts 1.1과 Jakarta HttpClient 2.0에 사용된다.

로깅 예제
Listing 7은 DAO 클래스에서 Jakarta Commons Logging을 사용하는 방법이다:

Listing 7. Jakarta Commons Logging 


import org.apache.commons.logging.*;

class DocumentDAOImpl implements DocumentDAO
{
      static private final Log log = LogFactory.getLog(DocumentDAOImpl.class);

      public void deleteDocument(String id)
      {
          // ...
          log.debug("deleting document: " + id);
          // ...
          try
          {
              // ... data operations ...
          }
          catch (SomeException ex)
          {
              log.error("Unable to delete document", ex);
              // ... handle the exception ...
  }
      }
}

로깅은 미션 수행에 중요한 애플리케이션의 중요한 일부이다. DAO에서 오류가 생기면 무엇이 잘못되었는지를 이해할 수 있게끔 최고의 정보를 로그가 제공한다. 로깅과 DAO를 결합하면 디버깅과 문제해결은 확실하다.

DAO에서의 예외 핸들링

DAO 패턴을 구현할 때 다음 사항을 자문해보라:

  • DAO의 퍼블릭 인터페이스의 메소드들이 검사된 예외를 던지는가?
  • 그렇다면 어떤 예외들인가?
  • DAO 구현 클래스에서 예외는 어떻게 처리되는가?

DAO 패턴을 작업하는 과정에서 우리 팀은 예외 핸들링에 대한 가이드라인을 개발했다:

  • DAO 메소드는 의미있는 예외를 던져야한다.

  • DAO 메소드는 java.lang.Exception을 던져서는 안된다. java.lang.Exception은 너무 일반적이다. 근본 문제에 대한 정보를 제공하지 않을 것이다.

  • DAO 메소드는 java.sql.SQLException 메소드를 던져서는 안된다. SQLException은 저급 JDBC 예외이다. DAO는 JDBC를 나머지 애플리케이션에 노출하는 것이 아니라 JDBC를 캡슐화 해야한다.

  • DAO 인터페이스의 메소드들은 콜러가 예외를 처리할 수 있다고 합리적으로 판단될 때 에만 검사된예외를 던져야 한다. 콜러가 예외를 핸들할 수 없다면 검사되지 않은(런타임) 예외를 던질 것을 고려하라.

  • 데이터 액세스 코드가 예외를 잡으면 이를 무시하지 말아라. 잡힌 예외를 무시하는 DAO는 문제해결에 애를 먹는다.

  • 연쇄 예외를 사용하여 저급 예외를 고급 예외로 트랜슬레이팅 한다.

  • 표준 DAO 예외 클래스를 정의하라. Spring Framework (참고자료)은 사전 정의된 DAO 예외 클래스를 제공한다.

구현 예제: MovieDAO
MovieDAO는 이 글에 논의된 모든 기술을 보여주는 DAO이다: 트랜잭션 경계설정, 로깅, 예외 핸들링. 코드는 세 개의 패키지로 나뉜다. (참고자료):

  • daoexamples.exception
  • daoexamples.movie
  • daoexamples.moviedemo

DAO 패턴 구현은 클래스와 인터페이스로 구성된다:

  • daoexamples.movie.MovieDAOFactory
  • daoexamples.movie.MovieDAO
  • daoexamples.movie.MovieDAOImpl
  • daoexamples.movie.MovieDAOImplJTA
  • daoexamples.movie.Movie
  • daoexamples.movie.MovieImpl
  • daoexamples.movie.MovieNotFoundException
  • daoexamples.movie.MovieUtil

MovieDAO 인터페이스는 DAO의 데이터 작동을 정의한다. 이 인터페이스는 다섯 개의 메소드를 갖고 있다:

  • public Movie findMovieById(String id)
  • public java.util.Collection findMoviesByYear(String year)
  • public void deleteMovie(String id)
  • public Movie createMovie(String rating, String year, String, title)
  • public void updateMovie(String id, String rating, String year, String title)

daoexamples.movie 패키지에는 두 개의 MovieDAO 인터페이스 구현이 포함되어 있다. 각 구현은 트랜잭션 경계설정에 다른 접근방식을 사용한다. (표 3):

표 3. MovieDAO 구현

MovieDAOImplMovieDAOImplJTA
MovieDAO 인퍼페이스 구현YesYes
JNDI를 통한 DataSourc 획득YesYes
DataSource에서 java.sql.Connection 객체 획득YesYes
DAO가 트랜잭션을 내부적으로 경계설정하는가?YesNo
JDBC 트랜잭션 사용YesNo
XA DataSource 사용NoYes
JTA 트랜잭션 참여NoYes

MovieDAO 데모 애플리케이션
이 데모 애플리케이션 이름은 daoexamples.moviedemo.DemoServlet 이다. DemoServlet은 Movie DAO를 사용하여 무비 데이터를 쿼리 및 업데이트 한다.

Listing 8은 싱글 트랜잭션 에서의 JTA-aware MovieDAO와 Java Message Service의 결합 방법이다.

Listing 8. MovieDAO와 JMS 코드 결합


  UserTransaction utx = MovieUtil.getUserTransaction();
  utx.begin();
  batman = dao.createMovie("R",
      "2008",
      "Batman Reloaded");
  publisher = new MessagePublisher();
  publisher.publishTextMessage("I'll be back");
  dao.updateMovie(topgun.getId(),
      "PG-13",
      topgun.getReleaseYear(),
      topgun.getTitle());
  dao.deleteMovie(legallyblonde.getId());
  utx.commit();

데모를 실행하려면 XA 데이터소스와 비 XA 데이터소스를 애플리케이션 서버에 설정해야 한다. 그런다음 daoexamples.ear 파일을 전개한다.


출처 -http://lbass.tistory.com/entry/%EB%B3%B8%EB%AC%B8%EC%8A%A4%ED%81%AC%EB%9E%A9-%EA%B3%A0%EA%B8%89-DAO-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

'DB' 카테고리의 다른 글

트랜잭션 서비스 사용  (0) 2016.12.20
트랜잭션(Transaction)과 2PC(two-phase commit)  (0) 2016.12.20
OLTP / OLAP  (1) 2016.11.05
다차원 모델링(1/2)  (0) 2016.11.05
DW, DM, OLAP의 이해  (2) 2016.11.05
:

트랜잭션 서비스 사용

DB 2016. 12. 20. 17:16

트랜잭션은 비즈니스의 통합된 일부입니다. 일반 비즈니스 트랜잭션은 두 개 이상의 관련 부분 사이 자산 이동과 관련되어 있습니다. 정확성을 요하는 기록은 보통 하나 이상의 데이터베이스에 저장됩니다. 이 정보는 비즈니스 작업에 꼭 필요하기 때문에 항상 유효하고, 현재성을 가지고, 신뢰할 수 있어야 합니다. 초보 프로그래머에게는 트랜잭션 처리가 어려울 수 있습니다. J2EE 플랫폼은 종속 가능한 트랜잭션 처리 응용 프로그램 전개를 쉽게 해주는 여러 추상적 개념을 제공합니다. 이 장에서는 Sun ONE Application Server의 J2EE 트랜잭션 및 트랜잭션 지원을 설명합니다.

이 장에서는 일반적으로 Java 트랜잭션, 구체적으로는 Sun ONE Application Server에 포함되어 있는 트랜잭션 지원에 대해 설명합니다.

이 장에서는 다음 내용을 설명합니다.

트랜잭션 정보

비즈니스 트랜잭션을 에뮬레이트하려면 프로그램이 여러 단계를 수행해야 할 수 있습니다. 예를 들어, 재무 프로그램이 다음 의사 코드에 나열된 단계를 수행하면 자금을 수표 계좌에서 예금 계좌로 이체할 수 있습니다.

begin transaction

debit checking account

credit savings account

update history log

commit transaction

앞의 의사 코드에서 begin 및 commit 명령은 트랜잭션 경계를 표시합니다. 트랜잭션을 완료하려면 세 단계가 모두 완료되어야 합니다. 세 단계가 모두 완료되지 못하면 데이터 통합이 손상될 수 있습니다.

이 보장을 원자성이라고 합니다. 트랜잭션은 commit 또는 rollback 명령으로 끝납니다. 트랜잭션을 완결하면 트랜잭션 경계 내의 명령으로 수행한 모든 수정이 저장 및 지속됩니다. 변경은 영구적이며 이후 시스템 장애가 일어나도 그대로 유지됩니다. 트랜잭션 내의 명령 중 하나라도 실패하면 트랜잭션 전체가 롤백하며, 그 때까지 트랜잭션 내에서 실행된 모든 명령은 취소됩니다. 예를 들어, 의사 코드의 credit 단계 중 디스크 드라이브에 오류가 발생하면, 트랜잭션은 롤백되고 debit 명령으로 수행되었던 데이터 변경도 모두 취소됩니다.

트랜잭션이 실패해도 트랜잭션 계정 잔액은 여전히 유지되기 때문에 데이터 통합이 손상되지 않습니다. 트랜잭션 작동의 이런 측면을 트랜잭션 일관성이라 합니다.

트랜잭션 서비스는 고립화도 제공합니다. 이것은 트랜잭션이 완결 또는 롤백되기 전까지는 트랜잭션 내 구문을 다른 응용 프로그램에서 관찰할 수 없음을 의미합니다. 일단 트랜잭션이 완결되면 이 완결된 트랜잭션은 응용 프로그램 및 스레드가 안전하게 관찰할 수 있습니다.

J2EE 트랜잭션

J2EE의 트랜잭션 처리는 트랜잭션 관리자, 응용 프로그램 서버, 자원 관리자, 자원 어댑터 및 사용자 응용 프로그램의 다섯 참가자에 의해 수행됩니다. 각 엔티티는 다음에서 설명하는 여러 API 및 기능을 구현하여 신뢰할 수 있는 방법으로 트랜잭션을 처리합니다.

  • 트랜잭션 관리자는 트랜잭션 구분, 트랜잭션 자원 관리, 동기화 및 트랜잭션 컨텍스트 전파 지원에 필요한 서비스 및 관리 기능을 제공합니다.
  • 응용 프로그램 서버는 트랜잭션 상태 관리 등의 응용 프로그램 런타임 환경 지원에 필요한 기반 구조를 제공합니다.
  • 자원 관리자(자원 어댑터를 통한)는 응용 프로그램에게 자원에 대한 액세스를 제공합니다. 자원 관리자는 트랜잭션 관리자가 트랜잭션 연결, 트랜잭션 완료 및 복구 작업과 통신할 때 사용하는 트랜잭션 자원 인터페이스를 구현하여 분산된 트랜잭션에 참여합니다. 이런 자원 관리자의 예로 관계형 데이터베이스 서버를 들 수 있습니다.
  • 자원 어댑터는 응용 프로그램 서버 또는 클라이언트가 자원 관리자와의 연결에 사용하는 시스템 수준 소프트웨어 라이브러리입니다. 자원 어댑터는 일반적으로 자원 관리자마다 따로 지정됩니다. 자원 어댑터는 라이브러리로 사용 가능하며 이것을 사용하는 클라이언트 주소 공간 내에서 사용됩니다. 이런 자원 어댑터의 예로는 JDBC 드라이버가 있습니다.
  • J2EE 응용 프로그램 서버 환경에서 작업하기 위해 개발된 트랜잭션 사용자 응용 프로그램은 JNDI를 사용하여 트랜잭션 데이터 소스 및 선택적으로 트랜잭션 관리자를 조회합니다. EJB의 선언적 트랜잭션 속성 설정 또는 명시적인 프로그램형 트랜잭션 구분을 사용할 수 있습니다.

자원 관리자와 자원 어댑터 엔티티는 서로 밀접하게 연관되어 있어서, 자원 관리자라는 용어가 자원 어댑터와 혼용되는 경우도 많습니다.

트랜잭션 자원 관리자

다음 트랜잭션 자원 관리자는 J2EE 트랜잭션 내에서 지원됩니다.

데이터베이스

가장 자주 접하게 되는 J2EE 응용 프로그램의 트랜잭션 자원 관리자는 데이터베이스입니다. JDBC는 J2EE 구성 요소가 데이터베이스 액세스에 사용하는 API입니다. 데이터베이스 자원은 JDBC 자원으로 구성됩니다. JDBC 자원은 자원 관리자 또는 JDBC 드라이버가 관리합니다. JDBC 드라이버는 로컬 트랜잭션 또는 전역 트랜잭션 및 때로 로컬 및 전역 트랜잭션 모두에 대한 지원을 제공할 수 있습니다.

Sun ONE Application Server는 여러 J2EE 구성 요소의 JDBC 및 트랜잭션 사용을 지원합니다. JDBC 자원의 등록 및 구성 방법에 대한 자세한 내용은 "JDBC 자원 정보"를 참조하십시오. 응용 프로그램 서버는 트랜잭션 연속성 제공(즉 여러 응용 프로그램 구성 요소로부터 트랜잭션 초기화 및 데이터베이스 액세스 수행)을 담당합니다. 예를 들어, 서블릿이 트랜잭션을 시작하고, 데이터베이스를 액세스하고, 동일한 트랜잭션의 일부로 동일한 데이터베이스를 액세스하는 Enterprise Bean을 불러낸 후, 마지막으로 트랜잭션을 완결할 수 있습니다.

JMS 공급자

JMS는 Java Message Service의 약자입니다. JMS 공급자는 메시지 브로커 서비스를 의미하는 J2EE 용어입니다. JMS API는 응용 프로그램 사이에 신뢰할 수 있는 트랜잭션 방식의 교환을 제공합니다. 트랜잭션 JMS 데이터 소스 지원은 J2EE의 필수 기능입니다. JMS 자원 및 JDBC 자원이 함께 동일한 트랜잭션에 사용될 수 있습니다.

Sun ONE Application Server는 Sun ONE 메시지 대기열, 완전한 기능의 JMS 공급자 및 해당 트랜잭션 자원 관리자에 통합됩니다. 이렇게 하면 Sun ONE Application Server가 서블릿, JSP 페이지 및 Enterprise Bean에서 트랜잭션 JMS에 액세스할 수 있습니다. Sun ONE Application Server에 타사 JMS 공급자를 사용할 수도 있습니다. 자세한 내용은 "JMS 서비스 사용"을 참조하십시오.

J2EE 커넥터

Sun ONE Application Server는 트랜잭션 자원 관리자로 XATransaction 모드를 사용하는 자원 어댑터를 지원합니다. 플랫폼에서는 서블릿, JSP 페이지 및 Enterprise Bean에서 자원 어댑터로 트랜잭션 액세스할 수 있어야 합니다. 단일 트랜잭션 내의 여러 응용 프로그램 구성 요소에서 자원 어댑터에 액세스할 수 있습니다. 예를 들어, 서블릿이 트랜잭션을 시작하고, 자원 어댑터를 액세스하고, 동일한 트랜잭션의 일부로 자원 어댑터를 액세스하는 Enterprise Bean을 불러낸 후, 마지막으로 트랜잭션을 완결할 수 있습니다.

로컬 및 분산 트랜잭션

한 자원과만 관련 있는 트랜잭션은 로컬 트랜잭션을 사용하여 완료될 수 있습니다. 또한 로컬 트랜잭션은 모든 참여 응용 프로그램 구성 요소가 하나의 프로세스 내에서 실행되어야 합니다. 두 개 이상의 자원 또는 여러 참여 프로세스가 관련된 트랜잭션은 분산 또는 전역 트랜잭션이 될 수 있습니다. 로컬 트랜잭션 최적화는 최적화 전용 자원 관리자를 사용하며, 이것은 J2EE 응용 프로그램에 투명합니다.

트랜잭션 유형은 관련 자원 관리자에 구현된 인터페이스로 판단할 수 있습니다. 예를 들어, javax.sql.DataSource 인터페이스를 구현하는 JDBC 데이터 소스는 로컬 트랜잭션에 참여할 수 있습니다. javax.sql.XADataSource를 구현하는 데이터 소스는 전역 트랜잭션의 일부를 취할 수 있습니다. 일부 JDBC 자원은 두 인터페이스를 모두 구현하며, 이런 JDBC 자원이 Sun ONE Application Server에 등록되어 있으면 Sun ONE Application Server의 구성에 해당 자원의 선호 기능을 표시하는 구성 정보를 추가해야 할 수 있습니다.

로컬 트랜잭션이 더 간단하며 기본적으로 전역 트랜잭션보다 효율적입니다. 변형해야 할 데이터가 여러 데이터 소스에 있을 경우에는 로컬 트랜잭션이 적절하지 않습니다. 때로 몇 개의 데이터 소스가 트랜잭션에 나열되어야 하는지 예측할 수 없는 경우도 있습니다. 이 때문에 실제로는 전역 트랜잭션을 더 많이 사용합니다. 전역 트랜잭션에 사용할 수 있는 몇 가지 성능 개선 최적화가 있습니다.

J2EE는 트랜잭션 내의 여러 Enterprise Bean에 액세스하는 서블릿이나 JSP의 임의 조합을 모두 포함하는 트랜잭션 응용 프로그램을 지원합니다. 각 구성 요소는 하나 이상의 트랜잭션 자원 관리자에 대해 하나 이상의 연결을 가질 수 있습니다. 다음 그림에서, 호출 트리는 여러 Enterprise Bean을 액세스하는 서블릿 또는 JSP에서 시작하며, 이후 다른 Enterprise Bean을 액세스할 수 있습니다. 구성 요소는 연결을 통해 자원 관리자에 액세스합니다.

트랜잭션의 자원에 액세스하는 J2EE 구성 요소

이 그림은 트랜잭션에 대한 모든 구성 요소를 보여주는 호출 트리입니다.
 

예를 들어, 응용 프로그램은 위 그림의 모든 구성 요소가 단일 트랜잭션의 일부로 자원에 액세스해야 할 수도 있습니다. 응용 프로그램 서버 공급자는 이런 시나리오를 지원하는 트랜잭션 기능을 제공해야 합니다.

J2EE 트랜잭션 관리는 플랫 트랜잭션을 지원합니다. 플랫 트랜잭션은 자식(중첩된) 트랜잭션을 가질 수 없습니다.

트랜잭션 복구는 분산 트랜잭션에 있어 중요한 측면입니다. 크리티컬 포인트 동안 자원을 사용할 수 없거나 기타 복구할 수 없는 오류가 발생하면, 분산 트랜잭션의 상태를 모르게 될 수 있습니다. 꼬이거나 완료되지 못한 트랜잭션을 자동 및 수동으로 복구하는 것은 Sun ONE Application Server의 중요한 기능입니다. 자동 트랜잭션 복구는 관리 인터페이스를 사용하여 수행할 수 있습니다. 트랜잭션 복구 제어 방법의 자세한 내용은 "트랜잭션 서비스 관리"를 참조하십시오.

연결(여기에서는 자원과 동의어로 사용됨)은 공유 가능 여부가 표시될 수 있습니다. 공유 불가능한 방법으로 연결을 사용하려는 J2EE 응용 프로그램 구성 요소는 영향을 받는 측에 배포 정보를 제공하여 컨테이너가 연결을 공유하지 못하도록 해야 합니다. 이것이 필요할 수 있는 경우의 예로는 보안 속성, 고립화 수준, 문자 집합 및 로컬화 구성을 변경하는 경우가 포함됩니다.

컨테이너는 공유 불가능으로 표시된 연결을 공유하지 말아야 합니다. 연결이 공유 불가능으로 표시되어 있지 않으면, 이것은 연결이 실제 공유되어 있는지 여부와 상관없이 응용 프로그램에 투명해야 합니다.

J2EE 응용 프로그램 구성 요소는 선택적 전개 설명자 요소 res-sharing-scope를 사용하여 자원 관리자에 대한 연결의 공유 가능 여부를 표시할 수 있습니다. 컨테이너는 전개 관련 정보가 제공되지 않으면 공유 가능한 연결이라고 간주합니다. J2EE 응용 프로그램 구성 요소는 연결 객체를 캐시하여 여러 트랜잭션에서 다시 사용할 수 있습니다. 공유 연결을 제공하는 컨테이너는 이런 캐시된 연결 객체를 투명하게 전환하여(디스패치할 때) 올바른 트랜잭션 범위를 가진 적절한 공유 연결을 가리키도록 해야 합니다.

Enterprise Bean 응용 프로그램을 설계하는 경우, 개발자는 경계 지정 방법을 결정해야 합니다.

컨테이너 관리 트랜잭션

컨테이너 관리 트랜잭션이 있는 Enterprise Bean의 경우에는 EJB 컨테이너가 트랜잭션 경계를 설정합니다. Enterprise Bean 유형으로 Session, Entity 또는 Message-Driven을 가진 컨테이너 관리 트랜잭션을 사용할 수 있습니다. 컨테이너 관리 트랜잭션은 Enterprise Bean 코드가 트랜잭션의 경계를 명시적으로 표시하지 않기 때문에 간단하게 배포할 수 있습니다. 이 코드에는 트랜잭션 시작 및 종료 명령이 없습니다.

일반적으로 컨테이너는 Enterprise Bean 메소드가 시작하기 직전에 트랜잭션을 시작하고, 메소드가 종료되기 직전 트랜잭션을 완결합니다. 각 메소드는 단일 트랜잭션에 관련될 수 있습니다. 한 메소드 내에 중첩된 트랜잭션 또는 여러 트랜잭션을 허용하지 않습니다.

컨테이너 관리 트랜잭션이 트랜잭션에 연결될 때 모든 메소드가 필요하지는 않습니다. Bean을 배포할 때에는 트랜잭션 속성을 설정하여 트랜잭션과 관련된 Bean의 메소드를 지정합니다.

이 절에서는 다음 내용을 설명합니다.

트랜잭션 속성

트랜잭션 속성은 트랜잭션 범위를 제어합니다. 다음 그림은 범위 제어가 왜 중요한지 보여주고 있습니다. 다이어그램에서, 메소드 A는 트랜잭션을 시작하고 Bean 2의 메소드 B는 트랜잭션을 불러냅니다. 메소드 B가 실행되면 메소드 A가 시작한 트랜잭션 범위 내에서 실행될까요? 아니면 새 트랜잭션으로 실행될까요? 답은 메소드 B의 트랜잭션 속성에 따라 달라집니다.

이 그림은 트랜잭션의 범위입니다.

   
 
트랜잭션 속성

트랜잭션 속성은 다음 값 중 하나를 가질 수 있습니다.

Required

클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 이 메소드는 클라이언트 트랜잭션 내에서 실행됩니다. 클라이언트가 트랜잭션과 관련되어 있지 않으면, 메소드가 실행되기 전 먼저 컨테이너가 새 트랜잭션을 시작합니다.

Required 속성은 대부분의 트랜잭션에 사용됩니다. 이 때문에 최소한 개발 초기에는 이것을 기본값으로 사용하는 것이 좋습니다. 트랜잭션 속성은 선언적이기 때문에 나중에 쉽게 변경할 수 있습니다.

RequiresNew

클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 컨테이너는 다음 단계를 수행합니다.

  • 클라이언트의 트랜잭션 일시 중단
  • 새 트랜잭션 시작
  • 메소드에게 호출 위임
  • 메소드 실행 완료 후 클라이언트의 트랜잭션 다시 시작

클라이언트가 트랜잭션과 관련되어 있지 않으면, 메소드가 실행되기 전 먼저 컨테이너가 새 트랜잭션을 시작합니다.

메소드가 새 트랜잭션 내에서 항상 실행되도록 하려면 RequiresNew 속성을 사용해야 합니다.

Mandatory

클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 이 메소드는 클라이언트 트랜잭션 내에서 실행됩니다. 클라이언트가 트랜잭션과 관련되어 있지 않으면 TransactionRequiredException이 발생합니다.

Enterprise Bean의 메소드가 클라이언트 트랜잭션을 사용해야 하는 경우 Mandatory 속성을 사용합니다.

NotSupported

클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 컨테이너는 이 메소드를 불러내기 전 먼저 클라이언트 트랜잭션을 일시 중단합니다. 메소드가 완료된 다음 컨테이너는 클라이언트 트랜잭션을 다시 시작합니다.

클라이언트가 트랜잭션과 관련되어 있지 않으면, 컨테이너는 메소드가 실행되기 전 새 트랜잭션을 시작하지 않습니다.

트랜잭션이 필요하지 않은 메소드에는 NotSupported 속성을 사용합니다. 트랜잭션 불러내기는 오버헤드가 있기 때문에 이 속성은 성능을 개선할 수 있습니다.

Supports

클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 이 메소드는 클라이언트 트랜잭션 내에서 실행됩니다. 클라이언트가 트랜잭션과 관련되어 있지 않으면, 컨테이너는 메소드가 실행되기 전 새 트랜잭션을 시작하지 않습니다.

메소드의 트랜잭션 작업은 다양하기 때문에 Supports 속성은 주의해서 사용해야 합니다.

Never

클라이언트가 트랜잭션 내에서 실행 중일 때 Enterprise Bean의 메소드를 불러내면, 컨테이너는 RemoteException를 발생합니다. 클라이언트가 트랜잭션과 관련되어 있지 않으면, 컨테이너는 메소드가 실행되기 전 새 트랜잭션을 시작하지 않습니다.

속성 요약

다음 표는 트랜잭션 속성의 영향을 요약합니다. T1 및 T2 트랜잭션은 모두 컨테이너로 제어됩니다. T1 트랜잭션은 Enterprise Bean의 메소드를 호출하는 클라이언트와 관련되어 있습니다. 대부분의 경우 클라이언트도 별도의 Enterprise Bean입니다. T2 트랜잭션은 메소드가 실행되기 전 컨테이너에 의해 시작됩니다.

마지말 열의 '없음'이라는 단어는 비즈니스 메소드가 컨테이너가 제어하는 트랜잭션 내에서 실행되지 않음을 표시합니다. 하지만 이런 비즈니스 메소드에 호출된 데이터베이스는 DBMS의 트랜잭션 관리자가 제어할 수 있습니다.

   트랜잭션 속성

트랜잭션 속성

 

클라이언트 트랜잭션

 

비즈니스 메소드의 트랜잭션

 

Required

없음

 

T2

 

T1

 

T1

 

RequiresNew

없음

 

T2

 

T1

 

T2

 

Mandatory

없음

 

오류

 

T1

 

T1

 

NotSupported

없음

 

없음

 

T1

 

없음

 

Supports

 

없음

T1

 

없음

T1

 

트랜잭션 속성 설정

트랜잭션 속성은 배포 설명자에 저장되기 때문에 Enterprise Bean 작성, 응용 프로그램 어셈블리 및 배포 등 J2EE 응용 프로그램 전개자의 여러 단계 도중 변경될 수 있습니다. 하지만 Bean 작성시 속성을 지정하는 것은 개발자가 해야 합니다. 속성은 구성 요소를 더 큰 응용 프로그램으로 어셈블리하는 응용 프로그램 개발자만 수정할 수 있어야 합니다. J2EE 응용 프로그램을 배포하는 사람은 트랜잭션 속성을 지정할 책임이 없습니다.

전체 Enterprise Bean 또는 각 메소드에 대해 트랜잭션 속성을 지정할 수 있습니다. 한 속성은 메소드에 대해 지정하고 다른 속성은 Bean에 대해 지정한 경우에는 메소드에 대해 지정한 속성이 우선권을 갖습니다. 각 메소드에 대해 속성을 지정하는 경우 필요한 사항은 Bean 유형에 따라 달라집니다. Session Bean에는 비즈니스 메소드에 정의된 속성이 필요하지만, 생성 메소드에 대해서는 허용하지 않습니다. Entity Bean에는 비즈니스, 생성, 제거 및 검색 메소드에 대한 트랜잭션 속성이 필요합니다. Message-Driven Bean에는 onMessage 메소드에 대한 트랜잭션 속성(Required 또는 NotSupported 중 하나)이 필요합니다.

컨테이너 관리 트랜잭션 롤백

컨테이너 관리 트랜잭션의 롤백에는 두 가지 방법이 있습니다. 먼저 시스템 예외가 발생하면 컨테이너는 자동으로 트랜잭션을 롤백합니다. 두 번째로 EJBContext 인터페이스의 setRollbackOnly 메소드를 불러내서, Bean 메소드가 컨테이너에게 트랜잭션 롤백을 지시할 수 있습니다. Bean이 응용 프로그램 예외를 발생시키면 롤백이 자동으로 실행되지 않아도 setRollbackOnly를 호출하여 초기화할 수 있습니다.

다음 예에서 BankEJB 예의 transferToSaving 메소드는 setRollbackOnly 메소드를 나타내고 있습니다. 수표 계정의 잔액이 마이너스가 되면, transferToSaving은 setRollBackOnly를 불러내고 응용 프로그램 예외(InsufficientBalanceException)를 발생시킵니다. updateChecking 및 updateSaving 메소드는 데이터베이스 테이블을 업데이트합니다. 업데이트에 실패하면 메소드는 SQLException을 발생시키고 transferToSaving 메소드는 EJBException을 발생시킵니다.

EJBException은 시스템 예외기 때문에, 컨테이너는 자동으로 트랜잭션을 롤백합니다. 다음은 transferToSaving 메소드의 코드입니다.

public void transferToSaving(double amount) throws
InsufficientBalanceException {

checkingBalance -= amount;
savingBalance += amount;

if (checkingBalance < 0.00) { 
context.setRollbackOnly();

throw new InsufficientBalanceException(); 
}
try {
updateChecking(checkingBalance);

updateSaving(savingBalance);
} catch (SQLException ex) {
throw new EJBException 
("Transaction failed due to SQLException: " 
+ ex.getMessage());
}
}

컨테이너가 트랜잭션을 롤백하는 경우, 이것은 항상 트랜잭션 내의 SQL 호출로 발생한 데이터 변경을 모두 실행 취소합니다. 하지만 컨테이너는 Entity Bean에서만 인스턴스 변수에 대한 변경을 취소합니다(이 작업은 Entity Bean의 ejbLoad 메소드를 자동으로 호출하여 수행하며, 데이터베이스에서 인스턴스 변수가 로드됨). 롤백이 발생하면 Session Bean은 트랜잭션 내에 변경된 인스턴스 변수를 명시적으로 다시 설정합니다. Session Bean 인스턴스 변수를 다시 설정하는 가장 쉬운 방법은 SessionSynchronization 인터페이스를 구현하는 것입니다.

트랜잭션 ID를 명령줄 인터페이스를 통해 전달하여 트랜잭션을 롤백할 수도 있습니다. 자세한 내용은 "명령줄 인터페이스를 사용한 트랜잭션 관리"를 참조하십시오.

Session Bean의 인스턴스 변수 동기화

SessionSynchronization 인스턴스(선택적)를 사용하면 인스턴스 변수를 데이터베이스 내의 대응하는 값과 동기화할 수 있습니다. 컨테이너는 트랜잭션의 각 주요 단계에서 SessionSynchronization 메소드(afterBeginbeforeCompletion 및 afterCompletion)를 불러냅니다.

afterBegin 메소드는 새 트랜잭션이 시작되었음을 인스턴스에게 알립니다. 컨테이너는 처음으로 트랜잭션 내의 비즈니스 메소드를 불러내기 전에 먼저 afterBegin을 불러냅니다. afterBegin 메소드는 데이터베이스에서 인스턴스 변수를 로드하기에 좋은 위치입니다. 예를 들어, BankBean 클래스는 afterBegin 메소드 내에 checkingBalance 및 savingBalance 변수를 로드합니다.

public void afterBegin() {

System.out.println("afterBegin()");
try {
checkingBalance = selectChecking();
savingBalance = selectSaving();
} catch (SQLException ex) {
throw new EJBException("afterBegin Exception: " +
ex.getMessage());
}
}

컨테이너는 비즈니스 메소드는 완료되었지만 트랜잭션이 완결되기 전에 beforeCompletion 메소드를 불러냅니다. beforeCompletion 메소드는 Session Bean이 트랜잭션을 롤백할 수 있는(setRollbackOnly를 호출하여) 마지막 장소입니다. 아직 인스턴스의 변수 값을 데이터베이스에 업데이트하지 않았다면, Session Bean은 이 작업을 beforeCompletion 메소드에서 수행합니다.

afterCompletion 메소드는 트랜잭션이 완료되었음을 표시합니다. 여기에는 boolean 값의 매개 변수 하나가 있으며, 트랜잭션이 완결되면 true, 트랜잭션이 롤백되면 false 값을 갖습니다. 롤백이 발생하면 Session Bean은 afterCompletion 메소드에서 데이터베이스의 인스턴스 변수를 새로 고칠 수 있습니다.

public void afterCompletion(boolean committed) {

System.out.println("afterCompletion: " + committed);
if (committed == false) {
try {
checkingBalance = selectChecking();
savingBalance = selectSaving();
} catch (SQLException ex) {
throw new EJBException("afterCompletion SQLException:
" + ex.getMessage());
}
}
}

컨테이너 관리 트랜잭션에 허용되지 않는 메소드

컨테이너가 설정한 트랜잭션 경계를 간섭할 수 있는 메소드는 모두 불러낼 수 없습니다. 금지되는 메소드 목록은 다음과 같습니다.

  • java.sql.Connection의 완결, setAutoCommit 및 롤백 메소드.
  • javax.ejb.EJBContext의 getUserTransaction 메소드.
  • javax.transaction.UserTransaction의 모든 메소드.

하지만 Bean 관리 트랜잭션에는 이 메소드들을 사용하여 경계를 설정할 수 있습니다.

Bean 관리 트랜잭션

Bean 관리 트랜잭션의 경우, Session 또는 Message-Driven Bean 내의 코드에서 명시적으로 트랜잭션 경계를 표시합니다. Entity Bean은 Bean 관리 트랜잭션을 가질 수 없으며 대신 컨테이너 관리 트랜잭션을 사용해야 합니다. 컨테이너 관리 트랜잭션을 가진 Bean은 필요한 코드가 줄어들지만 한 가지 제한을 갖습니다. 메소드가 실행되면 Bean은 단일 트랜잭션에 관련되거나 아무런 트랜잭션에도 관련되지 않을 수 있습니다. 이 제한 때문에 Bean 코딩이 어려워지는 경우, Bean 관리 트랜잭션 사용을 고려해야 합니다.

다음 의사 코드는 Bean 관리 트랜잭션으로 구할 수 있는 세분화된 제어 종류를 표시합니다. 의사 코드는 여러 조건을 확인하여 비즈니스 메소드 내에서 여러 트랜잭션의 시작 또는 중지 여부를 결정합니다.

begin transaction
...
update table-a
...
if (condition-x)
commit transaction
else if (condition-y)
update table-b
commit transaction
else
rollback transaction
begin transaction
update table-c
commit transaction

트랜잭션 서비스 관리

관리 인터페이스 또는 명령줄 인터페이스를 사용하여 트랜잭션을 관리할 수 있습니다.

이 절에는 다음 주제가 포함됩니다.

관리 인터페이스를 사용한 트랜잭션 관리

관리 인터페이스를 사용하여 트랜잭션 모니터링, 로그 수준 설정, 고급 옵션 지정 등을 수행할 수 있습니다.

복구 정책 및 시간 초과와 같은 인스턴스 범위의 트랜잭션 서비스 속성을 제어할 수 있습니다. 여기에서 지정하는 등록 정보 및 구성은 server.xml 파일에 저장됩니다.

트랜잭션 서비스 옵션을 구성하려면 다음 작업을 수행합니다.

  1. 관리 인터페이스의 왼쪽 창에서 트랜잭션 구성을 수정할 Sun ONE Application Server 인스턴스 트리를 엽니다.
  2. 배포된 J2EE 서비스에서 트랜잭션 서비스를 선택합니다. 관리 인터페이스 오른쪽 창의 그림 트랜잭션 서비스 구성 옵션에 표시된 다음 창이 나타납니다.

   트랜잭션 서비스 구성 옵션

이 그림은 Java Transaction Service에 대해 구성할 수 있는 고급 서비스 옵션입니다.
 

  1. 트랜잭션에 대한 모니터링을 활성화하려면 "모니터링 활성화" 확인란을 표시합니다. 다음 표는 모니터링될 수 있는 Java Transaction Service 기능을 나열합니다.

   Java Transaction Service의 모니터링 가능한 속성

등록 정보

 

Type

 

설명

 

transactionsCompleted

 

int

 

모니터링이 활성화된 후 완료된 트랜잭션 개수

 

transactionsRolledBack

 

int

 

모니터링이 활성화된 후 롤백된 트랜잭션 개수

 

transactionsRecovered

 

int

 

모니터링이 활성화된 후 복구된 트랜잭션 개수

 

transactionsInFlight

 

int

 

현재 처리 중인 트랜잭션 개수

 

timeStamp

 

long

 

통계가 작성된 타임스탬프(밀리초 단위). 이것은 모두 System.getCurrentTimeInMillis()에서 보고합니다.

 

  1. "로그 수준" 드롭다운 목록에서 트랜잭션에 설정할 로그 수준을 선택합니다. 로그 수준 및 통합 방법의 자세한 내용은 "로깅 사용"을 참조하십시오.
  2. 서버 재시작시 실패한 트랜잭션을 자동으로 복구하려면 "재시작시 복구" 확인란을 표시합니다. 트랜잭션 완결 프로토콜의 크리티컬 포인트 동안 자원을 사용할 수 없으면, 트랜잭션은 완료되지 못하고 트랜잭션 로그 파일에 남을 수 있습니다. 이 확인란이 표시되어 있으면 서버는 서버 재시작시 오류가 발생한 트랜잭션 복구를 시도합니다. 관련 자원에 여전히 접근할 수 없으면 서버 재시작 시간이 지연될 수 있습니다. 이 확인란은 기본적으로 표시되지 않습니다.
  3. 컨테이너 관리 트랜잭션이 있는 Enterprise Bean의 경우, 트랜잭션 시간 초과(초) 등록 정보의 값을 설정하여 트랜잭션 시간 초과 간격을 제어할 수 있습니다.
  4. 이 등록 정보의 값이 0으로 설정되면 트랜잭션은 시간 초과되지 않습니다.

    "트랜잭션 시간 초과(초)" 필드에 트랜잭션 시간 초과 간격을 지정합니다. 트랜잭션이 지정된 시간 내에 완료되지 않으면 트랜잭션은 롤백됩니다. 이 속성의 값이 0으로 설정되면 트랜잭션은 시간 초과되지 않습니다.

  5. "트랜잭션 로그 위치" 필드에 로그 파일을 저장할 디렉토리의 절대 경로를 지정합니다. 새로 지정한 트랜잭션 로그 디렉토리를 적용하려면 서버를 재시작해야 합니다.
  6. "발견적 결정" 드롭다운 상자에서 트랜잭션에 적용할 발견적 결정을 선택합니다. 명백한 결과를 결정할 수 없는 경우 표시된 옵션에서 완결 또는 롤백을 선택하여 응용 프로그램 서버에서 복구 도중 의심스러운 트랜잭션의 결과를 결정하는 방법을 지정합니다. 발견적 결정을 롤백으로 설정하면 트랜잭션을 롤백합니다. 이런 트랜잭션을 완결하는 것이 허용되는 경우도 있습니다.
  7. "키 포인트 간격(트랜잭션)" 필드에 로그의 키 포인트 작업 사이의 트랜잭션 개수를 지정합니다. 키 포인트 작업은 완료된 트랜잭션의 항목을 제거하고 파일을 압축하여 트랜잭션 로그 파일의 크기를 줄입니다. 이 속성 값이 커지면 트랜잭션 로그 파일이 커지지만, 키 포인트 작업이 줄어들어 성능이 좋아질 수 있습니다. 이 값이 작아지면(예를 들어, 100) 로그 파일이 작아지지만, 키 포인트 작업 빈도가 높아져서 성능이 약간 낮아질 수 있습니다.

명령줄 인터페이스를 사용한 트랜잭션 관리

다음 절에서 설명한 것처럼, CLI (Command Line Interface)를 사용하여 데이터베이스 트랜잭션을 관리 및 모니터링할 수 있습니다.

이 절은 명령줄 인터페이스를 사용한 트랜잭션 관리 및 모니터링 방법을 설명합니다.

실행 중인 트랜잭션 나열

다음 명령은 실행 중인 트랜잭션 데이터를 구할 때 사용됩니다(multimode에 있고 이미 사용자 이름 및 암호를 설정했다고 가정합니다).

- asadmin> get --monitor
<instanceName>.transaction-service.inflight-tx

다중 행 출력은 다음과 같습니다.

Transaction Id State Elapsed Time (ms)

txnid1 Prepared 20

txnid2 Active 100

txnid3 Active 120

... ... ...

트랜잭션 관리

실행 중인 트랜잭션 나열의 예에서는 트랜잭션 ID txn-idstxnid2 및 txnid3로 트랜잭션을 롤백한다고 가정합니다. 선택한 트랜잭션을 롤백하는 샘플 명령은 다음의 예와 같습니다.

asadmin> set --monitor <instanceName>.transaction-service.rollback-list=txnid2,txnid3

트랜잭션 서비스 고정

트랜잭션 서비스를 고정하려면 다음 명령을 실행합니다.

asadmin> set --monitor <instanceName>.transaction-service.freeze=true

트랜잭션 서비스가 고정되면 응용 프로그램 서비스 내의 트랜잭션 관리자는 모든 실행 중인 트랜잭션이 일시 중단됩니다. 고정은 제품 배포 시스템에서는 권장하지 않습니다.

트랜잭션 서비스를 고정 해제하려면 다음 명령을 실행합니다.

asadmin> set --monitor <instanceName>.transaction-service.freeze=false

트랜잭션 서비스가 다시 동작 중으로 설정되면 시스템은 중단되었던 지점부터 다시 계속합니다. 활성 시스템을 너무 오래 고정 상태로 두면 일부 데이터베이스 연결이 시간 초과되어 트랜잭션이 롤백될 수 있습니다.

트랜잭션 모니터링

실행 중인 트랜잭션 데이터를 포함하여 트랜잭션 데이터를 모니터링하려면 다음 명령을 실행합니다.

asadmin> get --monitor <instanceName>.transaction-service.*

명령을 실행했을 때 활성 트랜잭션이 없으면 다음 출력을 구할 수 있습니다.

total-tx-completed = 5

total-tx-rolledback = 2

total-tx-inflight = 0

isFrozen = false

tx-inflight = No active transactions found.

명령을 실행했을 때 활성 트랜잭션이 있으면 다음 출력을 구할 수 있습니다.

total-tx-completed = 5

total-tx-rolledback = 2

total-tx-inflight = 2

isFrozen = false

tx-inflight =

Transaction Id State Elapsed Time(ms)

txnid1 Prepared 500

txnid2 Active 360



출처 - https://docs.oracle.com/cd/E19957-01/816-6865-10/agjts.html#266545

'DB' 카테고리의 다른 글

고급 DAO 프로그래밍 (Transaction)  (0) 2016.12.20
트랜잭션(Transaction)과 2PC(two-phase commit)  (0) 2016.12.20
OLTP / OLAP  (1) 2016.11.05
다차원 모델링(1/2)  (0) 2016.11.05
DW, DM, OLAP의 이해  (2) 2016.11.05
:

트랜잭션(Transaction)과 2PC(two-phase commit)

DB 2016. 12. 20. 13:41
2010.01.24 01:52


이번 글에서는 엔터프라이즈 환경에서 매우 중요한 개념인 트랜잭션에 대해서 설명하고자 한다. WAS와 DB를 이용하는 어플리케이션을 만들려면 트랜잭션에 대해서 알아야 한다. 특히 웹 인터페이스만 구현하는 위치를 넘어서, 좀더 뛰어난 엔터프라이즈 어플리케이션 개발자로 성장하려면 트랜잭션이란 벽을 반드시 넘어야 한다. 트랜잭션에 관해 검색엔진을 뒤져보면 대부분 사전적이고 딱딱한 말로 설명하는 경우가 많다. 그래서 호안은 좀더 현실적인 비유와 예를 통해서 설명해 보려고 한다.

트랜잭션(Transaction, 줄여서 Tx)


트랜잭션은 시작과 끝이 있는 독립적인 일 여러 개를 하나로 묶어놓고 그 중 어느 하나라도 실패하면 모든 일들을 시작하기 전 상태로 돌리는 하나의 작업 단위를 말한다. 여러 개의 일을 묶어놓은 것이지만 일체화된 하나의 작업으로 보는 것이다. 딱딱한 설명은 그만두고 실제 우리가 겪는 일을 예로 들면 아래와 같다.

트랜잭션 : 은행 간 이체

철수는 영희에게 100원을 이체하고 싶다. 이체라는 작업에는 크게 두 개의 독립적인 일들이 있다.

- 철수의 평민은행 계좌에서 100원을 꺼낸다.

- 영희의 니네은행 계좌에 100원을 넣는다.

만약 철수의 계좌에 100원을 꺼내는게 성공했는데 영희의 계좌에 100원을 넣는건 실패했다고 가정하자. 그럼 철수의 계좌에서 꺼낸 100원은 어떻게 해야 하는 것인가? 당연히 도로 넣어줘야 한다. 이것이 바로 시작하기 전 상태로 돌리는 것이다. 계좌에서 돈을 꺼내는 일과 계좌에 돈을 넣는 일은 각각 시작과 끝이 있는 독립적인 일들이지만 이를 이체라는 하나의 작업 단위로 묶게 되면 유기적으로 연결이 된다.

 

이 예에서 알 수 있듯이 철수의 계좌에서 100원을 꺼내는 일이 성공했더라도, 영희의 계좌에 그 돈을 넣는 일이 실패하면 철수의 계좌에 도로 100원을 넣어줘야 한다. 이렇게 되면 이체라는 트랜잭션 입장에서 봤을 때, 일을 먼저 시작한 쪽은 항상 하던 일을 중단하고 다시 처음으로 되돌릴 가능성을 지니게 된다. 즉, 먼저 시작한 쪽은 항상 했던 일을 다시 취소하고 처음 상태 그대로 돌려놔야 하는 번거로움을 안게 되는 것이다.

 

그렇다면 철수의 계좌에서 돈을 완전히 꺼내서 주지 말고 꺼낼 준비를 하면서 영희의 계좌에도 넣을 준비를 하라고 한 다음, 두 쪽 다 준비가 끝났을 때만 이체를 하면 어떻겠는가? 준비를 끝낸다는 것은 반드시 그 일이 성공할 수 있도록 보장하겠다는 의미다. 이렇게 되면 굳이 평민은행에서는 돈을 꺼내지 않고 준비만 해놓고 있다가 니네은행에서 준비를 할 수 없다고 알려주면 간단하게 준비 작업을 취소만 하면 된다. 이 경우에도 늘 취소를 해야하는 번거로움을 안고 있지만 준비 작업을 간소화해두면 번거로움을 최대한 줄일 수 있다.

 

이것이 바로 트랜잭션의 2PC이다. Two-Phase Commit의 약자로, 각각의 독립적인 일들을 완료하는 과정을 <준비>, <결과 반영> 두 단계로 나누고 모든 독립적인 일들의 준비가 끝났을 때만 실제 결과를 반영하는 것이다. 이체 트랜잭션의 경우에는 결과 반영이란 각각 '계좌에서 돈을 꺼낸다'와 '계좌에 돈을 넣는다'이다. 그리고 <준비>라는 개념은 일 자체를 시작하기 전의 준비가 아니다. 일을 다 끝내놓고 그 결과를 반영하기 전의 준비를 의미한다.

 

여기서 한 가지 주의할 점은 2PC는 번거로움을 없애기 만들기 위해서 만든 알고리즘은 아니다. 전산 시스템에서는 한번 <결과 반영>을 하고 나면 그것을 되돌리기 굉장히 어렵기 때문에 어느 일이라도 먼저 <결과 반영>이 되면 안 된다. 그래서 2PC가 필요한 것이다.


 

트랜잭션의 2PC(two-phase commit) 알고리즘


트랜잭션이란 개념도, 2PC라는 개념도 미국에서 나온 것이기 때문에 각각에 맞는 영어 용어가 있다. <준비>는 prepare이고 <결과 반영>은 커밋(commit) 이다. 그리고 독립적인 일을 시작하는 것은 begin(<시작>)이고 준비 이전까지 일을 끝내는 것은 end(<끝>) 라고 한다. 이를 요약하면


begin -> end -> prepare -> commit


와 같은 수행 단계를 거쳐서 하나의 독립적인 일을 처리하게 되고, 독립적인 일들을 묶어서 하나의 단위로 처리하는 것이 바로 트랜잭션이다. 트랜잭션이 성공적으로 끝나기 위해서는 트랜잭션에 참여(participate)한 모든 독립적인 일들이 <준비(prepare)>가 되어야 한다. 그렇게 모든 일이 <준비>가 된 상태에서만 각각 커밋을 해서 트랜잭션이 성공적으로 끝나는 것이다.

 

만약 어느 일 하나라도 <준비>가 실패하면 모든 일들이 <시작(begin)> 이전 단계로 돌아가야만 한다. 이 돌아간다는 용어가 바로 <롤백>(rollback)이다. 롤백이 되는 경우는 <준비> 뿐만 아니라 <시작>이나 <끝>이 실패해도 마찬가지다. 그러나 모든 일이 <준비>까지 성공했다면 그것은 커밋을 성공하는 걸 보장하겠다는 의미이기 때문에 트랜잭션에 속한 어느 일 하나가 일시적으로 커밋이 실패했더라도 계속 커밋을 시도하는게 일반적이다. 이체처럼 독립적인 일이 두 개인 경우에는 둘 다 <준비>가 성공했다고 하더라도 어느 한 쪽이 커밋이 실패하면 롤백을 할 수 있다. 돈 꺼낸 걸 다시 넣어준다는게 그런 의미다. 그런데 독립적인 일이 10개인 경우에는 문제가 달라진다. 10개 모두 prepare가 성공해서 커밋을 시도했는데 9개가 커밋이 성공했고 1개가 실패했다고 하자. 그럼 그 1개 때문에 9개의 커밋을 다시 돌려야 한다는 얘기인데 이런 삽질이 또 어디 있겠는가? 그래서 트랜잭션의 <준비> 단계가 완전히 성공해서 <커밋>이 시작되었다면 완전히 끝날 때까지 계속 해야 한다. 해도 해도 <커밋> 처리가 안 되는 일이 있다면? 그건 사람 손으로 해주는 수 밖에 없다. 관리자가 괜히 월급을 받는 것이 아니다.

begin과 end의 개념이 좀 모호할 것 같은데 이를 트랜잭션 진행 단계에 맞춰 좀더 잘게 나눠 보겠다.

1. 철수의 평민은행 계좌에서 100원을 꺼낸다.

[begin] 철수가 창구 직원에게 이체를 요청한다 -> [end] 철수가 서류 작성을 완료한다 -> [prepare] 창구 직원이 철수가 준 서류를 포함하여 결제 서류를 작성 완료하고 결제를 받아둔다. -> [commit] 금고 열고 100원 꺼내서 니네은행으로 송금한다.

2. 영희의 니네은행 계좌에 100원을 넣는다.

[begin] 철수의 이체 요청을 평민은행로부터 받는다 -> [end] 영희 계좌에 대한 서류 작성을 완료한다 -> [prepare] 서류 결제 받고 금고 딸 준비를 한다 -> [commit] 100원 받은 걸 집어넣는다


대략 이렇게 나눌 수 있다. begin, end, prepare 단계에서 실패를 하게 되면 그냥 없던 일로 하거나 서류를 찢기만 하면 되는 것이다.

트랜잭션은 기업 업무에서 많이 찾아볼 수 있으며 트랜잭션 처리가 굉장히 중요한 소프트웨어가 바로 데이터베이스(Database)이다. 데이터베이스와 트랜잭션의 관계는 WAS를 설명하는데 있어서 매우 중요한 내용이지만 이걸 얘기하려면 다른 개념을 얘기해야 하는 것이 많기 때문에 뒤로 미루고자 한다.

참고로 데이터베이스의 최대 공룡 업체가 미국의 오라클(Oracle)이다. 현재로선 부동의 세계 1위 점유율을 자랑하고 있다. 우리 나라에서도 수많은 공공기관, 기업들이 오라클 데이터베이스를 쓰고 있다. 그러나 매년 내야 하는 유지보수비가 점점 비싸져서 탈 오라클 조짐이 조금씩 일고 있다. 그러나 워낙 널리 퍼져있고 그 제품에 익숙하다 보니까 다른 회사의 데이터베이스로 바꾸는 결정을 하는 것도 쉽지는 않다. 데이터베이스가 워낙 고난이도의 소프트웨어이기 때문에 그동안 우리나라에서는 그걸 개발할 엄두를 못 냈지만 다행히도 최근 몇몇 회사에서 데이터베이스를 선보이고 있다. 그리고 조금씩 판매를 하면서 선전을 하고 있는 중이다.

탈 오라클 조짐에 관한 기사

http://www.itdaily.kr/news/articleView.html?idxno=14597

http://itnews.inews24.com/php/news_view.php?g_serial=337562&g_menu=020200



이 기회에 우리 회사 데이터베이스 제품을 소개한다.

티베로 3.0 : http://www.tibero.com

http://www.ddaily.co.kr/news/news_view.php?uid=45386

출처 - http://swdev.tistory.com/2


'DB' 카테고리의 다른 글

고급 DAO 프로그래밍 (Transaction)  (0) 2016.12.20
트랜잭션 서비스 사용  (0) 2016.12.20
OLTP / OLAP  (1) 2016.11.05
다차원 모델링(1/2)  (0) 2016.11.05
DW, DM, OLAP의 이해  (2) 2016.11.05
: