'2016/12'에 해당되는 글 26건

  1. 2016.12.20 고급 DAO 프로그래밍 (Transaction)
  2. 2016.12.20 트랜잭션 서비스 사용
  3. 2016.12.20 트랜잭션(Transaction)과 2PC(two-phase commit)
  4. 2016.12.15 jQuery Plugin - Plugin 작성 가이드
  5. 2016.12.15 jQuery:$.extend() 와 $.fn.extend()
  6. 2016.12.15 pply(), call() 메서드
  7. 2016.12.15 arguments 객체
  8. 2016.12.14 Undo tablespace
  9. 2016.12.14 DML 문의 처리과정(트랜잭션 내부작업)
  10. 2016.12.13 오라클 액세스

고급 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
:

jQuery Plugin - Plugin 작성 가이드

Language/jQuery 2016. 12. 15. 16:35

jQuery plugin이란 것은

 

이미 instance화 되어진 object인 jQuery object를 확장하여 새로운 function을 만들어서 사용할 수 있게 하는 것을 의미합니다.

 

이전 강좌에서 배웠듯이 간단하게 instance화된 새로운 함수 명에 새로운 함수를 작성하면 된다고 볼 수 있다.

 

하지만 jQuery object의 강점중에 하나인 selector로 반환되어져오는 jQuery object를 그대로 사용할 수 있는 형태여야 할 것이다.

 

그래서 미리 만들어진 방법인 $.fn 이라는 namespace밑에 확장해주면 원하는 결과를 얻을 수 있다.

 

이렇게 보면 jQuery plugin의 작성이라는 건 굉장히 단순해 보인다. 실제로도 그렇다.


하지만 특정 plugin을 작성하려면 많은 methods, event procedures 그리고 속성 등을 사용할 수 있어야 편리할 것이다.

 

그래서 jQuery org에서 말하는 plugin 작성법을 기준으로 몇가지를 숙지해 두는 편이 나은 방법인 것과 공유되질 수있는 방법론이 될 것이다.

 

1. $.fn을 확장하면 $ jQuery object를 활용하여 사용할 수 있는 plugin 작성가능하고 $.fn은 jQuery effin'이라고 읽어라는 군요. 제이쿼리 에핀 이렇게 읽으면 되는 건가?(영어가 편한 언어가 아니라. 아픔이 큽니다.)

 

 

2. 외부 코드와 분리해주시기 위해서 self-invating function을 이용하여 작성하자.

 

 

3. method의 호출 결과로 반드시 특정 object나 value를 반환해주는 것이 아니라면(왠만하면 그러지 않는 것이 좋을 것다.) jQuery에 chainability(사전에도 없는 말이다.
   굳이 한글로 바꾸자면 연쇄적으로 내지는 연속적으로 호출가능한 형태)를 유지해주자.

 

 

4. 동작에 필요한 defaults 값들을 object정의하고 외부에서 받아올 options object을 받아서 $.extend()로 확장하여 사용한다.

 

 

5. 하나의 plugin이라도 수많은 methods를 다른 함수로 일일히 작성하지 말고 하나의 plugin함수 안에서 paramter를 받아서 내부에서 분기하도록 하자.

 

 

6. bind 등(애매한 표현 등... 하하 이벤트에 procedure를 붙이는 방법이 다른 좋은 방법들과 이슈가 되는 많다고 하니 이렇게 애매하게 표현하는게 상책이죠.)을 통해서 event procedure를 호출하려고 할때에 다른 plugin과 구분하거나 한번에 unbind하기 위해서라도 plugin이름을 활용하여 명명하자.

 

 

7. 일반적으로 object의 속성과 비교하면 상이한 점이 꽤나 있다.
   하지만 이 instance화되어져 있는 jQuery의 plugin으로서 마찬가지 instance화되어져 있는 속성이라는 것이 각 개체의 특정 값을 유지하거나 공유하기 위해서라면
   이걸 jQuery에서는 data라고 하고 data메서드를 활용하여 작성한다.
   여기서 마찬가지 하나 data메서드, 결국 하나의 data라는 object인데 그 하위에 plugin과 같은 이름 명명하고 그 하위에  값이나 개체의 형태로 data안에 해당 plugin의 속성을 작성해준다.


위의 방법이 반드시 강제성을 띠는 것은 아니다. 단지 가이드 라인이라고 해야할 것이다.


필요하고 더 나은 방법이 있다면 다른 방식으로 구현하고 그 방법이 실제로 더 나은 방벙이라면 역으로 제시하여 새로운 가이드가 만들어질 수도 있을 것이다.

 

이제 위의 항목들을 하나 하나 살펴보도록 하자.

 

 

1. $.fn을 확장하면 $ jQuery object를 활용하여 사용할 수 있는 plugin 작성가능하고 $.fn은 jQuery effin'이라고 읽어라는 군요. 제이쿼리 에핀 이렇게 읽으면 되는 건가?(영어가 편한 언어가 아니라. 아픔이 큽니다.)

01.<html>
02.<head>
03.<title>Javascript Sample Page - jQuery plugin basic</title>
04.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
05.<script language="javascript" type="text/javascript">
06./*
07.가장 기본적인 형태의 jQuery plugin으로 jQuery instance의 $.fn을 확장하면 jQuery object를 확장하여 plugin으로 사용할 수 있다.
08.*/
09.$.fn.GetInnerText = function () {
10.this.each(function () { alert($(this).text()); });
11.}
12.$(document).ready(
13.function () { $(".title").GetInnerText(); }
14.)
15.</script>
16.</head>
17.<body>
18.<table>
19.<tr>
20.<td class="title">제목</td>
21.<td>진달래</td>
22.</tr>
23.<tr>
24.<td class="title">시인</td>
25.<td>김소월</td>
26.</tr>
27.</table>
28.</body>
29.</html>


 

 


2. 외부 코드와 분리해주시기 위해서 self-invating function을 이용하여 작성하자.

 

01.<html>
02.<head>
03.<title>Javascript Sample Page - jQuery plugin standard</title>
04.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
05.<script language="javascript" type="text/javascript">
06./*
07.좀 더 복잡한 형태의 jQuery plugin 으로 사용되면서는 private function과 private 변수의 사용이 불가피해진다.
08.그러므로 다른 global 코드와 이름 중복으로 발생할 문제를 해결하기 위해서 jQuery를 parameter로 하는 self-invacation function을 사용해줍니다.
09.*/
10.(
11.function ($) {
12.$.fn.GetInnerText = function () {
13.this.each(function () { alert($(this).text()); });
14.}
15.}
16.)($)
17.$(document).ready(
18.function () { $(".title").GetInnerText(); }
19.)
20.</script>
21.</head>
22.<body>
23.<table>
24.<tr>
25.<td class="title">제목</td>
26.<td>진달래</td>
27.</tr>
28.<tr>
29.<td class="title">시인</td>
30.<td>김소월</td>
31.</tr>
32.</table>
33.</body>
34.</html>

 


자 그러므로 가장 단순한 형태의 jQuery Plugin 작성형태라고 하면 "(function ($){ $.fn.myplugin = function () { } })($)"이 될 것이다.

 

 

3. method의 호출 결과로 반드시 특정 object나 value를 반환해주는 것이 아니라면(왠만하면 그러지 않는 것이 좋을 것다.) jQuery에 chainability(사전에도 없는 말이다.
   굳이 한글로 바꾸자면 연쇄적으로 내지는 연속적으로 호출가능한 형태)를 유지해주자.

 

