JDBC 프로그래밍의 단점을 보완하는 스프링
JDBC API를 이용하면 DB 연동에 필요한 Connection을 구한 다음 쿼리를 실행하기 위한 PreparedStatement를 생성한다. 그리고 쿼리를 실행한 뒤에는 finally 블록에서 ResultSet, PreparedStatement, Connection을 닫는다.
Member member;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DriverManager.getConnection("~~");
// 핵심코드는 여기서부터
pstmt = conn.prepareStatement("query ~~");
pstmt.setString(1, param~~);
..생략..
// 여기까지 (생략했지만)
} catch(SQLException e) {
e.printstackTrace();
throw e;
} finally {
if(rs != null) {
}
..생략..
}
여기서 문제는 핵심코드를 제외한 코드는 사실상 데이터 처리와는 상관없는 코드지만 JDBC 프로그래밍을 할 때 구조즉으로 반복된다.
구조적인 반복을 줄이기 위한 방법은 템플릿 메서드 패턴과 전략 패턴을 함께 사용하는 것이다. 스프링은 바로 이 두 패턴을 엮은 JdbcTemplate 클래스를 제공한다.
템플릿 메서드 패턴 : 어떤 작업을 처리하는 일부분을 서브클래스로 캡슐화해,
전체 일을 수행하는 구조는 바뀌지 않으면서 특정 단계에서 수행하는 내역을 변경함
ex.
전략 패턴 : 객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화하는 인터페이스를 정의하여
객체의 행위를 동적으로 바꾸고 싶은 경우 행위의 수정 없이 전략만 바꿔 유연하게 확장함
ex.
DB 연동
실습을 위해 gradle 파일에 필요 기능을 임포트한다.
// JdbcTemplate 등 JDBC 연동에 필요한 기능을 제공한다
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
// DB 커넥션풀 기능을 제공한다
implementation group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: '8.5.32'
// MySQL 연결에 필요한 JDBC 드라이버를 제공한다
implementation 'mysql:mysql-connector-java'
DataSource 설정
DataSource 란 DB와 관계된 커넥션 정보를 담고 있으며 빈으로 등록하여 인자를 넘겨준다. 이 과정에서 spring은 DataSource로 DB와의 연결을 획득한다.
스프링이 제공하는 DB 연동 기능은 DataSource를 사용해서 DB Connection을 구한다. DB 연동에 사용할 DataSource를 스프링 빈으로 등록하고 DB 연동 기능을 구현한 빈 객체는 DataSource를 주입받아 사용한다.
Tomcat JDBC 모듈은 javax.sql.DataSource를 구현한 DataSource 클래스를 제공한다.
package config;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import spring.MemberDao;
@Configuration
public class AppCtx {
// close 메서드는 커넥션 풀에 보관된 Connection을 닫음
@Bean(destroyMethod = "close")
public DataSource dataSource() {
// 1.DataSource 객체 생성
DataSource ds = new DataSource();
// 2.JDBC 드라이버 클래스 지정(mysql 사용)
ds.setDriverClassName("com.mysql.jdbc.Driver");
// 3.JDBC URL 지정, 데이터베이스와 테이블 캐릭터 셋을 UTF-8로 설정했으므로 파라미터를 이용해 연결 시 사용할 캐릭터셋 지정
ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
// 4.DB 연결 시 사용할 계정과 암호 지정
ds.setUsername("spring5");
ds.setPassword("spring5");
// 5.커넥션 풀을 초기화할 때 생성할 초기 커넥션 개수 지정(기본값은 10)
ds.setInitialSize(2);
// 6.커넥션 풀에서 가져올 수 있는 최대 커넥션 개수 지정(기본값은 100)
ds.setMaxActive(10);
return ds;
}
@Bean
public MemberDao memberDao() {
return new MemberDao(dataSource());
}
}
Tomcat JDBC의 주요 프로퍼티
커넥션 풀은 커넥션을 생성하고 유지한다. 커넥션 풀에 커넥션을 요청하면 해당 커넥션은 활성(active) 상태가 되고, 커넥션을 다시 커넥션 풀에 반환하면 유휴(idle) 상태가 된다.
🙋♀️ 커넥션 풀이 뭔가요?
💡 커넥션 풀은 일정 개수의 DB 커넥션을 미리 만들어두는 기법이다.
최초 연결에 따른 응답 속도 저하와 동시 접속자가 많을 때 발생하는 부하를 줄이기 위해 사용하는 것이다.