ConnectionPool / DataSource

NNIIE·2022년 9월 9일
0

java

목록 보기
7/7
post-custom-banner

커넥션 획득

데이터베이스 커넥션을 획득할 때는 다음과 같은 과정을 거치게 된다.

  • 애플리케이션 로직은 DB Driver를 통해 커넥션을 조회한다.
  • DB Driver는 데이터베이스와 TCP/IP커넥션을 연결하는데, 이 과정에서 3 way handshake같은 네트워크 동작이 발생하게 된다. -> 많은 리소스가 들게 된다.
  • DB Driver는 TCP/IP커넥션이 연결되면, ID / PW 같은 정보를 데이터베이스에 전달한다.
  • 데이터베이스는 부가정보를 통해 내부 인증을 완료하고, 내부에 세션을 생성한다.
  • 데이터베이스가 커넥션 생성이 완료되었다는 응답을 보낸다.
  • DB Driver는 커넥션 객체를 생성해서 클라이언트에 반환한다.

    커넥션을 새로 만드는 과정은 복잡하고 시간도 많이 소모된다.
    데이터베이스 뿐만 아니라 애플리케이션 서버에서도
    TCP/IP커넥션을 생성하기위한 리소스를 매번 사용하게 되고
    그 결과 좋지 않은 유저경험을 주게 된다.

커넥션 풀

위와 같은 문제를 해결하기 위해 커넥션을 미리 생성해두고 재사용 하는 Connection Pool 이라는 방법이다.

애플리케이션이 시작하는 시점에서 미리 필요한 만큼의 커넥션을 미리 확보해서 풀에 보관한다.
서버 스펙에 따라 다르겠지만 기본값은 보통 10개이다.

커넥션 풀에 들어있는 커넥션 들은 애플리케이션 실행 시점에 이미 데이터베이스와 TCP/IP연결이 완료된 상태이기 때문에 언제든지 TCP/IP연결 과정을 생략하고 데이터베이스와 통신할 수 있다.

  • 커넥션 풀을 통해 이미 생성되어 있는 커넥션을 객체 참조로 가져다 쓰면 된다.
  • 커넥션 풀은 요청이 오면 가지고 있는 커넥션 중 하나를 반환한다.
  • 애플리케이션은 로직을 통해 커넥션 풀에서 받은 커넥션을 사용하고 커넥션 풀에 다시 반환한다.
    (커넥션을 종료하는 것이 아닌 살아있는 상태로 커넥션 풀에 반환)
  • 적절한 커넥션 풀 숫자는 서비스 특징과 서버스펙에 따라 다르기 때문에 성능테스트를 통해 정한다.
  • 커넥션 풀은 서버당 최대 커넥션 수를 제한할 수 있기 때문에 커넥션이 무한정 생성되는 것을 막을 수 있다.
  • 스프링의 대표적인 커넥션 풀 오픈소스로는 HikariCP가 있다.

DataSource

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

public interface DataSource {
	Connection getConnection() throws SQLException;
}
  • 대부분의 커넥션 풀은 DataSource 인터페이스를 이미 구현해 뒀기 때문에
    우리는 HikariCP 커넥션 풀에게 의존 하는것이 아닌 DataSource인터페이스 에게만 의존하면 된다.
  • 스프링의 핵심 개념 DI + OCP를 지킬수 있게 된다.

DirverManager 사용

public void dataSourceDriverManager() throws SQLException {
	DriverManagerDataSource dataSource = new DriverManagerDataSource(URL,USERNAME, PASSWORD);
    useDataSource(dataSource);
}

private void useDataSource(DataSource dataSource) throws SQLException {
	Connection con1 = dataSource.getConnection();
 	log.info("connection={}, class={}", con, con.getClass());
}

커넥션 풀 사용

void dataSourceConnectionPool() throws SQLException, InterruptedException {
 	HikariDataSource dataSource = new HikariDataSource();
 	dataSource.setJdbcUrl(URL);
 	dataSource.setUsername(USERNAME);
 	dataSource.setPassword(PASSWORD);
 	dataSource.setMaximumPoolSize(10);
 	dataSource.setPoolName("MyPool");
 	useDataSource(dataSource);
}

설정과 사용의 분리

  • 설정 : DataSource 를 만들고 필요한 속성들을 사용해서
    URL , USERNAME , PASSWORD 같은 부분을 입력하는 것을 말한다.
    이렇게 설정과 관련된 속성들은 한 곳에 있는 것이 향후 변경에 더 유연하게 대처할 수 있다.
  • 사용 : 설정은 신경쓰지 않고, DataSource 의 getConnection() 만 호출해서 사용하면 된다.

DataSource 적용

public class MemberRepository {
	private final DataSource dataSource;
    
 	public MemberRepositoryV1(DataSource dataSource) {
 		this.dataSource = dataSource;
	}
    
    private void close(Connection con, Statement stmt, ResultSet rs) {
 		JdbcUtils.closeResultSet(rs);
 		JdbcUtils.closeStatement(stmt);
 		JdbcUtils.closeConnection(con);
 	}
    
 	private Connection getConnection() throws SQLException {
 		Connection con = dataSource.getConnection();
 		log.info("get connection={}, class={}", con, con.getClass());
 		return con;
 	}
  • DataSource 의존관계 주입
    • 외부에서 DataSource 를 주입 받아서 사용한다. 이제 직접 만든 DBConnectionUtil 을 사용하지
      않아도 된다.
    • DataSource 는 표준 인터페이스 이기 때문에 DriverManagerDataSource 에서
      HikariDataSource 로 변경되어도 해당 코드를 변경하지 않아도 된다.
  • JdbcUtils 편의 메서드
    • 스프링은 JDBC를 편리하게 다룰 수 있는 JdbcUtils 라는 편의 메서드를 제공한다.
    • JdbcUtils 을 사용하면 커넥션을 좀 더 편리하게 닫을 수 있다.
post-custom-banner

0개의 댓글