01.<html>
02.<head>
03.<title>Javascript Sample Page - Chainability 1 </title>
04.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
05.<script language="javascript" type="text/javascript">
06./*
07.예제에서 파악할 수 있듯이 기 구현되어있는 대부분의 jQuery의 function은 jQuery개체를 최종적으로 계속 반환함으로써 연쇄적인 호출이 가능한 형태로 구현되어져 있습니다.
08.*/
09.(
10.function ($) {
11.$.fn.GetInnerText = function () {
12.this.each(function () { alert($(this).text()); });
13.}
14.}
15.)($)
16.$(document).ready(
17.function () {
18.$(".title").css("background-color""#eeeeee").GetInnerText();
19.$(".title").GetInnerText().css("background-color""#eeeeee"); // css method 에러 발생
20.}
21.)
22.</script>
23.</head>
24.<body>
25.<table>
26.<tr>
27.<td class="title">제목</td>
28.<td>진달래</td>
29.</tr>
30.<tr>
31.<td class="title">시인</td>
32.<td>김소월</td>
33.</tr>
34.</table>
35.</body>
36.</html>

 

 

 

 

그럼 chainability하게 작성하는 방법에 관해서 알아보자.

 

01.<html>
02.<head>
03.<title>Javascript Sample Page - Chainability 2 </title>
04.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
05.<script language="javascript" type="text/javascript">
06./*
07.chainability를 유지해주기. chainability(사전에도 없는 걸 보면 지어낸 말이거나 아니면 신조어일까요?)
08.*/
09.(
10.function ($) {
11.$.fn.GetInnerText = function () {
12.return this.each(function () { alert($(this).text()); });
13.}
14.}
15.)($)
16.$(document).ready(
17.function () {
18.$(".title").GetInnerText().css("background-color""#eeeeee");
19.//$("td").each(function () {$(this).width();});
20.}
21.)
22.</script>
23.</head>
24.<body>
25.<table>
26.<tr>
27.<td class="title">제목</td>
28.<td>진달래</td>
29.</tr>
30.<tr>
31.<td class="title">시인</td>
32.<td>김소월</td>
33.</tr>
34.</table>
35.</body>
36.</html>

 

 

 

 

적절한 예제라고 보기에는 억지가 많지만 작성법만을 보도록 하자.

결국 마지막에 instance화된 자신의 object를 의미하는 this를 반환하면 된다.

 

 


4. 동작에 필요한 defaults 값들을 object정의하고 외부에서 받아올 options object을 받아서 $.extend()로 확장하여 사용한다.

 

01.<html>
02.<head>
03.<title>Javascript Sample Page - defaults and options with $.extend </title>
04.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
05.<script language="javascript" type="text/javascript">
06.//$.extend를 이용하여 좀 더 사용하기 편리한 parameters와 default값들을 지정하기
07.(
08.function ($) {
09.// plugin내에서 사용할 기본값으로 setting된 object를 미리 만들어 둡니다.
10.StylingDefaults = { font: "맑은 고딕", foreColor: "blue", backColor: "#eeeeee" };
11. 
12.$.fn.MyCompanyStyling = function (options) {
13.this.each(
14.//function (options) { //이것은 each라는 메서드가 넘겨주는 첫번째 parameter로 options은 each의 각 index가 넘어옵니다.
15.function () {
16.// plugin 내의 기본값을 가진 object를 기준으로 받은 options을 덮어 씁니다.
17.$.extend(StylingDefaults, options);
18.//$.extend(options, StylingDefaults); // 이렇게 하면 받은 options 값을 기준으로 원래 기본값을 덮어쓰면서 기본값이 적용됩니다.
19. 
20.//원하는 코드를 작성합니다.
21.$(this).css("font-family", StylingDefaults.font).css("color", StylingDefaults.foreColor).css("background-color", StylingDefaults.backColor);
22.}
23.);
24.return this;
25.}
26.}
27.)($)
28. 
29.$(document).ready(
30.function () {
31.$(".title").MyCompanyStyling({ foreColor:"red" });
32.}
33.)
34.</script>
35.</head>
36.<body>
37.<table>
38.<tr>
39.<td class="title">제목</td>
40.<td>진달래</td>
41.</tr>
42.<tr>
43.<td class="title">시인</td>
44.<td>김소월</td>
45.</tr>
46.</table>
47.</body>
48.</html>

 


 

 

 


5. 하나의 plugin이라도 수많은 methods를 다른 함수로 일일히 작성하지 말고 하나의 plugin함수 안에서 paramter를 받아서 내부에서 분기하도록 하자.

 

01.<html>
02.<head>
03.<title>Javascript Sample Page - Methods Namespacing</title>
04.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
05.<script language="javascript" type="text/javascript">
06.// 근본적으로 jQuery plugin이라는 것이 fn이라는 namespace 아래에 자리 잡는 것입니다.
07.// 그래서 plugin 하나 하나가 다수의 method를 만들면 결국 plugin 몇 개만 써도 엄청난 수의 method가 fn밑에 자리 잡게 되고
08.// 결국 어떤 plugin의 메서드인지 뭐하는 method인지 헤갈리게 될 가능성이 높을 것 같습니다.
09.// 그래서 jQuery org는 method이름을 paramter의 형태로 받아서 해당 plugin 내부에서 분기하라고 가이드 하고 있습니다.
10.(
11.function ($) {
12. 
13.// 사용할 method 선언부
14.var actions = {
15.TitleStyling: function (options) {
16.Defaults = { font: "맑은 고딕", foreColor: "blue", backColor: "#eeeeee" };
17.this.each(
18.function () {
19.$.extend(Defaults, options);
20.$(this).css("font-family", Defaults.font).css("color", Defaults.foreColor).css("background-color", Defaults.backColor);
21.}
22.);
23.return this;
24.},
25.ValueCellStyling: function () { this.each(function () { $(this).css("font-weight""normal"); }); returnthis; }
26.}
27. 
28.// 각각의 sub procedure를 호출해주는 main
29.$.fn.MyCompanyStyling = function (action) {
30.if (actions[action])
31.return actions[action].apply(this, Array.prototype.slice.call(arguments, 1));
32.else
33.return actions.TitleStyling.apply(this, arguments);
34.}
35.}
36.)($)
37. 
38.$(document).ready(
39.function () {
40.$(".title").MyCompanyStyling({ foreColor: "red" });
41.$(".cellcontent").MyCompanyStyling("ValueCellStyling");
42.}
43.)
44.</script>
45.</head>
46.<body>
47.<table>
48.<tr>
49.<td class="title">제목</td>
50.<td class="cellcontent" style="font-weight:bold">진달래</td>
51.</tr>
52.<tr>
53.<td class="title">시인</td>
54.<td class="cellcontent">김소월</td>
55.</tr>
56.</table>
57.</body>
58.</html>


 

 


6. bind 등(애매한 표현 등... 하하 이벤트에 procedure를 붙이는 방법이 다른 좋은 방법들과 이슈가 되는 많다고 하니 이렇게 애매하게 표현하는게 상책이죠.)을 통해서 event procedure를 호출하려고 할때에 다른 plugin과 구분하거나 한번에 unbind하기 위해서라도 plugin이름을 활용하여 명명하자.

 

