[데이터베이스] 커넥션 풀(connection pool)이란?
[데이터베이스] 커넥션 풀(connection pool)이란? — #데이터베이스 #커넥션풀 #데이터베이스커넥션풀 #connectionpool #개발자의도구들 🚨📝 📖 📒 A...
#데이터베이스 #커넥션풀 #데이터베이스커넥션풀 #connectionpool #개발자의도구들
🚨📝 📖 📒
AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니다
\* 현재 Spring 프로젝트를 진행 중입니다. 전체적인 목차를 보시려면 여기를 눌러주세요.
커넥션 풀이 필요한 이유
Database connection pool
이전글에서 MVC 패턴을 구현하며, Model Layer를 구현했었늗네요, 스프링 사용전이라, 직접 JDBC를 통해 제가 만든 서버와 DB를 연결하였습니다.
당시 코드입니다.
package com.example.webserver;import jakarta.annotation.PostConstruct;import lombok.Getter;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Repository;import java.sql.\*;import java.util.HashMap;@Getter@Repository@Slf4jpublic class DataBaseModel { private Connection connection; private final Object dataBaseLock = new Object(); private final String url = "jdbc:mariadb://localhost:3306/http"; private final String user = "root"; private final String password = "3353"; @PostConstruct public void startConnection() { log.info("start connection!!"); try { this.connection = DriverManager.getConnection(url, user, password); log.info("connecting success"); } catch (SQLException e) { log.error("<<DataBaseManger>>\n - sql err: " + e.getMessage() + "\n"); } } public boolean putText(String key, String value) { String sql = "INSERT INTO texts (text\_id, text\_value) VALUES (?, ?)"; try { PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, key); preparedStatement.setString(2, value); int effectedRows = preparedStatement.executeUpdate(); preparedStatement.close(); if (effectedRows > 0) { log.info("A new row has been inserted successfully."); return true; } else { log.error("A new row insertion failed"); return false; } } catch (SQLException e) { log.error("DataBase Manger: putText err: " + e.getMessage()); return false; } } --- 생략 ---} |
|---|
뭐 일단 크게 문제되는건 없어보이지만... 사실 이 방법은 현실과는 전혀 맞지 않는 코드임을 깨닫게 되었습니다. 이유는 DB connection을 객체내 전역으로 선언하여 하나의 커넥션으로 모든 로직을 처리하고 있다는 것입니다. (현재 putText에서만 사용되는 것처럼 보이나, 모든 DB로직에서 처음 생성된 하나의 커넥션을 불러와 사용하고 있습니다.)
무엇이 문제인가?
당연하게도 DB서버가 멀티 쓰레드에 대해 처리를 알아서 해주겠지라고 생각했었습니다. 하지만, 하나의 connection을 모든 로직에서 사용하려고 한다면, 여러개의 쿼리를 동시에 날릴 수 없게 됩니다.
해결 방법
그럼 모든 로직에 대해 로직이 발생할 때마다, connection을 새로만들어서 처리하게끔 할 수 있습니다. 하지만 여기에는 큰 문제가 있는데 connection 작업은 생각보다 큰 작업이라, 멀티 쓰레드 환경에서는 큰 overhead가 발생할 수 있다는 것입니다.
그래서 한번 connection은 재사용하는 편이 좋은데, 재사용 한다면 다시금 이전과 같은 문제에 직면하게 될 것 입니다.
이를 해결하기 위해 데이터 베이스 커넥션 풀에 대해 공부하였습니다.
커넥션 풀이란?
데이터 베이스 커넥션 풀은 캐시의 일종인데, 한번 연결된 데이터 베이스 커넥션을 캐시로 저장하여 필요할 때마다 재사용하게끔 하는 개념입니다.
https://medium.com/@sujoy.swe/database-connection-pool-647843dd250b
위 사진을 보면 단번에 이해가 가시리라 생각되네요.
작동원리
Initialization
어플리케이션이 시작할 때 커넥션 풀이 만들어지며, 고정된 데이터 베이스 커넥션들이 풀에 추가됩니다.
Connection Request
어플리케이션에서 DB작업이 생길 때마다, pool에 커넥션을 request하여 받을 수 있씁니다.
Usage
어플리케이션은 connection을 대여하고, DB로직을 수행합니다.
Return
로직이 모두 완료되면, connection을 완전 닫아버리는 것이 아닌, pool로 다시 반납합니다.
Reuse
다음번에 또 다시 connection이 필요하면 어플리케이션은 pool에서 connection을 받아 사용할 수 있습니다.
장점
- Improved Perfromance
Connection을 여닫는 작업을 줄여주어 overhead를 감소시켜, 전체적인 성능 향상을 기대할 수 있습니다.
- Resource Efficiency
DB Connection 자원은 커넥션 풀은 커넥션들을 효율적으로 그 수를 제한하며,
- Connection Reuse
- Connection Mangement
- Concurrency Contol
-
적용
JDBC Hikari CP를 사용하여 DB connection pool을 적용해보았습니다. 따로 글로 정리해 두었으니여기를 클릭해서 확인해 주세요.
