Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- 튜닝
- 진경혜
- MSSQL
- 스프링
- dm_exec_requests
- 앵커멤버
- 자바
- TRANCOUNT
- 재귀멤버
- java
- getChannel()
- XACT_STATE
- 요청매핑
- SQLSTATE=42705
- 홈스쿨링
- 교육법
- git
- 함수
- 프론트컨트롤러
- transferTo
- 아이
- spring
- 요약
- 배치
- ERROR_MESSAGE
- XWPF
- SQL
- HWPF
- 디스패처서블릿
- renameTo
Archives
- Today
- Total
필기노트
김영한 스프링 강의 요약 - 커넥션풀과 데이터소스 이해 본문
반응형
1. 커넥션 풀 이해
1) 데이터베이스 커넥션을 매번 획득
커넥션을 새로 만드는 것은 과정도 복잡하고 시간도 많이 많이 소모되는 일이다.
이런 문제를 한번에 해결하는 아이디어가 바로 커넥션을 미리 생성해두고 사용하는 커넥션 풀이라는 방법이다.
2) 커넥션 풀 초기화와 연결 상태
- 애플리케이션을 시작하는 시점에 커넥션 풀은 필요한 만큼 커넥션을 미리 확보해서 풀에 보관한다. 기본값은 보통 10개이다. 실무에서는 항상 기본으로 사용한다.
- 커넥션 풀에 들어 있는 커넥션은 TCP/IP로 DB와 커넥션이 연결되어 있는 상태이기 때문에 언제든지 즉시 SQL을 DB에 전달할 수 있다.
3) 커넥션 풀 사용
- 애플리케이션 로직에서 이제는 DB 드라이버를 통해서 새로운 커넥션을 획득하는 것이 아니다.
- 이제는 커넥션 풀을 통해 이미 생성되어 있는 커넥션을 객체 참조로 그냥 가져다 쓰기만 하면 된다.
- 애플리케이션 로직은 커넥션 풀에서 받은 커넥션을 사용해서 SQL을 데이터베이스에 전달하고 그 결과를 받아서 처리한다.
- 커넥션을 모두 사용하고 나면 이제는 커넥션을 종료하는 것이 아니라, 다음에 다시 사용할 수 있도록 해당 커넥션 을 그대로 커넥션 풀에 반환하면 된다.
2. DataSource 이해
커넥션을 획득하는 방법은 앞서 학습한 JDBC DriverManager 를 직접 사용하거나, 커넥션 풀을 사용하는 방법이 존재한다. DataSource 는 커넥션을 획득하는 방법을 추상화하는 인터페이스이다.
- 대부분의 커넥션 풀은 DataSource 인터페이스를 이미 구현해두었다. 따라서 개발자는 DBCP2 커넥션 풀, HikariCP 커넥션 풀 의 코드를 직접 의존하는 것이 아니라 DataSource 인터페이스에만 의존하도록 애플리 케이션 로직을 작성하면 된다.
- 커넥션 풀 구현 기술을 변경하고 싶으면 해당 구현체로 갈아끼우기만 하면 된다.
- 성능과 사용의 편리함 측면에서 최근에는 hikariCP를 주로 사용한다.
- 이 인터페이스의 핵심 기능은 커넥션 조회 하나이다.
public interface DataSource {
Connection getConnection() throws SQLException;
}
3. DataSource 적용
@Slf4j
public class MemberRepositoryV1 {
private final DataSource dataSource;
public MemberRepositoryV1(DataSource dataSource) {
this.dataSource = dataSource;
}
//save()...
//findById()...
//update()....
//delete()....
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;
}
}
1) DataSource 의존관계 주입
- 외부에서 DataSource를 주입 받아서 사용한다. 이제 직접 만든 DBConnectionUtil을 사용하지 않 아도 된다.
- DataSource는 표준 인터페이스 이기 때문에 DriverManagerDataSource에서 HikariDataSource로 변경되어도 해당 코드를 변경하지 않아도 된다.
2) JdbcUtils 편의 메서드
- 스프링은 JDBC를 편리하게 다룰 수 있는 JdbcUtils라는 편의 메서드를 제공한다.
- JdbcUtils을 사용하면 커넥션을 좀 더 편리하게 닫을 수 있다.
4. DataSource 테스트
@Slf4j
class MemberRepositoryV1Test {
MemberRepositoryV1 repository;
@BeforeEach
void beforeEach() throws Exception {
//기본 DriverManager - 항상 새로운 커넥션 획득
//DriverManagerDataSource dataSource =
// new DriverManagerDataSource(URL, USERNAME, PASSWORD);
//커넥션 풀링: HikariProxyConnection -> JdbcConnection
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
repository = new MemberRepositoryV1(dataSource);
}
@Test
void crud() throws SQLException, InterruptedException {
log.info("start");
//save
Member member = new Member("memberV0", 10000);
repository.save(member);
//findById
Member memberById = repository.findById(member.getMemberId());
assertThat(memberById).isNotNull();
//update: money: 10000 -> 20000
repository.update(member.getMemberId(), 20000);
Member updatedMember = repository.findById(member.getMemberId());
assertThat(updatedMember.getMoney()).isEqualTo(20000);
//delete
repository.delete(member.getMemberId());
assertThatThrownBy(() -> repository.findById(member.getMemberId()))
.isInstanceOf(NoSuchElementException.class);
}
}
- MemberRepositoryV1은 DataSource 의존관계 주입이 필요하다.
get connection=HikariProxyConnection@xxxxxxxx1 wrapping conn0: url=jdbc:h2:...user=SA
get connection=HikariProxyConnection@xxxxxxxx2 wrapping conn0: url=jdbc:h2:...user=SA
get connection=HikariProxyConnection@xxxxxxxx3 wrapping conn0: url=jdbc:h2:...user=SA
get connection=HikariProxyConnection@xxxxxxxx4 wrapping conn0: url=jdbc:h2:...user=SA
get connection=HikariProxyConnection@xxxxxxxx5 wrapping conn0: url=jdbc:h2:...user=SA
get connection=HikariProxyConnection@xxxxxxxx6 wrapping conn0: url=jdbc:h2:...user=SA
- 커넥션 풀 사용시 conn0 커넥션이 재사용 된 것을 확인할 수 있다.
- 테스트는 순서대로 실행되기 때문에 커넥션을 사용하고 다시 돌려주는 것을 반복한다. 따라서 conn0만 사용된다.
- 웹 애플리케이션에 동시에 여러 요청이 들어오면 여러 쓰레드에서 커넥션 풀의 커넥션을 다양하게 가져가는 상황 을 확인할 수 있다.
반응형
'김영한 강의 요약' 카테고리의 다른 글
김영한 스프링 강의 요약 - @Transactional 이해 (0) | 2024.02.13 |
---|---|
김영한 스프링 강의 요약 - 트랜잭션 이해 (0) | 2024.01.31 |
김영한 스프링 강의 요약 - JDBC 이해 (1) | 2024.01.23 |
김영한 스프링 강의 요약 - API 예외 처리 (0) | 2024.01.10 |
김영한 스프링 강의 요약 - 예외 처리와 오류 페이지 (0) | 2023.12.28 |
Comments