01. 
02.<html>
03.<head>
04.<title>Javascript Sample Page - Events Namespacing</title>
05.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
06.<script language="javascript" type="text/javascript">
07.(
08.function ($) {
09.var actions = {
10.// Event Procedure를 각각의 events에 bind해주는 역활의 함수
11.// 일반적으로 jQuery org예제처럼 plugin이 초기화되면 해당 동작을 많이 하므로 init이라는 이름으로 만들고 초기화하면서 bind해주는 경우가 많다.
12.// 본 예제에서는 이해를 돕기 위해 이름을 별나게 작성하였다.
13.AttachEvents: function () {
14.this.each(function () {
15.// 해당 plugin이름으로 하나씩 event bind해준다.
16.$(this).bind('click.myCompanyStyling', displayClickedCoordinate);
17.$(this).bind('mousemove.myCompanyStyling', displayMovingCoordinate);
18.});
19.return this;
20.},
21.// 필요할 경우나 개인적인 의견으로 한 페이지에서 끝나고 다음 페이지로 이동하는 웹페이지의 형태에서 잘 사용하지 않을 것 같으나 소멸자에서 사용이 되어진다.
22.// unbind해주는 method로 소멸자의 경우 일반적으로 destory라는 이름을 많이 사용한다.
23.// 본 예제에서는 이해를 돕기 위해 이름을 별나게 작성하였다.
24.DisattachEvents: function () {
25.// 해당 plugin 이름으로 한번 unbind
26.$(this).unbind('.myCompanyStyling');
27.return this;
28.}
29.}
30.// plugin 내부에 private한 함수들이다.
31.// self-invacation 되어 있으므로 현재 상태로는 외부에서 접근이 불가능한 코드이다.
32.function displayClickedCoordinate(e) {
33.$("#divClickedCoordinate").text('styling clicked coordinate x: ' + e.pageX + ', y: ' + e.pageY);
34.}
35.function displayMovingCoordinate(e) {
36.$("#divMovingCoordinate").text('mouse coordinate x: ' + e.pageX + ', y: ' + e.pageY);
37.}
38.// method로 분기해주는 main procedure
39.$.fn.MyCompanyStyling = function (action) {
40.if (actions[action])
41.return actions[action].apply(this, Array.prototype.slice.call(arguments, 1));
42.else
43.return actions.init.apply(this, arguments);
44.}
45.}
46.)($)
47.$(document).ready(
48.function () {
49.// 위의 plugin의 namespace가 아닌 다른 곳에서의 bind 2가지
50.// 1. window의 mousemove bind
51.$(window).bind('mousemove'function (e) {
52.$("#divGlobalMousePosition").text('mouse coordinate x: ' + e.pageX + ', y: ' + e.pageY);
53.});
54.// 2. plugin과 같은 개체의 같은 event에 bind
55.$('#tableContent').bind('click'function (e) {
56.$("#divClickedCoordinate").text('clicked coordinate x: ' + e.pageX + ', y: ' + e.pageY);
57.});
58.}
59.);
60.</script>
61.</head>
62.<body>
63.<table id="tableContent">
64.<tr>
65.<td class="title">제목</td>
66.<td class="cellcontent" style="font-weight:bold">진달래</td>
67.</tr>
68.<tr>
69.<td class="title">시인</td>
70.<td class="cellcontent">김소월</td>
71.</tr>
72.</table>
73.<div id="divGlobalMousePosition"></div>
74.<div id="divClickedCoordinate"></div>
75.<div id="divMovingCoordinate"></div>
76.<!-- plugin을 통한 이벤트 프로시저 bind -->
77.<input type="button" value="attach events"onclick="javascript:$('#tableContent').MyCompanyStyling('AttachEvents');" />
78.<!-- plugin을 통한 이벤트 프로시저 unbind -->
79.<input type="button" value="disattach events"onclick="javascript:$('#tableContent').MyCompanyStyling('DisattachEvents');" />
80.</body>
81.</html>
82. 

 

 


7. 일반적으로 object의 속성과 비교하면 상이한 점이 꽤나 있다.
   하지만 이 instance화되어져 있는 jQuery의 plugin으로서 마찬가지 instance화되어져 있는 속성이라는 것이 각 개체의 특정 값을 유지하거나 공유하기 위해서라면
   이걸 jQuery에서는 data라고 하고 data메서드를 활용하여 작성한다.
   여기서 마찬가지 하나 data메서드, 결국 하나의 data라는 object인데 그 하위에 plugin과 같은 이름 명명하고 그 하위에  값이나 개체의 형태로 data안에 해당 plugin의 속성을 작성해준다.

 

 

먼저 간단하게 table cell 까만 막대기를 그려주는 jQuery plugin을 작성법대로 기본을 잡아주자.

 

01. 
02.<html>
03.<head>
04.<title>Javascript Sample Page - Events Namespacing</title>
05.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
06.<script language="javascript" type="text/javascript">
07.(
08.function ($) {
09.var methods = {
10.init: function () {
11.this.each(function () {
12.$(this).append($('<div style=\"background-color:black;height:15px;width:100px;\">&nbsp;</div>'));
13.});
14.return this;
15.},
16.}
17.$.fn.RandomBar = function (method) {
18.if (methods[method])
19.return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
20.else
21.return methods.init.apply(this, arguments);
22.}
23.}
24.)($)
25.$(document).ready(
26.function () {
27.$(".sample tr td").RandomBar();
28.}
29.);
30.</script>
31.</head>
32.<body>
33.<table class="sample">
34.<tr>
35.<td></td>
36.</tr>
37.<tr>
38.<td></td>
39.</tr>
40.<tr>
41.<td></td>
42.</tr>
43.<tr>
44.<td></td>
45.</tr>
46.</table>
47.</body>
48.</html>
49. 

 

 

 

자! 이제 랜덤한 길이로 보이도록 하자.
(참고로 차분히 이해를 돕기 위해서 step별로 하는 것이지 절대로 원고 불리기가 아닙니다. ㅡㅡ;)

 

01. 
02.<html>
03.<head>
04.<title>Javascript Sample Page - Events Namespacing</title>
05.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
06.<script language="javascript" type="text/javascript">
07.(
08.function ($) {
09.var methods = {
10.init: function () {
11.this.each(function () {
12.$(this).append($('<div style=\"background-color:black;height:15px;width:' + Math.floor(Math.random()*1001).toString() + 'px;\">&nbsp;</div>'));
13.});
14.return this;
15.}
16.}
17.$.fn.RandomBar = function (method) {
18.if (methods[method])
19.return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
20.else
21.return methods.init.apply(this, arguments);
22.}
23.}
24.)($)
25.$(document).ready(
26.function () {
27.$(".sample tr td").RandomBar();
28.}
29.);
30.</script>
31.</head>
32.<body>
33.<table class="sample">
34.<tr>
35.<td></td>
36.</tr>
37.<tr>
38.<td></td>
39.</tr>
40.<tr>
41.<td></td>
42.</tr>
43.<tr>
44.<td></td>
45.</tr>
46.</table>
47.</body>
48.</html>
49. 

 

 

 

자! 그럼 이제 길이과 미리 정해진 색상과 라벨을 할당하고 이에 관한 속성을 만들어 보도록 하겠습니다.

 

