스프링 DB 1편 - 데이터 접근 핵심 원리 - 섹션2. 커넥션풀과 데이터소스 이해
CS/김영한 스프링 강의

스프링 DB 1편 - 데이터 접근 핵심 원리 - 섹션2. 커넥션풀과 데이터소스 이해

앞에서 해온 방식인데 DriverManager를 통해 getConnection()을 했었다. 그래서 뭔가를 할 때마다 연결하고 닫고 연결하고 닫고.. 드라이버랑 실제 DB랑 연결하는 방식은 http에서 했던 것처럼 TCP/IP 통신이라 3 way handshake같은것들도 다 한 뒤에 연결되면 id, pw 및 부가 정보를 전달하면 db에서 확인하고 검증되었으면 내부에 세션을 생성해서 완료했다는 응답 메시지를 클라이언트한테 보냈다. 이 커넥션 시간도 DB마다 다르다.

이게 원리고 정석이지만, 너무 많은 시간 및 자원 낭비가 있었다. 그래서 커넥션 풀이라고 미리 여러개 연결시켜놓은 뒤 닫지 않고 계속 써먹는거다.

 

기본적으로 10개 정도 사용한다고 하고, 서버 사용자 상황에 따라 늘리거나 줄인다. 거기다 갯수를 제한하기 때문에 DB가 무리하지 않고 안전선을 정할 수 있다는 것도 있다. 당연히 연결 시간이 줄기 때문에 이득이 커서 실무에선 항상 기본으로 쓰인다.

이 커넥션 풀을 직접 만들어 사용할 수도 있지만 미리 오픈소스로 잘 만들어 놓은걸 쓴다. 경쟁소스로 commons-dbcp2, tgomcat-jdbc pool, HikariCP등이 있었지만 HikariCP가 너무 좋아서 다 통일하고 스프링에서도 기본 기술로 채택했다. 그래서 이걸 쓸거다.

 

커넥션을 획득하는 것도 다양한 방법이 있다. 그래서 만약 DriverManager를 쓰다가 HikariCP를 사용하고 싶다고 하면 코드를 변경해야 했었다.

그래서 이걸 얻는걸 DataSource로 추상화 했다. 안의 구조가 어떻게 되어있는지는 잘 모르겠지만 어쨋든 줘~~ 하는 것. 마치 resolver와 비슷하다.

그래서 DataSource를 사용하기 위해 DBCP2 커넥션 풀, HikariCP같은 애들은 DataSource를 상속해서 만들었으므로 사용자는 그냥 DataSource의 getConnection() 함수만 무작정 사용하면 된다. 하지만 DriverManager는 옛날에 만들어졌다보니 DataSource를 상속하지 않아 쌩 DriverManager로 바꿀 때는 애플리케이션 코드를 바꿔야 한다. 그래서 스프링이 DataSource를 상속하는 DriverManager인 DriverManagerDataSource를 만들었다.

 

그럼 DriverManager 대신 DriverManagerDataSource를 사용해보자.

지금 보면 무슨 차인가 싶다. 어쨌든 커넥션은 둘 다 똑같이 하는건 알겠는데 왜 굳이 새로운 DriverManagerDataSource 객체를 만들어서 번거롭게 하느냐?

하지만 잘 보면 쌩 DriverManager는 저 클래스로만 getConnection을 하는 반면에 DriverManagerDataSource는 아까 위에서 봤던 DataSource를 상속하고 있기 때문에 useDataSource 함수 안에선 아몰라 dataSource.getConnection() 해줘 하면 해주는 거다. 즉 저기 안의 dataSource가 DriverManagerDataSource던지 HikariCP던지 몰라도 추상화되어 그냥 함수만 쓰면 가져올 수 있다는 것이다. 그래서 로그를 잘 보면 새로운 DriverManager를 알아서 가져와 만드는 걸 볼 수 있다.

또 중요한 게 저기 안에선 설정 코드와 사용 코드가 한 곳에 있기 때문에 실감이 안나지만 설정코드에 URL, USERNAME, PASSWORD를 하나 넣으면 사용하는 코드에선 몰라도 되도록 하고 사용할 수 있다는 것, 즉 설정 코드와 사용 코드를 분리할 수 있는것이 정말 큰 장점이다. 어디 수정할 때 설정 코드만 건들면 되기 때문.

 

이제 한번 HikariCP를 써보자. 깐 적이 없어도 이젠 스프링 표준이라 JDBC를 깔며 기본으로 깔린다.

뭔가 로그가 엄청 많고 마지막엔 현재 커넥션들을 출력해준다. 커넥션하는 거는 자원을 많이 잡아먹는 작업이기 때문에 메인 스레드에 피해들 덜 주려고 따로 쓰레드를 만들어서 동작하고 그 쓰레드 이름이 로그를 자세히 보면 나오는 MyPool connection adder인 것. 이상한거는 아직 커넥션 한게 없는데 2개가 사용중이라고 나온다. 이건 아까 앞에서 2개 커넥션 연결 시켜놓고 close를 안해서...

만약 한계 풀 이상으로 할당하면 어떻게 될까

10개로 제한했지만 11개 할당 받았을 때의 강의 예시인데, 다 차고 마지막 하나 할당받으려고 돌면서 기다렸다가 설정되어 있는 한계 대기 시간이 넘어가면 에러가 뜨면서 종료된다. 이런식으로 오픈소스를 쓰면 구현해야 될 기능들이 이미 다 구현되어있기 때문에 정말 안정적이고 좋다.

 

이제 내 프로젝트에 HikariCP를 적용해보자. 하는김에 JdbcUtils도 보여줄거다.

방식을 바꿔서 DataSource를 생성자로 받는 방식으로 바꿀거고, close는 아까 했던 try catch 3개 써가지고 한 대신 utils를 사용하겠다. 어차피 안의 코드 보면 작성했던 거랑 똑같다.

 

 

V0은 직접 repository 클래스 만들고 안의 내용들을 sql문을 만들어 직접 짰지만 이번엔 그냥 기본으로 해주는거 사용하고 url만 잘 연결해주겠다.

위의 로그가 DriverManagerDataResource를 썼을 때고 아래 로그가 HikariCP를 썼을 때. 위 DriverManagerDataResource는 커넥션 풀 방식이 아니라 그때그때 만드는거라 매번 커넥션을 만드는 것을 알 수 있다. 반면 HikariCP는 하나의 커넥션 가지고 꺼냈다 넣었다하며 한 개만 사용함을 알 수 있다. 물론 꺼내고 넣고 하는 과정 자체도 시간이 걸릴 순 있지만, 커넥션을 새로 만드는것 보다는 훨씬 양반이다.