관리 메뉴

HAMA 블로그

JDBC 와 디자인패턴 - 1.소개 및 2. Abstract Factory 패턴 본문

디자인패턴

JDBC 와 디자인패턴 - 1.소개 및 2. Abstract Factory 패턴

[하마] 이승현 (wowlsh93@gmail.com) 2015. 7. 28. 22:34


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

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

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

순서

1. 소개 

2. Abstract Factory 패턴 

3. State 패턴

4. Adapter 패턴

5. Bridge 패턴 

6. chain of Responsibility 패턴

 



1. 소개 

이 글은 JDBC 에 녹아져있는 패턴들을 살펴볼것인데 , 그 전에  DB 에 대해서 잠시 살펴보자.

가. DB  

A 군은  학교/학원에서 자바 / 객체지향 프로그래밍을 배웠습니다.  무엇을 만들어 볼까 생각하다가 "오키" 에 물어보니 DB 를 만들어 보라는 댓글을 보고 DB 에 대해 곰곰히 생각해 보았습니다.  데이터를 저장한다라..   - .-a
그래 결심했어!! 이름은 HAMASQL 이라고 짓고 . 
일단 데이타베이스는 '폴더' 라고 하자.  그리고 테이블을 '파일' 이라고 하자.!! 그리고 파일에 한줄씩 콤마(,) 로 나누어서 컬럼을 구분하고 , 각각의 데이터를 문자열로 넣자.  이렇게 되면 데이타베이스 하나에 테이블이 여러개 들어갈것이다.

PSEUDO  코드 

class HAMADatabase {

   public  createDatabase(String db_path , String db_name) {

             makeDirectory(db_pathdb_name);    // db_path위치에 , db_name이라는 폴더를 만들어라.

   }

}

class Table {

  String [] column;

   public  createTable(String db_path, String name, String column){

makeFile(db_path, name);       // db_path 데이타베이스에 name 이라는 테이블( 파일 ) 을 만들고,               

    this.column = column.split(',');   // 컬럼은 column 문자열에서 , 로 토큰을 나누자.      

   }

   public insertRow(...) ...

   public deleteRow(...) ...

   public updateRow(...) ...

   public select(...) ...

}

class Cursor {

    ...

}

                                                                     (코드 -1)