01. 
02.<html>
03.<head>
04.<title>Javascript Sample Page - Events Namespacing</title>
05.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
06.<script language="javascript" type="text/javascript">
07.(
08.function ($) {
09.// private variables
10.var barnames = ['사랑''평온''행복']
11.var barcolors = ['red''blue''gray''black''yellow']
12.var methods = {
13.init: function () {
14.this.each(function () {
15.// set data
16.$(this).data('RandomBar', {
17.name: barnames[Math.floor(Math.random() * 3) - 1],
18.barcolor: barcolors[Math.floor(Math.random() * 6) - 1],
19.barlength: Math.floor(Math.random() * 1001).toString() + 'px'
20.});
21.// get data
22.$(this).append($('<div style=\"background-color:' + $(this).data().RandomBar.barcolor + ';height:15px;width:' + $(this).data().RandomBar.barlength + ';\">&nbsp;</div>'));
23.});
24.return this;
25.}
26.}
27. 
28.$.fn.RandomBar = function (method) {
29.if (methods[method])
30.return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
31.else
32.return methods.init.apply(this, arguments);
33.}
34.}
35.)($)
36.$(document).ready(
37.function () {
38.$(".sample tr td").RandomBar();
39.}
40.);
41.</script>
42.</head>
43.<body>
44.<table class="sample">
45.<tr>
46.<td></td>
47.</tr>
48.<tr>
49.<td></td>
50.</tr>
51.<tr>
52.<td></td>
53.</tr>
54.<tr>
55.<td></td>
56.</tr>
57.</table>
58.</body>
59.</html>
60. 

 

 

 

이렇게 만들어진 속성에 해당하는 data로 유지된 value를 event procedure에 활용하는 형태로 마무리해보겠습니다.

 

01. 
02.<html>
03.<head>
04.<title>Javascript Sample Page - Events Namespacing</title>
05.<script language="javascript" type="text/javascript" src="jquery-1.6.2.min.js"></script>
06.<script language="javascript" type="text/javascript">
07.(
08.function ($) {
09.// private variables
10.var barnames = ['사랑''평온''행복']
11.var barcolors = ['red''blue''gray''black''yellow']
12.//private event procedure
13.function displayBarInfo() {
14.$(".barinfo").text('이름: ' + $(this).data().RandomBar.name + ', 길이: ' + $(this).data().RandomBar.barlength + ', 색상: ' + $(this).data().RandomBar.barcolor);
15.}
16.function hideBarInfo() {
17.$(".barinfo").text('');
18.}
19.var methods = {
20.init: function () {
21.this.each(function () {
22.// set data
23.$(this).data('RandomBar', {
24.name: barnames[Math.floor(Math.random() * 3)],
25.barcolor: barcolors[Math.floor(Math.random() * 5)],
26.barlength: Math.floor(Math.random() * 1001).toString() + 'px'
27.});
28.// get data
29.$(this).append($('<div style=\"background-color:' + $(this).data().RandomBar.barcolor + ';height:15px;width:' + $(this).data().RandomBar.barlength + ';\">&nbsp;</div>'));
30.// attach event procedure
31.$(this).bind('mouseover.Randombar', displayBarInfo);
32.$(this).bind('mouseout.Randombar', hideBarInfo);
33.});
34.return this;
35.}
36.}
37. 
38.$.fn.RandomBar = function (method) {
39.if (methods[method])
40.return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
41.else
42.return methods.init.apply(this, arguments);
43.}
44.}
45.)($)
46.$(document).ready(
47.function () {
48.$(".sample tr td").RandomBar();
49.}
50.);
51.</script>
52.</head>
53.<body>
54.<!-- 절대 분량을 늘릴려고 줄 수 많이 한 것 아닙니다. 재미있어요. 하하하 -->
55.<table class="sample">
56.<tr>
57.<td></td>
58.</tr>
59.<tr>
60.<td></td>
61.</tr>
62.<tr>
63.<td></td>
64.</tr>
65.<tr>
66.<td></td>
67.</tr>
68.<tr>
69.<td></td>
70.</tr>
71.<tr>
72.<td></td>
73.</tr>
74.<tr>
75.<td></td>
76.</tr>
77.<tr>
78.<td></td>
79.</tr>
80.<tr>
81.<td></td>
82.</tr>
83.<tr>
84.<td></td>
85.</tr>
86.</table>
87.<div class="barinfo"></div>
88.</body>
89.</html>
90. 

 

출처 - http://www.sqler.com/456517

'Language > jQuery' 카테고리의 다른 글

jQuery:$.extend() 와 $.fn.extend()  (0) 2016.12.15
jQuery Mask Plugin  (0) 2014.12.10
jQuery checkbox 컨트롤  (0) 2014.12.08
jQuery grid - jqGrid  (0) 2014.11.20
jQuery BlockUI Plugin  (0) 2014.11.20
:

jQuery:$.extend() 와 $.fn.extend()

Language/jQuery 2016. 12. 15. 16:34

jQuery:$.extend() 와 $.fn.extend() 의 혼동

.extend() 함수를 사용할 때 하나의 인수를 넘기는 것과 두 개 이상의 인수를 넘기는 것에는 아주 큰 차이가 있습니다.

 

.extend() 함수가 하나의 객체를 받을 때

선언된 메소드를 jQuery 나 jQuery.fn (jQuery.prototype, 또는 $.fn 이라고 불리죠.) 에 추가시킵니다.

 

일반적으로 함수를 위해서는 jQuery 객체를 extend 시키고 메소드를 위해서는 jQuery.fn 을 extend 시킵니다. 함수는 DOM 에서 바로 접근이 불가능하고 메소드는 바로 접근이 가능하죠.

 

다음 예제에서 jQuery.fn 또는 jQuery 객체를 extend 시킬 때 부르는 방식이 달라짐을 눈여겨 보시기 바랍니다.

 

  1. $.fn.extend({
  2. myMethod: function(){...}
  3. });
  4. //jQuery("div").myMethod();
  5.  
  6. $.extend({
  7. myMethod2: function(){...}
  8. });
  9. //jQuery.myMethod2(); 

 

 

.extend() 함수가 2개 이상의 객체를 받을 때

일반적으로 알려진 것 처럼 첫 번째 객체와 두 번째 객체를 병합(merge) 합니다.

 

  1. var defaults = { size3 };
  2. var options = { height6 };
  3. var opts = $.extend(defaults, options)
  4. // 'defaults' 가 'options' 에 정의된 메소드와 변수들을 받아옵니다.
  5. // opts == defaults == { size: 3, height: 6 }
  6. // options == { height: 6 };

 

 

만약에 첫 번째 객체가 빈 객체라면 메소드와 변수들을 새로운 객체에 추가시킵니다.

만약 여러 개의 객체들을 단 하나의 객체도 변화시키지 않고 새로운 객체에 만들 때 아주 유용합니다.

 

  1. var opts = $.extend( {}, defaults, options);
  2. // 'opts' 가 'defaults' 와 'options'에 선언된 모든 메소드와 변수들을 받습니다.
  3. // 'defaults' 와 'options' 는 변하지 않습니다.
  4. // opts == { size: 3, height: 6 }
  5. // defaults == { size: 3 };
  6. // options == { height: 6 };


출처 - http://m.blog.naver.com/k_rifle/178134527

'Language > jQuery' 카테고리의 다른 글

