DB

JDBC 사용 시 자원 반환에 정리

프로호구래머 2020. 8. 12. 13:45

오늘은 JSP/Servlet에서 JDBC를 이용하여 DB와 연동하는 부분의 공부를 했다.

그러다 문득 JDBC를 사용하는 부분을 try~catch문으로 감싸서 사용하고 finally부분에서 사용이 끝난 JDBC의 자원을 반환하게 되는데, 자원의 반환을 하는 부분에서 의문이 생겨서 좀 더 깊게 공부하게 되었고 거기서 배운 내용을 조금이나마 정리해 보려고 한다.

 

우선, 내가 지금 공부하고 있는 JSP책에서의 해당 코드는 이렇다.

 

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) {}
}

 

결론부터 말하자면 이 코드가 자원 반환에 관해서는 100점 만점의 코드이다.

(아직은 부족하겠지만 이 부분을 공부하면서 느낀 나의 주관적인 점수는 그렇다..)

 

우선 이 부분을 공부하다가 문뜩 try~catch문을 하나로 통합해서 코드를 작성했다면 try~catch문을 3번이나 작성할 필요가 있었을까 하는 의문에서부터 시작되었다. 왜냐면 직접 교재를 보며 타이핑하던 도중 반복된 일을 하는 것을 싫어하는 작자로서 2번이나 try~catch문을 더 작성하는 것은 비효율적으로 생각했기 때문이다. 

 

finally {
    try {
    	if(rs != null) rs.close();
        if(stmt != null) stmt.close(); 
        if(conn != null) conn.close();
    } catch(SQLException ex) {}
}

 

어떤가? 좀 전의 코드와 외적으로 봤을 때는 좀더 눈에 잘 들어오고 이쁘기 까지하다.

하지만, 그러한 생각은 잘못된 생각이었다. 만약 저 3개의 자원에 대한 반환을 하나의 try~catch문에 작성하게 되었다고 하자. 만약 rs.close()에서 예외가 발생한다면 나머지 뒤에 stmt.close()나 conn.close()는 실행되지 못한채 finally문은 종료될 것이다. 그러면 stmt와 conn은 반환되지 못하고 계속 메모리를 잡아먹고 있을 것이다. 그렇게 계속해서 자원이 반환되지 못하고 쌓이게 되면 결국 프로그램은 멈추고 말 것이다.

 

또한 반환에는 순서가 존재한다.

rs -> stmt -> conn (선언의 역순)

 

만약 Connection 객체를 먼저 반환하게되면 Connection 객체는 DB와의 connection을 close하는게 아니라 connection pool에 자원을 반환하는 것이기에 Statement 객체의 close까지 장담을 할 수 없다. conn.close를 하게되면 stmt도 자동으로 반환되는 경우도 있지만. 이는 각 벤더별 드라이버의 구현이나 WAS의 Connection Pool의 구현 등에 따라 다르게 동작할 수 있기 때문에 항상 명시적으로 자원들을 해제 해주는 것이 올바른 코딩 자세일 것이다. 

 

마지막으로 DB에 query를 하기위해서는 Statement나 PreparedStatement 객체를 선언하게 되는데, 객체를 하나만 선언해두고 해당 변수로만 query의 내용을 여러번 변경해서 사용하게 되면 이 또한 문제를 야기할 수 있다. 기존에 할당된 Statement를 반환하지 않고 다른 Statement를 할당하게되면 기존의 Statement의 reference를 잃게 되는데 이를 GC(Garbage Collection)이 reference를 잃은 Statement에 대해서 반환을 해주면 좋겠지만 이러한 상황은 GC의 관할이 아니라서(해당 부분은 좀더 공부를 해봐야 할듯) 해당 Statement는 영원히 close()되지 못하고 메모리 상에 남게된다. 그래서 Statement를 새로 할당하기 전에는 반드시 close를 해주거나 Statement 변수를 할당 할 만큼 선언해주는 것이 이를 예방하는 방법이 되겠다.

 

이상 JDBC 자원의 반환에 관한 문제를 정리해 보았는데, 관련된 고려사항이 이것 뿐만 아니라 다른 경우도 상당히 많은 것으로 보였다. 그 중에서 내가 직접 겪었던 문제와 관련해서만 포스팅을 우선 해두었고, 조금 더 자세한 설명과 많은 상황을 공부하고 싶다면 아래 출처에 남겨둔 사이트에서 직접 살펴 보면 좋을 것 같다.

 


출처

https://blog.benelog.net/1898928.html

 

JDBC에서 Connection, Statement,ResultSet의 close - 개발수양록

이미 많이 알려진 내용이지만, 아직도 문제를 많이 일으키는 주제입니다. 그래서 보다 이 주제를 검색엔진에서 쉽게 찾을 수 있었으면 하는 마음에서 이 글을 정리해봤습니다. Connection conn = null;

blog.benelog.net

https://winmargo.tistory.com/46?category=428145

 

서블렛 + JDBC 연동시 코딩 고려사항 -제1탄- (장문 풀버전)

제목 : 서블렛 + JDBC 연동시 코딩 고려사항 -제1탄- 글쓴이: 이원영(javaservice) 2000/09/06 05:19:47 조회수:104610 줄수:1544 최초작성일자: 2000/09/05 16:19:47 최근 수정일 : 2001.01.27 최근 수정일 : 200..

winmargo.tistory.com