관리 메뉴

HAMA 블로그

JDBC 와 디자인패턴 - 4. chain of Responsibility 패턴 본문

디자인패턴

JDBC 와 디자인패턴 - 4. chain of Responsibility 패턴

[하마] 이승현 (wowlsh93@gmail.com) 2015. 8. 14. 20:07

순서


1. 소개 

2. Abstract Factory 패턴 

3. State 패턴

4. chain of Responsibility 패턴 

5. Adapter 패턴

6. Bridge 패턴 

 

디자인 패턴을 공부할때 가장 유념해야할 단어는 "의도" 이다.  절대 모양 (구조) 가 아니다.  그리고 구현함에 있어서 책 등에 나와 있는 모양 그대로 구현하려고 할 필요도 없다. 너무 잘 하려고 하다보면 아예 하지도 못할지도 모른다.  "의도" 만 확실히 이해한 다음에 구현을 이것저것 거침없이 하다보면.... 코딩에 대한 재미는 생겨날 것이다. 재미는 실력향상을 의미하기도 하고 ~  


JDBC 는 자바에서 정한 DB 와의 관계에 대한  행동 지침이다. 행동지침을 공통화하려면 어느 정도의 유사성이 있어야 한다. 세상에는 많은 자동차가 있지만 행동 지침은 비슷하다. 그러기에 운전자들이 다른 메이커의 자동차를 운전하더라도 어느정도는 쉽게 할수있지 않은가.. 마찬가지로  세상에는 많은  DB 가 있고.   각각의 DB 에서 데이터를 가져오는 방법(행동) 이  DB  마다 다르다면 따로 따로 공부를 해야하지만 , 행동지침이 정해져 있고, 모든 DB 가 그것에 맞춰서 개발을 한다면 , 개발자는 정해져있는 행동지침 ( JDBC ) 만 공부하면 된다.  


JDBC  를 디자인패턴과 함게 묶은 이유는 ,  일단 디자인 패턴을 이해하는 가장 효율적인 방법은 다른사람(특히 구루들) 이 잘 구현해놓은 코드(패턴)을 보고 감흥하는것인데 JDBC 를 구현한 코드들에는 몇몇개의 패턴이 뚜렷하게 녹아져 있다.  


4. Chain of Responsibility 패턴





* chain of responsibility 패턴은 위 전체 JDBC 패턴 모식도중 빨강 네모상자 안에서 이루어집니다.



1. DriverManager 와 Driver 와의 관계 


먼저 DriverManager 와 Driver 에대해서  알아보겠습니다.

보통 JDBC 프로그래밍할때 아래처럼 하는데요

static final String JDBC_DRIVER = "com.hama.jdbc.HAMADriver";  
static final String DB_URL = "jdbc:hama://localhost/EMP";

   
      // 1. JDBC driver 등록 
      Class.forName(JDBC_DRIVER);

      // 2. DB 로의 connection
      conn = DriverManager.getConnection(DB_URL,USER,PASS);

      // 3. Statement 를 통한 Query 명령 
      stmt = conn.createStatement();
      
      String sql = "SELECT id, age FROM Employees";
      
      // 4. result set 으로 부터 데이터 가져오

      ResultSet rs = stmt.executeQuery(sql);

      // 5. 커서를 통해 한 로우씩
      while(rs.next()){

         // 6. 한 컬럼씩 가져오기 
         int id  = rs.getInt("id");
         int age = rs.getInt("age");
       

      }
                             (코드 -1)


위의 소스 예제에서 

// 1. JDBC driver 등록 Class.forName(com.hama.jdbc.HAMADriver); // JDBC_DRIVER -> com.hama.jdbc.HAMADriver // 2. DB 로의 connection conn = DriverManager.getConnection(DB_URL,USER,PASS);


이 부분에 집중해 보도록 하겠습니다.

1 번에서 com.hama.jdbc.HAMADriver 를 자바 리플렉션을 이용하여 메모리로 올리고 있습니다.

JDBC 드라이버를 메모리로 올릴때 어떤 행동을 할가요? 소스를 살펴보겠습니다.


public class HAMADriver implements java.sql.Driver {

private HAMAConnection connection;

static{

java.sql.DriverManager.registerDriver(new HAMADriver() );

}

..

public boolean acceptsURL(Stirng url){

return url.startWith("jdbc:hama");

}

}


(코드 -2)


HAMADriver  라는 클래스 파일이 하드에서 메모리로 Class.forName 을 통해서 메모리로 끌어 올려

질때  위의 (코드-2) 의 빨강색 코드가 호출됩니다. 코드를 보시면 DriverManager 에 스스로의 인스턴

스를 생성해 서 등록시키고 있습니다. 


그렇습니다~!!!  그렇기 때문에 아래의 코드가 성립이 되는것이지요.

conn = DriverManager.getConnection(DB_URL,USER,PASS);


위의 코드에서 DriverManager 가 어떻게 내가 원하는 DB 에 접속할수 있는 Connection 을 리턴할수있었겠습니까?  Class.forName 을 통해서 HAMADriver 가 DriverManager 에 등록되 있기때문에 가능한것입니다.


자!! 여기서 질문 !~


Class.forName 에  위의 HAMA 데이터베이스에 접근할수있는 Driver 에 추가적으로

MySql 에 접근할수있는 드라이버를  Class.forName("com.mysql.jdbc.Driver");  요렇게 

아래에 추가했다고 칩시다.


이럴때 conn = DriverManager.getConnection(DB_URL,USER,PASS);는 어떤 DB 에 접속할수있는 드라이버의 Connection 인터페이스를 리턴해줄까요??


