[되새김질] 스프링 DB 1편 - 커넥션풀과 데이터소스 이해

jeyong·2023년 8월 28일
0

해당 게시물은 인프런 "스프링 DB 1편 - 데이터 접근 핵심 원리" 강의를 참고하여 작성한 글 입니다.

1. 커넥션 풀 이해

딱봐도 과정이 굉장히 복잡하다.
이런 문제를 해결하기 위한 방법이 미리 커넥션을 생성해 두고, 이를 재사용하는 것이 커넥션 풀이다. 서비스 시작 시점에 필요한 개수의 커넥션을 생성해 풀에 보관한다.

클라이언트의 요청이 들어오면 서비스 로직은 이제 커넥션 풀에서 커넥션을 객체 참조로 사용한다.
커넥션은 이미 DB서버와 연결되어 있으므로 sql 쿼리를 날리고 , 사용이 끝나면 그대로 커넥션 풀에 반환한다.
이러한 방법은 무한정 커넥션을 연결하려는 위험에서도 DB를 보호하므로 실무에서도 항상 사용된다.

2. DataSource 이해

커넥션을 획득하는 다양한 방법이 사진과 같이 존재한다.
이전 글에서의 CRUD 기능은 DriverManger를 통해 가져온 커넥션이었다.

public static Connection getConnection(){
    try {
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        return connection;
    } catch (SQLException e) {
        throw new IllegalStateException();
    }
}

커넥션 풀을 통해 가져오려면 DriverManger에 의존적인 코드를 변경해야한다.
따라서 획득 방법을 DataSource라는 인터페이스로 추상화해보자.

DataSource

DataSource 는 커넥션을 획득하는 방법을 추상화 하는 인터페이스이다.

DriverManager

void dataSourceDriverManager() throws SQLException {
    //설정 정보 입력
    DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
    useDateSource(dataSource);
}

private void useDateSource(DataSource dataSource) throws SQLException{
    Connection con1 = dataSource.getConnection();   //dataSource 만으로 호출가능
    Connection con2 = dataSource.getConnection();
}
  • DriverManagerDataSource를 사용하면 설정 시에만 정보 입력을 받고, 이후에는 설정 없이 사용이 가능하다.
  • 사용 시점에는 dataSource를 이용해서 설정 정보의 의존 없어지기 때문에, 설정과 사용을 분리할 수 있다.

HikariCP

void dataSourceConnectionPool() throws SQLException, InterruptedException {
   HikariDataSource dataSource = new HikariDataSource();
   dataSource.setJdbcUrl(URL);
   dataSource.setUsername(USERNAME);
   dataSource.setPassword(PASSWORD);
   dataSource.setMaximumPoolSize(10);  //풀 크기 지정
   dataSource.setPoolName("MyPool");   //풀 이름 지정

   useDateSource(dataSource);
   Thread.sleep(1000);
}

커넥션 풀은 초기 생성 작업에 시간이 소모되므로 별도의 쓰레드에서 생성 작업이 진행된다.

  • 로그를 확인해 보면 10개의 커넥션이 생성되고 2개는 활성화, 나머지 8개는 대기 상태임을 확인할 수 있다.
  • 10개의 생성을 모두 기다리는 것이 아니라 useDataSource()가 커넥션 생성을 대기하고 있다가, 생성이 된 커넥션을 getConnection을 통해 바로 휙득하기 때문에 효율적이다.

여기서 궁금증이 들 것이다. 2개의 커넥션을 가져가서 언제 반환하지? 반환에 대한 처리도 필요한 것이다.
근데 반환을 코드로 구현해봤었는데 매우 귀찮았었다. 이를 좀 쉽게 할 수는 없을까?
JdbcUtils 간단하게 구현해보자!

JdbcUtils

JdbcUtils을 사용하면 훨씬 간단히 커넥션을 close를 할 수 있다.

private void close(Connection con, Statement stmt, ResultSet rs){
    //예외 처리가 잘 되어 있는 메서드의 이용
    JdbcUtils.closeResultSet(rs);
    JdbcUtils.closeStatement(stmt);
    JdbcUtils.closeConnection(con);
}

커넥션 풀을 사용한다면, 실제로 커넥션의 연결이 종료되는 것이 아니라 커넥션 풀로 반환만 되도록 동작한다.

정리

이제 커넥션의 내부 로직이 DataSource를 의존하면 DI를 통해 OCP를 지킬 수 있다.

profile
천천히 잊어가기

0개의 댓글