반응형

개발자의 실수를 줄여주는 java.sql.Connection 만들기







흔히 close()를 하지 않아서 발생하는 자원 누수 현상을 줄여주는 Connection 클래스를 만들어본다.

JDBC API 사용시 흔히 하는 개발자의 실수

JDBC API를 사용하여 데이터베이스 프로그래밍을 할 때 가장 많이 사용되는 코드는 아마도 다음과 같은 형태일 것이다.

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    
    try {
        conn = DBPool.getConnection(); //
        stmt = conn.createStatement();
        rs = stmt.executeQuery(..);
        ...
    } catch(SQLException ex) {
        // 예외 처리
    } finally {
        if (rs != null) try { rs.close(); } catch(SQLException ex) {}
        if (stmt != null) try { stmt.close(); } catch(SQLException ex) {}
        if (conn != null) try { conn.close(); } catch(SQLException ex) {}
    }

그런데 위와 같은 프로그래밍을 할 때 흔히 하는 실수가 close()를 제대로 해 주지 않는 것이다. 특히, 하나의 메소드에서 5-10개의 (PreparedStatement를 포함한)Statement와 ResultSet을 사용하는 경우에는 개발자의 실수로 같은 Statement를 두번 close() 하고 한두개의 Statement나 ResultSet은 닫지 않는 실수를 하곤 한다. 이처럼 close() 메소드를 알맞게 호출해주지 않을 경우에는 다음과 같은 문제가 발생한다.

  1. Statement를 닫지 않을 경우, 생성된 Statement의 개수가 증가하여 더 이상 Statement를 생성할 수 없게 된다.
  2. close() 하지 않으므로 불필요한 자원(네트워크 및 메모리)을 낭비하게 된다.
  3. 커넥션 풀을 사용하지 않는 상황에서 Connection을 닫지 않으면 결국엔 DBMS에 연결된 새로운 Connection을 생성할 수 없게 된다.
위의 문제중 첫번째와 두번째 문제는 시간이 지나면 가비지 콜렉터에 의해서 해결될 수도 있지만, 만약 커넥션 풀을 사용하고 있다면 그나마 가비지 콜렉션도 되지 않는다. 따라서 커넥션 풀을 사용하는 경우 Statement와 ResultSet은 반드시 닫아주어야만 한다. 하지만, 제아무리 실력이 뛰어난 개발자라 할지라도 각각 수십에서 수백줄로 구성된 수십여개의 .java 파일을 모두 완벽하게 코딩할 수는 없으며, 따라서 한두군데는 close()를 안 하기 마련이다. 운이 좋으면 빨리 찾을 수 있겠지만, 그렇지 않다면 close() 안한 부분을 찾는 데 몇십분, 몇시간, 심한 경우 1-2일 정도가 걸리기도 한다.

Statement를 자동으로 닫아주는 MVConnection 클래스 구현

실제로 필자도 앞에서 언근했던 문제들 때문에 고생하는 사람들을 종종 봐 왔었으며, 그때마다 그 버그를 고치기 위해서 소스 코드를 일일이 찾아보는 노가다를 하는 개발자들을 보기도 했다. 그래서 만든 클래스가 있는데, 그 클래스의 이름을 MVConnection이라고 붙였다. 이름이야 여러분의 입맛에 맛게 수정하면 되는 것이므로, 여기서는 원리만 간단하게 설명하도록 하겠다.

먼저, MVConnection을 구현하기 전에 우리가 알고 있어야 하는 기본 사항이 있다. JDBC API를 유심히 읽어본 사람이라면 다음과 같은 내용을 본 적이 있을 것이다.

  • Statement를 close() 하면 Statement의 현재(즉, 가장 최근에 생성한) ResultSet도 close() 된다.
  • ResultSet은 그 ResultSet을 생성한 Statement가 닫히거나, 또는 executeQuery 메소드를 실행하는 경우 close() 된다.
MVConnection은 바로 이 두가지 특성을 사용한다. 위의 두 가지 특징을 정리하면 결국 Statement만 알맞게 닫아주면 그와 관련된 ResultSet은 자동으로 닫힌다는 것을 알 수 있다. 따라서 ConnectionWrapper 클래스는 Connection이 생성한 Statement들만 잘 보관해두었다가 각 Statement를 닫아주기만 하면 되는 것이다. PreparedStatement나 CallableStatement는 Statement를 상속하고 있으므로 따로 처리할 필요 없이 Statement 타입으로 모두 처리할 수 있으므로, PreparedStatement와 CallableStatement를 위한 별도의 코드는 필요하지 않다.

