연결을 미리 만들어두고 빌려 쓴다
JDBC는 DB와 연결해야 SQL을 실행할 수 있다.
그래서 Connection이 필요하다.
그런데 문제가 있다.
Connection 생성은 생각보다 비용이 큰 작업이다
요청이 들어올 때마다 매번 새 연결을 만들면
- 느려지고
- DB 연결 수가 급격히 늘고
- 결국 서버가 버티기 힘들어진다
그래서 실무에서는 거의 무조건 Connection Pool을 쓴다.
Connection을 새로 만드는 게 왜 비싼가
Connection을 만든다는 건 단순히 객체 하나 만드는 게 아니다.
- DB와 네트워크(TCP) 연결을 맺는다
- 인증/권한 확인 같은 협상이 들어간다
- 네트워크 왕복이 발생한다
즉, 요청마다 이 과정을 반복하면 성능이 크게 떨어진다.
Connection Pool의 아이디어는 단순하다
해결책은 미리 만들어두는 것이다.
- 서버가 시작할 때 Connection을 여러 개 만들어둔다
- 요청이 오면 그 중 하나를 “빌려준다”
- 사용이 끝나면 “반납받는다”
이게 Connection Pool이다.
즉 풀은 “Connection 재사용 시스템”이다.
// ================================
// [DataSource 사용 예시] (풀에서 Connection을 빌려온다)
// - getConnection()을 호출하면 "새로 연결"이 아니라 "풀에서 꺼내온 Connection"일 수 있다
// - close()는 실제 종료가 아니라 "풀에 반납"이 된다
// ================================
public class TodoDAO {
private final DataSource dataSource;
public TodoDAO(DataSource dataSource) {
this.dataSource = dataSource;
}
public List<TodoVO> findAll() throws SQLException {
String sql = "select tno, title, finished from tbl_todo order by tno desc";
try (Connection conn = dataSource.getConnection(); // 풀에서 빌림
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
List<TodoVO> list = new ArrayList<>();
while (rs.next()) {
list.add(new TodoVO(
rs.getLong("tno"),
rs.getString("title"),
rs.getBoolean("finished")
));
}
return list;
}
// conn.close()는 try-with-resources에 의해 호출되지만,
// "진짜 종료"가 아니라 보통 풀에 "반납"하는 의미가 된다.
}
}
DataSource는 “풀을 쓰기 위한 표준 인터페이스”이다
자바에서는 Connection Pool을 통일된 방식으로 쓰기 위해
javax.sql.DataSource라는 인터페이스를 제공한다.
DataSource 관점에서 개발자는 딱 한 줄만 중요하다.
- dataSource.getConnection()
이 호출이 “새 연결 생성”일 수도 있고,
대부분은 “풀에서 빌려오기”이다.
즉 DataSource는 개발자에게
- “Connection을 얻는 표준 창구”
를 제공한다.
풀을 쓰면 close()의 의미가 달라진다
여기서 가장 중요한 오해 포인트가 있다.
풀을 쓰는 상황에서 conn.close()는 보통
- DB 연결을 진짜 끊는다
가 아니라
- 풀에 Connection을 반납한다
의 의미가 된다.
즉 close는 “반납”이다.
그래서 풀을 쓰더라도 close는 반드시 해야 한다.
close를 안 하면 풀에 반납이 안 되고 연결이 고갈된다.
HikariCP는 대표적인 Connection Pool 구현체이다
Connection Pool은 구현체가 필요하다.
그 구현체 중에서 가장 널리 쓰이는 게 HikariCP이다.
HikariCP의 구조는 보통 이렇게 잡는다.
- HikariConfig로 설정을 만든다
- HikariDataSource를 만든다
- 이 DataSource를 DAO에 주입해서 사용한다
즉 HikariDataSource는 DataSource 구현체이다.
// ================================
// [HikariCP 설정 예시] (가장 많이 쓰는 커넥션 풀 구현체 중 하나)
// - HikariConfig -> HikariDataSource
// - HikariDataSource는 DataSource 구현체이다
// ================================
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mariadb://localhost:3306/app");
config.setUsername("root");
config.setPassword("1234");
// 풀 크기 같은 옵션
config.setMaximumPoolSize(10);
config.setMinimumIdle(2);
DataSource ds = new HikariDataSource(config);
전체 흐름
- DAO는 DataSource를 가진다
- DAO는 필요할 때 getConnection()으로 Connection을 얻는다(빌림)
- try-with-resources로 작업이 끝나면 close된다(반납)
- 풀은 Connection을 재사용해서 성능을 올린다
핵심 정리
- Connection 생성은 비싸서 요청마다 새로 만들면 느리다
- Connection Pool은 연결을 미리 만들어두고 빌려 쓰는 방식이다
- DataSource는 풀을 쓰기 위한 표준 인터페이스이다
- 풀 환경에서 close()는 보통 “종료”가 아니라 “반납”이다
- HikariCP는 대표적인 커넥션 풀 구현체이다
'Web > Web Basics' 카테고리의 다른 글
| [상태 유지와 공통 처리] 5. MyBatis 설정 흐름 (0) | 2026.03.30 |
|---|---|
| [상태 유지와 공통 처리] 4. MyBatis는 무엇을 해결하는가 (0) | 2026.03.30 |
| [상태 유지와 공통 처리] 2. JDBC란? (0) | 2026.03.30 |
| [데이터 처리와 DB연동] 1. DTO / VO(Entity) / DAO / Service는 왜 나누는가? (0) | 2026.03.30 |
| [상태 유지와 공통 처리] 5. 리스너(Listener)란? (0) | 2026.03.30 |