dev💻/백엔드 및 DB
HikariCP와 DB Connection Pool의 이해
귤랑귤랑
2024. 10. 4. 22:57
Spring Boot를 사용하면서 자연스럽게 접하게 되는 HikariCP는 커넥션 풀(Connection Pool)로, 그 원리를 깊게 이해하지 못한 채 사용하곤 했습니다. 최근 웹서핑 중 HikariCP에서 발생할 수 있는 데드락 문제에 대한 글을 읽고, 이를 정리해보았습니다.
1. DB Connection Pool이란?
DB Connection Pool은 WAS(Web Application Server)와 DB(Database) 사이의 연결을 미리 생성하여 Pool에 보관하고, 이를 재사용하여 데이터를 교환하는 방식입니다. 이는 연결을 매번 새로 생성하는 대신, 미리 생성된 연결을 재사용함으로써 성능을 향상시킵니다.
2. Connection Pool의 필요성
WAS와 DB의 연결은 비용이 많이 드는 작업입니다. 커넥션을 위해 3-way handshaking을 통해 소켓을 생성하고, 여러 번의 패킷 교환이 필요합니다. 쿼리마다 이 작업을 반복하면 네트워크 병목 현상이 발생할 수 있습니다. 이를 해결하기 위해, 미리 정해진 개수의 커넥션을 만들어 Pool에 보관하고 관리하며 재사용합니다. 이를 통해 반복적인 3-way handshaking을 방지하고 빠른 통신이 가능합니다.
3. Connection Pool의 동작 원리
- 커넥션 획득: WAS의 Thread가 Connection을 요청하면, Connection Pool은 이용 가능한(Idle) 커넥션을 반환합니다. HikariCP의 경우, 이전에 사용한 적 있는 커넥션을 우선적으로 반환합니다.
- 대기: 사용 가능한 커넥션이 없으면, HandOffQueue에서 대기하며 다른 Thread가 커넥션을 반환하기를 기다립니다. 이때, Connection Pool의 크기가 작으면 대기하는 Thread가 많아져 성능이 저하되고, 경우에 따라 Deadlock이 발생할 수 있습니다. 이를 방지하기 위해 Pool 크기를 조정해야 합니다.
4. Connection Pool 사이즈 결정
Connection Pool의 크기를 늘리면 성능 및 Deadlock 문제를 피할 수 있지만, 필요 이상의 메모리를 사용하게 됩니다. 또한, Disk I/O와 Thread의 Context Switching 등의 이유로 증가에도 한계가 있습니다.
- Disk I/O: 하드디스크의 성능이 받쳐주지 못하면 blocking이 발생할 수 있습니다.
- Context Switching: 멀티 스레드 환경에서 Thread의 오버헤드로 인해 성능적 증가를 기대하기 어렵습니다.
HikariCP에서는 Deadlock을 피하기 위한 최소 Pool Size를 정할 때, Thread의 갯수와 동시에 필요한 커넥션 수를 고려한 공식을 제공합니다. 그러나 이 수치는 절대적이지 않으며, 시스템에 따라 달라질 수 있습니다. 따라서 성능 테스트를 통해 적절한 사이즈를 찾아야 합니다.
4-1. Simultaneous Connection
- @GenerationType.IDENTITY : 한 개의 커넥션이 필요합니다.
- @GeneratedValue(strategy = GenerationType.AUTO) : 두 개의 커넥션이 필요합니다.
결론
Connection Pool은 서버와 DB의 연결을 재사용하여 연결에 드는 비용을 최소화하기 위한 방식입니다. Pool의 크기가 작으면 대기시간이 길어져 성능 저하가 발생하며, 크기가 너무 크면 메모리를 낭비하게 됩니다. 적절한 Pool Size를 찾기 위해 성능 테스트가 필요합니다.
부족하지만 정리해보았고, 틀린 내용이 있다면 댓글로 알려주시길 바랍니다. :D