jQuery Plugin - Plugin 작성 가이드  (0) 2016.12.15
jQuery Mask Plugin  (0) 2014.12.10
jQuery checkbox 컨트롤  (0) 2014.12.08
jQuery grid - jqGrid  (0) 2014.11.20
jQuery BlockUI Plugin  (0) 2014.11.20
:

pply(), call() 메서드

Language/JAVASCRIPT 2016. 12. 15. 16:32

함수의 apply(), call() 메서드

From. 프론트엔드 개발자를 위한 자바스크립트 프로그래밍

함수에는 apply()와 call() 두 가지 메서드가 더 있습니다. 이들 메서드는 모두 소유자인 함수를 호출하면서 this를 넘기는데, 결과적으로는 함수 내부에서 this 객체의 값을 바꾸는 것이나 마찬가지입니다. apply() 메서드는 매개변수로 소유자 함수에 넘길 this와 매개변수 배열으로 받습니다. 두 번째 매개변수는 Array의 인스턴스일 수도 있고 arguement 객체일 수도 있습니다. 다음 예제를 보십시오.

01function sum(num1, num2) {
02    return num1 + num2;
03}
04 
05function callSum1(num1, num2) {
06    return sum.apply(this, arguments);  // arguments 객체를 넘깁니다.
07}
08 
09function callSum2(num1, num2) { // 배열을 넘깁니다.
10    return sum.apply(this, [num1, num2]);
11}
12 
13alert(callSum1(10, 10));    // 20
14alert(callSum2(10, 10));    // 20                          

이 예제에서 callSum1()은 sum()을 호출하면서 자신의 this와 arguments 객체를 매개변수로 넘겼습니다. callSum2() 역시 sum()을 호출하지만 이번에는 arguments 객체가 아니라 매배변수 배열을 넘겼습니다. 두 함수 모두 올바르게 실행됩니다.

call() 메서드도 apply()와 마찬가지로 동작하지만 매개변수를 전달하는 방식이 다릅니다. this가 첫 번째 매개변수인 점은 똑같지만 call()을 사용할 때는 반드시 다음 예제와 같이 매개변수를 각각 나열해야 합니다.

1function sum(num1, num2) {
2    return num1 + num2;
3}
4 
5function callSum(num1, num2) {
6    return sum.call(this, num1, num2);
7}
8 
9alert(callSum(10, 10)); // 20                  

결과는 apply()와 마찬가지입니다. apply()와 call() 중 어느 쪽을 쓸지는 순전히 개발자의 재량이며 매개변수를 전달하기 편리한 방식으로 택하면 됩니다. arguments 객체를 그대로 전달해도 되거나 매개변수로 전달할 데이터가 이미 배열 형태로 준비되어 있다면 apply()가 나을 것이고, 그렇지 않다면 call()이 더 나을 겁니다. 전달할 매개변수가 없다면 두 메서드는 완진히 똑같습니다.

물론 apply()와 call()의 진가는 매개변수를 전달해 호출하는 것이 아니라 this를 바꾸는데 있습니다. 다음 예제를 보십시오.

01window.color = "red";
02var o = {color: "blue"};
03 
04function sayColor() {
05    alert(this.color);
06}
07 
08sayColor(); // red
09 
10sayColor.call(this);    // red
11sayColor.call(window);  // red
12sayColor.call(o)    // blue            

이 예제는 this 객체를 설명할 때 썼던 예제를 조금 고친 겁니다. 이번에도 sayColor()는 전역 함수로 정의되었으므로 전역 스코프에서 호출하면 this.color를 window.color로 평가하여 "red"를 표시합니다. sayColor.call(this)나 sayColor.call(window)와 같이 호출하면 함수 컨텍스트를 명시적으로 전역 스코프로 지정하는 것인데 이렇게 해도 마찬가지로 "red"를 표시합니다. 반면 sayColor.call(o)는 함수의 컨텍스트를 o로 설정하므로 "blue"를 표시합니다.

call()이나 apply()를 써서 스코프를 바꾸면 객체마다 일일히 메서드를 등록하지 않아도 된다는 장점이 있습니다. this 객체를 설명할 때는 o 객체에 직접 sayColor() 메서드를 등록했었지만 이번에는 그렇게 하지 않았습니다.

ECMAScript 5판의 함수에는 bind()라는 메서드도 정의되었습니다. 이 메서드는 새 함수 인스턴스를 만드는데 그 this는 bind()에 전달된 값입니다. 예를 들어 다음 코드를 보십시오.

1window.color = "red";
2var o = {color: "blue"};
3 
4function sayColor() {
5    alert(this.color);
6}
7 
8var objectSayColor = sayColor.bind(o);
9objectSayColor();       // blue

이 예제에서는 sayColor()에서 bind()를 호출하면서 객체 o를 넘겨 objectSayColor()라는 함수를 생성했습니다. objectSayColor() 함수의 this는 o에 묶이므로 전역에서 함수르 호출하더라도 항상 "blue"를 표시합니다.


출처 - http://www.florakid.com/florakid_lib/sub/javascript/apply_call_method.html

'Language > JAVASCRIPT' 카테고리의 다른 글

프로토타입의 이해 01  (0) 2016.12.23
참고 강좌  (0) 2016.12.23
arguments 객체  (0) 2016.12.15
구글맵(차트)  (0) 2014.12.12
prototypejs  (0) 2013.11.13
:

arguments 객체

Language/JAVASCRIPT 2016. 12. 15. 16:32

arguments 객체는 함수에 전달된 인수에 해당하는 Array같은 객체입니다.

구문

arguments

설명

arguments 객체는 모든 함수 내에서 이용 가능한 지역 변수입니다. arguments 객체를 사용하여 함수 내에서 함수의 인수를 참조할 수 있습니다. 이 객체는 함수에 전달된 각 인수를 위한 항목(entry)을 포함합니다, 첫 번째 항목의 인덱스가 0에서 시작하는. 예를 들어, 함수에 인수 셋이 전달된 경우, 다음과 같이 참조할 수 있습니다:

arguments[0]
arguments[1]
arguments[2]

arguments는 설정될 수도 있습니다:

arguments[1] = 'new value';

arguments 객체는 Array가 아닙니다. Array와 비슷하지만 length 빼고는 어떤 Array 속성도 없습니다. 예를 들어, pop 메서드가 없습니다. 그러나 실제 Array로 변환될 수 있습니다:

var args = Array.prototype.slice.call(arguments);

arguments를 실제 Array로 변환하기 위해 Array.from() 메서드 또는 전개 연산자를 사용할 수도 있습니다:

var args = Array.from(arguments);
var args = [...arguments];

arguments에 slice를 사용하면 일부 JavaScript 엔진(예를 들어 V8 - 자세한 정보는 여기)에서 최적화를 막습니다. 그게 신경 쓰이면, 대신에 arguments 객체를 차례로 반복하여 새로운 배열을 구성해 보세요. 대안은 함수로서 멸시된(despised) Array 생성자를 사용하는 것입니다:

var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));

당신이 형식상 받기로 선언된 것보다 많은 인수로 함수를 호출하는 경우 arguments 객체를 사용할 수 있습니다. 이 기법은 가변 인수가 전달될 수 있는 함수에 유용합니다. 함수에 전달된 인수의 수를 결정하기 위해 arguments.length를 쓰세요, 그 뒤에 arguments 객체를 사용하여 각 인수를 처리하세요. 함수 signature에 매개변수의 수를 결정하기 위해서는, Function.length 속성을 쓰세요.