다음은 MVConnection 클래스의 핵심 코드이다.

    public class MVConnection implements Connection {
        
        private Connection conn; // 실제 커넥션
        
        private java.util.List statementList; // statement를 저장
        
        public MVConnection(Connection conn) {
            this.conn = conn;
            statementList = new java.util.ArrayList();
        }
        
        public void closeAll() {
            for (int i = 0 ; i < statementList.size() ; i++) {
                Statement stmt = (Statement)statementList.get(i);
                try {
                    stmt.close();
                } catch(SQLException ex) {}
            }
        }
        
        public void close() throws SQLException {
            this.closeAll();            conn.close();
        }
        
        public Statement createStatement() throws SQLException {
            Statement stmt = conn.createStatement();
            statementList.add(stmt);
            return stmt;
        }
        
        public CallableStatement prepareCall(String sql) throws SQLException {
            CallableStatement cstmt = conn.prepareCall(sql);
            statementList.add(cstmt);
            return cstmt;
        }
        
        public PreparedStatement prepareStatement(String sql) throws SQLException {
            PreparedStatement pstmt = conn.prepareStatement(sql);
            statementList.add(pstmt);
            return pstmt;
        }
        
        ...
    }

위 코드를 보면 Statement를 저장하기 위한 List와 그 List에 저장된 Statement 객체를 모두 닫아주는 closeAll() 이라는 메소드가 정의되어 있다. 바로 이 List와 closeAll() 메소드가 이 MVConnection 클래스의 핵심이다. Statement를 생성해주는 메소드(createStatement, prepareCall, prepareStatement)를 보면 생성된 Statement를 statemetList에 추가해주는 것을 알 수 있다. 이렇게 저장된 Statement는 실제로 Connection을 닫을 때, 즉 Connection의 close() 메소드를 호출할 때 닫힌다. (코드를 보면 close() 메소드에서 closeAll() 메소드를 먼저 호출하고 있다.) 따라서, close() 메소드만 호출하면 그와 관련된 모든 Statement와 ResultSet은 자동으로 닫히게 된다.

위 코드에서 다른 메소드들은 모두 다음과 같이 간단하게 구현된다.

    public boolean getAutoCommit() throws SQLException {
        return conn.getAutoCommit();
    }

MVConnection은 java.sql.Connection을 implements 하기 때문에, 그 자체가 Connection으로 사용될 수 있다. 따라서 MVConnection을 사용한다고 해서 특별히 코드가 많이 변경되지는 않으며 다음과 같이 전체적으로 코드가 단순하게 바뀐다.

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    
    try {
        // MV Connection 생성
        conn = new MVConnection(DBPool.getConnection());
        stmt = conn.createStatement();
        rs = stmt.executeQuery(..);
        ...
    } catch(SQLException ex) {
        // 예외 처리
    } finally {
        // conn 만 close() 해준다.
        if (conn != null) try { conn.close(); } catch(SQLException ex) {}
    }

때에 따라서는 Connection을 close() 하지 않고 커넥션 풀에 되돌려 놔야 할 때가 있다. 그런 경우에는 다음과 같은 형태의 코드를 사용하면 된다.

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    
    try {
        // MV Connection 생성
        conn = new MVConnection(DBPool.getConnection());
        stmt = conn.createStatement();
        rs = stmt.executeQuery(..);
        ...
    } catch(SQLException ex) {
        // 예외 처리
    } finally {
        if (conn != null) try { 
            ((MVConnection)conn).closeAll();
            DBPool.returnConnection(conn);
        } catch(SQLException ex) {}
    }

즉, Connection을 닫지 않는 경우에는 위와 같이 커넥션 풀에 반환하기 전에 closeAll() 메소드 하나만을 호출해주면 된다. 그러면 Connection과 관련된 모든 Statement, ResultSet 등이 닫히게 된다.

결론

필자의 경우는 이 글에서 작성한 MVConnection을 실제 프로젝트에 응용하여 코드 작성의 편리함 뿐만 아니라 실수로 인해서 발생하는 시스템의 버그 문제를 어느 정도 해결할 수 있었다. 특히, Statement를 생성하거나 ResultSet을 생성할 때 발생하는 커서부족 문제를 획기적으로 줄일 수 있었다. 여러분도 이 클래스를 응용하여 보다 나은 방법으로 코딩의 실수 및 자원의 낭비를 줄일 수 있는 클래스를 작성해보기 바란다.

반응형
반응형

1. Quick Batch File Compiler (Quick BFC)


1.png
Quick Batch File Compiler (Quick BFC) 는 BAT 파일을 EXE 파일로 변환하는 프로그램 입니다.
특히 프로그램 작업 하다 보면 BAT 파일을 자주 만지게 되는데 BAT 파일의 내용을 감추고 싶을때, 또는 lnk(바로가기) 파일에서 지원 되 지 않는 상대경로를 이용한 프로그램 실행 (Launcher) 을 만들때 유용합니다.





2. 프로그램 구하기


1359DB144B85303A18ED7A
Quick Batch File Compiler 3.2.4.0 (Portable, Registered)