자!! 이럴때 필요한게 Chain of Responsibility 입니다~ 이름에 "의도" 가 그대로 뭍어나 있습니다.

"체인을 돌면서 해당 행위에 책임감있는 놈에게 일을 시키겠다." 뭐 이쯤 이겠지요.


그럼 책임감 있는놈을 어떻게 찾을것인가?? 

위의 그림 2의 파랑색 코드를 보시면 


public boolean acceptsURL(Stirng url){

return url.startWith("jdbc:hama");

}


요렇게 되있습니다.  그렇습니다. DB 에 접속하기위한 URL 이 어떻게 시작되냐에 따라서 선택된다는 야그~

무지 간단하죠??  DriverManager 는 자신한테 등록되있는 드라이버를 for 문 돌면서 각 드라이버의 

acceptsURL 를 호출해서 ok 떨어진놈을 찾는거죠. 


실제 오라클(썬?)에서 구현한 java.sql.DriverManager 코드를 보면



public static Driver getDriver(String url)

  258           throws SQLException {

                 .... 생략 ...

  268           for (DriverInfo aDriver : registeredDrivers) {   //  (1)  for 문 돌면서 

  269               // If the caller does not have permission to load the driver then

  270               // skip it.

  271               if(isDriverAllowed(aDriver.driver, callerCL)) {

  272                   try {

  273                       if(aDriver.driver.acceptsURL(url)) {  //  (2) 적합한 드라이버를 찾는다.

  274                           // Success!

  275                           println("getDriver returning " + aDriver.driver.getClass().getName());

  276                       return (aDriver.driver);

  277                       }

  278   

  279                   } catch(SQLException sqe) {

  280                       // Drop through and try the next driver.

  281                   }

  282               } else {

  283                   println("    skipping: " + aDriver.driver.getClass().getName());

  284               }

  285   

  286           }

              ......

  290       }



위 처럼 (1) 등록된 드라이버를 순회하면서 (2) 적합한 드라이버를 찾고 있습니다.


jdbc:hama:// 로 시작되는 DB_URL 일 경우는 HAMADriver 가 가지고있는 Connection 을 

리턴해주고  Postgresql 은 jdbc:postgresql 일테고  MySQL 은 jdbc:mysql 입니다.


chain of responsibility 패턴 은 이렇게 끝났습니다.  너무 간단해서 허무할 정도네요 ^^



너무 간단하게 끝나서 , 각자 판단할꺼리를 던저 보도록 하겠습니다. 댓글로 각자의 생각을 달아주시

면 고맙겠는데요. 웹 개발자분들은 대부분 아시는 서블릿 필터에 대한 이야기입니다. 몇몇 책이나 사들이 

필터를 얘기할때  "데코레이터 패턴" 이라 고 말하기도 하는데요  토비의 스프링인가 ? 그 책에서도 언급된거 같

은데 잘 기억은 안납니다만..~  (다이나믹 프록시 설명할때 나왔나 하기도 하네요) 

참고로 데코레이터 패턴의 전형적인 사용예는 자바의 IO 가 있지요.   


자~!!!   서블릿 필터는 진짜 데코레이터 패턴에 가까울까요?


그럼 이 시리즈에서 강조한 각 패턴의 "의도" 를 써 봅니다. 너무중요해서 빨강색 쫙~~

( 제가 정리한건 아니고, "GOF 책" 과 실용주의 디자인 패턴" 책 참고)

Chain of Responsibility 패턴 

일련의 객체 집합이 잘 정의된 통로(chain) 을 통해 메세지를 전달함으로써 하나 이상의 객체에 메시지를 처리할수 있는 기회를 준다.

주어진 메세지에 가장 적합한 객체가 메시지를 처리한다. 또한 하나 이상의 객체가 메시지를 처리하는것이 가능하다.


GOF :  요청을 처리할수 있는 기회를 하나 이상의 객체에게 부여함으로써 요청하는 객체와 처리하는 객체 사이의 결합도를 없애려는 것이다. 요청을 해결할 객체를 만날 때 까지 객체 고리를 따라서 요청을 전달한다.


Decorator 패턴 

런타임시 객체에새로운 능력을 추가하거나 객체의 행위를 변화시킨다. Decorator 는 상속 대신 합성을 사용하여 클래스 계층 구조를 단순화 시킬수 있다. 

GOF: 객체에 동적으로 책임을 추가할수 있게한다. 데코레이터 패턴은 기능의 유연한 확장을 위해 상속대신 사용할수 있는 방법이다.



자 어떠십니까?? 

필터는 브라우저에서 요청에 대해서 파이프라인을 가지면서 , 어떤 선행 처리를 합니다.

그 처리를 단계별로 거치면서 중첩적인 ( 꾸미는) 처리를 하는걸까요?

파이프라인중 일부분을 선택해서 처리를 하는걸까요? 

필터는 기능의 유연한 확장일까요? 


뭐에 더 가까울까요? 선택은 여러분의 몫입니다. 저는 결정했지만 말하지는 않겠습니다. 


p.s 

제 3의 패턴이다. 라고 말할수도있습니다.  이것 저것 생각해보는 시간을 갖으면  좋겠습니다.

Core J2EE Patterns: Intercepting Filter Pattern  :

http://www.informit.com/articles/article.aspx?p=1398619&seqNum=3





레퍼런스 :  실용주의 디자인 패턴 (http://www.kangcom.com/sub/view.asp?sku=200607180006 )




Comments