속성

arguments.callee
현재 실행 중인 함수를 가리킵니다.
arguments.caller 
현재 실행 중인 함수를 호출한 함수를 가리킵니다.
arguments.length
함수에 전달된 인수의 수를 가리킵니다.
arguments[@@iterator]
arguments의 각 인덱스 값을 포함하는 새로운 Array Iterator 객체를 반환합니다.

여러 문자열을 연결하는 함수 정의하기

이 예는 여러 문자열을 연결하는 함수를 정의합니다. 함수의 유일한 형식 인수는 연결할 항목을 구분하는 문자를 지정하는 문자열입니다. 함수는 다음과 같이 정의됩니다:

function myConcat(separator) {
  var args = Array.prototype.slice.call(arguments, 1);
  return args.join(separator);
}

이 함수에 인수를 얼마든지 전달할 수 있으며 리스트 내 항목처럼 각 인수를 사용하여 리스트를 만듭니다.

// "red, orange, blue" 반환
myConcat(", ", "red", "orange", "blue");

// "elephant; giraffe; lion; cheetah" 반환
myConcat("; ", "elephant", "giraffe", "lion", "cheetah");

// "sage. basil. oregano. pepper. parsley" 반환
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");

HTML 리스트를 만드는 함수 정의하기

이 예는 리스트 HTML을 포함하는 문자열을 만드는 함수를 정의합니다. 함수의 유일한 형식 인수는 리스트가 정렬되지 않은(bulluet(글 머리 기호)가 붙는) 경우 "u" 또는 정렬된(번호가 매겨진) 경우 "o"인 문자열입니다. 함수는 다음과 같이 정의됩니다:

function list(type) {
  var result = "<" + type + "l><li>";
  var args = Array.prototype.slice.call(arguments, 1);
  result += args.join("</li><li>");
  result += "</li></" + type + "l>"; // end list

  return result;
}

이 함수에 인수를 얼마든지 전달할 수 있고, 표시된 유형의 리스트에 항목으로 각 인수를 추가합니다. 예를 들면:

var listHTML = list("u", "One", "Two", "Three");

/* listHTML은:

"<ul><li>One</li><li>Two</li><li>Three</li></ul>"

*/

나머지, 기본 및 비구조화된 매개변수

arguments 객체는 나머지 매개변수기본 매개변수 또는 비구조화된 매개변수와 함께 사용될 수 있습니다.

function foo(...args) {
  return arguments;
}
foo(1, 2, 3); // { "0": 1, "1": 2, "2": 3 }

그러나, 비엄격 함수에서는 mapped arguments 객체는 함수가 어떤 나머지 매개변수기본 매개변수 또는 비구조화된 매개변수든 포함하지 않는 경우에만 제공됩니다. 예를 들어, 기본 매개변수를 사용하는 다음 함수에서는, 100 대신에 10이 반환됩니다:

function bar(a=1) {
  arguments[0] = 100;
  return a;
}
bar(10); // 10

이 예에서, 어떤 나머지 매개변수기본 매개변수 또는 비구조화된 매개변수가 없는 경우에는, 100이 반환됩니다:

function zoo(a) {
  arguments[0] = 100;
  return a;
}
zoo(10); // 100

출처 - https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/arguments

'Language > JAVASCRIPT' 카테고리의 다른 글

참고 강좌  (0) 2016.12.23
pply(), call() 메서드  (0) 2016.12.15
구글맵(차트)  (0) 2014.12.12
prototypejs  (0) 2013.11.13
마우스 커서 포지션 이동  (0) 2013.05.22
:

Undo tablespace

DB/ORACLE 2016. 12. 14. 09:26

Undo tablespace

- 사용자가 DML 을 수행할 경우 원본 데이터(undo data)들을 저장해 두는 특별한 Tablespace

- 사용자가 생성 가능하며 관리 할 수 있음

- Undo 라는 용어는 8i 버전까지 rollback 이라는 용어로 사용됨

 

1. Undo tablespace 의 특징

- Oracle Server Process 는 이 Tablespace 에 Undo segment 를 생성하고 기본적으로 각 사용자 별로 undo segment(ex: _SYSMU1$) 를 할당하여 관리하며 사용자는 관여할 수 없음

- Undo tablespace 는 Instance 당 여러 개가 동시에 존재 할 수 있지만 사용되는 것은 한번에 1개이다.

-> create undo tablespace undo01 datafile '/~~~~/undo01.dbf' size 10M 으로 만들어 줘도 파라미터에 적용 시키지 않으면 바뀌지 않음

- 관리 방법은 AUM(Automatic Undo Management) 과 MUM(Manual Undo Management) 이 있음 -> 9i 버전 부터는 AUM 방식을 권장

 

2. Undo Tablespace 의 사용 목적

- Transaction Rollback – 사용자가 rollback 이라는 명령어를 수행할 경우에 이곳에 저장된 undo data를 사용해서 rollback 을 수행함

- Read Consistency (읽기 일관성) –CR 작업을 통해 트랙잭션이 끝나지 않은 데이터는 변경 전 데이터를 보여줌.


- 다음 그림과 같이 update 가 발생하면 Datafile 에서 DB Buffer Cache 로 데이터 블록을 불러오게 되며 블록에는 lock 이 설정되어 아무도 내용을 볼 수 없는 상태

- 또한 원본 Data(Undo Data) 는 undo segment 에 저장되게 된다.

 

 - Update 가 수행되던 중 사용자 2에 의해서 select 가 수행되었을 때 undo segment 에서 DB Buffer Cache 로 원본 Data 를 복사하여 사용자 2에게 결과값을 보여주게 됩니다. 대신 1(홍길동) Data 는 lock 이 설정되어 commit 이나 rollback 이 수행되기 전까지는 1 block 에 다른 사용자가 접근할 수 없습니다.

- Transaction Recovery (Instance recovery) : 운영 중이던 DB 서버가 비정상적으로 종료 되었을 때 Roll Forward 와 Roll backward 작업을 수행해서 Dirty Database 를 Clean DB 로 만들어 주는 과정에 사용됨

 

- Undo Parameter 확인


- 신규 Undo Tablespace 생성

SQL>create undo tablespace undo01

2 datafile '/data/temp2/undo01.dbf' size 10M

3 autoextend on;

Tablespace created.

- Undo tablespace 를 생성 하여도 파라미터 파일을 변경 하여야 함.

SQL>alter system set undo_tablespace=undo01;

 

-PFILE 의 경우 파라미터 값을 직접 변경해야 나중에 다시 DB Open 시 문제가 발생하지 않는다.


 

- 각 세션 별로 사용중인 undo segment 확인

SQL>select s.sid,s.serial#,s.username,r.name "ROLLBACK SEG"

1 from v$session s,v$transaction t,v$rollname r

2 where s.taddr=t.addr

3 and t.xidusn = r.usn;

 

 

3. Undo segment 할당되는 원리

- Undo tablespace 는 Data file 의 크기가 증가만 되고 절대 줄어들지 않는다.


<하늘색 : 트랜잭션 완료, 갈색 : 트랜잭션 미완료>

 