자 일단 데이터를 저장하는 방법과 클래스를 작성했고 (-.-)  
이제 사용자와의 커뮤니케이션을 해야하는데 SQL  언어를 통해서 명령을 받아드려야지.
SQL 엔진은 인터프리터 패턴으로 개발하자. (http://brad2014.tistory.com/200자 이제 SQL 엔진도 개발했고 

(-.-;;  이 글은 JDBC  디자인패턴이 목적이니 양해를..이제 JDBC 인터페이스만 구현하면 될것 같다.  !!!

나. JDBC 

                             (그림 1: http://docstore.mik.ua/orelly/java-ent/jenut/ch18_01.htm 이미지참조)

위의 이미지는 java.sql 패캐지에 포함되어 있는 개별 JDBC 드라이버를 만들기 위한 뼈대(인터페이스) 입니다.우리는 저기에서 Connection / Driver / PreparedStatement/ ResultSet / 등을 구현하면서 패턴이 어떤식으로 적용되는지 자세하게 살펴볼 것입니다.

먼저 인터페이스 각각을 간략하게 설명하자면 java.sql 패키지는 전체 JDBC API 를 포함합니다.  SQL 구문을 데이타베이스에 보내며 그것에 따른 결과셋을 가져오는데  Driver 인터페이스는 특정 데이타베이스를 위한 JDBC 구현을 하게되며 , Statement 등등은 SQL 구문을 실행하는데 사용됩니다.  ResultSet 은 데이타베이스에 의해 SQL 명령이 실행되어진후에 결과 데이터 를 담게되며, 커서등을 통해서 최종 사용자가 데이터를 사용하게됩니다. ResultSetMetaData 는 ResultSet 의 메타데이터를 담당하게되며 DatabaseMetaData 는 데이타베이스 전체에 대한 메타데이터를 제공합니다.

다. JDBC 구현 전체 클래스 다이어그램 및 패턴 

                                       (그림 2) 

이것은 "실용주의 디자인 패턴 그림 4-18" 을 조금 각색한 그림이다.힘들게 그리고 이렇게 올려두니 매우 뿌듯하다. ^^
간략히 소개하자면

1. 연한주황색은 인터페이스이다. 이것은 java.sql 패키지에서 기본적으로 제공하는것으로 "공통 행위 지침" 이다.  
2. 검정색 네모칸은 우리가 구현한 클래스를 나타낸다. 인터페이스를 상속받았다. (  ◁-----  : 인터페이스 상속
3. 색깔이 있는 동그란원은 특정 패턴을 나타낸다. 그것과 연결된 점선은 해당 패턴에 포함된 클래스들이다. 
4. <----  점선 화살표는 의존관계를 나타낸다. DriverManager 는 HAMADriver / HAMADriver 는 HAMAConnection 의존한다.
5. ◆-----  다이아몬트 직선은복합연관(컴포지트) 관계이며, ◇------ 빈다이아몬드 직선은 집합연관 관계이다.

   중요한 차이점은 복합연관 관계는 좀더 강한 결합관계를 가진다. 즉  HAMAResultSet 이 소멸되면 Cursor 도 소멸한다. 

위의 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"); } (코드 -2)                    

MySQL 을 사용할때  jdbc:mysql  를 사용한것처럼 jdbc:hama 를 사용하였으며 , DriverManager 는 저것을 통해 DB를 구분한다.  나의 디비를 접속하기위해 새로만든 com.hama.jdbc.HAMADriver  를 사용한다. MySql 을 사용한다면 

com.mysql.jdbc.Driver 를 사용해야할것이다.

1. 내가 만든 JDBC 드라이버 클래스를 로딩한다. (로딩함과 동시에 내부에서 HAMADriver 인스턴스를 생성한후에 DriverManager 에게 넘겨준다.)
2.  DriverManager 는 1번에서 얻게된 HAMADriver  를 통해서 디비에 접속한후에 HAMAConnection 객체를 얻는다. 
3. HAMAConnection 클래스를 통해서 HAMAStatement 객체를 생성한다. 
4. HAMAStatement  클래스를 통해서 디비에 쿼리명령을 실행후 ResultSet 로 테이블의 일부분의 데이터를 가져온다. 
5. ResultSet 안의 커서를 통해서 ROW 별로 접근한다.
6. 하나의 컬럼에 접근한다. 

자 JDBC 에 대해 전반적인 사항을 알아보았다. 이제 진짜 패턴에 대해서 집중해서 살펴보자. 



2. Abstract Factory 패턴 

JDBC 에서 사용하는 패턴중 가장 눈에 뛰는 패턴은 "Abstract Factory" 이다.  위의 그림 2를 보면 Abstract Factory 으로 빼곡한 모습을 볼수있다. 한부분을 떼어내 보면 아래 그림과 같다.

                    (그림 3) 
공장역활을 하는것은 Driver 이며 , 공장이 만들어 내는것은 Connection 이다.
JDBC 에서 특이한것은 생산품이 다시 공장역할을 한다는것인데 Connection  이 생산품에서 
공장역할을 하게되면 , Connection   의 생산품은 ?  그렇다 Statement 클래스가 된다. 

Abstract Factory 의 모호함

패턴중에 가장 이름에 현혹되지 말아야하는 패턴이 Abstract Factory  라고 생각한다. 서두에도 말했다시피 패턴은 "의도" 가 가장중요한데 , 이 패턴은 이름으로 의도를 느끼기에는 좀 힘든면이 있다. Abstract Factory 는 의도를 전혀 나타내고 있지 못한다. Abstract Factory 는 단지 Abstract Factory 패턴에서 이루어지고있는 "의도" 에 하나의 부품일 뿐이다.  Abstract Factory 는 Bridge 패턴과 함께 , 패턴이라기보다는 아키텍처를 나타낸다고 볼만큼 규모가 있는 느낌의 패턴이다.  그래서 실제로 일반개발자가 이 패턴을 사용할일은 그다지 많지 않다. 

팩토리!!! 란 무엇인가?  

팩토리는 무엇인가를 만들어 주는 공장이다. 실생활에서 우리는 공장에 집중하지 않는다. 공장에서 만들어주는 "어떤것"에 더 친숙하고 집중하게 되는데 Abstract Factory 패턴에서도 마찬가지이다. Abstract Factory 는 무엇인가를 만들어주는것이며, 실제 만들어지는것이 우리가 집중해야할 "어떤것" 이다.  이름에서 느껴지듯이 Abstract Factory  는 실제 무엇을 만들수있는 공장이 아니다. 어떤 방식으로 만들라는 "행동지침" 만 정의하며 실제 공장은 concrete Factory 라고 한다.  위의 JDBC 에서는 그림 1을 보자. Abstract Factoryjdbc.sql.Driver 인터페이스이며  Concrete Factory 는 그것을 구현상속한 HAMADriver 가 된다.  팩토리는 공장이며, 위에 말한것처럼 "어떤것" 을 만들어주는 역할을 한다고 했다. 그럼 HAMADriver  라는 Concrete Factory 가 만들어주는 "어떤것" "상품" 은 무엇이 될까?

그것은 바로 jdbc.sql.Connection 을 상속받은 HAMAConnection 이 바로 Concrete Product 가 된다.   

코드로 보면 (PSEUDO

// abstract factory   :  필요한 생산품 ( Connection ) 을 생산하는 추상공장 


interface Driver {

public Connection connect(String url);

}


// concrete factory  :  실제 필요한 생산품 ( HAMAConnection or MySQLConnection ) 을 생산하는 실제공장 

class HAMADriver implements java.sql.Driver{


public Connection connect(String url) {

return new HAMAConnection(url);

}


}

// abstract product  : 생산품의 공통  행동 양식을 나타내는 인터페이스 ( Connection )

interface Connection {

public close();

public commit();

public createStatement();

}


// concrete Product  : 구체적인 생산품  ( HAMAConnection or MySQLConnection  )

class HAMAConnection implements java.sql.Connection{


   private HAMADatabase database;

   public HAMAConnection(Sting url) {

database = new Database(url);

   }

   public close() {

      ...

   }

   public commit() {

     . ..

   }

   public Statement createStatement() {

return new HAMAStatement(database);

   }


}

이걸 왜 쓰는건가?  

실생활에서 공장에는 여러가지의 공장(자동차, 핸드폰) 이 있을수 있다. 

=> JDBC 를 구현하는 DB 에는 여러가지가 있다.

생산되는 제품(핸드폰) 은 회사마다 내부작동법 (아이폰, 갤럭시 ) 이 다양할수있다. 

=> Connection 하는 방법, 데이터를 가져오는 방법은 DB 마다 다르다. 

이처럼 공장과 생산품을 클래스로 분류시켜놓으면 새로운 공장 / 새로운 생산품을 기존의 시스템에 끼워넣을때 

기존의 코드는 전혀 건드리지 않아도 된다는 장점이 있습니다. 대규모의 프로덕트'군'의 추가/삭제가 유연해 진다는것이지요.

여기에 중요한 장점이 추가되는데 

공장이나 생산품을 사용하는 방법은 회사마다 내부 구현은 다르지만 , 사용자한테는 동일합니다. 핸드폰의 경우를 예로들면 내부적으로는 다르겠지만 외부적으로는 ,"통화하기" "인터넷보기" 처럼 같으며 자동차를 예로들면 엔진은 다르겠지만 "핸들돌리" "브레이크 밟기" 는 동일합니다.

무슨 이야기냐하면. Abstract Factory 를 사용하면 클라이언트는 어떤 프로덕트 '군' 이 추가되더라도 기존에 사용하는 방식 그대로 사용할수 있게됩니다. 위의 예에서 MySQL 의 JDBCDriver 를  사용하던 방법대로 HAMA DB 의 JDBCDriver ( 위에서는 HAMADriver) 를 어떤 추가적인 러닝커브 없이도 바로 사용할수 있다는 점이지요. ^^ 

단점 

만약 생산품이 원하는 기능이 없거나 그게 아니라면 Abstract Product 의 인터페이스를 추가하거나 고쳐야하며 이 이야기는 그것을 구현한 모든것의 변경을 요한다는 점이다.jdbc.sql.Driver 에서 어떤 큰 변경이 일어난다면 그것을 구현한 수 많은 데이타베이스 밴더( 오라클, MySQL 등) 이 골치아파진다는 이야기이다.

다른 사용 예

사용Abstract FactoryConcrete 
Factory

Abstract
Product
Concrete Product
JDBCjava.sql.DriverHAMADriver /
MySQLDriver
java.sql.ConnectionHAMAConnection/
MySQLConnection
Collection 
Collection LinkedList /
Tree / 
IteratorLinkedListIterator/
TreeIterator
UI systemUIFactoryWindowUIFactory/
LinuxButton
ButtonWindowButton / 
LinuxButton 


다음에는 State 패턴에 대해서 알아보겠습니다~ 




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


Comments