## 51. DB 커넥션 풀을 이용한 Connection 재사용하기
- 여러 스레드에서 DB 커넥션 객체를 공유할 때의 문제점 이해
- ThreadLocal을 이용하여 스레드 전용 변수를 만드는 방법
- 풀링 기법을 이용하여 커넥션 재사용하는 방법
여러 스레드에서 DB 커넥션 객체를 공유할 때의 문제점 이해
ㄴ 필요 없는 클래스 제거하여 정리
ㄴ DataSource 라는 이름의 클래스 파일을 생성
DataSource.java
ㄴ DB 커넥션을 관리하고 제공하며, 스레드 별로 DB 커넥션을 보관하도록하는 DataSource.java 클래스 파일 작성
=>
DataSource.java
ㄴ 생성자 추가
ThreadLocal을 이용하여 스레드 전용 변수를 만드는 방법
DataSource.java
ㄴ ThreadLocal 을 이용하여 스레드 별로 Connection 보관할 저장소 준비
=>
DataSource.java
ㄴ 현재 스레드의 Connection 보관소에서 Connection 객체를 꺼내도록 함
=>
ㄴ ConnectionBox를 통해 현재 스레드 보관소에 저장된 Connection 객체를 꺼내도록 함
DataSource.java
ㄴ 만약 현재 스레드에 Connection 객체가 보관되어 있지 않다면 새로 생성하도록 함
ㄴ JDBC(Java Database Connectivity) 드라이버를 사용하여 데이터베이스에 연결하는 데 사용
DataSource.java
ㄴ connectionBox를 통해 새로 생성한 Connection 객체를 현재 스레드에 보관하도록 함
DataSource.java
ㄴ 보관되어 있는 Connection 객체든 새로 생성한 Connection 객체든 리턴하도록 함
DataSource.java
ㄴ 스레드가 작업을 끝냈으면, 이 스레드에 보관된 Connection 객체를 remove 메서드를 이용하여 제거하도록 함
=>
DataSource.java
ㄴ connectionBox 에 들어있는 Connection 가 null 이 아니라면 해당 Connection 을 close 한 후 제거하도록 함
ServerApp.java
ㄴ AutoCommit 이 true 가 디폴트 값이므로 false 로 변경해주기
BoardAddListener.java
ㄴ insert 를 3번 하도록 테스트 해보기
ㄴ 목록에서 3개가 등록된 것으로 조회됨
=>
ㄴ 실제 데이터베이스에 추가되지 않음
BoardAddListener.java
ㄴ 등록 한 것을 commit 까지 하도록 함
ServerApp.java
ㄴ BoardAddListener 클래스에서 생성자에 Connection 도 받기로 변경했으므로 con 추가
=>
ㄴ 목록에서 3개가 등록된 것으로 조회됨
=>
ㄴ 실제 데이터베이스에도 반영됨을 확인할 수 있음
BoardAddListener.java
ㄴ 각각 5초동안 잠들도록 해줌
BoardAddListener.java
ㄴ 잠든 시간 사이에 다른 클라이언트가 접속해서 rollback 할 경우를 테스트할 것임
=>
ㄴ 직원1이 글을 등록하는 도중에 직원2가 글을 등록하면서 rollback 을 해서 직원1이 등록하던 글도 rollback 되는 현상이 발생함
DataSource.java
ㄴ 어떤 커넥션이 생성되는지 출력해서 확인하기 위함
DataSource.java
ㄴ 제거되는 커넥션 이름을 출력하여 확인하기 위함
MySQLBoardDao.java
ㄴ MySQLBoardDao 에서 Connection 대신 미리 만들어둔 DataSource 를 사용하기 위해 필드에 선언
MySQLBoardDao.java
ㄴ Connection -> DataSource 로 변경해주기
MySQLBoardDao.java
ㄴ con -> ds.getConnection() 으로 변경
=>
Member , item 도 Board 와 동일하게 설정해주기
=>
MySQLMemberDao.java
=>
ㄴ con -> ds.getConnection() 으로 변경
ServerApp.java
ㄴ DataSource 를 사용하기 위해 선언 및 import
ServerApp.java
=>
ServerApp.java
ㄴ 해당 코드 잘라내기
=>
DataSource.java
ㄴ AutoCommit 은 디폴트 값이 true 이므로 false 로 변경해주기
DataSource.java
ㄴ autoCommit 이 true 라면 con에 대해 autoCommit 을 true 로 설정하여 커넥션을 리턴하고 그 반대는 false 로 설정하여 커넥션을 리턴함
DataSource.java
ㄴ 자동 커밋을 true 로 했기 때문에 모든 쿼리가 즉시 커밋되게 됨
ServerApp.java
ㄴ con -> ds 로 변경해주기
ServerApp.java
ㄴ 해당 코드 삭제
ServerApp.java
ㄴ BoardAddListener 클래스의 생성자에 ds 를 넘겨주도록 설정
BoardAddListener.java
ㄴ 생성자에도 DataSource 적용
BoardAddListener.java
ㄴ con -> ds.getConnection() 으로 변경
DataSource.java
ㄴ 스레드에 보관된 커넥션을 사용한다면 해당 문구 출력하도록 함
=>
=>
ㄴ 로그인 할 때 커넥션이 생성되고, 해당 커넥션이 스레드에 보관됨
ㄴ 리스트를 조회할 때 스레드에 보관된 커넥션 사용
=>
ㄴ 새로운 클라이언트가 접속할 경우 새로운 스레드와 새로운 커넥션이 생성됨
=>
MySQLBoardDao.java
ㄴ 자동커밋을 false 로 설정하기
MySQLBoardDao.java
ㄴ finally 를 이용해 DataSource 를 clean 해주도록 함 (스레드가 작업을 끝냈으면, 이 스레드에 보관된 Connection 객체를 제거)
풀링 기법을 이용하여 커넥션 재사용하는 방법
DataSource.java
ㄴ 커넥션 목록을 유지하기 위한 객체
DataSource.java
ㄴ 커넥션 풀에 사용할 수 있는 객체가 있다면, 꺼내도록 함
=> remove(0) : 가장 오래된 연결을 가져와서 제거한 후 해당 값 리턴
DataSource.java
ㄴ 새 커넥션이 생성될 경우 해당 문구를 출력하도록 함
DataSource.java
DataSource.java
ㄴ 스레드가 사용한 DB 커넥션을 다른 스레드에서 사용할 수 있도록 커넥션 풀에 저장함
=> 커넥션 재사용을 위함
=> 스레드에서는 제거하되 사용했던 커넥션을 재사용 하기 위해 커넥션 풀에 저장하는 것
DataSource.java
ㄴ 커넥션 풀에 DB 커넥션을 저장하는지 눈으로 확인하기 위해 해당 문구를 출력하도록 함
=>
DataSource.java
DataSource.java
ServerApp.java
ㄴ DB 커넥션 재활용 테스트를 하기 위해 스레드 2개로 제한
ㄴ 클라이언트 2명이 접속했으므로 더이상 쓸 수 있는 스레드가 없어서 3번째 클라이언트는 대기
=>
=>
ㄴ 2번째 클라이언트 나감
=>
ㄴ 2번째 클라이언트가 나간 후 3번째 클라이언트가 접속 가능
=>
ㄴ 세 커넥션을 생성하지 않고 2번째 클라이언트가 썼던 2번 스레드를 새롭게 재사용하는 것을 알 수 있음