다음과 같이 사용자가 DML(E) 을 수행하게 되면 가장 먼저 Server Process 는 Undo Segment 를 확보하게 되는데 이 때 기존에 만들어져 있던 Segment 중 트랜잭션이 완료된 것이 없는지를 확인한 후 그 곳에 덮어쓰게 됩니다.

 


- 다음과 같이 완료된 트랜잭션이 존재하지 않을 경우 새로운 undo segment 를 새로 생성하게 됩니다.

- 이런 식으로 더 이상 빈 공간이 존재하지 않을 경우 Data file 의 저장 공간이 허요하는 범위까지 늘어나다가 만약 더 이상 공간이 없게 되면 하나의 Segment 에 2개 세션 이상의 undo data를 함께 기록하게 됩니다. 이것조차 불가능하게 된다면 해당 트랜잭션은 에러를 발생 합니다.

- Undo tablespace 의 용량을 줄이기 위해서는 새로운 Undo Tablespace 를 생성후 파라미터 값을 변경시킨 다음 기존 Undo Tablespace 를 삭제 하셔야 합니다.

 

4. 주요 Parameter

- undo_retention àcommit 수행 후에도 해당 undo segment 내의 데이터를 다른 서버 프로세스가 덮어 쓰지 못하고 일정 시간동안 대기 시켜주는 파라미터이며 이 파라미터는 undo segment 의 여분이 존재할 경우에만 적용되며 항상 보장하지 않습니다.

 

- undo_retention_guarantee à undo_retention 파라미터는 여분이 존재하지 않을 경우 undo segment 가 재사용 되어지는데 반해 undo_retention_guarantee 파라미터는 설정된 시간동안 무조건 보장해줍니다.

 

- Oracle 10g 버전 부터는 ORA-01555:Snapshot too old 라는 에러를 줄이기 위해 undo retention 을 자동으로 관리하는 기능을 제공합니다.


- 다음은 undo tablespace 를 확인하고 guarantee 로 바꿔주는 명령어


 

SQL>alter tablespace undotbs retention noguarantee;

- no guarantee 로 변경하는 명령어

 

- NOT APPLY 는 Undo tablespace 가 아니므로 적용할 수 없습니다.


출처 - http://thankyeon.tistory.com/31

'DB > ORACLE' 카테고리의 다른 글

DML 문의 처리과정(트랜잭션 내부작업)  (0) 2016.12.14
오라클 액세스  (0) 2016.12.13
오라클 구성요소의 개요  (0) 2016.12.13
참조 사이트  (0) 2014.09.02
[oracle] dump/import 명령어  (0) 2014.01.10
:

DML 문의 처리과정(트랜잭션 내부작업)

DB/ORACLE 2016. 12. 14. 08:14

DML 문의 처리과정
==================

1. 해당 트랜잭션에 대해 언두 세그먼트를 할당한다.  이 경우 현재 온라인 상태인 언두 세그먼트 중
   하나를 우선적으로 사용한다. 언두 세그먼트의 선택은 랜덤하게 이루어지며, 다른 트랜잭션이 사용
   중이면 3번까지 재시도 한다.(undo segment는 block 단위로 owner ship을 갖는다.)
   이 과정에서 실패하면 오프라인 상태의 언두 세그먼트를 온라인화해서 사용한다.
   만인 이과정까지 실패하면, 새로운 언두 세그먼트를 생성한다.
   위 과정에서 언두 세그먼트를 할당받지 못하면 오라클 8i까지 사용하던 롤백 세그먼트
   알고리즘을 사용한다. 즉, 이미 다른 트랜젝션에 의해 사용 중인 언두 세그먼트 중 가장 사용량이
   적은 것을 사용한다. 서버 프로세스가 언두 세그먼트를 획득하는 시점에 적당한 온라인 상태의
   언두 세그먼트가 없으면 온라인 상태의 언두 세그먼트가 확보될 때까지 
   enq: US - contention 이벤트를 대기한다.
   
2. 언두 세그먼트를 할당받으면, 언두 세그먼트 헤더에 트랜잭션 테이블 슬롯(Transaction table slot)을
   생성한다.
   
3. 트랜젝션 테이블을 생성하고 나면 TXID(Transaction ID)를 생성하고, 현재 트랜잭션에 할당한다.
   TXID는 V$TRANSACTION 뷰의 XIDUSN, XIDSLOT, XIDSQN으로 표현되는데, 이 값은 트랜젝션에 할당된
   언두 영역의 언두 세그먼트 헤더에 존재하는 트랜잭션 테이블의 정확한 위치를 가리킨다. 트랜잭션은
   반드시 언두 영역을 할당받은 다음에 ID를 부여받은 것에 유의하자.
 
4. 트랜잭션의 대상이 되는 블록들을 버퍼 캐시로 적재하고 블록 헤더의 ITL(Interested Transaction List)에
   트랜잭션 엔트리(Transaction Entry)를 등록한다. 만일 ITL에 엔트리를 등록할 공간이 없다면, 공간이
   확보될 때까지 enq:TX - allocate ITL entry 이벤트를 대기한다.
   
5. 변경할 블록들의 변경 정보는 PGA에 체인지 벡터라는 이름으로 저장된다. 보통 하나의 로우가 변경되는 경우
   각각 언두 헤더 블록(체인지 벡터#1), 언두 블록(체인지 벡터#2), 데이터 블록(체인지 벡터#3)에 해당하는
   체인지 벡터들이 생긴다. 프로세스는 PGA의 체인지 벡터들을 리두 레코드(또는 리두 엔트리)라는 이름으로
   리두 버퍼(Redo Buffer)로 복사한다. 리두 버퍼에 변경 내용을 복사하는 과정에서 redo copy 래치, redo
   allocation 래치, redo writing 래치를 획득해야 한다. 이 과정에서 래치 경합이 발생하면 각각 
   latch: redo copy, latch: redo allocation, latch:redo writing 이벤트를 대기한다.
   
6. 이전 이미지(Before Image)에 대한 정보를 언두 블록에 기록하고, 데이터 블록을 변경한다. 변경된
   데이터 블록은 더티(Dirty) 상태가 된다. 또한 변경된 데이터 블록에 대한 CR 블록이 버퍼 캐시에 생성된다.
   만일 변경하고자 하는 로우가 현재 다른 트랜잭션에 의해 변경 중(즉 변경 후 아직 트랜잭션이 종료되지 않은
   상태)이라면 해당 트랜잭션이 종료되기를 기다려야 하며 enq: TX - row lock contention 이벤트를 대기한다.
   
7. 커밋이 수행되면, 트랜잭션에 SCN을 할당한다. 커밋 정보는 리두 버퍼에 저장된다.

8. 언두 세그먼트 헤더의 트랜잭션 테이블에 커밋이 이루어졌음을 저장하고, 락을 포함한 모든 리소스에 대한 점유를
   해제한다.
   
9. 리두 버퍼의 내용이 리두 로그 파일에 기록된다. 변경된 블록들은 이후 DBWR에 의해 데이터 파일로 기록된다.


출처 - http://support.dbworks.co.kr/index.php?document_srl=3593&mid=ora_tb



트랜잭션 내부작업 진행 9단계

1.  해당 트랜잭션에 대해 언두 세그먼트를 할당.

2. 언두 세그먼트에 트랜잭션 테이블 슬롯을 생성.

3. TXID(transaction ID) 생성

SQL> delete scott.emp;

SQL> select xidusn, xidslot, xidsqn from v$transaction;

4. 블록헤더의 ITL에 트랜잭션 엔트리를 등록, ITL에 공간이 없다면 enq:TX – allocate ITL entry 이벤트 대기


5. 변경정보는 PGA에 체인지 벡터라는 이름으로 저장된다언두헤더블록언두블록,데이터블록 프로세스는 PGA의 체인지 벡터들을 리두 레코드라는 이름으로 리두버퍼에 복사한다.

6. 이전 이미지에 대한 정보를 언두 블록에 기록하고변경된 데이터 블록에 대한 CR블록이 버퍼캐시에 생성된다만일 다른 트랜잭션에 의해 변경 중이라면 종료될 때까지 enq:TX – row lock contention 이벤트 대기

7. 커밋이 수행되면트랜잭션에 SCN을 할당커밋 정보는 리두버퍼에 저장

8. 언두 세그먼트헤더의 트랜잭션 테이블에 커밋정보를 저장락을 포함한 리소스에 대한 점유 해제

9.  리두버퍼의 내용이 리두 로그파일에 기록된다


출처 - http://salme.tistory.com/1


'DB > ORACLE' 카테고리의 다른 글

Undo tablespace  (0) 2016.12.14
오라클 액세스  (0) 2016.12.13
오라클 구성요소의 개요  (0) 2016.12.13
참조 사이트  (0) 2014.09.02
[oracle] dump/import 명령어  (0) 2014.01.10
:

오라클 액세스

DB/ORACLE 2016. 12. 13. 16:45

1)SELECT 명령어 처리

