프로필사진

Go, Vantage point

가까운 곳을 걷지 않고 서는 먼 곳을 갈 수 없다.


Github | https://github.com/overnew/

Blog | https://everenew.tistory.com/





티스토리 뷰

반응형

 

 

 

* 김영한님의 스프링 DB 1편 강좌를 수강하며 정리한 글입니다. *

 

스프링 DB 1편 - 데이터 접근 핵심 원리 - 인프런 | 강의

백엔드 개발에 필요한 DB 데이터 접근 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의

www.inflearn.com

 

 

 

이전 글에서는 JDBC 자바 표준 인터페이스에 대해 정리하였다.

 

 

 

커넥션 풀

 

저번 글에서는 커넥션 풀과 비슷한 커넥션 풀에 대해서는 간단히 다뤄 보았다.

 

 

 

클라이언트의 요청마다 서비스 로직은 커넥션을 조회한다.

DB 드라이버가 DB 서버와 커넥션(TCP/IP 연결)을 수행하고, DB 서버에 세션을 생성해 커넥션을 반환한다.

단순히 회원의 조회만 수행하는 sql문을 실행하더라도 항상 커넥션 연결의 비용과 시간이 소모된다.

 

이런 문제를 해결하기 위한 방법이 미리 커넥션을 생성해 두고, 이를 재사용하는 것이 커넥션 풀이다.

서비스 시작 시점에 필요한 개수의 커넥션을 생성해 풀에 보관한다.

 

 

IBM’s article https://www.ibm.com/developerworks/data/library/techarticle/dm-1105fivemethods/index.html

 

 

 

클라이언트의 요청이 들어오면 서비스 로직은 이제 커넥션 풀에서 커넥션을 객체 참조로 사용한다.

커넥션은 이미 DB서버와 연결되어 있으므로 sql 쿼리를 날리고 , 사용이 끝나면 그대로 커넥션 풀에 반환한다.

이러한 방법은 무한정 커넥션을 연결하려는 위험에서도 DB를 보호하므로 실무에서도 항상 사용된다.

 

대표적으로 사용하는 커넥션 풀 오픈소스는 HikariCP이고, 스프링 부트의 세팅이기도 하다.

 

 

 

커넥션 획득의 추상화 DataSource

 

커넥션을 로직에서 얻기 위해서는 DriverManager를 통해 새로 생성하거나, 커넥션 풀(도 결국에는 DriverManager를 통해 생성해둠)을 통해 가져올 수 있다.

 

이전 글에서의 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는 커넥션 획득을 추상화하는 표준 인터페이스이다.

 

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를 이용해서 설정 정보의 의존 없어지기 때문에, 설정과 사용을 분리할 수 있다.

하지만 DriverManagerDataSource는 항상 새로운 커넥션을 생성해 반환해 준다.

 

 

 

이번에는 커넥션 풀인 HikariCP를 사용해보자.

 HikariDataSource도 DataSource로 설정과 사용이 분리된다.

 

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개는 대기 상태임을 확인할 수 있다.

 

 

2개를 useDataSource()에서 사용하는데, 로그를 보면 나머지 8개가 생성되기 전에 2개는 커넥션이 활성화되어 있다.

이는 10개의 생성을 모두 기다리는 것이 아니라 useDataSource()가 커넥션 생성을 대기하고 있다가, 생성이 된 커넥션을 getConnection을 통해 바로 획득하기 때문이다.

 

만약 커넥션 풀에 커넥션이 부족하다면, block 상태로 대기하고 반환을 기다린다.

 block 시간의 설정도 OS의 스케줄링처럼, 전체 서비스 효율에 영향을 미치게 된다.

 

 

 

 

JdbcUtils

 

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

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

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

 

 

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

 

 

 

반응형
댓글
반응형
인기글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함