18741C054B8549E55422B7
1. http://rapidshare.com 에서 미등록 사용자는 다운 받기위해 30초를 대기 하셔야 되요. ㅠ_ㅠ
 
2. 무설치 버전은 Windows7 에서 정상 동작 함을 확인 하였습니다.
3. 해당 파일은 저와는 무관한 파일 입니다. (구글링 했어요.)







3. 간단한 사용


<test.bat>

".\..\..\..\..\Program Files\7-Zip\7zFM.exe"

위 내용의 배치 파일을 만듭니다.
해당 내용은 7zFM.exe 파일을 실행하며 이때 7zFM.exe 파일을 test.bat 파일이 위치한 경로로부터 상대경로로 접근합니다.



2.png
Quick BFC 에서 해당 bat 파일을 Open 하고 Build 하는 것 만으로 원하는 exe 파일을 얻을 수 있습니다.
(어때요, 참 쉽죠잉~?)

헌데 만들어진 exe 파일을 실행시켜뜨니 이상합니다.

3.png
에레? cmd 창도 같이 떠버리네요?!!!



4.png
Option 에서 Output EXE type 을 Ghost Application 으로 변경해주고 다시 Build 합니다.
그러면 cmd 창은 뜨지 않을거에요.





4. 생성되는 exe 파일의 icon을 정하고 싶어요


5.png
Embedded Files 탭에서 Application Icon 을 선택하여 줍니다. (Icon 이미지 파일은 ico 파일만을 지원합니다.)
그러고 다시 Build를 하면 아래와 같이 exe 파일의 아이콘이 등록됩니다.

반응형
반응형
반응형
반응형




주석을 달고자 하는 PDF를 열고 [주석] 작업 버튼에서 [주석 및 마크업 도구 모음 표시]를 클릭하여 주석 도구 및 마크업 모음을 표시합니다.


【Acrobat Pro/Pro Extended의 주석 도구 모음】


PDF에 주석 메모 달기



주석을 추가할 PDF를 열고 [스티커노트] 도구를 선택합니다



주석을 추가할 위치를 클릭하면 스티커노트가 추가되고 팝업으로 표시되므로 주석을 입력합니다.



텍스트에 수정 사항을 입력 - 텍스트 편집하기



[텍스트 편집] 도구를 선택한 상태로 수정 내용에 따라 아래와 같이 조작합니다.



▶【텍스트 삽입】주석

문자와 문자 사이에 텍스트 삽입을 지시하는 주석을 추가합니다.
▶【텍스트 삭제】주석
텍스트 삭제를 지시하는 주석을 추가합니다.
▶【텍스트 바꾸기】주석
텍스트 교체를 지시하는 주석을 추가합니다.



텍스트 삽입하기


텍스트를 추가할 위치를 클릭하여 커서를 삽입

[텍스트 편집] 도구가 선택되어 있는 것을 확인하고 텍스트를 삽입할 위치에 커서를 둡니다.



그대로 텍스트를 입력하면 삽입기호가 표시되고 텍스트가 팝업 노트에 추가됩니다.



텍스트 삭제하기


삭제할 텍스트를 드래그하여 선택

[텍스트 편집] 도구가 선택되어 있는 것을 확인하고 삭제할 텍스트를 선택합니다.



그대로 BackSpace키 또는 Delete키를 누르면 대상 텍스트가 취소선으로 표시되어 삭제 대상임을 나타냅니다.



텍스트 교체하기


교체할 텍스트를 드래그하여 선택

[텍스트 편집] 도구가 선택되어 있는 것을 확인하고 교체할 텍스트를 선택합니다.



그대로 텍스트를 입력하면 텍스트가 취소선으로 표시되고 교체 텍스트가 팝업 노트에 추가됩니다.





이미지나 특정 범위에 수정 사항을 입력 - 마크업



마크업을 추가할 PDF를 열고 적당한 [주석 및 마크업] 도구를 선택합니다.
예로는 [사각형] 그리기 도구를 사용합니다.

* 일부 마크업은 Pro, Pro Extended에만 탑재됩니다


지시할 영역을 드래그

수정을 지시할 영역을 드래그합니다.
([구름] 도구 나 [다각형] 도구 등을 사용할 경우에는 정점을 클릭하여 선택해 갑니다.)



주석을 추가할 경우에는 마크업을 더블 클릭하여 팝업 노트를 표시하고 텍스트를 입력합니다.





스탬프 및 스탬프 사용하기

Acrobat에 탑재되어 있는 스탬프를 사용하여 PDF 상에 날짜와 부서명, 회사명 등이 들어간 스탬프를 찍거나, 비즈니스 스탬프 및 날인한 날짜, 사용자 이름이 자동으로 표시되는 다이내믹 스탬프 등 다양한 스탬프를 간단히 삽입할 수 있습니다.



스탬프의 사용과 설정



주석을 달 PDF를 열고 [주석] 작업 버튼에서 [스탬프 팔레트 표시] 버튼을 클릭하여 [스탬프 팔레트]를 엽니다. 버튼이 표시되지 않을 경우에는 [도구] 메뉴 > [도구 모음 사용자 정의]에서 [스탬프 도구]에 체크한 후 [확인] 버튼을 누릅니다.


* [편집] 메뉴의 [기본 설정] > [ID]에서도 수정 및 변경이 가능합니다.

처음으로 스탬프를 사용할 경우에는 사용자 정보 입력이 요구되므로 이름, 직함, 회사명 등의 필요사항을 키보드로 입력하십시오. 다음부터는 여기에서 입력한 내용이 스탬프에 반영됩니다.



[스탬프] 팔레트의 풀 다운 메뉴에서 [스탬프]를 선택합니다. 비즈니스 스탬프나 날짜ㆍ이름 등을 자동으로 삽입하는 다이내믹한 스탬프 등도 [스탬프] 팔레트에서 선택할 수 있습니다.

사용할 스탬프를 선택하고 사용위치에서 클릭합니다


출처 : http://www.acrobatpdf.com/tip/detail.asp?id=96&gotopage=7&code=
반응형
반응형


PDF 포트폴리오 작성하기 




[결합] 작업 버튼에서 [PDF 포트폴리오 조합]을 클릭합니다.





새 PDF 포트폴리오 편집화면으로 이동합니다. 파일을 PDF 포트폴리오상에 끌어놓거나 [파일 추가] 또는 [기존 폴더 추가]를 클릭하여 PDF 포트폴리오에 포함할 파일을 선택하고 [확인]을 클릭합니다.
Standard를 사용하고 있는 경우에는 [변경] 버튼을 클릭하고 [파일 추가] 또는 [기존 폴더 추가]에서 파일을 추가합니다.

* Extended에※ 만 탑재되어 있습니다.
* Standard에서는 PDF 포트폴리오의 신규작성 및 ※ 파일 추가, 삭제만 가능합니다.





PDF 포트폴리오에 파일이 추가됩니다.



PDF 포트폴리오 작성하기 
Acrobat 9 Pro 또는 Pro Extended를 사용하여 PDF 포트폴리오를 간단하게 사용자 정의할 수 있습니다.



PDF 포트폴리오가 편집모드가 아닐 경우에는 [수정] 버튼에서 [포트폴리오 편집]을 클릭합니다.





기본 레이아웃
기본 레이아웃을 선택합니다



커버 시작 및 머리말 추가 
PDF 포트폴리오를 열면 처음에 표시되는 화면을 말하며, PDF 포트폴리오의 내용을 소개하는 표지를 추가할 수 있습니다.



[PDF 포트폴리오 편집] > [시작 및 머리말 추가] > [시작페이지]에서 시작화면의 템플릿을 선택합니다. 여기에서는 [Flash 동영상]를 선택합니다.





시작 페이지 편집화면으로 바뀌면 Flash 동영상을 넣을 화면을 클릭하거나 [선택]에서 제목이 되는 Flash 동영상을 추가합니다.





시작페이지에 동영상이 추가되고 재생됩니다. 시작페이지 도구 모음에서 필요에 따라 배경색이나 불투명도 등을 사용자 정의합니다. 사용자 정의가 종료되면 [완료]를 클릭합니다.



머리말을 추가하기 
머리말을 추가하여 PDF 포트폴리오에 기업 로고나 이미지, 텍스트를 추가함으로써 통일감 있는 PDF 포트폴리오로 작성할 수 있습니다.




[PDF 포트폴리오 편집] > [시작 및 머리말 추가] > [머리말]에서 머리말의 템플릿을 선택합니다. 여기에서는 [로고 및 구조화된 텍스트]를 선택합니다.




머리말이 추가되고 편집화면으로 이동하므로 각각의 항목을 클릭하여 머리말을 사용자 정의합니다.



머리말을 추가하기 



색상 구성표 선택
PDF 포트폴리오에 사용하는 색을 변경할 수 있습니다.





파일 세부 사항 지정
PDF 포트폴리오에 포함되는 문서 파일 정보의 보이기/숨기기 설정을 변경할 수 있습니다





게시
작성한 PDF 포트폴리오의 배포방법을 선택합니다.





PDF 포트폴리오의 편집이 종료되면 [PDF 포트폴리오 편집]의 [X] 버튼을 클릭하거나 [PDF 포트폴리오] 도구 모음에서 [수정] > [포트폴리오 편집 닫기]를 클릭하여 포트폴리오의 편집을 종료합니다.


출처 : http://www.acrobatpdf.com/tip/detail.asp?id=95&gotopage=7&code=
반응형

+ Recent posts