(PARSING LEVEL) 

1.서버 프로세스 구문분석 요청

 

  사용자가 SQL 명령어들을 입력하면 SQL명령어는 text string으로 서버로 전송하게 된다.

 

2.소프트 파싱과 하드 파싱

 

  SGA의 라이크러리 캐쉬에서 동일문장을 실행했던 실행계획을 검색 동일 실행계획을 존재하면 DB버퍼캐쉬에서 해당결과를 찾아 바로 유저에서 Fetch 작업을 함, 동일문장이 존재하지 많으면 딕셔너리 캐쉬에서 오브젝트를 참조하여 하드파싱한다.

 

  하드 파싱 : 하드파싱은 공유 풀에 해당 SQL에 대한 구문 분석이 존재 하지 
않을 경우 이다. 이와 같은 경우에는 구문분석을 처음부터 수행하게 된다. 
 

 소프트 파싱 : 반대로 공유풀에 해당 SQL에 대한 구문분석이 존재할 경우이다. 
이 경우는 구문분석을 재 수행하지 않고 기존 구문분석을 이용하게 되므로 성능 면에서 유리하다.


 

3. 문장검사

 

parsing과정이 많기 때문에 오라클의 처리 속도를 올리기 위해서는 동일한 SQL문을 사용하여 library cache에서 바로 실행을 할 수 있게 해주는 것이 기본이 된다.

 

 1. 대/소문자 동일

 2. 스키마 동일

 3. 빈 스페이스 일치

 4. 주석도 일치

 5. bind변수 type도 동일해야 동일한 문장이다.

 

   

4. 데이터베이스 분석

  딕셔너리 캐쉬에서 티이블 및 갈럼 존재 유무를 확인한다.

 

5. 쿼리 단순화

  옵티마이져가 좀 더 좋은 실행계획을 생성하기 위해 내부적으로 SQL을 변경한다.

 

6. 권한확인

  시스템 테이블 스페이스에 저장된 DBA_SYS_PRIVS, DBA_TAB_PRIVS 뷰를 이용해 권한 확인한 후 딕셔너리 캐쉬에 저장한다.

 

7. 락 수행

   USER가 DML를 던지면 변경되는 ROW에 대한 ROW LOCK과 TABLE에 대한 TABLE LOCK이 발생.

 

 ROW LOCK (TX)

SQL 문장에서 WHERE 조건에 해당되는 ROW에 대하여 다른 유저들이 변경할 수 없도록  EXCLUSIVE LOCK 이 생긴다.  TX LOCK이 걸린 ROW는 DML 문장을 실행한 유저가 COMMIT이나 ROLLBACK을 할때 까지 걸리므로 다른 유저들이 변경할 수 없다.

 

 TABLE LOCK (TM)

   TX LOCK이 걸린 ROW가 저장된 TABLE에 대한 LOCK 이다.
DML SQL 문장을 수행하는 중에, 해당 테이블이 ALTER 나 DROP 되는 것을 방지하기 위해서 TM LOCK을 사용한다.
 같은 테이블에서 실행할 수 있는 SQL 문장과 실행할 수 없는 SQL 문장을 구분하기 위해서다. 
TM LOCK에는 RS(ROW SHARE), RX(ROW EXCLUSIVE), S(SHARE), SRX(SHARE ROW EXCLUSIVE), X(EXCLUSIVE) 가 있다.
 


 

 

8. Excute Plan 및 Tree 생성

 

9. 결과물이 SGA에 저장

 

(EXCUTE LEVEL)

  실행계획을 가지고 DB버퍼 캐쉬에서 해당 ROW를 검색 후 존재하면 결과값을 우저에서 전홍 한다.

 존재하지 않으면 데이터 파일에서 해당값을 검색하여 DB버퍼 캐쉬로 읽어 올린다.

 

(FETCH LEVEL) 

 유저에서 해당 결과값을 화면으로 출력해준다.

 

 

2) DML 구문 처리

 

(PARSING LEVEL)

1. 서버프로세스 구문분석요청

2. SGA의 라이브러리 캐쉬에서 동일문장 검색 .........-> 소프트 파싱 or 하드 파싱

3. 문장검사 

4. 데이터 베이스 분석 ... 딕셔너리 캐쉬에서 데이블 및 칼럼 존재 유무 확인

5. 옵티 마이저가 좀더 좋은 실행계획을 생성하기위한 쿼리 단순화

6. 권한확인

7. 락수행

8. Excute Plan 및 Patse Tree 생성

9. 결과물이 SGA에 저장

 

(EXCUTE LEVEL)

1. 실행 계획을 가지고 데이터파일의 해당 값을 검색하여 DB 버퍼 캐쉬로 읽어 올린다.

2. 서버프로세스는 언두 세그 먼트를 확보한다.

3. 변경된 내용을 리두 로그버퍼에 저장한다.

4. 변경 이전 이미지를 언두 세그먼트에 저장한다.

5. DB버퍼 캐쉬에 변경된 내용을 적용한다.

6. 유저에게 1row update라는 결과를 전송한다.

7. commit 명령어를 수행하면 리두 로그버퍼에 있는 변경된 내용을 리두 로그 파일에 기록한다.

   단 시점은 사용자에 의한 commit 명령이 발생 했을 경우

       리두로그 버퍼가 1/3이상 사용되었을 경우

       1MB 이상의 리두가 생성되었을 경우

       3초마다 리두 로그 파일에 내려 쓰여 진다.



출처 - http://mes2good.egloos.com/761982

'DB > ORACLE' 카테고리의 다른 글

Undo tablespace  (0) 2016.12.14
DML 문의 처리과정(트랜잭션 내부작업)  (0) 2016.12.14
오라클 구성요소의 개요  (0) 2016.12.13
참조 사이트  (0) 2014.09.02
[oracle] dump/import 명령어  (0) 2014.01.10
: